首页 > 其他分享 >打印数组的全部排列

打印数组的全部排列

时间:2022-10-02 19:56:44浏览次数:69  
标签:arr 排列 位置 int 打印 List result 数组 swap

打印数组的全部排列

作者:Grey

原文地址:

博客园:打印数组的全部排列

CSDN:打印数组的全部排列

无重复值情况

题目描述见: LeetCode 46. Permutations

主要思路

由于是所有排列,所以每个 i 后面位置的元素都有机会来到 i 位置。

定义递归函数

void p(int[] arr, int i, List<List<Integer>> result)

递归含义是:数组 arr 的 i 位置以后的元素,都来到 i 位置(即:和 i 位置的元素交换),得到的排列是多少。

所以,base case 是,当 i 来到 arr 的最后一个元素的位置的时候,此时可以收集一种排列状况(因为最后一个元素后面没有元素可以与之交换了)

        if (i == arr.length - 1) {
            // 来到最后一个位置,收集答案
            result.add(Arrays.stream(arr).boxed().collect(Collectors.toList()));
            return;
        }

到普遍位置的时候,即遍历 i 后面的每个位置,让每个位置都和 i 位置的值交换

        for (int j = i; j < arr.length; j++) {
            swap(arr, i, j);
            p(arr, i + 1, result);
            swap(arr, i, j);
        }

完整代码见

class Solution {
    public static List<List<Integer>> permute(int[] arr) {
        if (arr == null ) {
            return Collections.emptyList();
        }
        if (arr.length == 0) {
            List<List<Integer>> ans = new ArrayList<>();
            ans.add(new ArrayList<>());
            return ans;
        }
        List<List<Integer>> result = new LinkedList<>();
        p(arr, 0, result);
        return result;
    }

    private static void p(int[] arr, int i, List<List<Integer>> result) {
        if (i == arr.length - 1) {
            // 来到最后一个位置,收集答案
            result.add(Arrays.stream(arr).boxed().collect(Collectors.toList()));
            return;
        }
        for (int j = i; j < arr.length; j++) {
            swap(arr, i, j);
            p(arr, i + 1, result);
            swap(arr, i, j);
        }
    }

    public static void swap(int[] arr, int i, int j) {
        if (i != j) {
            arr[i] = arr[i] ^ arr[j];
            arr[j] = arr[i] ^ arr[j];
            arr[i] = arr[i] ^ arr[j];
        }
    }
}

有重复值情况

题目描述见: LeetCode 47. Permutations II

有重复值的情况可以借鉴上述递归方法的思想,我们还是定义如下递归函数

void p(int i, int[] arr, List<List<Integer>> result)

递归含义还是:数组 arr 的 i 位置以后的元素,都来到 i 位置(即:和 i 位置的元素交换),得到的排列是多少。

但是由于有重复值,所以我们在交换之前,需要判断和 i 交换的元素曾经有没有访问过,如下示意图

image

当我们将i位置的 a 和 i + n位置的 x 交换过以后,得到了一个全排列的数量,当我们来到i+n+1位置的时候,如果这个位置还是 x ,就无须再和 i 位置的 a 交换了。

为了标识哪个值是否交换过,我们可以定义一个boolean类型的数组,由于题目中的数据范围比较小-10<=num[i]<=10, 所以我们只需要一个boolean[] visited = new boolean[21]长度的数组即可。要判断某个位置的值 m 是否访问过,只需要判断visited[m+10]是否为 TRUE。

完整代码见

class Solution {
    public static List<List<Integer>> permuteUnique(int[] arr) {
        List<List<Integer>> ans = new ArrayList<>();
        p(0, arr, ans);
        return ans;
    }

    private static void p(int i, int[] arr, List<List<Integer>> result) {
        if (i == arr.length - 1) {
            // 来到最后一个位置,收集答案
            result.add(Arrays.stream(arr).boxed().collect(Collectors.toList()));
            return;
        }
        boolean[] visited = new boolean[21];
        for (int index = i; index < arr.length; index++) {
            if (!visited[arr[index] + 10]) {
                visited[arr[index] + 10] = true;
                swap(index, i, arr);
                p(i + 1, arr, result);
                swap(index, i, arr);
            }
        }
    }

    private static void swap(int i, int j, int[] arr) {
        if (j == i) {
            return;
        }
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }
}

更多

算法和数据结构笔记

标签:arr,排列,位置,int,打印,List,result,数组,swap
From: https://www.cnblogs.com/greyzeng/p/16749313.html

相关文章

  • java---数组的学习
    数组数组是最简单的数据结构//无论定义什么都满足变量类型变量的名字=变量的值;int[]num;num=newint[10];//等同于下方写法int[]num=newint[10];一.数组的......
  • 1008 数组元素循环右移问题
    1.1题目1.2题解1.3代码   题目:一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0​A1​⋯AN−1​)变换......
  • 打印数组的所有子集
    打印数组的所有子集作者:Grey原文地址:博客园:打印数组的所有子集CSDN:打印数组的所有子集无重复值情况题目描述见:LeetCode78.Subsets主要思路定义递归函数voidp......
  • java将一个有序数组按是否连续进行分组
    代码:importjava.util.Arrays;importjava.util.Comparator;importjava.util.List;/***@authorliyinlong*@since2022/8/229:45上午*/publicclassSemTest{......
  • 后缀数组小结
    后缀数组小结借用了一下别人的\(\rmblog\)。简介介绍一下基本数组。我们把原串\(\rmA\)的所有后缀按字典序从小到大排个序,则排名为\(\rmi\)的字符串是以第\(......
  • 代码随想录 哈希表理论基础,有效的字母异位词(LeetCode 242),两个数组的交集 (LeetCode
    哈希表理论基础哈希表是根据关键码的值而直接进行访问的数据结构。哈希碰撞拉链法拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会......
  • 前端中数组的方法之 --- Array.prototype.reduce()
    参数:reduce((previousValue,currentValue,currentIndex,array)=>{/*…*/},initialValue)回调函数:previousValue:上一次调用 callbackFn 时的返回值。在第......
  • 数组操作の旋转二维数组
    一、题目描述:​​旋转图像​​给定一个n × n的二维矩阵 matrix表示一个图像。请你将图像顺时针旋转90度。你必须在原地旋转图像,这意味着你需要直接修改输入的二......
  • 机试题 三数之和变形-三数和赛高数组01
    数组a对任意的i、j、k都能找到l,使得ai+aj+ak=al,那么这个数组就是被称为三数和赛高数组,特别的i、j、k需要满足(1<=i<j<k<=n,1<=l<=n)。输入:首先t(1......
  • 机试题 三数之和变形-三数和赛高数组02 存在
    数组a存在i、j、k能找到l,使得ai+aj+ak=al,那么这个数组就是被称为三数和赛高数组,特别的i、j、k需要满足(1<=i<j<k<=n,1<=l<=n)。输入:首先t(1<=......