回溯算法解题总结

回溯算法即递归的算法,其核心的思想是尝试,如果符合,则进一步尝试,知道其符合题意,若不符合,则进行回溯。

这种算法具有明显的模板,要学会套用模板,下面以题目来进行说明。

1. LeetCode Combination Sum

/************************************************************************
* Given a set of candidate numbers (C) and a target number (T), find all unique combinations
* in C where the candidate numbers sums to T.
*
* The same repeated number may be chosen from C unlimited number of times.
*
* Note:
*
* All numbers (including target) will be positive integers.
* Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
* The solution set must not contain duplicate combinations.
*
* For example, given candidate set 2,3,6,7 and target 7,
* A solution set is:
* [7]
* [2, 2, 3]

************************************************************************/
解析:给一个集合2,3,6,7找到其相加为7,很明显的回溯解法,首先加入2,2,2时需要1,不符合,进行回溯2,2,3符合,因此加入输出矩阵中。
下面用代码实现:

class Solution {
public:
   void combinationSum(vector<int> &candidates, int target,vector<vector<int> > &res,vector<int> &combination, int begin) {
    if (!target) {       //满足条件,加入res中
        res.push_back(combination);
        return;
    }
    for (int i = begin; i != candidates.size() && target >= candidates[i]; ++i) {
        combination.push_back(candidates[i]);
        combinationSum(candidates, target - candidates[i], res, combination, i);
        combination.pop_back();    //回溯
    }
}
    vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<vector<int> > res;
        vector<int> combination;
        combinationSum(candidates, target, res, combination, 0);
        return res;
}
};

2.LeetCode Combination Sum II

********************************************************************************** 
* Given a collection of candidate numbers (C) and a target number (T), find all 
* unique combinations in C where the candidate numbers sums to T.
* 
* Each number in C may only be used once in the combination.
* 
* Note:
* 
* > All numbers (including target) will be positive integers.
* > Elements in a combination (a1, a2, … , ak) must be in non-descending order. 
*   (ie, a1 ≤ a2 ≤ … ≤ ak).
* > The solution set must not contain duplicate combinations.
* 
* For example, given candidate set 10,1,2,7,6,1,5 and target 8, 
* A solution set is: 
* [1, 7] 
* [1, 2, 5] 
* [2, 6] 
* [1, 1, 6]               
**********************************************************************************/

与上面一题代码非常的相似,这个要注意的是:
1. 数字不能重复使用
2. 无能有相同的答案
实现如下:

class Solution {
public:
   void combinationSum2(vector<int> &candidates, int target,vector<vector<int> > &res,vector<int> &combination, int begin) {
    if (!target) {
        res.push_back(combination);
        return;
    }
    for (int i = begin; i != candidates.size() && target >= candidates[i]; ++i) {
        if (i==begin||candidates[i]!=candidates[i-1]) {
            combination.push_back(candidates[i]);
            combinationSum2(candidates, target - candidates[i], res, combination, i+1);
            combination.pop_back();
        }
    }
}
vector<vector<int> > combinationSum2(std::vector<int> &candidates, int target) {
    sort(candidates.begin(), candidates.end());
    vector<vector<int> > res;
    vector<int> combination;
    combinationSum2(candidates, target, res, combination, 0);
    return res;
}
};

3 LeetCode N-Queens

/**********************************************************************************  
* The n-queens puzzle is the problem of placing n queens on an n×n chessboard 
* such that no two queens attack each other.
* 
* Given an integer n, return all distinct solutions to the n-queens puzzle.
* 
* Each solution contains a distinct board configuration of the n-queens' placement, 
* where 'Q' and '.' both indicate a queen and an empty space respectively.
* 
* For example,
* There exist two distinct solutions to the 4-queens puzzle:
* 
* [
*  [".Q..",  // Solution 1
*   "...Q",
*   "Q...",
*   "..Q."],
* 
*  ["..Q.",  // Solution 2
*   "Q...",
*   "...Q",
*   ".Q.."]
* ]             
**********************************************************************************/

