面试笔试算法之回溯法

一、何为回溯法?

回溯法,顾名思义,当问题解不了时,向上回溯,重新选择路径求解。也就是说当问题很大时,我们常常会把一个大问题分解为一个个的小问题,而当每个小问题有多个解法(有对有错)时(类似二叉树),就需要将解法逐个实验,选择出符合既定规则的答案。那么回溯法就是当选择一个解法而解出不符合规则的解后,能回溯到前一步,选择另外一条解法的一种算法思想。

二、具体图例

比如下面的图,男主每当遇到小绿发就得回退到上一个步骤重新选择路径,直到救出女主!
在这里插入图片描述

三、解空间结构之排列树和子集树

  1. 子集树
    所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间成为子集树。
    如0-1背包问题,从所给重量、价值不同的物品中挑选几个物品放入背包,使得在满足背包不超重的情况下,背包内物品价值最大。它的解空间就是一个典型的子集树。(只放一部分)
  2. 排列树
    所给的问题是确定n个元素满足某种性质的排列时,相应的解空间就是排列树。
    如旅行售货员问题,一个售货员把几个城市旅行一遍,要求走的路程最小。它的解就是几个城市的排列,解空间就是排列树。(全都要)

四、回溯法算法构造套路

1 定义问题的解空间

2 确定易于搜索的解空间结构

3 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

五、练习:(选自Leetcode题库)

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
链接:https://leetcode-cn.com/problems/generate-parentheses

该题目倘若使用暴力法,需要选择出所有的可能,然后根据规则遍历挑选出符合规则的解,也就是时间复杂度为(2^(2n)n),代码量也有一定量。那么,因为该题也涉及有多种解,且要选择出符合要求的解,倘若我们使用回溯法如何?(建议先试着自个儿写,然后再看答案)
答案如下:
第一层得出答案((()))
而后逐步返回函数,直到回到括号数为((
故第二层答案(()())
而后逐步返回函数,直到回到括号数为(()
故第三层答案(())()
而后逐步返回函数,直到回到括号数为(
故第四层答案()(())
而后逐步返回函数,直到回到括号数为()(
故第五层答案()()()

class Solution {
    public List<String> generateParenthesis(int n) {
       List<String> lst = new ArrayList();
       trackback(lst,"",0,0,n);
       return lst; 

    }

    public void trackback(List<String> lst,String curr,int open,int close,int max){
        //当括号数等于给定括号数的两倍(左右括号),添加进容器
        if(curr.length()==max*2){
            lst.add(curr);
            return ;
        }
        //当左括号小于给定的括号数,随便加
        if(open<max){
            trackback(lst,curr+"(",open+1,close,max);
        }
        //当右括号小于左括号数,随便加
        if(close<open){
            trackback(lst,curr+")",open,close+1,max);
        }
    }
}

练习二:八皇后问题

发布了24 篇原创文章 · 获赞 0 · 访问量 588

猜你喜欢

转载自blog.csdn.net/weixin_43896829/article/details/104892436