全排列方法大集合

ctrl alt+L自动整理代码

dfs+回溯
全排列问题很容易想到递归。在构造树的过程中进行深度优先遍历,将搜索到的节点入栈(回溯),栈的作用就是回溯,如果只是先序遍历那么节点1不会重复打印,所以用栈来实现回溯,每访问一个节点,就入栈,没回退一个节点,就出栈,如果访问到的是叶子结点,那么直接输出栈中的所有元素,这样就实现了全排列。
arraycopy()方法位于java.lang.System类中
语法:
System.arraycopy(dataType[] srcArray,
int srcIndex,int destArray,int destIndex,int length)
其中,srcArray表示原数组;srcIndex表示原数组中的起始索引;
destArray表示目标数组;destIndex表示目标数组中的起始索引;
length表示要复制的长度。

使用此方法复制数组时,length+srcIndex必然小于等于srcArray.length,同时length+destIndex必须小于等于destArray.length
注意:目标数组必然已经存在,且不会被重构,相当于替换目标数组中的部分元素。

实现全排列方法一:
全排列

import java.util.Arrays;
import java.util.Stack;
//dfs+回溯
public class 全排列 {
    public static void perm(int[] array, Stack<Integer>stack){
        if (array.length<=0)
        {
//            进入叶子结点,输出栈中内容
            System.out.println(stack);
        }
        else {
            for (int i = 0; i <array.length ; i++) {
//                tempArray是一个临时数组
                int[] tempArray = new int[array.length-1];
//                1,2,3的全排列,先取出1,那么tempArray中就是2,3
                System.arraycopy(array,0,tempArray,0,i);
                System.arraycopy(array,i+1,tempArray,i,array.length-i-1);
//                入栈
                stack.push(array[i]);
//                回溯
                perm(tempArray,stack);
                stack.pop();
            }
        }
    }
    public static void main(String[] args) {
        perm(new int[]{1,2,3},new Stack<>());
    }

}
实现全排列方法二:

import java.util.Arrays;

public class 全排列2 {
    public static void main(String[] args) {
        perm(new int[]{1,2,3},0,2);
    }

    private static void perm(int[] array, int start, int end) {
        if (start==end)
        {
            System.out.println(Arrays.toString(array));
        }
        else {
            for (int i = start; i <=end ; i++) {
//                eg.1,2,3全排列,相当于将其中一个提了出来,下次递归从start+1开始
                swap(array,start,i);
                perm(array,start+1,end);
//                复原数组,为了保证下次另外的同级递归使用数组不会出错
//                通过树来解释,每次回退一步操作,交换回去
                swap(array,start,i);
            }
        }
    }

    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

Java中的System.arraycopy()与Arrays.copyOf()的区别
System.arraycopy()

import java.util.Arrays;

```java
public class arraycopy {
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        int[] copied = new int[10];
        System.arraycopy(array,0,copied,1,5);
        System.out.println(Arrays.toString(copied));
        System.out.println(Arrays.toString(array));
    }
}

[0, 1, 2, 3, 4, 5, 0, 0, 0, 0]
[1, 2, 3, 4, 5]
Arrays.copyOf()
int[] copy = Arrays.copyOf(array,10);
System.out.println(Arrays.toString(copy));
copy = Arrays.copyOf(array,4);
System.out.println(Arrays.toString(copy));


不同之处在于Arrays.copyOf不仅复制元素,它还创建一个新数组。System.arraycopy()是复制到现有数组中。
Arrays.copyOf()的源代码,我们可以看到它使用System.arraycopy()

我习惯的方法

```java
import java.util.Arrays;

public class 全排列 {
    public static void swap(int[] array,int i,int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    public static void dfs(int[] array,int start,int end){
        if (start==end){
//            将排列后一整行的输出
            System.out.println(Arrays.toString(array));
        }
        else {
            for (int i = start; i <=end ; i++) {
//                以1,2,3为例
                swap(array,start,i);//因为i是取0,1,2的,所以先是123,213,312
                dfs(array,start+1,end);//这一步就是固定第一个元素之后,将第二个元素到最后一个元素进行排列
//                直到start等于end输出,反正就是后面两个元素交换位置
                swap(array,start,i);//回到最初的123,恢复现场

            }
        }
    }

    public static void main(String[] args) {
        int[] array = {1,2,3};
        dfs(array,0,2);
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值