1.N皇后
题目描述:n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
解题思路:不能相互攻击即不再同一条直线上,包括横线竖线和斜线
1.类中定义存放结果的vector
2.初始化queen数组,存放n个-1
3.递归核心,参数是第一个皇后对应的下标0,皇后总个数n,已经初始化的queen数组
4.如果皇后下标(第一个参数)==皇后总个数(第二个参数),{
定义temp临时数组,i从0遍历到n,now为空,j从0遍历到n,如果j和queen中i位置存的值相等,now加Q填充。否则加“.”填充
把该行now压入temp
把temp压入ans
}
5.如果不等,col从0到n,queen中第一个参数位置的值为col
判断能否摆放,如果可以,递归(下一行,n,queue),不行就回溯到上一行
6.判断是否能摆放,从0到当前row,如果queen在row位置的值等于在j位置的值,或者在一条斜线上(row-queen[row] == j-queen[j]||row+queen[row] == j+queen[j]),返回false,否则返回true。
class Solution {
public:
vector<vector<string>> ans;
vector<vector<string>> solveNQueens(int n) {
vector<int> queen(n,-1);
Queens(0,n,queen);
return ans;
}
void Queens(int row,int n,vector<int>& queen){
if(row == n){
vector<string> temp;
for(int i = 0;i<n;++i){
string now = "";
for(int j = 0;j<n;++j){
if(j == queen[i]){
now+="Q";
}
else{
now+=".";
}
}
temp.push_back(now);
}
ans.push_back(temp);
}
else{
for(int col=0;col<n;++col){
queen[row] = col;
if(isOk(row,n,queen)){
Queens(row+1,n,queen);
}
//如果row行所有列都不能摆放,回溯到上一行
}
}
}
bool isOk(int row,int n, vector<int>& queen){
for(int j = 0;j<row;++j){
if(queen[row] == queen[j]||row-queen[row] == j-queen[j]||row+queen[row] == j+queen[j]){
return false;
}
}
return true;
}
};
2.螺旋矩阵(该题作业帮遇到过,能解决)
题目描述:
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
解题思路:
到边界状态会转换。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> ans;
if(matrix.empty()) return ans;
int u = 0;
int d = matrix.size()-1;
int l = 0;
int r = matrix[0].size()-1;
while(true){
for(int i = l;i<=r;++i) ans.push_back(matrix[u][i]);
if(++u>d) break;
for(int i = u;i<=d;++i) ans.push_back(matrix[i][r]);
if(--r<l) break;
for(int i = r;i>=l;--i) ans.push_back(matrix[d][i]);
if(--d<u) break;
for(int i = d;i>=u;--i) ans.push_back(matrix[i][l]);
if(++l>r) break;
}
return ans;
}
};
3.合并区间 自定义sort
题目描述:
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
解题思路:
1.先排序,根据数组的第一位先升序排序,一旦第一位相等,则按照第二位降序排序。
2.声明二维数组存放结果,一个一维数组暂时存放要插入的数据。
3.因为第一步已经排序过,所以判断的时候
1.先判断区间下边界是否大于等于下个区间的上边界。是重复,否不重
2.继续判断当前区间的下边界是否小于下个区间的下边界,是交叉,否包含
class Solution {
public:
static bool cmp(vector<int>& a,vector<int>& b){
if(a[0]==b[0]){
return a[1]>b[1];
}
return a[0]<b[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> res;
if(intervals.empty()) return res;
vector<int> temp;
int count = 0;
sort(intervals.begin(),intervals.end(),cmp);
temp.push_back(intervals[0][0]);
temp.push_back(intervals[0][1]);
res.push_back(temp);
for(int i = 1;i<intervals.size();++i){
if(res[count][1] >= intervals[i][0]){
if(res[count][1]<=intervals[i][1]){
res[count][1] = intervals[i][1];
}
}
else{
count++;
temp[0] = intervals[i][0];
temp[1] = intervals[i][1];
res.push_back(temp);
}
}
return res;
}
};
4.不同路径II
题目描述:
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。
示例 1:
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
解题思路:
dp,由于只能向右或者向下,因此不用搜索,dp即可
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int w = obstacleGrid.size();
if(w == 0) return 0;
int h = obstacleGrid[0].size();
long long dp[w][h];
dp[0][0] = obstacleGrid[0][0] == 0 ? 1:0;
//先处理边界
for(int i = 1;i<w;++i){
//第一条竖边,判断i位置是否有障碍物,有的话返回0(到达i位置的路径为0条),没有障碍物返回他的上一个位置的路径条数,边界只有一种情况
dp[i][0] = obstacleGrid[i][0] == 1 ? 0:dp[i-1][0];
}
for(int i = 1;i<h;++i){
dp[0][i] = obstacleGrid[0][i] == 1 ? 0:dp[0][i-1];
}
//在处理内部
for(int i = 1;i<w;++i){
for(int j = 1;j<h;++j){
dp[i][j] = obstacleGrid[i][j] == 1 ? 0:dp[i-1][j]+dp[i][j-1];
}
}
return dp[w-1][h-1];
}
};
5.不同路径,递归记录
static int a[101][101];
class Solution {
public:
int uniquePaths(int m, int n) {
if(m <= 0||n <= 0) return 0;
else if(m == 1||n == 1) return 1;
else if(m == 2&&n == 2) return 2;
else if((m==3&&n==2)||(m==2&&n==3)) return 3;
else if(a[m][n]>0) return a[m][n];
a[m-1][n] = uniquePaths(m-1,n);
a[m][n-1] = uniquePaths(m,n-1);
a[m][n] = a[m-1][n]+a[m][n-1];
return a[m][n];
}
};