一、导读
本文主要介绍什么是回溯算法,以及使用回溯算法解决
leetcode
上面的一些小案例。好文章 记得 收藏+点赞+关注 !!!
二、背景
今天去银行办理银行卡,然后需要录入用户信息,在其中有一步中我填错了某个信息,所以需要返回上一步进行修改,这个操作让我联想到有一种算法可以实现这样的业务——回溯算法
三、回溯算法简介
- 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
- 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
- 回溯法可以看成是蛮力法的升级版,它从解决问题每一步的所有可能选项里系统地选择可行的解决方案。回溯算法基于深度优先搜索算法和递归算法,在搜索过程中寻找问题的解。
下面我们用LeetCode46 全排列来理解回溯算法:
四、回溯算法练习
我们先画图整理一下思路,先明白回溯的结束条件,进入回溯的条件,回溯的选择,回溯的参数选择。
每个叶子节点的形成路径就是一个全排列。
下面是代码实现:
import java.util.ArrayList;
import java.util.List;
/**
* LeetCode46全排列
*
* @author JiaMing
* @since 2021/12/2/0002 上午 10:06
**/
public class Solution {
/**
* 题目描述:给定一个不含重复数字的数组 nums ,返回其所有可能的全排列
* 示例:输入:nums = [1,2,3]
* 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
*/
//List<List<Integer>>这种写法是嵌套list 目的是让输出像矩阵一样
public List<List<Integer>> permute(int[] nums) {
//定义一个全局变量,保存所有的排列
List<List<Integer>> result = new ArrayList<>();
backtrack(result, new ArrayList<>(), nums);
return result;
}
public void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums) {
//结束条件
if (tempList.size() == nums.length) {
list.add(new ArrayList<>(tempList));
} else {
for (int num : nums) {
if (tempList.contains(num))
continue;
//如果tempList没有包含nums[i]才添加
tempList.add(num);
//递归调用,此时的tempList一直在变化,直到满足结束条件才结束
backtrack(list, tempList, nums);
System.out.println("tempList的内容为:" + tempList);
//它移除tempList最后一个元素的作用就是返回上一次调用时的数据,也就是希望返回之前的节点再去重新搜索满足条件。这样才能实现回溯
tempList.remove(tempList.size() - 1);
}
}
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
(new Solution()).permute(nums);
}
}
运行结果:
点击查看更多解题方法和视频讲解
参考文章:https://www.cnblogs.com/lzxin/p/9714133.html
https://blog.csdn.net/Dawn510/article/details/104305368