31. Next Permutation
题目:找到给出序列的下一序列。
思路:分三步:一是从后往前找到非递增的位置,即需要开始交换的位置;二是在该位置之后找到第一个比它大的数,并与其交换;三是对后面的序列做一个逆序,然后返回。如果没有找到第一步的位置,就对整个数组逆序。
public class Solution {
public void nextPermutation(int[] nums) {
int len = nums.length;
if(len < 2) return;
for(int i = len-2; i >= 0; i--){
if(nums[i+1] > nums[i]){
for(int j = len-1; j > i; j--){
if(nums[j] > nums[i]){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
for(int k = 0; k < (len-1-i)/2; k++){
temp = nums[k+i+1];
nums[k+i+1] = nums[len-1-k];
nums[len-1-k] = temp;
}
return;
}
}
}
}
for(int i = 0; i < len/2; i++){
int temp = nums[i];
nums[i] = nums[len-1-i];
nums[len-1-i] = temp;
}
return;
}
}
46. Permutations
题目:得到输入数组的所有排列序列。
思路:回溯(递归)——注意要判断list中是否已经包含该数,前提是输入数组每个元素均不相同。注意list也有contains方法。
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> ret = new LinkedList<>();
List<Integer> list = new LinkedList<>();
backtrack(ret, nums, list, 0);
return ret;
}
public void backtrack(List<List<Integer>> ret, int[] nums, List<Integer> list, int x){
if(x == nums.length){
ret.add(new LinkedList<Integer>(list));
return;
}
else if(x > nums.length){
return;
}
else{
for(int i = 0; i < nums.length; i++){
if(list.contains(nums[i])) continue;
list.add(nums[i]);
backtrack(ret, nums, list, x+1);
list.remove(list.size()-1);
}
}
}
}
改进的做法——在输入的nums做手脚,即打乱nums的顺序,每个交换相邻的位置,然后递归,最后复原。这样大大缩短了时间。
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> ret = new LinkedList<>();
backtrack(ret, nums, 0);
return ret;
}
public void backtrack(List<List<Integer>> ret, int[] nums, int x){
if(x == nums.length){
List<Integer> list = new LinkedList<>();
for(int n : nums){
list.add(n);
}
ret.add(list);
return;
}
else if(x > nums.length){
return;
}
else{
for(int i = x; i < nums.length; i++){
int temp = nums[i];
nums[i] = nums[x];
nums[x] = temp;
backtrack(ret, nums, x+1);
nums[x] = nums[i];
nums[i] = temp;
}
}
}
}
47. Permutations II
题目:数组有重复数时
思路:在40题基础上增加去重的部分,设置flag判断是否跳过重复部分。判断被交换节点和交换节点之间是否有与交换节点相同值的节点,有就跳过。
public class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ret = new LinkedList<>();
backtrack(ret, nums, 0);
return ret;
}
public void backtrack(List<List<Integer>> ret, int[] nums, int x){
if(x == nums.length){
List<Integer> list = new LinkedList<>();
for(int n : nums){
list.add(n);
}
ret.add(list);
return;
}
else if(x > nums.length){
return;
}
else{
for(int i = x; i < nums.length; i++){
boolean flag = true;
for(int j = x; j < i; j++){
if(nums[j] == nums[i]){
flag = false;
break;
}
}
if(flag == false) continue;
int temp = nums[i];
nums[i] = nums[x];
nums[x] = temp;
backtrack(ret, nums, x+1);
nums[x] = nums[i];
nums[i] = temp;
}
}
}
}
60. Permutation Sequence
题目:找到全排序列中第k位的序列
思路:从数学的角度来做,按模值分成若干组。新建一个List,每次从中取出一个数加到返回并移除。
public class Solution {
public String getPermutation(int n, int k) {
List<Integer> list = new LinkedList<>();
for(int i = 1; i <= n; i++){
list.add(i);
}
StringBuilder sb = new StringBuilder();
k--;
for(int i = n-1; i > 0; i--){
int jx = jie(i);
String x = list.get(k/jx).toString();
sb.append(x);
list.remove(k/jx);
k = k%jx;
}
sb.append(list.get(0).toString());
return sb.toString();
}
public int jie(int n){
int ret = 1;
for(int i = 1; i <= n; i++){
ret *= i;
}
return ret;
}
}