算法入门(回溯算法)

Posted 韶光不负

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法入门(回溯算法)相关的知识,希望对你有一定的参考价值。

当学习完递归后,就可以来学习与理解它好兄弟回溯了。回溯算法比较抽象,小编就以自己学习的角度来分析了!

 

回溯与递归有什么关系 

递归与回溯是相辅相成的,回溯算法在递归之后,(可以理解没有递归就没有回溯,递归下不一定使用回溯算法,要根据问题)

什么是回溯算法

回溯算法是一个暴力的搜索算法回溯就是一个递归的过程

按选优条件向前搜索,以达到目标。 但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术,而满足回溯条件的某个状态的点称为"回溯点"。

所有的回溯法可以抽象为一个树形结构

如下图二叉树

回溯算法模板

void backtracking(参数) 
     if (终⽌条件) 
     存放结果;
     return;
     
     for (选择:本层集合中元素(树中节点孩⼦的数量就是集合的⼤⼩)) 
           处理节点;
         backtracking(路径,选择列表); // 递归
         回溯,撤销处理结果
     

回溯算法能解决的题目

数组(leetcode 39,40,216),切割(140),子集(78,90),组合(46,47),少数棋盘(如n皇后(51),n数组问题)

数组总和(leetcode)

class Solution 
    List<List<Integer>> list = new ArrayList<>();
    List<Integer> list1 = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) 
        Arrays.sort(candidates);
        helper(candidates,0,target);
        return list;
    
    public void helper(int[] cand , int start ,int target)
        int len = cand.length;
        if (target == 0)
            list.add(new ArrayList<Integer>(list1));
            return;
        
        for (int i = start; i < len ; i++) 
            if (cand[i] > target) break;
            list1.add(cand[i]);
            helper(cand,i,target - cand[i]);
            list1.remove(list1.size()-1);
        
    

全排列(46)

class Solution 
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> output = new ArrayList<>();
    public List<List<Integer>> permute(int[] nums) 
        for (int num : nums) 
            output.add(num);
        

        int n = nums.length;
        backtrack(n, output, res, 0);
        return res;
    
    public void backtrack(int n, List<Integer> output, List<List<Integer>> res, int first) 
        // 所有数都填完了
        if (first == n) 
            res.add(new ArrayList<Integer>(output));
        
        for (int i = first; i < n; i++) 
            // 动态维护数组
            Collections.swap(output, first, i);
            // 继续递归填下一个数
            backtrack(n, output, res, first + 1);
            // 撤销操作
            Collections.swap(output, first, i);
        
    

n皇后

package com.itheima;


import java.util.ArrayList;
import java.util.List;

class Solution 
    
    int[] arr;
    List<List<String>> res = new ArrayList<>();
    public List<List<String>> solveNQueens(int n) 
        arr = new int[n];
        dnf(n,0);
        return res;
    
    public void dnf(int n , int index)
        if (n == index)
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < n;i++)
                StringBuilder str =new StringBuilder();
                for (int j = 0; j < n ; j++) 
                    if (arr[i] == j)
                        str.append('Q');

                    else 
                        str.append('.');
                    
                
                list.add(new String(str));
            
            res.add(list);
            return;
         else
            for (int i = 0; i < n ; i++) 
                arr[index] = i;
                if (judge(index))
                    dnf(n,index+1);
                
            
        

    
    private boolean judge(int index) 
        for (int i = 0; i < index; i++) 
            if (arr[i] == arr[index] || Math.abs(i - index) == Math.abs(arr[i] - arr[index])) 
                return false;
            
        
        return true;
    

以上是关于算法入门(回溯算法)的主要内容,如果未能解决你的问题,请参考以下文章

算法入门经典-第七章 例题7-4-1 拓展 n皇后问题 回溯法

回溯算法入门及经典案例剖析(初学者必备宝典)

算法入门经典7.4回溯法八皇后问题

回溯算法学习手册开放下载!!

算法竞赛入门码蹄集进阶塔335题(MT3330-3335)

回溯算法及题目