Leetcode全排列算法

本文后续将更新解题思路以及优化解题方法

46. 全排列

难度中等

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]

输出:

[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]

class Solution {

    public List> permute(int[] nums) {

        LinkedList> list = new LinkedList<>();

        permutation(list, nums, 0);

        return list;

    }

    public void permutation(LinkedList> list, int[] nums, int n) {

        if (n == nums.length) {

            List l = new LinkedList<>();

            for (int c : nums) {

                l.add(c);

            }

            list.add(l);

        } else {

            for (int i = n; i < nums.length; i++) {

                swap(nums, i, n);

                permutation(list, nums, n + 1);

                swap(nums, i, n);

            }

        }

    }



    public static void swap(int[] nums, int i, int n) {

        int temp = nums[n];

        nums[n] = nums[i];

        nums[i] = temp;

    }

}


 

47. 全排列 II

难度中等

给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

输入: [1,1,2]

输出:

[

[1,1,2],

[1,2,1],

[2,1,1]

]

class Solution {

    public List> permuteUnique(int[] nums) {

        ArrayList> list = new ArrayList<>();

        permutation(list, nums, 0);

        return list;

    }

    public void permutation(List> list,int[] nums,int n){

        if(n==nums.length){

            List l = new ArrayList<>();

            for(int i:nums){

                l.add(i);

            }

            if(!list.contains(l)){

                list.add(l);

            }

        }else{

            for (int i = n; i < nums.length; i++) {

                swap(nums, i, n);

                permutation(list, nums, n + 1);

                swap(nums, i, n);

            }

        }

    }

    public void swap(int[] nums, int i, int n) {

        int temp = nums[n];

        nums[n] = nums[i];

        nums[i] = temp;

    }

}


 

60. 第k个排列

难度中等

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

  1. "123"

  2. "132"

  3. "213"

  4. "231"

  5. "312"

  6. "321"

给定 n 和 k,返回第 k 个排列。

说明:

  • 给定 n 的范围是 [1, 9]。

  • 给定 k 的范围是[1,  n!]。

示例 1:

输入: n = 3, k = 3

输出: "213"

示例 2:

输入: n = 4, k = 9

输出: "2314"

class Solution {

    public String getPermutation(int n, int k) {

        // n!

        int[] nums = new int[n + 1];

        nums[0] = 1;

        int sum = 1;

        for (int i = 1; i < n + 1; i++) {

            sum *= i;

            nums[i] = sum;

        }

        // 1-n

        ArrayList list = new ArrayList<>();

        for (int i = 1; i < n + 1; i++) {

            list.add(i);

        }

        String result = "";

        k--;

        for (int i = 1; i <= n; i++) {

            int index = k / nums[n - i];

            result += list.get(index);

            list.remove(index);

            k = k % nums[n - i];

        }

        return result;

    }



}


 

31. 下一个排列

难度中等

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

 

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。

1,2,3 → 1,3,2

3,2,1 → 1,2,3

1,1,5 → 1,5,1

class Solution {

    public void nextPermutation(int[] nums) {

        int p = -1;

        for (int i = nums.length - 1; i >= 1; i--) {

            if (nums[i] > nums[i - 1]) {

                p = i - 1;

                break;

            }

        }

        if (p == -1) {

            reverse(nums, 0, nums.length - 1);

            return;

        }

        int q = -1;

        for (int i = nums.length - 1; i > p; i--) {

            if (nums[i] > nums[p]) {

                q = i;

                break;

            }

        }

        swap(nums, p, q);

        reverse(nums, p + 1, nums.length - 1);

    }



    public void swap(int[] nums, int i, int j) {

        int temp;

        temp = nums[i];

        nums[i] = nums[j];

        nums[j] = temp;

    }



    public void reverse(int[] nums, int i, int j) {

        while (i < j) {

            swap(nums, i, j);

            i++;

            j--;

        }

    }

}

78. 子集

难度中等

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]

输出:

[

[3],

[1],

[2],

[1,2,3],

[1,3],

[2,3],

[1,2],

[]

]

class Solution {

    public List> subsets(int[] nums) {

        List> result = new ArrayList<>();

        for (int i = 1; i <(int)Math.pow(2, nums.length);i++){

            char[] chs = toBinary(i, nums.length).toCharArray();

            ArrayList l = new ArrayList<>();

            for (int j = 0; j < nums.length; j++) {

                if (chs[j] == '1') {

                    l.add(nums[j]);

                }

            }

            result.add(l);

        }

        result.add(new ArrayList<>());

        return result;

    }



    public String toBinary(int num, int digits) {

        String cover = Integer.toBinaryString(1 << digits).substring(1);

        String s = Integer.toBinaryString(num);

        return s.length() < digits ? cover.substring(s.length()) + s : s;

    }

}

 

90. 子集 II

难度中等

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: [1,2,2]

输出:

[

[2],

[1],

[1,2,2],

[2,2],

[1,2],

[]

]

class Solution {

    public List> subsetsWithDup(int[] nums) {

        Arrays.sort(nums);

        List> result = new ArrayList<>();

        for (int i = 1; i < (int) Math.pow(2, nums.length); i++) {

            char[] chs = toBinary(i, nums.length).toCharArray();

            ArrayList l = new ArrayList<>();

            for (int j = 0; j < nums.length; j++) {

                if (chs[j] == '1') {

                    l.add(nums[j]);

                }

            }

            if (!result.contains(l)) {

                result.add(l);

            }

        }

        result.add(new ArrayList<>());

        return result;

    }



    public String toBinary(int num, int digits) {

        String cover = Integer.toBinaryString(1 << digits).substring(1);

        String s = Integer.toBinaryString(num);

        return s.length() < digits ? cover.substring(s.length()) + s : s;

    }

}

 

 

你可能感兴趣的:(leetCode,Java面试算法)