问题描述
https://leetcode.com/problems/number-of-provinces/
当我第一次尝试解决这个问题时,我非常兴奋,仅用了 20/30 分钟,但当我提交代码时,我最终获得了 8.43 个百分位。我查看了最快的解决方案是如何解决这个问题的,结果发现,示例顶级解决方案几乎与我的代码相同,但它的运行速度提高了 3 倍。我一直在比较代码,并不能真正指出足够大的差异。两者都应该同样快......谁能解释为什么?如果我没记错的话,这两种情况的性能都是 O(mn)。
以下是我的代码。这是不言自明的,所以不确定大量评论会有什么好处。
class Solution {
public:
int findCircleNum(vector<vector<int>>& isConnected) {
int components = 0;
vector<bool> visited (isConnected.size(),false);
// go through each row
for (int i = 0; i < isConnected.size(); i++) {
// explore only unvisited items
if (!visited[i]) {
queue<int> q;
q.push(i);
components++;
while (!q.empty()) {
int node = q.front();
q.pop();
visited[node] = true;
// push all direct connections onto the queue so we explore them
for (int j = 0; j < isConnected[0].size(); j++) {
if (isConnected[node][j] == 1 && !visited[j]) {
q.push(j);
}
}
}
}
}
return components;
}
};
class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
if (M.empty()) {
return 0;
}
int count = 0;
vector<bool> visited(M.size());
auto bfs = [&](int student) {
queue<int> q;
q.push(student);
visited[student] = true;
while (!q.empty()) {
auto current = q.front();
cout << "current " << current << endl;
q.pop();
for (int i = 0; i < M.size(); i++) {
if (M[current][i] == 1 and !visited[i]) {
visited[i] = true;
q.push(i);
}
}
}
};
for (int r = 0; r < M.size(); r++) {
if (visited[r] == false) {
count++;
bfs(r);
}
}
return count;
}
};
解决方法
区别就我可以[看到][1] visited[i] = true;
的位置而言,这会导致每次迭代的内存访问量减少一些。 OP代码需要重新获取bool的地方。
之间可能存在数据或控制流依赖
visited[node] = true;
和
!visited[j]
最好的代码中没有。
OP 代码内循环
.L118:
mov rax,QWORD PTR [rsi+rbx]
cmp DWORD PTR [rax+rcx*4],1
jne .L116
mov rax,rbp
mov r8,rcx
sal rax,cl
mov rcx,QWORD PTR [rsp+80]
shr r8,6
and rax,QWORD PTR [rcx+r8*8]
jne .L116
mov rax,QWORD PTR [rsp+192]
sub rax,4
cmp rdi,rax
je .L117
“最佳”代码
.L76:
mov rax,1
jne .L74
mov rax,QWORD PTR [r12]
mov rsi,rcx
shr rsi,6
mov rax,QWORD PTR [rax]
lea rsi,[rax+rsi*8]
mov eax,1
sal rax,QWORD PTR [rsi]
test rcx,rax
jne .L74
or rax,rcx <------------ visited[i] = true;
mov QWORD PTR [rsi],rax
mov rax,QWORD PTR [rsp+96]
sub rax,4
cmp r8,rax
je .L75
mov DWORD PTR [r8],edx
add r8,4
mov QWORD PTR [rsp+80],r8
jmp .L74
[1]: https://godbolt.org/z/obfqf7