• 递归实现排列型枚举


    题目描述

    1~n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。

    输入格式

    一个整数n。

    输出格式

    按照从小到大的顺序输出所有方案,每行1个。

    首先,同一行相邻两个数用一个空格隔开。

    其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。

    数据范围

    1(leq) n (leq) 9

    输入样例

    3

    输出样例

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

    思路

    我们尝试用递归的方式解决:先输出所有以1开头的排列(这一步是递归调用),然后输出以2开头的排列(又是递归调用),接着是以3开头的排列······最后才是以n开头的排列。
    以1开头的排列的特点是:第一位是1,后面是2~9的排列。根据字典序的定义,这些2~9的排列也必须按照字典序排列。不过需要注意的是,在输出时,每个排列的最前面要加上1。这样一来,所设计的递归函数需要以下参数:

    • 已经确定的“前缀”序列,以便输出。
    • 需要进行全排列的元素集合,以便依次选做第一个元素。

    因此我们可以得到下面的递归函数:

    void dfs(int u,int ans)
    {
        if(ans==n)//递归边界
        {
            for(int i=0;i<n;i++)
            cout<<stu[i]<<" ";
            cout<<endl;
            return;
        }
        
        int i=1,j=1;
        for(i=1;i<=n;i++)  //尝试在stu[u]中填写各种整数i
        {
            for(j=0;j<ans;j++)
            {
                if(stu[j]==i)//如果i已经在stu[0]~stu[u-1]出现过,则不能再选
                {
                    break;
                }
            }
            if(j==ans)
            {
                 stu[ans]=i;
                 dfs(i,ans+1);//递归调用
            }
        }
        
    }
    

    循环变量i是当前考察的stu[ans]。为了检查元素i是否已经用过,我们需要内层循环中加入一个判断,如果发现有某个stu[j] == i时,则break(跳出内层循环)。如果最终j == ans,则说明i没有在序列中出现过,把它添加到序列末尾后递归调用。

    递归C++ 代码

    #include<iostream>
    using namespace std;
    int n;
    int stu[10];
    void dfs(int u,int ans)
    {
        if(ans==n)//递归边界
        {
            for(int i=0;i<n;i++)
            cout<<stu[i]<<" ";
            cout<<endl;
            return;
        }
        
        int i=1,j=1;
        for(i=1;i<=n;i++)  //尝试在stu[u]中填写各种整数i
        {
            for(j=0;j<ans;j++)
            {
                if(stu[j]==i)//如果i已经在stu[0]~stu[u-1]出现过,则不能再选
                {
                    break;
                }
            }
            if(j==ans)
            {
                 stu[ans]=i;
                 dfs(i,ans+1);//递归调用
            }
        }
        
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>n;
        dfs(1,0);
        return 0;
    }
    

    递归Java代码

    import java.util.Scanner;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    
    public class Main {
        static int[] stu=new int[10];
        static int[] vis=new int[10];
        static int n;
        static PrintWriter out = new PrintWriter(System.out);
    	public static void main(String[] args) {
    		// TODO 自动生成的方法存根
            
            Scanner sc=new Scanner(System.in);
            n=sc.nextInt();
            dfs(1,0);
            out.flush();
    	}
        public static void dfs(int u,int ans)
        {
        	if(ans==n)//递归边界
            {
                for(int i=0;i<n;i++)
                out.print(stu[i]+" ");
                out.println();
                return;
            }
            
            int i=1,j=1;
            for(i=1;i<=n;i++)  //尝试在stu[u]中填写各种整数i
            {
            	if(vis[i]==0)
                {
            	 vis[i]=1;
                     stu[ans]=i;
                     dfs(i,ans+1);//递归调用
                     vis[i]=0;
                }
            }
        }
    }
    
    
    
  • 相关阅读:
    decode(解码)与encode(编码)——python
    Appium环境准备(二)
    cannot bind to 127.0.0.1:5037解决方法
    使用adb命令获取包名
    cookie的弊端
    jquery点击弹出一个页面+点击X可关闭的部分
    实现AJAX的异步交互的步骤
    HTML5,jQuery,ajax基础面试
    js 基础面试题
    JavaScript,DOM经典基础面试题
  • 原文地址:https://www.cnblogs.com/Acapplella/p/13558356.html
Copyright © 2020-2023  润新知