一个机器人位于一个 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;
}
};
。