1. 程式人生 > >回溯演算法解題總結

回溯演算法解題總結

回溯演算法即遞迴的演算法,其核心的思想是嘗試,如果符合,則進一步嘗試,知道其符合題意,若不符合,則進行回溯。

這種演算法具有明顯的模板,要學會套用模板,下面以題目來進行說明。

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

….未完待續

相關推薦

回溯演算法解題總結

回溯演算法即遞迴的演算法,其核心的思想是嘗試,如果符合,則進一步嘗試,知道其符合題意,若不符合,則進行回溯。 這種演算法具有明顯的模板,要學會套用模板,下面以題目來進行說明。 1. LeetCode Combination Sum /***********

leetcode-回溯演算法總結

leetcode-17-電話號碼的字母組合(letter combination of a phone number)-java 在類中建立一個數字對應字母的map,和對應的結果list 進入combine("",digits) 第一個字串為當前字串,後面的為還能加上的數字字串 每次從陣列字

SICP 習題 (1.41)解題總結

結果 調用 -m name 方法 定義 height double plain SICP 習題1.41 看似和周邊的題目沒有關系,突然叫我們去定義一個叫double的過程,事實上這道題的核心還是高階函數。題目要求我們定義一個過程double,它以一個過程作為參數,這個作為

[Leetcode] Backtracking回溯解題思路

一個 quad adr == should store .com 理解 force 碎碎念: 最近終於開始刷middle的題了,對於我這個小渣渣確實有點難度,經常一兩個小時寫出一道題來。在開始寫的幾道題中,發現大神在discuss中用到回溯法(Backtracking)的概

演算法技巧總結

1、巧用陣列下標 陣列的下標是一個隱含的很有用的陣列,特別是在統計一些數字,或者判斷一些整型數是否出現過的時候。 例如,給你一串字母,讓你判斷這些字母出現的次數時,我們就可以把這些字母作為下標,在遍歷的時候, 如果字母a遍歷到,則arr[a]就可以加1了,即 arr[a]++; 通過這種巧用

Java回溯演算法解數獨問題

    下面來詳細講一下如何用回溯演算法來解數獨問題。     下圖是一個數獨題,也是號稱世界上最難的數獨。當然了,對於計算機程式來說,只要演算法是對的,難不難就不知道了,反正計算機又不累。回溯演算法基本上就是窮舉,解這種數獨類的問題邏輯比較簡

遞迴、回溯-演算法框架

之前已經學習過回溯法的一些問題,從這篇文章開始,繼續深入學習一下回溯法以及其他經典問題。 回溯法有通用的解題法之稱。用它可以系統的搜尋一個問題的所有解或任一解,回溯法是一個既帶有系統性又帶有跳躍性的搜尋演算法。 它的問題的解空間樹中,按深度優先策略,從根結點出發搜尋解空間樹。演算法搜尋至

十大經典排序演算法詳細總結(含JAVA程式碼實現)

文章目錄 十大經典排序演算法詳細總結(含JAVA程式碼實現) 0、排序演算法說明 1、氣泡排序(Bubble Sort) 2、選擇排序(Selection Sort) 3、插入排序(Insertion Sort) 4、希爾

排序演算法總結

學習了選擇排序演算法、插入排序演算法、氣泡排序演算法等。   選擇排序演算法: 時間複雜度是O(n*n)       主要思想是:  每次迴圈是第i個與後面的元素逐個比較,一次迴圈後得出了最大值,放在了第i個位置上

九章演算法總結】Java 搞定連結串列-面試常考題目精選

面試大總結之連結串列CS3K.com一、OverView:連結串列是面試中常考的,本文參考了其它一些文章,加上小編的自己總結,基本每個演算法都測試並優化過。演算法大全(1)單鏈表 中還有一些連結串列題目,將來也會整理進來。這些題目雖然簡單,但如果能毫無BUG地寫出,定能讓面試官司對您印象分大增。小亮點是:主頁

基本排序演算法總結

# 插入排序 public static int[] insertSort2(int[] arr) { if (arr.length < 2 || arr == null) { return arr; } // 假設

名企演算法題目總結(4)

1.二叉樹的遞迴非遞迴遍歷  考慮一個完全二叉樹 1234567,  先序非遞迴,列印1,處理2,處理3  直接迴圈配合一個棧和hashtable,hashtable儲存節點的處理方式(列印為false,處理為true);        push(3),hasht

2018科大訊飛AI營銷演算法大賽總結(冠軍)

作者介紹:王賀,武漢大學,計算機專業,研二 寫在前面 首先很幸運能夠拿到這次冠軍,有兩位大佬隊友是這次獲勝的關鍵,再次感謝鵬哥和阿水。 同時希望我的分享與總結能給大家帶來些許幫助,並且一起交流學習。 接下來將會呈現ppt內容和部分程式碼 賽題分析 探索

常見機器學習演算法優缺點總結

一、樸素貝葉斯 1.1主要優點: 1)樸素貝葉斯模型發源於古典數學理論,有穩定的分類效率。 2)對小規模的資料表現很好,能個處理多分類任務,適合增量式訓練,尤其是資料量超出記憶體時,我們可以一批批的去增量訓練。 3)對缺失資料不太敏感,演算法也比較簡單,常用於文字分類

Relation-Network目標檢測演算法詳細總結分析(one/two-stage)(深度學習)(CVPR 2018)

論文名稱:《 Single-Shot Refinement Neural Network for Object Detection 》 論文下載:https://arxiv.org/abs/1711.06897 論文程式碼:https://github.com/sfzhang1

Faster R-CNN 目標檢測演算法詳細總結分析(two-stage)(深度學習)(NIPS 2015)

論文名稱:《 Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks 》 論文下載:https://papers.nips.cc/paper/5638-faster-r-cnn-t

Fast R-CNN 目標檢測演算法詳細總結分析(two-stage)(深度學習)(ICCV 2015)

論文名稱:《 Fast R-CNN 》 論文下載:https://arxiv.org/pdf/1504.08083.pdf 論文程式碼:https://github.com/rbgirshick/fast-rcnn 一、 網路結構:

R-CNN 目標檢測演算法詳細總結分析(two-stage)(深度學習)(CVPR 2014)

論文名稱:《 Rich feature hierarchies for accurate object detection and semantic segmentation 》 論文下載:https://arxiv.org/pdf/1311.2524.pdf 論文程式碼:ht

YOLOv3 目標檢測演算法詳細總結分析(one-stage)(深度學習)(CVPR 2018)

論文名稱:《 YOLOv3: An Incremental Improvement 》 論文下載:https://pjreddie.com/media/files/papers/YOLOv3.pdf 論文程式碼:   https://github.com/pjredd

YOLOv2 目標檢測演算法詳細總結分析(one-stage)(深度學習)(CVPR 2017)

論文名稱:《 YOLO9000: Better, Faster, Stronger 》 論文下載: https://arxiv.org/abs/1612.08242  論文程式碼: http://pjreddie.com/yolo9000/  一、演算法