ACWing--排列数字

159 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

给定一个整数 n,将数字 1∼n

排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

输入格式

共一行,包含一个整数 n

输出格式

按字典序输出所有排列方案,每个方案占一行。

数据范围

1≤n≤7

输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

二、思路分析:

  1. 这一题从题目上看是一个全排列的问题,我们可以利用DFS来解决这个问题

    具体解题思想为:

    例如:n = 3

    1. 预留n个空位用以填数字。 _ _ _
    2. 先列出第一个位置的所有可能。1 _ _ 和 2 _ _ 和 3 _ _
    3. 在以第一种情况的前提下去列出第二个位置的所有可能。1 2 _ 和 1 3 _
    4. 同样再填第3个位置。
    5. 直到位置填完输出排列后的情况,回溯。

    如图:

    截屏2022-03-08 下午9.47.59

  2. 这一题的容易错误的地方:

    for (int j = 1; j <= N; j++) {
        if(!visted[j]){
          dfs(i,j);
          visted[j] = false; 
        }
    }
    

    完整的输出一个数组后,回溯时要把数字设置为未访问状态。可以看做把位置再空出来。

三、AC 代码:

import java.util.Scanner;

public class PaiLieSZ {
    public static int N = 0;
    public static int [] num = null;
    public static boolean[] visted = null;
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        N = scan.nextInt();
        num = new int[N];
        visted = new boolean[N + 1];
        
        for (int j = 1; j <= N; j++) {
        
            dfs(0, j);
            visted = new boolean[N + 1];
        }
        
        scan.close();
    }
    public static void dfs(int i,int x){
        if( i == num.length -1 ){
            num[i] = x;
            for (int j = 0; j < num.length; j++) {
                System.out.print(num[j]);
            }
            System.out.println("");
            return;
        }
        if(visted[x]){
            
            return;
        }
        num[i] = x;
        visted[x] = true;
        i++;
        for (int j = 1; j <= N; j++) {
            if(!visted[j]){
                dfs(i,j);
                visted[j] = false; 
            }
        }
    }
}

四、总结:

要灵活转化思维,把全排列问题转化为DFS问题去解决、