回溯法求全排列-非递归形式-代码还没优化过
来源:互联网 发布:2017最新淘宝口令红包 编辑:程序博客网 时间:2024/05/01 20:19
回溯法递归的很好写,非递归的难写很多很多!
(看之前必须得理解递归形式的回溯法)
难写在哪?
因为回溯法递归,每次递归都有一个for循环,可以完美避开重复的路径。然而非递归的避免重复路径还要另花心思,这就是他的难点。
如何规避重复路径?
我们通过查找的时候,添加一个条件,就是回溯回来的时候,这个数不光要取没被使用的数,还要取一个比之前这个位置上的数更大的数,因为我们是从1234.。这样增序开始的,所以回溯的时候,当前位置上的值只有可能更大,不可能更小。
规避的时候还要注意一个小细节:
回溯的时候,要把后面的数都置为0,防止你之前的运算,对你后面的规避判断产生干扰。
(所以说代码还没优化过,以后会优化,不过这一次代码注释的很仔细,还是很容易看懂的)
部分代码:
private void sort2() { int level = 0; boolean ifFind = false; while (level >= 0) { //每换一次位,即深入或者回溯,都要用for循环找一次 for (int i = 0; i < n; i ++) { //找到的条件是:1.这个数没有被前面的数字使用2.考虑回溯回来的时候,你一定要比刚刚用过的数大,这是避开走过的路的办法 if (flag[i] && current[level] < i + 1) { //找到了,就放置这个数,当前的数就被占用了,把当前位置的数不可用 flag[i] = false; //放置这个数,即赋值 current[level] = i + 1; //如果当前操作的数没有到达最后一位,就继续向下探索 if (level < n - 1) { level += 1; } else if (level == n - 1) { //如果到了最后一位,就输出(回溯的情况:不把最后一位区别对待,和前面的回溯一样) System.out.println(Arrays.toString(current)); } //本次找到了 ifFind = true; break; } //如果这个for循环找完了,没有提前break,本次没找到 ifFind = false; } //如果找到了,就继续探寻;如果没找到,就必须要回溯了 if (!ifFind) { //让当前操作数左移一位 level -= 1; //如果这一次回溯,当前操作数变成负数,那就是第一位都已经没东西可排了,就真的结束了 if (level < 0) { break; } //如果当前操作数还没有变成负数,那就是还需要继续排。把当前的值和下一个值恢复为可用状态 else { flag[current[level + 1] - 1] = true; flag[current[level] - 1] = true; //把当前位置后面的数都置位0,意思就是回溯一位后,在进行寻找的时候,防止后面的数被之前的数干扰到 for (int i = level + 1; i <= n - 1; i++) { current[i] = 0; } } } }}
所有代码:
public class BackTracking { private int n; private int[] current; private boolean[] flag; BackTracking(int n) { this.n = n; current = new int[n]; flag = new boolean[n]; for (int i = 0; i < n; i ++) { flag[i] = true; current[i] = 0; } } private void sort2() { int level = 0; boolean ifFind = false; while (level >= 0) { //每换一次位,即深入或者回溯,都要用for循环找一次 for (int i = 0; i < n; i ++) { //找到的条件是:1.这个数没有被前面的数字使用2.考虑回溯回来的时候,你一定要比刚刚用过的数大,这是避开走过的路的办法 if (flag[i] && current[level] < i + 1) { //找到了,就放置这个数,当前的数就被占用了,把当前位置的数不可用 flag[i] = false; //放置这个数,即赋值 current[level] = i + 1; //如果当前操作的数没有到达最后一位,就继续向下探索 if (level < n - 1) { level += 1; } else if (level == n - 1) { //如果到了最后一位,就输出(回溯的情况:不把最后一位区别对待,和前面的回溯一样) System.out.println(Arrays.toString(current)); } //本次找到了 ifFind = true; break; } //如果这个for循环找完了,没有提前break,本次没找到 ifFind = false; } //如果找到了,就继续探寻;如果没找到,就必须要回溯了 if (!ifFind) { //让当前操作数左移一位 level -= 1; //如果这一次回溯,当前操作数变成负数,那就是第一位都已经没东西可排了,就真的结束了 if (level < 0) { break; } //如果当前操作数还没有变成负数,那就是还需要继续排。把当前的值和下一个值恢复为可用状态 else { flag[current[level + 1] - 1] = true; flag[current[level] - 1] = true; //把当前位置后面的数都置位0,意思就是回溯一位后,在进行寻找的时候,防止后面的数被之前的数干扰到 for (int i = level + 1; i <= n - 1; i++) { current[i] = 0; } } } } } public static void main(String[] args) throws Exception { BackTracking backTracking = new BackTracking(4); backTracking.sort2(); }}
阅读全文
0 0
- 回溯法求全排列-非递归形式-代码还没优化过
- 最简回溯法求全排列-递归形式 快速领悟回溯法窍门
- 回溯法求全排列
- 回溯法-求全排列
- 递归法求全排列
- Java回溯法求全排列
- 回溯法之求全排列
- 字典法求全排列(非递归的方法)
- 求全排列的非递归算法
- 递归法求全排列-java
- 递归求全排列
- 递归求全排列
- 递归求全排列
- 递归方法求全排列
- 递归求全排列
- 递归分治求全排列
- 递归求全排列
- 使用递归求全排列
- SQL学习笔记(五)
- xcode的环境变量,Build Settings参数,workspace及联编设置
- 软件工程项目--二手交易市场引言
- Python中re time os sys模块
- 常见设计模式-单例模式
- 回溯法求全排列-非递归形式-代码还没优化过
- 免费入驻商城 采购平台 购物平台 全免费资源大全总结 2017 2018年
- 文件权限基础
- Spark中文文本聚类
- 实现一个可以加载资源中隐藏的.exe可执行文件的程序
- Glide源码解析篇之框架主体结构(一)
- android7.0 之jack编译问题
- ROS常见问题1——找不到包
- hibernate缓存:一级缓存和二级缓存