Permutation类型题目整理

1.permutations

Given a list of numbers, return all possible permutations.

For nums = [1,2,3], the permutations are:

[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

显然需要需要用递归来找所有的全排列。关于这个递归,是返回找到的值加入到上层还是在把参数传到递归层,在递归层进行更新处理。对于分治策略,二叉树的问题,很明显左右子树能得到一个小问题的答案,大问题的答案是该小问题的答案的一个组合,那么用递归返回一个结果,在上层进行结合处理比较方便。对于这个题目,每次递归要做的事情是往下找permutations的下一个数字,在递归层处理结果更加自然。

注意深刻理解这个递归要干的事情,每一层分别是做什么的。

for (int i = 0; i < nums.length; i++) {
  。。。
  list.add(nums[i]);

  helper(nums, result, list);
  list.remove(list.size() - 1);

  。。。

}

这个for循环其实是在便利nums数组,找到第一个合适的permutation的首字母,这也就是为什么找到第一个首字母的时候,我们要把它更新的结果里面。这时候需要找第二个字母,那么我们跳到第二层递归里面去找第二个,这也就是为什么,这个时候需要使用递归。当以当前首字母开头的permutations找到并且加入到全局结果里以后,我们需要找下一个合适的开头字母,所以要把当前的开头字母给清空,这也就是为什么需要做remove操作。

 1 class Solution {
 2     /**
 3      * @param nums: A list of integers.
 4      * @return: A list of permutations.
 5      */
 6     public List<List<Integer>> permute(int[] nums) {
 7         List<List<Integer>> result = new ArrayList<List<Integer>>();
 8         if (nums == null) {
 9             return result;
10         }
11         List<Integer> list = new ArrayList<Integer>();
12         helper(nums,result,list);
13         return result;
14     }
15     private void helper (int[] nums, List<List<Integer>> result, List<Integer> list) {
16         if (list.size() == nums.length) {
17             result.add(new ArrayList<Integer>(list));
18         }
19         for (int i = 0; i < nums.length; i++) {
20             if (list.contains(nums[i])){
21                 continue;
22             }
23             list.add(nums[i]);
24             helper(nums, result, list);
25             list.remove(list.size() - 1);
26         }
27     }
28 }

permutations

2.  Permutations II

Given a list of numbers with duplicate number in it. Find all unique permutations.

Example

For numbers [1,2,2] the unique permutations are:

[
  [1,2,2],
  [2,1,2],
  [2,2,1]
]

注意3点, 1. 对于有重复的情况,用visited[]数组处理,判断这个数是否已经遍历过了

     2. 需要对数组进行排序,如果num是int[] 那么用Arrays.sort

                如果是ArrayList<Integer> 用Collections.sort

     3.对于重复的情况,112, 11第一次出现时是valid, 但是当把第二个1作为开头,第一个1作为第二时是invalid,所以添加了下面的判断条件:

      (i != 0 && nums.get(i) == nums.get(i - 1) && visited[i - 1] == 0)

     针对这个情况,下面是反例:

wrong answer:

Input:[1,1,2]

Output:[[1,1,2],[1,2,1],[1,1,2],[1,2,1],[2,1,1],[2,1,1]]

Expected:[[1,1,2],[1,2,1],[2,1,1]]

 1 public class Solution {
 2     public List<List<Integer>> permuteUnique(int[] nums) {
 3         List<List<Integer>> result = new ArrayList<List<Integer>>();
 4         if (nums == null || nums.length == 0) {
 5             return result;
 6         }
 7         List<Integer> list = new ArrayList<Integer>();
 8         int[] visited = new int[nums.length];
 9         Arrays.sort(nums);
10         helper(nums, result, list, visited);
11         return result;
12     }
13     private static void helper(int[] nums, List<List<Integer>> result, List<Integer> list, int[] visited) {
14         if (list.size() == nums.length) {
15             result.add(new ArrayList(list));
16             return;
17         }
18
19         for (int i = 0; i < nums.length; i++) {
20             if (visited[i] == 1 || (i != 0 && nums[i] == nums[i - 1] && visited[i - 1] == 0)) {
21                 continue;
22             }
23             visited[i] = 1;
24             list.add(nums[i]);
25             helper(nums, result, list, visited);
26             list.remove(list.size() - 1);
27             visited[i] = 0;
28         }
29     }
30 }

permuteUnique

3.Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

数学题,没啥可说的 = =

 1 public class Solution {
 2     /**
 3      * @param nums: an array of integers
 4      * @return: return nothing (void), do not return anything, modify nums in-place instead
 5      */
 6     public int[] nextPermutation(int[] nums) {
 7         if (nums == null || nums.length == 0) {
 8             return nums;
 9         }
10         int size = nums.length;
11         int violation = -1;
12         // search for first violation
13         for (int i = size - 1; i > 0; i--) {
14             if (nums[i - 1] < nums[i]) {
15                 violation = i - 1;
16                 break;
17             }
18         }
19
20         // if can not find violation, we need to sawp all the array
21         if (violation == -1) {
22             int i = 0, j = size - 1;
23             while(i < j) {
24             swap(nums, i++, j--);
25             }
26             return nums;
27         }
28
29
30         // search swap index
31         int index = -1;
32         for (int i = size - 1; i > violation; i--) {
33             if (nums[i] > nums[violation]) {
34                 index = i;
35                 break;
36             }
37         }
38         //swap violation and index
39         swap(nums, violation, index);
40
41         //swap the tail part after the violation
42         int i = violation + 1, j = size - 1;
43         while(i < j) {
44             swap(nums, i++, j--);
45         }
46         return nums;
47     }
48     private static void swap (int[] nums, int i, int j) {
49         int temp = nums[i];
50         nums[i] = nums[j];
51         nums[j] = temp;
52         return;
53     }
54 }

nextPermutation

时间: 2024-10-10 10:45:36

Permutation类型题目整理的相关文章

【Android进阶】Android面试题目整理与讲解

这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的增加,如果答案有错误,希望大家可以指正 1.简述Activity的生命周期 当Activity开始启动的时候,首先调用onCreate(),onStart(),onResume()方法,此时Activity对用户来说,是可见的状态 当Activity从可见状态变为被Dialog遮挡的状态的时候,会调用onPause()方法,此时的Activity对用户可见,但是不能相 应用户的点击事件 当Activity从可见状态变为被其他

【Java基础】Java面试题目整理与解说(二)

1.Collection 和 Collections 的差别. Collection 是集合类的上级接口,继承于他的接口主要有 Set 和 List. Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索.排序.线程安全化等操作. 2.HashMap 和 Hashtable 的差别. HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完毕了 Map 接口,HashMap是非线程安全,效率上可能高于 Hashtable.在多个线程

Android面试题目整理与讲解(二)

1.Dalvik和标准Java虚拟机之间的主要差别? Dalvik和标准Java虚拟机(JVM)之间的首要差别之一,就是Dalvik基于寄存器,而JVM基于栈. Dalvik和Java之间的另外一大区别就是运行环境--Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个 Dalvik应用作为一个独立的Linux进程执行. (1)虚拟机很小,使用的空间也小: (2)Dalvik没有JIT编译器: (3)常量池已被修改为只使用32位的索引,以简化解释器: (4)它使用自己的字

【Java基础】Java面试题目整理与讲解(二)

1.Collection 和 Collections 的区别. Collection 是集合类的上级接口,继承于他的接口主要有 Set 和 List. Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索.排序.线程安全化等操作. 2.HashMap 和 Hashtable 的区别. HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,HashMap是非线程安全,效率上可能高于 Hashtable.在多个线程

ACM 矩阵题目整理

先从最基础的矩阵快速幂加速递推开始. HDU 1005 Number Sequence |f[n-2],f[n-1]|* |0 B| =|f[n-1], B*f[n-2]+A*f[n-1]|=|f[n-1],f[n]|   |1 A| 建立矩阵如上然后利用快速幂求解即可.答案是mat[0][1]. #include<iostream> #include<vector> #include<cmath> #include<map> #include<alg

数据库题目整理及详解(四)

前言 有多少次挥汗如雨,伤痛曾添满记忆,只因为始终相信,去拼搏才能胜利.总在鼓舞自己,要成功就得努力.热血在赛场沸腾,巨人在赛场升起. 相信自己,你将赢得胜利,创造奇迹:相信自己,梦想在你手中,这是你的天地.当一切过去,你们将是第一. 相信自己,你们将超越极限,超越自己! 相信自己,加油吧,健儿们,相信你自己. 坐在中体对面, 听着这振奋激昂的加油欢呼声, 照样可以感受到校运会的气势磅礴, 虽然我还在敲代码-- 来个这个吧, 特殊纪念, 沃夫慈悲: 说明 老生常谈! 接着之前的SQL语句继续整理

ACM 字符串 题目整理

AC自动机 UVa 11468  Substring AC自动机+概率DP. 注意要补全不存在的边. 为什么要补全不存在的边呢?补全以后可以直接找到状态的转移,即从所有子节点就可以实现所有状态转移. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cst

ACM 暴力搜索题 题目整理

UVa 129 Krypton Factor 注意输出格式,比较坑爹. 每次要进行处理去掉容易的串,统计困难串的个数. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cstdio> #include<cstdlib> #include

博弈论 题目整理

博弈论里面一个非常重要的结论: 如果前一个状态所有可能都是必败态,那么当前状态一定是必胜态. 如果前一个状态所有可能有一个是必胜态,那么当前状态一定是必败态. POJ 2484 A Funny Game 博弈游戏里面后手经常占据优势.除了A可以一次性全部拿光的情况,其他时候B都可以采取与A相同的策略,这样每次将石子分为相同的两组,最后获胜的一定是B. #include <cstdio> #include <cstring> #include <algorithm> us