zoukankan      html  css  js  c++  java
  • n个人排队都不站在原来的位置

    一、题目描述

    有n个人首先站成一排,请问,当n个人第二次再重新排列,每个人都不在原来的位置上,问有多少种站法。例如,原来有3个人,ABC,那么第二次每个人都不在原来的位置上有2种站法,BCA和CAB,这题其实是一道数学题,考察排列组合的知识。

    解题思路:假设有n个人,我们的问题规模设为A(n),A(n)代表n个人都不在原来的位置上一共有多少种站法。令第1个人站在非1号位置,一共有n-1种站法,假设第1个人站在2号位置,那么第2个人的站的位置分2类:第一类是第2个人站在1号位置,这样第1个人和第2个人的位置都确定了,那么剩下n-2个位置,问题规模变成了A(n-2),相当于第3个人不站在3号位置,第4个人不站在4号位置.....第n个人不站在n号位置第二类是第2个人不是站在1号位置,那么问题的规模又变成了A(n-1),相当于第2个人不站在1号位置,第3个人不站在3号位置,第4个人不站在4号位置......第n个人不站在n号位置。所以A(n) = (n-1) * ( A(n-1) + A(n-2) ),这样解题的思路就清晰了,只需要定义一个数组arr[n + 1],首先保存arr[1] = 0,arr[2] = 1,从arr[3]开始,迭代计算 arr[i] = (i - 1) * (arr[i - 1]  + arr[i - 2]),最后返回arr[n]就行了,也可以定义三个变量分别保存arr[1],arr[2],arr[3],然后交替赋值,这样能节省空间。为了清晰,我还是以定义数组来演示程序。

    二、代码演示

    /**
         * n个人原来站成一排,重新再排一次,要求每个人都不能
         * 站在原来的位置,求有多少种站法。
         * @param n 
         */
        public static int fun(int n) {
            if(n <= 1) return 0;
            if(n == 2) return 1;
            int[] arr = new int[n + 1];
            arr[1] = 0;
            arr[2] = 1;
            for(int i = 3; i <= n; i++) {
                arr[i] = (i - 1) * (arr[i - 1] + arr[i - 2]);
            }
            return arr[n];
        }
  • 相关阅读:
    java基础英语---第二天
    树莓派的版本
    Linux系统下安装.deb文件
    在Raspberry上安装ROS
    树莓派文件权限的转换
    树莓派中Linux的相关命令
    raspberry连接ssh和vnc
    链表的建立及释放
    一些小细节问题
    关于构建二维动态内存(堆)及释放
  • 原文地址:https://www.cnblogs.com/neuzk/p/9664631.html
Copyright © 2011-2022 走看看