首页 > 其他 > 详细

回溯法详解

时间:2020-03-22 23:32:48      阅读:81      评论:0      收藏:0      [点我收藏+]

一、概述

  解决一个回溯问题,实际上就是一个决策树的遍历过程。只需要考虑以下三个问题:

  (1)路径:已经做出的选择。

  (2)选择列表:也就是你当前所做出的选择。

  (3)结束条件:也就是到达决策树底层,无法在做出的条件。

二、代码模板

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return
    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

  核心:其实就是for循环里面的递归,在递归调用之前做选择,在递归调用之后撤销选择。

三、代码实战

(1)无重复的全排列:非交换

class Solution{
    List<List<Integer>> res=new ArrayList<>();
    public List<List<Integer>>premute(int []nums){
        List<Integer>track=new ArrayList<>();
        backTrack(res,list); 
        return res;
    }
    
    // 路径:记录在 track 中
    // 选择列表:nums 中不存在于 track 的那些元素
    // 结束条件:nums 中的元素全都在 track 中出现
    public void backTrack(int nums[],List<Integer>track){
        //触发结束条件
        if(nums.length==track.size()){
            res.add(new ArrayList<>(track));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(track.contains(nums[i])){
                continue;
            }
            track.add(nums[i]);
            backTrack(res,track);
            track.remove(track.size()-1);
        }
    }
}

(2)无重复排列:非交换

class Solution {
    public List<List<Integer>> permute(int[] nums) {

        List<List<Integer>> res = new ArrayList<>();
        int[] visited = new int[nums.length];
        backtrack(res, nums, new ArrayList<Integer>(), visited);
        return res;

    }

    private void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
        if (tmp.size() == nums.length) {
            res.add(new ArrayList<>(tmp));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (visited[i] == 1) continue;
            visited[i] = 1;
            tmp.add(nums[i]);
            backtrack(res, nums, tmp, visited);
            visited[i] = 0;
            tmp.remove(tmp.size() - 1);
        }
    }
}

(3)无重复的全排列:交换

class Solution {
    List<Integer>res=new ArrayList<>();
    public List<List<Integer>>premute(int[] nums){
        List<Integer>track=new ArrayList<>();
        backTrack(nums,track,0);
        return res;
    }

    public void backTrack(int[] nums,List<Integer>track,int cur){
        if(cur==nums.length){
            track=new ArrayList<>();
            for(int item:nums){
                track.add(item);
            }
        }
        for(int i=cur;i<nums.length;i++){
            swap(nums,i,cur);
            backTrack(nums,track,cur);
            swap(nums,i,cur);
        }
    }

    public void swap(int nums[],int i,int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

回溯法详解

原文:https://www.cnblogs.com/hdc520/p/12548568.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!