994. 腐烂的橘子
解法一:DFS
1 int dx[4]={-1,0,1,0}; 2 int dy[4]={0,-1,0,1}; 3 class Solution { 4 public: 5 //这里需要对普通的DFS进行一定的处理,即DFS进化版本。。。 6 void dfs(vector<vector<int>>& grid,int i,int j,int res){ 7 if(i<0||j<0||i>=grid.size()||j>=grid[0].size())return ; 8 if(grid[i][j]!=1&&grid[i][j]<res)return ;//预防不符合条件的再次访问。。。 9 grid[i][j]=res; 10 res++; 11 12 for(int k=0;k<4;k++){ 13 int x=dx[k]+i,y=dy[k]+j; 14 dfs(grid,x,y,res); 15 } 16 } 17 int orangesRotting(vector<vector<int>>& grid) { 18 int m=grid.size(); 19 int n=grid[0].size(); 20 21 for(int i=0;i<m;i++){ 22 for(int j=0;j<n;j++){ 23 if(grid[i][j]==2){ 24 dfs(grid,i,j,2);//很好解决我没法解决的问题。。。 25 } 26 } 27 } 28 int cnt=0; 29 for(int i=0;i<m;i++){ 30 for(int j=0;j<n;j++){ 31 if(grid[i][j]==1)return -1; 32 else{ 33 cnt=max(cnt,grid[i][j]); 34 //cout<<cnt<<endl; 35 } 36 } 37 } 38 if(cnt==0)return 0; 39 return cnt-2; 40 41 42 } 43 };
解法二:BFS
1 int dx[4]={-1,0,1,0}; 2 int dy[4]={0,-1,0,1}; 3 class Solution { 4 public: 5 int orangesRotting(vector<vector<int>>& grid) { 6 queue<pair<int,int>>que; 7 int m=grid.size(); 8 int n=grid[0].size(); 9 for(int i=0;i<m;i++){//初始化 10 for(int j=0;j<n;j++){ 11 if(grid[i][j]==2){ 12 que.push({i,j}); 13 } 14 } 15 } 16 int res=0; 17 while(!que.empty()){ 18 int k=que.size(); 19 bool flag=false; 20 for(int i=0;i<k;i++){ 21 pair<int,int>q=que.front(); 22 que.pop(); 23 int f1=q.first,f2=q.second; 24 for(int j=0;j<4;j++){ 25 int x=dx[j]+f1,y=dy[j]+f2; 26 if(x>=0&&y>=0&&x<m&&y<n&&grid[x][y]==1){ 27 flag=true; 28 grid[x][y]=2; 29 que.push({x,y}); 30 } 31 } 32 } 33 if(flag)res++; 34 } 35 for(int i=0;i<m;i++){ 36 for(int j=0;j<n;j++){ 37 if(grid[i][j]==1)return -1; 38 } 39 } 40 return res; 41 } 42 };
面试题57 - II. 和为s的连续正数序列
滑动窗口:
解法一:list STL:
1 class Solution { 2 public: 3 //滑动窗口求解。。。。或者叫做双指针 4 vector<vector<int>> findContinuousSequence(int target) { 5 vector<vector<int>>ans; 6 list<int>ls;//使用一个链表来实现滑动窗口。。。 7 vector<int>temp; 8 int k=0,i=1; 9 while(i<target){ 10 if(k==target){ 11 for(auto v:ls){ 12 temp.push_back(v); 13 } 14 ans.push_back(temp); 15 temp.clear(); 16 k=k-ls.front(); 17 ls.pop_front(); 18 }else if(k>target){ 19 k=k-ls.front(); 20 ls.pop_front(); 21 }else{ 22 k=k+i; 23 ls.push_back(i); 24 i++; 25 } 26 } 27 return ans; 28 } 29 };
方法二:双指针:
1 class Solution { 2 public: 3 vector<vector<int>> findContinuousSequence(int target) { 4 vector<vector<int>>ans; 5 for(int i=1,j=2;i<j;){ 6 int sum=(i+j)*(j-i+1)/2; 7 if(sum==target){ 8 vector<int>res; 9 for(int k=i;k<=j;k++){ 10 res.push_back(k); 11 } 12 ans.push_back(res); 13 } 14 if(sum>target){ 15 i++; 16 }else j++; 17 } 18 return ans; 19 } 20 };
322. 零钱兑换
解法一:DFS
1 class Solution { 2 public: 3 //DFS解法,优先使用大的币值,之后加上一些剪枝,因为之前DFS使用大的币值,需要的硬币的数目更少。。。所以之后DFS的到的硬币数目多余之前的数目直接剪枝掉。。。 4 void dfs(vector<int>& coins, int amount,int count,int& ans,int s){ 5 //递归结束条件 6 int coin=coins[s]; 7 if(amount<0)return ; 8 if(s==coins.size()-1){ 9 if(amount%coin==0){ 10 ans=min(ans,count+amount/coin);//表示的当前需要的硬币数加上之前需要的硬币数 11 } 12 }else{ 13 for(int k=amount/coin;k>=0&&count+k<ans;k--){//count+k<ans就是剪枝,表示的意思是:之前硬币的数量加上当前的硬币的数量大于等于已经求得的数量的时候,就不要DFS下去啦。。。 14 dfs(coins,amount-k*coin,count+k,ans,s+1); 15 } 16 } 17 } 18 int coinChange(vector<int>& coins, int amount) { 19 sort(coins.begin(),coins.end(),greater<int>()); 20 //count=0;//count表示的意思是之前递归,使用之前的币值需要的硬币数。 21 int ans=amount+1; 22 dfs(coins,amount,0,ans,0); 23 return ans==amount+1?-1:ans; 24 } 25 };
解法二:一维DP,背包问题的进化版本
1 class Solution { 2 public: 3 //DP:经典的DP问题 4 int coinChange(vector<int>& coins, int amount) { 5 sort(coins.begin(),coins.end()); 6 vector<int>dp(amount+1,amount+1);//初始化:初始化一个比较大的数字,amount+1足矣,因为需要的硬币数不可能大于总共需要的硬币。。。。 7 dp[0]=0;//初始化 8 for(int i=0;i<coins.size();i++){ 9 int num=coins[i]; 10 for(int k=num;k<=amount;k++){ 11 dp[k]=min(dp[k],dp[k-num]+1); 12 } 13 } 14 return dp[amount]==amount+1?-1:dp[amount]; 15 } 16 };
1071. 字符串的最大公因子
1 inline int gcd(int a,int b){ 2 return b==0?a:gcd(b,a%b); 3 } 4 class Solution { 5 public: 6 string gcdOfStrings(string str1, string str2) { 7 if(str1+str2!=str2+str1)return "";//如果 str1 和 str2 存在最大公约数 str,那么就相当于 str1 和 str2 都是由 str 组成的,那么 str1 + str2 和 str2 + str1 应该是相等的 8 //如果不满足,那么不存在最大公约数 9 return str1.substr(0,gcd(str1.length(),str2.length())); 10 } 11 };
300. 最长上升子序列
解法一:暴力dp求解,但是注意将dp初始化为1,因为我们往往在记录的时候通常不会将当前的结点算上。
1 class Solution { 2 public: 3 int lengthOfLIS(vector<int>& nums) { 4 int n=nums.size(); 5 if(n==0)return 0; 6 vector<int>dp(n+1,1); 7 cout<<dp[0]; 8 int res=0; 9 for(int i=0;i<n;i++){ 10 for(int j=0;j<i;j++){ 11 if(nums[i]>nums[j]){ 12 dp[i]=max(dp[i],dp[j]+1); 13 } 14 } 15 res=max(res,dp[i]); 16 } 17 return res; 18 } 19 };
解法二:二分法进行优化求解最长上升子序列:
1 class Solution { 2 public: 3 int lengthOfLIS(vector<int>& nums) { 4 int n=nums.size(); 5 vector<int>dp; 6 for(int i=0;i<n;i++){ 7 if(dp.size()==0||nums[i]>dp.back()){ 8 dp.push_back(nums[i]); 9 }else{ 10 *lower_bound(dp.begin(),dp.end(),nums[i])=nums[i];//注意lower_bound返回的是地址,所以要进行取地址操作 11 //还有就是:lower_bound返回的是大于等于nums[i]的数的地址,upper_bound返回的是大于nums[i]的数的地址,这是两者不同的地方 12 } 13 } 14 return dp.size(); 15 } 16 };
695. 岛屿的最大面积
1 int dx[4]={1,-1,0,0}; 2 int dy[4]={0,0,1,-1}; 3 class Solution { 4 public: 5 //求解最大连通块的大小。。。DFS 6 void dfs(vector<vector<int>>& grid,vector<vector<int>>&vis,int i,int j,int &cnt){ 7 // vis[i][j]=true; 8 // cnt++; 9 for(int k=0;k<4;k++){ 10 int x=i+dx[k]; 11 int y=j+dy[k]; 12 if(x>=0&&x<grid.size()&&y>=0&&y<grid[0].size()&&!vis[x][y]&&grid[x][y]){ 13 cnt++; 14 //cout<<cnt<<endl; 15 vis[x][y]=1; 16 dfs(grid,vis,x,y,cnt); 17 } 18 } 19 20 } 21 int maxAreaOfIsland(vector<vector<int>>& grid) { 22 int res=0; 23 int m=grid.size(); 24 int n=grid[0].size(); 25 vector<vector<int>>vis(m+1,vector<int>(n+1,0)); 26 for(int i=0;i<m;i++){ 27 for(int j=0;j<n;j++){ 28 if(vis[i][j]==0&&grid[i][j]){ 29 int cnt=1; 30 vis[i][j]=1; 31 dfs(grid,vis,i,j,cnt); 32 //cout<<cnt<<endl; 33 res=max(cnt,res); 34 } 35 } 36 } 37 return res; 38 } 39 };