赞
踩
把力扣学习计划之图论基础写完了,萌生出挑出几道我觉得好的题目出来的想法。
在“图论基础”学习计划中搜索占主体。本篇博客也将围绕搜索展开。
搜索中抓住:方向 + 去重
知识点:(循循渐进)
解法:bfs、dfs、并查集。
这道题的评论区有很多优质解法,不再赘述。
写完这道题后你将了解 邻接矩阵、直观的搜索。
知识点:多源bfs ,不了解的读者可以参考我原来的写过的一篇博客
什么是 多源bfs ? 无非是普通bfs初始化的时候把符合某条件的点全部加进队列中。
知识点:邻接链表、图的深度优先搜索
对于每一个点搜索所有与他相连的点、并一直搜到底。
写了这题后读者将对图的常规表示形式(邻接矩阵、邻接链表)有一个大致的了解。
还有一种表示形式是结构体数组,只存储边的信息。感兴趣的读者可以翻阅我之前的博客学习Kruskal算法。
知识点:抽象图的 bfs
不是在图中的遍历,但是有 bfs 的特征。
搜索的本质是什么?我的理解是每次将所有可能加入队列、像一滴墨水滴入水中不停扩散、直到到达终点。
这题的难点是如何用哈希表表示pair
。这里使用自定义哈希函数来存储pair
。用到的函数是decltype
,同样用到过该函数的有堆的自定义排序。
typedef pair<int, int> PII; class Solution { public: bool canMeasureWater(int a, int b, int c) { queue<PII> q; //a b q.push({0, 0}); auto hash_function = [](const PII &o) { return hash<int>()(o.first) ^ hash<int>()(o.second); }; unordered_set<PII, decltype(hash_function)> seen(0, hash_function); while(q.size()) { auto [x, y] = q.front(); q.pop(); if(x == c || y == c || x + y == c) return true; if(seen.count({x, y})) continue; seen.emplace(x, y); //全x 全y 空x 空y x->y y->x q.push({a, y}); q.push({x, b}); q.push({0, y}); q.push({x, 0}); q.push({x - min(x, b - y), y + min(x, b - y)}); q.push({x + min(a - x, y), y - min(a - x, y)}); } return false; } };
知识点:起点到终点带中间限制的最小步数
模板如下:
unordered_set<set> Set(a.begin(), a.end()); //查询 a是题目给的限制表 unordered_map<string, int> m; //word step 去重+计数 queue<string> q; //bfs while(q.size()) { auto it = q.front(); q.pop(); int val = m[it]; if(it == end) return val; //到了终点 for(int i = 0; i < it.size(); ++ i) { string s = it; //这里依据题目决定写在哪个循环的里面 for(int j = 0; j < t; ++ j) //次数依题意 含义是向外拓展所有可能 { s[i] = j; if(Set.count(s) && !m.count(s)) //与限制表挂钩 + 去重 + 计数 { m.insert({s, val + 1}); q.push(s); } } } }
这题的 AC 代码:
class Solution { public: //bfs 将每一步能到达的加到队列里面 char ch[4] = {'A', 'C', 'G', 'T'}; int minMutation(string start, string end, vector<string>& bank) { unordered_set<string> bankSet(bank.begin(), bank.end()); if(!bankSet.count(end)) return -1; unordered_map<string, int> m; m.insert({start, 0}); queue<string> q; q.push(start); while(q.size()) { string s = q.front(); q.pop(); int val = m[s]; if(s == end) return val; for(int i = 0; i < 8; ++ i) { string ss = s; for(int j = 0; j < 4; ++ j) { ss[i] = ch[j]; if(bankSet.count(ss) && !m.count(ss)) { m[ss] = val + 1; q.push(ss); } } } } return -1; } };
还有两个类似的题目供读者自测:
知识点:二分图。读者看了这篇博客后能直接 AC
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。