目录
1.岛屿数量
直接走就可以,看代码比较好理解,不过多解释
void dfs(int i, int j, vector<vector<char> >& grid)
{
if (i >= grid.size() || j >= grid[0].size() || grid[i][j] != '1') return;
//如果是1
grid[i][j] = '0';
dfs(i - 1, j, grid);
dfs(i, j - 1, grid);
dfs(i, j + 1, grid);
dfs(i + 1, j, grid);
}
int solve(vector<vector<char> >& grid) {
// write code here
int ans = 0; //记录岛屿数量
int row = grid.size(); int col = grid[0].size(); //记录行和列
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (grid[i][j] == '1') //如果遇到土地,判断一下他构不构成岛屿
{
dfs(i, j, grid);
ans++;
}
}
}
return ans;
}
2.字符串的排列
一定要记得剪枝
void recursion(string& str,string& a,vector<bool>& ed,vector<string>& ans)
{
if(a.size()==str.size())
{
ans.push_back(a);
return ;
}
for(int i=0;i<str.size();i++)
{
if(i>0 && str[i]==str[i-1] && ed[i-1]==false) //数层上的去重
continue;
if(ed[i]==false)
{
a.push_back(str[i]);
ed[i]=true;
recursion(str,a,ed, ans);
a.pop_back();
ed[i]=false;
}
}
}
vector<string> Permutation(string str) {
sort(str.begin(),str.end());
vector<string> ans;
string a;
vector<bool> ed(str.size(),false);
recursion(str,a,ed,ans);
return ans;
}
3.N皇后
还是回溯的思想,设置一个棋盘,把他每个位置都初始化成.,然后开始从row=0开始遍历每一行,在每一行中,判断这个棋盘是否合法,然后放入皇后Q,回溯,然后把状态恢复
int ans=0;
bool isValid(int row, int col, vector<string>& chessboard, int n) {
// 检查列
for (int i = 0; i < row; i++) { // 这是一个剪枝
if (chessboard[i][col] == 'Q') {
return false;
}
}
// 检查 45度角是否有皇后
for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
// 检查 135度角是否有皇后
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
return true;
}
void backtracking(int n, int row, vector<string>& chessboard) {
if (row == n) {
ans++;
return;
}
for (int col = 0; col < n; col++) {
if (isValid(row, col, chessboard, n)) { // 验证合法就可以放
chessboard[row][col] = 'Q'; // 放置皇后
backtracking(n, row + 1, chessboard);
chessboard[row][col] = '.'; // 回溯,撤销皇后
}
}
}
int Nqueen(int n) {
// write code here
vector<string> checkboard(n,string(n,'.'));
backtracking(n,0,checkboard);
return ans;
}
4.括号生成
记录一下左括号和右括号的数量,一开始都是n,然后dfs
vector<string> ans;
vector<string> generateParenthesis(int n) {
// write code here
string s;
dfs(n,n,s);
return ans;
}
void dfs(int left,int right,string s )
{
if(left == 0 && right==0)
{
ans.push_back(s);
return ;
}
if(left>0)
{
s.push_back('(');
dfs(left-1,right,s);
s.pop_back();
}
if(right>0 && left<right)
{
s.push_back(')');
dfs(left,right-1,s);
s.pop_back();
}
}
5.矩阵最长递归子路径
把路径保存在path。如果插入元素会破坏原来路径的递增结构,或者位置不合法就return
int ans=0;
int solve(vector<vector<int> >& matrix) {
// write code here
if(matrix.empty()) return 0;
int row=matrix.size(),col=matrix[0].size();
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
vector<int> path;
dfs(matrix,i,j,path);
}
}
return ans;
}
void dfs(vector<vector<int>>& a,int i,int j,vector<int> path)
{
if(i<0 || j<0 || i>=a.size() ||j>=a[0].size() || (!path.empty() && a[i][j]<=path.back()) )
{
ans=ans>path.size()?ans:path.size();
return ;
}
path.push_back(a[i][j]);
dfs(a,i+1,j,path);
dfs(a,i-1,j,path);
dfs(a,i,j+1,path);
dfs(a,i,j-1,path);
path.pop_back();
}
6.手套问题
int findMinimum(int n, vector<int> left, vector<int> right) {
int left_sum = 0, left_min = INT_MAX;
int right_sum = 0, right_min = INT_MAX;
int sum = 0;
//遍历每一种颜色的左右手套序列
for (int i = 0; i < n; i++) {
//对于有0存在的颜色手套,累加
if (left[i]==0 ||right[i] == 0)
sum += left[i] + right[i];
//对于左右手都有的颜色手套,累加
//找到最小值 和 总数
else {
left_sum += left[i];
right_sum += right[i];
left_min = min(left_min, left[i]);
right_min = min(right_min, right[i]);
}
}
//结果为 有0存在的手套数+左右都有数量的手套+最后再加一
return sum + min(left_sum - left_min + 1, right_sum - right_min + 1) + 1;
}