蓝桥杯:排列问题

问题描述

小婷很生气,因为她不会做下面这道题,给定一个数组,现在需要你回答这个数组有多少个子序列是一个排列。

注意:子序列指的是原数组删除若干个数形成的新序列。

输入格式

第一行含有一个数字 n ,代表数组长度。

第二行含有 n 个数字,代表给定数组 a。

输出格式

输出一行一个数字,表示子序列个数。

样例输入

5
1 2 1 3 4

样例输出

8

解题思路

        首先,我们要理解什么是子序列以及什么是排列,子序列就是指对于一个序列,将他里面的元素删除若干个之后(也可以是0个)得到的新的序列,就叫原来序列的子序列;而排列,就是对于一个序列,能够将他排序之后变成从1~n的序列(中间不能缺少某个数,比如[2,1,3,4],它通过过排序之后可以变成[1,2,3,4],从1~4每个数都存在),那么原来的序列就叫做一个排列(我是这样理解的)。

        然后,我们就可以转换一种思维,对于通过排序后相同的不同的子序列(排列),它在原序列中存在的种类数仅有子序列中包含的每个元素的个数决定,比如说对于原序列为[1,2,1,3,4],它的一个子序列为[1,2],还有一个子序列为[2,1],这两个子序列通过排序后均可以变成[1,2]的序列,那我们就可以把他们看成是同一个序列的两个不同形式,他分别是通过原序列删除1(第三个1),3,4和删除1(第一个1),3,4得到,它的形式种类个数为2*1(1的个数乘以2的个数)。

        最后,理解了上一步,我们就可以通过遍历1~n来获取序列[1],[1,2],[1,2,3],······一直到[1,2,3,······,n]每个序列存在的种类数,再加起来就可以得到整个原序列的子序列是排列的个数。

        在输入信息的同时我们可以吧每个数的个数更新到l数组中,l数组里面存放的是从1~1000000(由于测试用例中最大的数没有超过这个数,我们就暂时设这么大的范围,如果对于更大的数,我们就需要增大范围),然后去循环变量i,i可以理解为是新的序列的长度,也可以理解为需要加入的数,两者意义差不多,这里我们可以使用一个sums来存储前面几个数的成绩,这样可以节省计算时间,再每次用counts累加起来的到新加入数i后的得到的更新后的符合条件的子序列个数,终止条件为l[i-1]!=0,表示新加入的这个数在原序列中不能不存在,也就是个数不能是0,否则就不符合是一个排列的条件。

java解题代码

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();

        long[] l = new long[1000000];
        for (int i = 0;i < n;i ++){
            int a = input.nextInt();
            l[a-1] += 1;
        }
        int counts = 0;
        int sums = 1;
        for (int i = 1;l[i-1] != 0;i ++){
            sums *= l[i-1];
            counts += sums;

        }
        System.out.println(counts);
    }
}

python解题代码

n = int(input())
lst = [0]*1000000
l = list(map(int,input().split()))
for i in l:
    lst[i-1] += 1

counts,sums = 0,1
for i in lst:
    if i == 0:
        break
    sums *= i
    counts += sums

print(counts)

你可能感兴趣的:(蓝桥杯,数据结构,职场和发展)