Leetcode Learning: Backtracking Algorithm of Five Algorithms

1 Introduction

1.1 Introduction

The definition given by Baidu Baike is as follows:
Backtracking (exploration and backtracking) is a selective search method, also known as heuristic method, which searches forward according to the selection criteria to achieve the goal. But when you explore a certain step, you find that the original choice is not good or the goal is not achieved, so you go back one step and choose again. This technique of going back and going again is the backtracking method, and the point of a certain state that meets the backtracking condition This is called the "backtrack point."

Obviously, this algorithm is closely related to depth-first traversal. They are both "as soon as you reach the end, turn around to the next fork and continue to the end". But different from DFS is that there needs to be a "state reset" operation, because every "go to the end" corresponds to a solution. If there is no state reset when returning, it is equivalent to repeating again and losing the other understanding of the space. solution.

1.2 Algorithm core

Backtracking = DFS + state reset (+ pruning)

2 Answer template

void backTrack(track ,allChoise)
{
    
    
	if('结束条件')//到达了最底层
	{
    
    
		'结束操作';
		return;
	}
	for(i : allChoise)
	{
    
    
		allChoise[i] = true;
		backTrack(track+1, allChoise)//回溯:本质是DFS
		allChoise[i] = false;//状态重置
	}
}

3 sample questions

According to the answer template, we can put in the following classic examples of backtracking to see the power of backtracking.

3.1 Full arrangement problem

class Solution {
    
    
public:
    vector<vector<int>> permute(vector<int>& nums) {
    
    
        int begin = 0;
        int end = nums.size();

        vector<int> result;
        vector<vector<int>> ret;

        dfs(nums,result,ret,begin,end);
        return ret;
    }

    void dfs(vector<int>& nums, vector<int> result, vector<vector<int>>& ret, int begin, int end)
    {
    
    
        if(begin == end - 1)
        {
    
    
            ret.push_back(nums);
            return;   
        }

        for(int  i = begin; i < end; i++)
        {
    
    
            swap(nums[begin],nums[i]);
            result.push_back(nums[i]);
            
            dfs(nums,result,ret,begin+1,end);

            swap(nums[begin],nums[i]);
            result.pop_back();
                
        }

    }

    void swap(int& a, int& b)
    {
    
    
        int temp = a;
        a = b;
        b = temp;
    }
};

3.2 N queen problem

#include<iostream>
#include<vector>

using namespace std;

vector<vector<string>> ans;//存储N皇后的解

bool isok(vector<int>& record, int row)//record[row]就是col
{
    
    
	for (int i = 0; i < row; i++)
	{
    
    
		if (record[i] == record[row]
			|| row - record[row] == i - record[i]
			|| row + record[row] == i + record[i])
		{
    
    
			return false;
		}		
	}
	return true;
}

void findQueue(int row, int n, vector<string>&temp, vector<int>& record)
{
    
    
	if (row == n)//N皇后有解了
	{
    
    
		ans.push_back(temp);//把解放进全部解空间中
		return;
	}
	for (int col = 0; col < n; col++)
	{
    
    
		record[row] = col;

		if (isok(record, row))//回溯的过程:record表示在第几列(这一行的第几个位置),l表示在第几行
		{
    
    
			temp[row][col] = 'Q';//设为Q递归回溯一下
			findQueue(row + 1, n, temp, record);//去下一行找
			temp[row][col] = '.';//不论找没找到,回归原始状态继续找
		}
	}
}

vector<vector<string>> solveNQueens(int n)
{
    
    
	string s = "";
	vector<int> record(n);//初始化为n个0
	for (int i = 0; i < n; i++)
	{
    
    
		s += '.';
	}
	vector<string> temp(n, s);//初始化为全是.的nxn的二维数组


	findQueue(0, n, temp, record);//findQueue
	return ans;
}



int main()
{
    
    
	vector<vector<string>> ret = solveNQueens(4);

	system("pause");
	return 0;
}

3.3 Solving Sudoku Problems

bool isValidPart(char **board, int i, int j, int *a)
{
    
    
    char c = board[i][j];
    if(c != '.')
    {
    
    
        int index = c - '1';
        if(a[index]==1)return false;
        else a[index]=1;
    }
    return true;
}

bool isValidSudoku(char** board, int boardRowSize, int boardColSize)
{
    
    
    if(boardRowSize != 9|| boardColSize != 9)
    	return false;
    int a[9]={
    
    0};  //标记一行
    int b[9]={
    
    0};  //标记一列
    int c[9][9]={
    
    0}; //c[i]标记一个9宫格
    
    for(int i = 0; i < 9; i++)
    {
    
    
        memset(a,0,sizeof(int)*9);
        memset(b,0,sizeof(int)*9);
        
        for(int j = 0; j < 9; j++)
        {
    
    
            if(isValidPart(board, i, j, a)==false)
            	return false;
            if(isValidPart(board, j, i, b)==false)
            	return false;
            if(isValidPart(board, i, j, c[(i/3)*3 + j/3])==false)
            	return false;
        }
    }
    return true;
}

Guess you like

Origin blog.csdn.net/weixin_42979679/article/details/103654142