皇后问题:即每一行,每一列,和每个对角线都不能有两个皇后存在。
这个问题是典型的回溯问题,一个个的进行尝试,没什么好说的,code can explain.

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> que(n,string(n,'.'));
        solveQueue(res,que,0,n);
        return res;
    }
private:
    void solveQueue(vector<vector<string>>& res,vector<string>& que,int row,int& n) {
        if (row==n) {     //满足条件
            res.push_back(que);return;
        }
        for (int col=0;col!=n;col++) {
            if (isValid(que,row,col,n)) {  //检查是否符合条件
                que[row][col]='Q';
                solveQueue(res,que,row+1,n);
                que[row][col]='.';         //回溯
            }
        }
    }     
    bool isValid(vector<string>& que,int row,int col,int& n) {
        for (int i=0;i!=row;i++)               //column
            if (que[i][col]=='Q') return false;
        for (int i=row-1,j=col-1;i>=0&&j>=0;i--,j--)  //45
            if (que[i][j]=='Q') return false;
        for (int i=row-1,j=col+1;i>=0&&j<n;i--,j++)   //135
              if (que[i][j]=='Q') return false;
        return true;

    }
};

4. LeetCode Sudoku Solver

/********************************************************************************** 
* 
* Write a program to solve a Sudoku puzzle by filling the empty cells.
* 
* Empty cells are indicated by the character '.'.
* 
* You may assume that there will be only one unique solution.
* 
* A sudoku puzzle...
* 
* ...and its solution numbers marked in red.
* 
*               
**********************************************************************************/

与皇后问题非常的相似,是一个模板。code can explain.

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        solve(board);
    }
private:
    bool solve(vector<vector<char>>& board) {
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                if (board[r][c] == '.') {
                    for (char d = '1'; d <= '9'; d++) {
                        if (isValid(board, r, c, d)) {
                            board[r][c] = d;
                            if (solve(board)) return true;
                            board[r][c] = '.';
                        }
                    }
                    return false;
                }
            } 
        }
        return true;
    }
    bool isValid(vector<vector<char>>& board, int r, int c, char d) {
        for (int row = 0; row < 9; row++)
            if (board[row][c] == d) return false;
        for (int col = 0; col < 9; col++)
            if (board[r][col] == d) return false;
        for (int row = (r / 3) * 3; row < (r / 3 + 1) * 3; row++)
            for (int col = (c / 3) * 3; col < (c / 3 + 1) * 3; col++)
                if (board[row][col] == d) return false;
        return true;
    }
};

矩阵中路径问题

给定一个矩阵和一个字符串,在这个矩阵中找出是否有一个路径包含了这个字符串。
例如:
a b c e
s f c s
a d e e
则,这个矩阵中包含一个bcced的路径
这个题是一个可用深度优先搜索去解决。下面代码实现过程:

#include<iostream>
#include<vector>
#include <string>
using namespace std;
bool valid(vector<vector<char>>& matrix, string& str,vector<vector<int>>& vis,int i, int j,int k) {
    int m = matrix.size(), n = matrix[0].size(), len = str.size();
    if (i < 0 || i >= m || j < 0 || j >= n || vis[i][j] || matrix[i][j] != str[k])
        return false;
    if (k == len - 1) return true;   //满足条件
    vis[i][j] = 1;   //标记访问
    int next[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
    for (int t = 0; t < 4; t++) {   //搜索周围的
        int x = i + next[t][0];
        int y = j + next[t][1];
        if (valid(matrix, str, vis, x, y, k + 1)) 
            return true;
    }
    vis[i][j] = 0;  //回溯
    return false;
}
bool hasPath(vector<vector<char>>& matrix, string str) {
    int m = matrix.size(), n = matrix[0].size(), len = str.size();
    vector<vector<int>> vis(m, vector<int>(n, 0));
    for (int i=0;i<m;i++) 
        for (int j = 0; j < n; j++) {
            if (valid(matrix, str, vis, i, j, 0))
                return true;
        }
    return false;
}
int main(){
    vector<vector<char>> vv = { {'a','b','c','e'},{'s','f','c','s'},{'a','d','e','e' } };
    string s = "bcced";
    cout << hasPath(vv, s) << endl;
    return 0;
}

….未完待续

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值