62不同路径;64最小路径和;75颜色分类;78子集;79单词搜索

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

 

例如,上图是一个7 x 3 的网格。有多少可能的路径?

 

示例 1:

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右


示例 2:

输入: m = 7, n = 3
输出: 28

 

提示:


    1 <= m, n <= 100
    题目数据保证答案小于等于 2 * 10 ^ 9

class Solution {//递归超时
public:
    int uniquePaths(int m, int n) {
        if(n<1||m<1)return 0;
        if(m==1||n==1)return 1;
        return uniquePaths(m-1,n)+uniquePaths(m,n-1);
    }
};
class Solution {//动态规划
public:
    int uniquePaths(int m, int n) {
        if(m==1||n==1)return 1;
        vector<int> a(n,1);
        vector<vector<int>> path(m,a);
        for(int i=1;i<m;++i)
            for(int j=1;j<n;++j)
                path[i][j]=path[i-1][j]+path[i][j-1];   
        return path[m-1][n-1];
    }
};

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

class Solution {//递归超时
public:
    long long resminSum=INT_MAX,pathminSum=0;
    vector<vector<int>> v;
    int minPathSum(vector<vector<int>>& grid) {
        if(grid.size()==0)return 0;
        this->v=grid;
        helper(0,0);
        return resminSum;
    }
    void helper(int rows,int cols){
        if(rows==v.size()||cols==v[0].size())return;
        pathminSum+=v[rows][cols];
        if(rows==v.size()-1&&cols==v[0].size()-1)            
            resminSum=min(resminSum,pathminSum);
        else{
            helper(rows+1,cols);
            helper(rows,cols+1);
        }
        pathminSum-=v[rows][cols];
    }
};
class Solution {//动态规划+原数组操作
public: 
    int minPathSum(vector<vector<int>>& grid) {
        if(grid.size()==0)return 0;
        for(int i=1;i<grid[0].size();++i)
            grid[0][i]+=grid[0][i-1];
        for(int j=1;j<grid.size();++j)
            grid[j][0]+=grid[j-1][0];
        for(int i=1;i<grid.size();++i)
            for(int j=1;j<grid[0].size();++j)
                grid[i][j]+=min(grid[i-1][j],grid[i][j-1]);
        return grid[grid.size()-1][grid[0].size()-1];
    }
  
};
//可以动态规划+额外二维数组[][]操作
//或动态规划+额外一位数组[]操作

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

进阶:


    一个直观的解决方案是使用计数排序的两趟扫描算法。
    首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
    你能想出一个仅使用常数空间的一趟扫描算法吗?

class Solution {
//[,le)都是0
//[le,cur]都是1
//(cur,ri]未扫描检测
//(ri,]都是2
public:
    void sortColors(vector<int>& nums) {
        if(nums.size()<=1)return;
        int le=0,ri=nums.size()-1,cur=0;
        while(cur<=ri){//=
            if(nums[cur]==0)
                swap(nums[cur++],nums[le++]);//注意cur++
            else if(nums[cur]==2)
                swap(nums[cur],nums[ri--]);//cur 不++
            else    
                ++cur;
        }
    }
};

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

class Solution {//回溯
public:
    vector<vector<int>> res;
    vector<int> path;
    vector<int> nums;
    vector<vector<int>> subsets(vector<int>& nums) {
        if(nums.size()==0)return {};
        this->nums=nums;
        helper(0);
        return res;
    }
    void helper(int cur){
        res.push_back(path);
        for(int i=cur;i<nums.size();++i){
            path.push_back(nums[i]);
            helper(i+1);//不是cur+1
            path.pop_back();
        }
    }
};
class Solution {//bit运算 0~2^(nums.size()-1) i的第j位为0表示不选择nums[j]
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        if(nums.size()==0)return {};
        int bitSet=1<<nums.size();
        vector<vector<int>> res(bitSet);
        for(int i=0;i<bitSet;++i)
            for(int j=0;j<nums.size();++j)
                if(i>>j&1)
                    res[i].push_back(nums[j]);
        return res;
    }    
};

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

 

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false

 

提示:


    board 和 word 中只包含大写和小写英文字母。
    1 <= board.length <= 200
    1 <= board[i].length <= 200
    1 <= word.length <= 10^3

class Solution {//回溯
public:
    vector<vector<char>> board;
    string word;
    bool exist(vector<vector<char>>& board, string word) {
        if(word.size()==0)return false;
        this->board=board;
        this->word=word;
        vector<vector<bool>> covered(board.size(),vector<bool>(board[0].size(),false));
        for(int i=0;i<board.size();++i)
            for(int j=0;j<board[0].size();++j)
                if(board[i][j]==word[0]){                    
                    if(backTrack(covered,0,i,j))//找到相同起点,开始回溯遍历
                        return true;
                }
                    
        return false;
    }
    bool backTrack(vector<vector<bool>> &covered,int cur,int le,int ri){
        if(le<0||le>=covered.size()||ri<0||ri>=covered[0].size()||covered[le][ri])return false;
        if(cur==word.size()-1)return word[cur]==board[le][ri];
        if(word[cur]!=board[le][ri])return false;
        covered[le][ri]=true;
        bool resBool=backTrack(covered,cur+1,le+1,ri)||backTrack(covered,cur+1,le,ri+1)||backTrack(covered,cur+1,le-1,ri)||backTrack(covered,cur+1,le,ri-1);
        covered[le][ri]=false;
        return resBool;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值