算法复习:BFS与DFS
BFS
leetcode 279. 完全平方数
vector存每一层的节点,弹出一个节点就压入这个节点所有的子节点。
从上往下维护一颗树,根节点是要找的n,第一层子节点是父节点减去i*i以后的值,一直到发现0为止。
注意必须要用一个标记数组记录已经走过的点避免重复查找,否则会超时
如果更改一下顺序,按从大到小的顺序查会更快一点。
#include<vector> #include<queue> #include<map> class Solution { public: int numSquares(int n) { vector<int>donser; queue<int>tree; map<int,bool>lable; for(int i=1;i*i<=n;i++) { tree.push(n-i*i); donser.push_back(i*i); } int deepth=0; while(n) { int size=tree.size(); deepth++; for(int i=0;i<size;i++) { int next=tree.front(); tree.pop(); if(next==0) return deepth; for(int j=0;j<donser.size();j++) { if(lable[next-donser[j]]==true) { continue; } if(donser[j]<=next) { tree.push(next-donser[j]); lable[next-donser[j]]=true; } else break; } } } return 0; } };
DFS
leedcode 695. 岛屿的最大面积
向四个方向搜,走过的地方做标记
class Solution { public: int dfs(int i,int j,vector<vector<int>>& grid,map<int,int>& lable,int count) { lable[i*grid[0].size()+j]=1; if(i>=1&&lable[(i-1)*grid[0].size()+j]!=1&&grid[i-1][j]==1)//向上 { count=dfs(i-1,j,grid,lable,++count); } if(i+1<grid.size()&&lable[(i+1)*grid[0].size()+j]!=1&&grid[i+1][j]==1)//向下 { count=dfs(i+1,j,grid,lable,++count); } if(j>=1&&lable[i*grid[0].size()+j-1]!=1&&grid[i][j-1]==1)//向左 { count=dfs(i,j-1,grid,lable,++count); } if(j+1<grid[0].size()&&lable[i*grid[0].size()+j+1]!=1&&grid[i][j+1]==1)//向右 { count=dfs(i,j+1,grid,lable,++count); } return count; } int maxAreaOfIsland(vector<vector<int>>& grid) { map<int,int>lable; int max=0,count=0; for(int i=0;i<grid.size();i++) { vector<int>line=grid[i]; for(int j=0;j<line.size();j++) { count=1; if(lable[i*line.size()+j]!=1)//没访问过 { if(grid[i][j]==0)//0就跳过 continue; count=dfs(i,j,grid,lable,count); if(max<count) max=count; } else continue; } } return max; } };
改进:不需要标记数组,直接将走过的地方赋值成0,时间和空间都会节省下来
class Solution { public: int dfs(int i,int j,vector<vector<int>>& grid,int count) { grid[i][j]=0; if(i>=1&&grid[i-1][j]==1)//向上 { count=dfs(i-1,j,grid,++count); } if(i+1<grid.size()&&grid[i+1][j]==1)//向下 { count=dfs(i+1,j,grid,++count); } if(j>=1&&grid[i][j-1]==1)//向左 { count=dfs(i,j-1,grid,++count); } if(j+1<grid[0].size()&&grid[i][j+1]==1)//向右 { count=dfs(i,j+1,grid,++count); } return count; } int maxAreaOfIsland(vector<vector<int>>& grid) { int max=0,count=0; for(int i=0;i<grid.size();i++) { vector<int>line=grid[i]; for(int j=0;j<line.size();j++) { count=1; if(grid[i][j]==0)//0就跳过 continue; count=dfs(i,j,grid,count); if(max<count) max=count; } } return max; } };
leetcode 200. 岛屿数量
和上面的一样,改成char,不需要标记数组,不需要统计每一块内的数量,统计不联通的数量即可
class Solution { public: void dfs(int i,int j,vector<vector<char>>& grid) { grid[i][j]='0'; if(i>=1&&grid[i-1][j]=='1')//向上 { dfs(i-1,j,grid); } if(i+1<grid.size()&&grid[i+1][j]=='1')//向下 { dfs(i+1,j,grid); } if(j>=1&&grid[i][j-1]=='1')//向左 { dfs(i,j-1,grid); } if(j+1<grid[0].size()&&grid[i][j+1]=='1')//向右 { dfs(i,j+1,grid); } return ; } int numIslands(vector<vector<char>>& grid) { int max=0,count=0; for(int i=0;i<grid.size();i++) { vector<char>line=grid[i]; for(int j=0;j<line.size();j++) { if(grid[i][j]=='0')//0就跳过 continue; count++; dfs(i,j,grid); } } return count; } };
leetcode 17. 电话号码的字母组合
典型的深搜,要一眼看出来
class Solution { public: vector<string>result; vector<char>vec; string dictionary(char a) { string str; if(a=='2') str="abc"; if(a=='3') str="def"; if(a=='4') str="ghi"; if(a=='5') str="jkl"; if(a=='6') str="mno"; if(a=='7') str="pqrs"; if(a=='8') str="tuv"; if(a=='9') str="wxyz"; return str; } string mk_str(int maxlen) { string tmp(maxlen, ' '); for(int i=0;i<maxlen;i++) { tmp[i]=vec[i]; } return tmp; } void loop(string digs,int i,int maxlen) { if(i>=maxlen) { result.push_back(mk_str(maxlen)); return; } string now=dictionary(digs[i]); for(int m=0;m<now.size();m++) { //cout<<"push:"<<now[m]<<endl; vec.push_back(now[m]); i++; loop(digs,i,maxlen); i--; //cout<<"pop :"<<vec.back()<<endl; vec.pop_back(); } return; } vector<string> letterCombinations(string digits) { if (digits.size()==0) return result; loop(digits,0,digits.size()); return result; } };
leetcode 22. 括号生成
深搜+剪枝
class Solution { public: vector<char>tmp; vector<string>result; string char2string() { int maxlen=tmp.size(); string ttmp(maxlen, ' '); for(int i=0;i<maxlen;i++) { ttmp[i]=tmp[i]; } return ttmp; } void loop(int numA,int numB,int max) { if(numB>=max)//返回条件 { string mystr=char2string(); result.push_back(mystr); return; } if(numA>=max)//前括号已满 { numB++; tmp.push_back(')'); loop(numA,numB,max); tmp.pop_back(); numB--; } else//前括号未满 { if(numA>numB) { numA++; tmp.push_back('('); loop(numA,numB,max); tmp.pop_back(); numA--; numB++; tmp.push_back(')'); loop(numA,numB,max); tmp.pop_back(); numB--; } else { numA++; tmp.push_back('('); loop(numA,numB,max); tmp.pop_back(); numA--; } } return; } vector<string> generateParenthesis(int n) { loop(0,0,n); return result; } };
leetcode 39. 组合总和
class Solution { public: vector<vector<int>> result; vector<int>tmp; void dfs(vector<int>& candidates, int target,int i) { if(target==0)//可能找到了结果 { if(tmp.size()>0)//真的找到了结果 { result.push_back(tmp); return; } } if(i>=candidates.size())//找到最后了 return; if(candidates[i]>target)//超过去了 return; for(int k=i;k<candidates.size();k++) { target=target-candidates[k];//减 tmp.push_back(candidates[k]);//入栈 dfs(candidates,target,k); target=target+candidates[k];//还原 tmp.pop_back();//出栈 } return; } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { if(candidates.size()==0) return result; sort(candidates.begin(),candidates.end());//排序 dfs(candidates,target,0); return result; } };
78. 子集
class Solution { public: vector<vector<int>>result; vector<int>tmp; void dfs(vector<int>& nums,int deepth,int maxD,int x) { if(x>nums.size()) return; if(tmp.size()==maxD) { result.push_back(tmp); return; } for(int i=x;i<nums.size();i++) { tmp.push_back(nums[i]); deepth++; i++; dfs(nums,deepth,maxD,i); i--; deepth--; tmp.pop_back(); } return; } vector<vector<int>> subsets(vector<int>& nums) { result.push_back(tmp); if(nums.size()==0) return result; result.push_back(nums); for(int i=1;i<nums.size();i++) { dfs(nums,0,i,0); } return result; } };