leetcode之回溯backtracing专题2
46 Permutations
输入一个不重复的数组 ,写出这个数组的排列,不能重复。
例如 输入nums=[1,2,3],输出
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:可以看到 第0位(从左开始数)有nums.length个数字可以选择:1,2,3,在第0位确定以后,第1位有nums.length-1个数字可以选择,例如p[0] = 1,p[1]只可能为2 或者3。所以重要的是记录哪些下标的元素已经被选择过。
public class Solution {private boolean[] p;//记录选中过的下标private List<List<Integer>> list;public List<List<Integer>> permute(int[] nums) {int[] newarray=new int[nums.length];//存放选中的数字p = new boolean[nums.length];list = new ArrayList<List<Integer>>();robot(0,newarray,nums);return list;}public void robot(int idx,int[] newarray,int[] nums){if(idx>=nums.length){List<Integer> l = new ArrayList<Integer>();for(int i=0;i<newarray.length;i++){l.add(newarray[i]);}list.add(l);return;}for(int i=0;i<nums.length;i++){if(p[i]==false){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}}
}
47 Permutations II
输入一个重复的数组 ,写出这个数组的排列,不能重复。
例如输入 [1,1,2] 输出
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路:这与46的区别是输入的数组中有重复的数字。如果按照46的思路做,会出现重复的结果。我们先按照46的来做一下吧。用”数字(下标)”这种方式表示数组元素:1(0) 1(1) 2(2)。这样才能把相同的数字区分开来。为了方便,我们先将输入的数组排序。按照46的思路得到以下组合:
1(0) 1(1) 2(2)
1(0) 2(2) 1(1)
1(1) 1(0) 2(2)
1(1) 2(2) 1(0)
2(2) 1(0) 1(1)
2(2) 1(1) 1(0)
重点标记的是重复的元素。分析一下。第0位可以选择的元素有 nums[0], nums[1], nums[2],但是当已经选择nums[0]之后,再遇到nums[1]=nums[0]的时候,nums[1]是不能选择的,否则就重复了。所以第0位可以选择的元素有 nums[0], nums[2]。每一位都是,判断nums[idx]能不能选择标准是nums[idx-1]=nums[idx]是否为true。
这个判断怎么加呢?下面记录一下我自己犯过的错。
处理情况1
for(int i=0;i<nums.length;i++){if(p[i]==false){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;for (int j = i + 1; j < nums.length; j++){if (nums[j] != nums[j - 1]) {i = j - 1;break;}}}}
每到一个位置,先选择一个元素,再处理下一个元素和前面的元素是否相同。这里判断的时候没有考虑前面的元素是否会选中,可能会有多余的操作。更重要的是没有处理如果重复元素是最后一个元素怎么处理。失败用例:[1,1]。
for(int i=0;i<nums.length;i++){if(p[i]==false){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;int j = i + 1;for (; j < nums.length; j++){if (nums[j] != nums[j - 1]) {i = j - 1;break;}}if(j==nums.length){break;}}}
改成这样就对了。但是这样代码不够优雅。
处理情况2
for(int i=0;i<nums.length;i++){if(p[i]==false && (i==0 || (nums[i]!=newarray[idx]))){newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}
因为newarray[idx]记录了上一次选择的值,所以想到只要判断这次的候选值nums[i]和newarray[idx]不同就好了。这次的错误是因为i==0的判断是有误的。因为不一定每次都是nums[0]是第一个被选中的。例如当第0位选择nums[0],在选第2位的时候第一个被选中的一定是nums[1] ,所以这里应该用一个boolean变量表示本次是不是对idx已经选过一个值了。
boolean selected = false;for(int i=0;i<nums.length;i++){if(p[i]==false && (!selected || (nums[i]!=newarray[idx]))){selected = true;newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}
处理情况3
接着我还用了一种方式处理。使用了一个单独的变量记录在选择idx的候选值时候,上一个选择的值。
int preNum = -1;boolean selected = false;for(int i=0;i<nums.length;i++){if(p[i]==false && (selected==false || (nums[i]!=preNum))){selected = true;preNum = nums[i];newarray[idx]=nums[i];p[i]=true;robot(idx+1,newarray,nums);p[i]=false;}}
总结:大概可以在编程的时候行不通。一定是一定可以才可以。在backtracing中最重要的是理解每一步的状态。
leetcode之回溯backtracing专题2相关推荐
- leetcode之回溯backtracing专题5
参考链接 http://blog.csdn.net/zhongkeli/article/details/6966805 https://leetcode.com/problems/permutatio ...
- leetcode之回溯backtracing专题4
131 Palindrome Partitioning 输入一个字符串s,将s分割为n个子串,每个子串都是一个回文.返回s有多少种分割方式. 例如输入:"aab" 输出:[ [&q ...
- leetcode之回溯backtracing专题3
17 Letter Combinations of a Phone Number 手机上每个数字按钮旁边都有3-4个字母,输入数字字符串,输出可能的字母组合. 例如输入:"23" ...
- leetcode之回溯backtracing专题1
39 Combination Sum 给一组整数,给一个目标整数.从数组中任意选择几个数,这几个数的和等于目标整数.数组中每个数字可以选择多次. 例如given candidate set [2, 3 ...
- LeetCode Hot100 ---- 回溯算法专题
回溯算法是什么?解决回溯算法相关的问题有什么技巧?如何学习回溯算法?回溯算法代码是否有规律可循? 其实回溯算法其实就是我们常说的 DFS 算法,本质上就是一种暴力穷举算法. 解决一个回溯问题,实际上就 ...
- Leetcode总结(Island专题)
Leetcode总结之 Island专题 Table of Contents 总结 200. Number of Islands 305. Number of Islands II 695. Max ...
- leetcode的回溯算法题目用这个模板解题,一网打尽,so easy!!!
" 这是本人第 46 篇原创博文,每周至少两篇更新,谢谢赏脸阅读文章 这一篇文章来讲解一下如何做leetcode回溯算法题目,这一段时间我把leetcode上面的回溯算法的题目都刷了个遍,发 ...
- 【LeetCode】回溯 N皇后(DFS、子集、组合问题)
总结 技巧: 子集和组合问题经常需要一个start来标记开始选择的起始位置来达到去重的目的,排列问题不用 [46.全排列] 排列问题常需要一个used数组来标记已经选择的元素(也可以同时用于去重) C ...
- leetcode two sum python_LeetCode专题-Python实现之第1题:Two Sum
相关代码已经上传到github:https://github.com/exploitht/leetcode-python 文中代码为了不动官网提供的初始几行代码内容,有一些不规范的地方,比如函数名大小 ...
最新文章
- Wireshark数据抓包分析(网络协议篇)第1章网络协议抓包概述
- 蚂蚁疾奔:蚂蚁集团两地上市全速推进
- 算法讲解 -- 二分图之 匈牙利算法
- xCode 安装Mobile Device Framework出错的问题的解决方法
- mysql中having的例子_有关mysql中having子句对组记录进行筛选的例子
- Java Web提交任务到Spark Spark通过Java Web提交任务
- tornado之获取参数
- Matlab线型、标记、颜色表示代码
- eeupdate 更新MAC地址
- 论外挂入门(辅助入门)图色辅助与内存辅助的优与弊
- 围棋棋盘 -《跟小海龟学Python》案例代码
- 最新可用的快速FLV转MP4方法,解决转换后无声音及视频不流畅问题
- python优雅编程之旅
- kubernetes部署失败的原因
- pyqt5 等待界面 (QMovie 加载 gif)
- JS在VS coder界面写promt和alter语句无法在浏览器页面显示
- 有用的“歪门邪道”-设计模式
- web安全基础知识-part2
- 谷歌扩展插件官方下载地址
- 想做游戏测试工程师?这几点不知道可不行!
热门文章
- 部署OpenStack问题汇总(五)--openstack中删除虚拟主机,状态一直未deleting
- PHP扩展开发(3)-config.m4
- websocket + node.js聊天系统
- linux-tar命令详解
- 微软应提前发布专用于ARM处理器的Windows 8平板电脑系统
- SharePoint中的权限体系
- Linux循环登录怎么解决,文本模式循环登录! 求解决
- skywalking 源码解析——多线程变量传递 EnhancedInstance
- elasticsearch 6.x (一) 部署 windows入门 spingboot连接
- android任务 进程 线程详解,Android任务、进程、线程详解