Lintcode 15/16 Permutations I/ll
2018-03-19 21:45
274 查看
Permutations I
Given a collection of numbers, return all possible permutations.For example, [1,2,3] have the following permutations: [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].交换法
复杂度
时间 O(N^2) 空间 O(N) 递归栈思路
置换实际上是给出所有的排列方式,同样是用深度优先搜索,不过为了避免重复选择的情况,我们要保证两点:第一,所有数必须是数组中的,第二,数组中每个数只能用不多于也不少于一次。如果我们要单独写一个函数,来判断下一轮搜索该选择哪一个数就很麻烦了。这里有一个技巧,我们可以只将数两两交换,不过交换时只能跟自己后面的交换。代码
public class Solution { List<List<Integer>> res; public List<List<Integer>> permute(int[] nums) { res = new LinkedList<List<Integer>>(); helper(nums, 0); return res; } public void helper(int[] nums, int i){ // 找到转置完成后的解,将其存入列表中 if(i == nums.length - 1){ List<Integer> list = new LinkedList<Integer>(); for(int j = 0; j < nums.length; j++){ list.add(nums[j]); } res.add(list); } // 将当前位置的数跟后面的数交换,并搜索解 for(int j = i; j < nums.length; j++){ swap(nums, i , j); helper(nums, i + 1); swap(nums, i, j); } } private void swap(int[] nums, int i, int j){ int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
深度优先搜索
复杂度
时间 O(N) 空间 O(N) 递归栈思路
我们还可以简单的使用深度优先搜索来解决这题。每一轮搜索选择一个数加入列表中,同时我们还要维护一个全局的布尔数组,来标记哪些元素已经被加入列表了,这样在下一轮搜索中要跳过这些元素。代码
public class Solution { List<List<Integer>> res; boolean[] used; public List<List<Integer>> permute(int[] nums) { res = new LinkedList<List<Integer>>(); used = new boolean[nums.length]; List<Integer> tmp = new LinkedList<Integer>(); helper(nums, tmp); return res; } private void helper(int[] nums, List<Integer> tmp){ if(tmp.size() == nums.length){ List<Integer> list = new LinkedList<Integer>(tmp); res.add(list); } else { for(int idx = 0; idx < nums.length; idx++){ // 遇到已经加过的元素就跳过 if(used[idx]){ continue; } // 加入该元素后继续搜索 used[idx] = true; tmp.add(nums[idx]); helper(nums, tmp); tmp.remove(tmp.size()-1); used[idx] = false; } } } }
Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations.For example, [1,1,2] have the following unique permutations: [1,1,2], [1,2,1], and [2,1,1].深度优先搜索
复杂度
时间 O(N) 空间 O(N) 递归栈思路
这题和上题的深度优先搜索很相似,区别在于:1、要先将数组排序,确保重复的元素是在一起的。2、除了不能加入之前出现过的元素之外,还不能加入本轮搜索中出现过的元素。如何判断哪些元素本轮出现过呢?我们加过一个数字并搜索后,在这一轮中把剩余的重复数字都跳过就行了,保证每一轮只有一个unique的数字出现。这和Combination Sum II中跳过重复元素的方法是一样的,注意要判断nums[i] == nums[i + 1],因为for循环结束时i还会额外加1,我们要把i留在最后一个重复元素处。
代码
public class Solution { List<List<Integer>> res; boolean[] used; public List<List<Integer>> permuteUnique(int[] nums) { res = new LinkedList<List<Integer>>(); used = new boolean[nums.length]; Arrays.sort(nums); List<Integer> tmp = new LinkedList<Integer>(); helper(nums, tmp); return res; } private void helper(int[] nums, List<Integer> tmp){ if(tmp.size() == nums.length){ List<Integer> list = new LinkedList<Integer>(tmp); res.add(list); } else { for(int idx = 0; idx < nums.length; idx++){ // 遇到已经加过的元素就跳过 if(used[idx]){ continue; }
推荐网站:https://www.kancloud.cn/kancloud/data-structure-and-algorithm-notes/73051
http://www.jiuzhang.com/solution/permutations
相关文章推荐
- LintCode 15-全排列 16-带重复元素的全排列
- iPhone开发入门系列1(iOS8+Swift版)天天打靶APP学习15-16
- 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8
- 读书笔记之《深入理解LINUX内核》13、14、15、16 章
- stm32f051 TIM15、16、17 无法出PWM
- 循环-16. 猴子吃桃问题(15)
- lintcode 中等题:permutations 全排列
- With the approaching end of FIFA 15, FIFA16 is upcoming now
- 循环-16. 猴子吃桃问题(15)
- 触动精灵:零基础小白学触动15-16
- LintCode 15全排列
- Fedora 15/16 安装后需要做的28件事
- 15-11-16 Eclipse 操作菜单汉译之Edit [编辑]
- 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8
- 简明Python教程 14)标准库 15)更多内容 16)GUI
- 一周一总结(15~16)
- Fedora 15/16 安装后需要做的28件事
- Fedora 15/16 安装后需要做的28件事
- lintcode-15-全排列
- java 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,