【力扣打卡--day5】【有注释详解】

1.dp

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int n=grid.size();
        if(!n) return 0;
        int m=grid[0].size();

        vector<vector<int>> dp=vector<vector<int>>(n,vector<int>(m,INT_MAX));
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                if(!i&&!j) dp[i][j]=grid[i][j];
                else{
                    if(i) dp[i][j]=min(dp[i][j],dp[i-1][j]+grid[i][j]);//看看从上边走来的状态
                    if(j) dp[i][j]=min(dp[i][j],dp[i][j-1]+grid[i][j]);//看看从左边走来的状态
                }
            }

        return dp[n-1][m-1];
    }
};

思路

  • 动态规划,每个位置只可能从上或者左过来。

2.栈

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    string simplifyPath(string path) {
        int n=path.size();
        string res,name;
        if(path.back()!='/') path+='/';//加这个是为了统一格式,都以/结尾

        for(auto c:path){
            if(c!='/'){
                name+=c;//装名字
            }else{
                if(name==".."){//回退
                    while(res.size()&&res.back()!='/') res.pop_back();//吐名字
                    if(res.size()) res.pop_back();//吐/
                }else if(name!="."&&name!=""){//.和空被忽略
                    res+='/'+name;//装进/+名字
                }
                name.clear();
            }
        }
        if(res.empty()) res+='/';
        return res;
    }
};

3.脑筋急转弯

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int N=matrix.size();
        int M=matrix[0].size();
        int st1=0,st2=0;//用于判断第0行和第0列是否需要设0
        for(int i=0;i<N;i++){
            if(matrix[i][0]==0){
                st1=1;
                break;
            }
        }
        for(int i=0;i<M;i++){
            if(matrix[0][i]==0){
                st2=1;
                break;
            }
        }
        for(int i=1;i<N;i++){
            for(int j=1;j<M;j++){//从[1][1]开始找一旦有0则记录在对应行
            //和对应列的头部也就是第0行和第0列
                if(matrix[i][j]==0){
                    matrix[i][0]=0;
                    matrix[0][j]=0;
                }
            }
        }
        for(int i=1;i<N;i++){
            if(matrix[i][0]==0){
                for(int j=0;j<M;j++){
                    matrix[i][j]=0;
                }
            }
        }
        for(int i=1;i<M;i++){
            if(matrix[0][i]==0){
                for(int j=0;j<N;j++){
                    matrix[j][i]=0;//i是列噢
                }
            }
        }
        if(st1){//最后才处理第0行和第0列,因为前面拿来装东西了,脏了,所以留最后更新
            for(int i=0;i<N;i++){
                matrix[i][0]=0;
            }
        } 
        if(st2){
            for(int i=0;i<M;i++){
                matrix[0][i]=0;
            }
        }  
    }
};

思路

  • 先看第一行第一列是否要刷0,记录后,就遍历,看看哪行哪列需要刷0,用的话记在相应的第一行和第一列的位置。

4.二分

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int n=matrix.size(),m=matrix[0].size();
        if(n==0||m==0) return false;

        int l=0,r=n*m-1;
        while(l<r){
            int mid=(l+r)>>1;
            if(matrix[mid/m][mid%m]>=target){//记住一维转二维的公式[mid/m][mid%m]
                r=mid;
            }else l=mid+1;
        }
        return matrix[r/m][r%m]==target;
    }
};

5.脑筋急转弯

在这里插入图片描述

class Solution {
public:
    void sortColors(vector<int>& nums) {
        for(int i=0,j=0,k=nums.size()-1;i<=k;){//j是0和1分界,i是遍历到哪里,k是2和其他的边界
        //当i和k重合再过一步就可以保证0、1、2分完
            if(nums[i]==0){
                swap(nums[j],nums[i]);
                j++,i++;
            }else if(nums[i]==2){
                swap(nums[i],nums[k]);
                k--;
            }else i++;
        }
    }
};

6.dfs

在这里插入图片描述
在这里插入图片描述

class Solution {
public:

    vector<vector<int>> res;
    vector<int> path;

    vector<vector<int>> combine(int n, int k) {
        dfs(n,k,1);
        return res;
    }
    
    void dfs(int n,int k,int idx){
        if(!k){
            res.push_back(path);
            return;
        }
        for(int i=idx;i<=n;i++){//idx是为了保证从前往后,好马不吃回头草的顺序,保证不重不漏
            path.push_back(i);
            dfs(n,k-1,i+1);
            path.pop_back();
        }
    }
};

7.位运算

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        int n=nums.size();
        for(int i=0;i<1<<n;i++){//n位二进制
            vector<int> path;
            for(int j=0;j<n;j++){//看每一位是0还是1
                if(i>>j&1){//相应位为1就表示相应位的数字要
                    path.push_back(nums[j]);
                }
            }
            res.push_back(path);
        }
        return res;
    }
};

8.dfs

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        for(int i=0;i<board.size();i++)
            for(int j=0;j<board[i].size();j++){
                if(dfs(board,word,0,i,j)) return true;
            }
        return false;
    }

    int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};

    bool dfs(vector<vector<char>>& board,string& word,int c,int x,int y){
        if(board[x][y]!=word[c]) return false;
        if(c==word.size()-1){
            return true;
        }

        char t=board[x][y];
        board[x][y]='.';//表示用过
        for(int i=0;i<4;i++){
            int a=x+dx[i],b=y+dy[i];
            if(a<0||a>=board.size()||b<0||b>=board[0].size()||board[a][b]=='.'){//边界
                continue;
            }
            if(dfs(board,word,c+1,a,b)) return true;
        }
        board[x][y]=t;//恢复现场
        return false;
    }

};

9.栈

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int k=0;
        for(auto x:nums){
            if(k<2||nums[k-1]!=x||nums[k-2]!=x){//只要不和前俩重复就装
                nums[k++]=x;
            }
        }
        return k;
    }
};

10.二分

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        if(nums.empty()) return false;
        int n=nums.size()-1;//画图知道图像是两段以nums[0]为分界线的
        while(n>=0&&nums[n]==nums[0]) n--;//把第二段的nums[0]都去掉,
        //因为如果等于这个值两端都有就无法判断在哪段了
        if(n<0) return nums[0]==target;

        int l=0,r=n;
        while(l<r){
            int mid=(l+r+1)/2;
            if(nums[mid]>=nums[0]) l=mid;//找第一段的尾
            else r=mid-1;
        }

        if(nums[0]<=target) r=l,l=0;//在第一段
        else l=l+1,r=n;//在第二段

        while(l<r){
            int mid=(l+r)/2;
            if(nums[mid]>=target) r=mid;
            else l=mid+1;
        }

        return nums[r]==target;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值