LeetCode题目总结——回溯
1. 最短路径
BFS
当边的权重为0、1时,采用BFS即可获取起点与终点之间的最短路径。
当终点唯一且已知时,可采用双向BFS进行加速。
- 0126 - 单词接龙 II
注意在计算单词节点之间的连接关系时,可采用hash表加速运算。
map<string, vector<int>> hash;
for (int i = 0; i < N; ++i) {
for (int k = 0; k < M; ++k) {
string key = wordList[i];
key[k] = '*';
if (hash.find(key) == hash.end())
hash[key] = { i };
else
hash[key].emplace_back(i);
}
}
vector<set<int>> edges(N);
for (int i = 0; i < N; ++i) {
for (int k = 0; k < M; ++k) {
string key = wordList[i];
key[k] = '*';
for (int j : hash[key]) {
edges[i].insert(j);
}
}
}
Dijkstra算法
当边的权重不为0、1时,BFS维护的队列改用优先级队列。
// 定义队列元素
struct Item {
int idx;
int dist;
bool operator<(const Item& that) const {
dist > that.dist; // 小堆顶
dist < that.dist; // 大堆顶
}
};
// 定义seen数组
vector<bool> seen(N);
fill(seen.begin(), seen.end(), false);
// 定义优先级队列
priority_queue<Item> q;
q.emplace(0, 0);
// 搜索
while (!q.empty()) {
// 获取堆顶元素
auto item = q.top();
q.pop();
// 验证seen数组
if (seen[item.idx]) continue;
seen[item.idx] = true;
// 添加相邻元素至队列,并更新距离数组
for (auto neighbor : neighbors) {
if (seen[neighbor.idx]) continue;
q.emplace(neighbor.idx, op(item.dist, dist(neighbor, item)));
}
}
2. 并查集
class UnionFind {
int n;
vector<int> parent, size;
public:
UnionFind(int n) {
this->n = n;
parent = vector<int>(n);
size = vector<int>(n, 1);
for (int i = 0; i < n; ++i)
parent[i] = i;
}
int find(int idx) {
int p = parent[idx];
if (p != idx) {
parent[idx] = find(p);
}
return parent[idx];
}
void connect(int a, int b) {
int pa = find(a), pb = find(b);
if (pa != pb) {
if (size[pa] > size[pb]) {
parent[pb] = pa;
size[pa] += size[pb];
} else {
parent[pa] = pb;
size[pb] += size[pa];
}
}
}
void check(int a, int b) {
return find(a) == find(b);
}
- 周赛220-5632 - 检查边长度限制的路径是否存在
注意为离线判定,因此,可根据判定阈值将判定条件排序,然后从小判定阈值开始,每次只将小于判定阈值的边加入图中,这样可以保证加入图中的边全部满足判定需求,只需判定当前图中的两节点是否联通即可。
判断两节点是否联通,可使用并查集。