应用为层序遍历树、最短路径

14.1 752. 打开转盘锁

  1. class Solution {
  2. public:
  3. int openLock(vector<string>& deadends, string target) {
  4. unordered_set<string> deads;//记录死亡密码
  5. //初始化死亡密码
  6. for(string s:deadends){
  7. deads.insert(s);
  8. }
  9. if(deads.count("0000")){
  10. return -1;//锁死
  11. }
  12. int step=0; //需要的步数
  13. queue<string> q;
  14. q.push("0000");
  15. unordered_set<string> visited; //记录已经穷举过的密码
  16. visited.insert("0000");
  17. while(!q.empty()){
  18. int size=q.size();
  19. for(int i=0;i<size;i++){
  20. string cur=q.front();
  21. q.pop();
  22. //死亡密码,跳过
  23. if(deads.count(cur)){
  24. continue;
  25. }
  26. //判断是否到达终点
  27. if(cur==target){
  28. return step;
  29. }
  30. for(int j=0;j<4;j++){
  31. //向上转
  32. string up=plusOne(cur,j);
  33. if(!visited.count(up)){
  34. q.push(up);
  35. visited.insert(up);
  36. }
  37. //向下转
  38. string down=minusOne(cur,j);
  39. if(!visited.count(down)){
  40. q.push(down);
  41. visited.insert(down);
  42. }
  43. }
  44. }
  45. step++;
  46. }
  47. return -1;
  48. }
  49. string plusOne(string s,int i){
  50. if(s[i]=='9'){
  51. s[i]='0';
  52. }else{
  53. s[i]+=1;
  54. }
  55. return s;
  56. }
  57. string minusOne(string s,int i){
  58. if(s[i]=='0'){
  59. s[i]='9';
  60. }else{
  61. s[i]-=1;
  62. }
  63. return s;
  64. }
  65. };
  1. //双向BFS
  2. class Solution {
  3. public:
  4. int openLock(vector<string>& deadends, string target) {
  5. unordered_set<string> deads;//记录死亡密码
  6. //初始化死亡密码
  7. for(string s:deadends){
  8. deads.insert(s);
  9. }
  10. if(deads.count("0000")){
  11. return -1;//锁死
  12. }
  13. int step=0; //需要的步数
  14. unordered_set<string> q1,q2;
  15. q1.insert("0000");
  16. q2.insert(target);
  17. unordered_set<string> visited; //记录已经穷举过的密码
  18. visited.insert("0000");
  19. while(!q1.empty()&&!q2.empty()){
  20. //哈希表在遍历过程中不能修改,用temp存储
  21. unordered_set<string> temp;
  22. for(string cur:q1){
  23. //判断是否为死亡密码
  24. if(deads.count(cur)){
  25. continue;
  26. }
  27. //判断是否到达终点
  28. if(q2.count(cur)){
  29. return step;
  30. }
  31. visited.insert(cur);
  32. //将一个节点的未遍历相邻节点加入集合
  33. for(int i=0;i<4;i++){
  34. string up=plusOne(cur,i);
  35. if(!visited.count(up)){
  36. temp.insert(up);
  37. }
  38. string down=minusOne(cur,i);
  39. if(!visited.count(down)){
  40. temp.insert(down);
  41. }
  42. }
  43. }
  44. step++;
  45. //temp相当于q1
  46. q1=q2;
  47. //交换q1,q2,下一轮while就是扩散q2
  48. q2=temp;
  49. }
  50. return -1;
  51. }
  52. string plusOne(string s,int i){
  53. if(s[i]=='9'){
  54. s[i]='0';
  55. }else{
  56. s[i]+=1;
  57. }
  58. return s;
  59. }
  60. string minusOne(string s,int i){
  61. if(s[i]=='0'){
  62. s[i]='9';
  63. }else{
  64. s[i]-=1;
  65. }
  66. return s;
  67. }
  68. };

14.2 210. 课程表 II

  1. class Solution {
  2. public:
  3. vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
  4. vector<vector<int>> graph(numCourses);
  5. vector<int> indgree(numCourses);
  6. //统计入度
  7. for(auto p:prerequisites){
  8. int from=p[1],to=p[0];
  9. graph[from].push_back(to);
  10. indgree[to]++;
  11. }
  12. //根据入度将节点加入队列,入度为0加入
  13. queue<int> q;
  14. for(int i=0;i<numCourses;i++){
  15. if(indgree[i]==0){
  16. q.push(i);
  17. }
  18. }
  19. int count=0; //记录遍历节点的索引
  20. vector<int> result(numCourses); //记录排序结果
  21. while(!q.empty()){
  22. int cur=q.front();
  23. q.pop();
  24. //弹出节点的顺序就是拓扑排序顺序
  25. result[count]=cur;
  26. count++;
  27. for(int g:graph[cur]){
  28. //入度-1,为0加入队列
  29. indgree[g]--;
  30. if(indgree[g]==0){
  31. q.push(g);
  32. }
  33. }
  34. }
  35. if(count!=numCourses){
  36. return {};
  37. }
  38. return result;
  39. }
  40. };