Leetcode46 Permutations

来源:互联网 发布:知乎jenny wang 事件 编辑:程序博客网 时间:2024/05/23 01:58

Permutations

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].

Solution1

  • 典型的回溯问题,回溯问题一般说来用递归方法求解会比较简单
public class Solution {    public List<List<Integer>> permute(int[] nums) {        List<List<Integer>> result = new ArrayList<List<Integer>>();        HashSet<Integer> set = new HashSet<Integer>();        permute(nums,set,new ArrayList<Integer>(),result);        return result;    }    public void permute(int[] nums,HashSet<Integer> set,List<Integer> item,List<List<Integer>> result){        if(item.size()==nums.length){            result.add(item);            return;        }        for(int i=0;i<nums.length;i++){            if(set.contains(nums[i])) continue;            List<Integer> temp = new ArrayList<Integer>(item);            temp.add(nums[i]);            HashSet<Integer> newSet = new HashSet<Integer>(set);            newSet.add(nums[i]);            permute(nums,newSet,temp,result);        }            }}

Solution2

  • 用迭代的方法来实现上述回溯过程如下:
public class Solution {    public List<List<Integer>> permute(int[] nums) {        List<List<Integer>> result = new ArrayList<List<Integer>>();        if(nums.length==0) return result;        Stack<Integer> stack = new Stack<Integer>();        HashSet<Integer> set = new HashSet<Integer>();        List<Integer> item = new ArrayList<Integer>();        while(true){            for(int i=0;i<nums.length;i++){//往下递归的过程                if(set.contains(i)) continue;                stack.push(i);                set.add(i);                item.add(nums[i]);                break;            }            if(item.size()==nums.length){                result.add(new ArrayList<Integer>(item));                item.remove(item.size()-1);                set.remove(stack.pop());                int j;                for(j = nums.length;j>=nums.length;){//实现回溯过程                    if(stack.empty()) return result;                    j = stack.pop();                    set.remove(j);                    item.remove(item.size()-1);                    for(j++;j<nums.length&&set.contains(j);j++);                }                stack.push(j);                set.add(j);                item.add(nums[j]);            }        }    }}
  • 从上可以看出,一般说来,用迭代的方法来实现递归,都要借用到栈来保存当前的数组下标,在合适的时候回溯时,要在这个下标的地方往下递归,所以这里使用到栈来保存下标,但是可以看到迭代方法比较复杂。

Solution3

  • 另一种类型的递归,更加trick一些
public class Solution {    public List<List<Integer>> permute(int[] nums) {        List<List<Integer>> result = new ArrayList<List<Integer>>();        permute3(nums,0,result);        return result;    }    public void permute3(int[] nums,int start,List<List<Integer>> result){        if(start==nums.length){            List<Integer> item = new ArrayList<Integer>();            for(int num:nums) item.add(num);            result.add(item);            return;        }        for(int i=start;i<nums.length;i++){            int temp = nums[start];            nums[start] = nums[i];            nums[i] = temp;            permute3(nums,start+1,result);            nums[i] = nums[start];            nums[start] = temp;        }    }}

Solution4

  • 这里实际可以用动态规划的方法来求解。基本思路如下:当数组为[1]时,则答案为[1];当数组为[1,2]时,则答案为[1,2]和[2,1];当数组为[1,2,3]时,则答案可以在[1,2]和[2,1]的基础上构成。即往这两个数组中的不同位置插入3即可。如此得到下面的解法
import java.util.List;import java.util.ArrayList;public class Solution {    public List<List<Integer>> permute(int[] nums) {        List<List<Integer>> result = new ArrayList<List<Integer>>();        if(nums.length==0) return result;        List<Integer> temp = new ArrayList<Integer>();        temp.add(nums[0]);        result.add(temp);        for(int i=1;i<nums.length;i++){            int size = result.size();            for(int j=0;j<size;j++){                temp = result.get(j);                   for(int k=0;k<=temp.size();k++){//这里便是各个位置插入的过程                    ArrayList<Integer> temp1 = new ArrayList<Integer>(temp);                    temp1.add(k,nums[i]);                    result.add(temp1);                }            }            while(size-->0) result.remove(0);        }        return result;    }}

Solution5

  • 这里借鉴 Leetcode31 Next Permutation的思路来求解本题。
public class Solution {    public List<List<Integer>> permuteUnique(int[] nums) {        List<List<Integer>> result = new ArrayList<List<Integer>>();        Arrays.sort(nums);        while(true){            List<Integer> item = new ArrayList<Integer>();            for(int num:nums) item.add(num);            result.add(item);            int i,j;            for(i=nums.length-1;i>0;i--) if(nums[i-1]<nums[i]) break;            if(i<=0) break;            for(j=nums.length-1;j>0;j--) if(nums[j]>nums[i-1]) break;            int temp = nums[j];            nums[j] = nums[i-1];            nums[i-1] = temp;            for(j = nums.length-1;i<j;i++,j--){                temp = nums[j];                nums[j] = nums[i];                nums[i] = temp;            }        }        return result;    }}
  • 思路清晰易懂,并且还复用性还非常高。不管是有重复数字还是没有重复数字都可以用这种方法求解。所以比回溯法更值得推荐。
0 0
原创粉丝点击