【C++】面试101,岛屿数量,字符串的排列,N皇后,括号生成,矩阵最长递归子路径,手套问题

文章介绍了六个使用递归和回溯算法解决的问题,包括寻找岛屿数量、字符串排列、N皇后问题、括号生成、矩阵最长递增子路径和手套问题。每个问题都提供了详细的解题思路和代码实现,重点在于回溯和剪枝策略的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.岛屿数量

2.字符串的排列

3.N皇后

4.括号生成

5.矩阵最长递归子路径

6.手套问题


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;
     }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值