网易编程题:数列还原

牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
输入描述:

每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。

输出描述:

输出一行表示合法的排列数目。

输入例子:

5 5
4 0 0 2 0

输出例子:

2

思路:首先将模糊的数字统计出来,并求出这些数字的全排列,然后分别求已有的序列的排列对和新增模糊数字的排序对,将两个结果相加,如果等于k,则结果加1。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

public class WangyiTest14 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int n = scanner.nextInt();
            int k = scanner.nextInt();
            int[] a = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = scanner.nextInt();
            }
            System.out.println(legalSortNum(n, k, a));
        }
    }

    public static int legalSortNum(int n, int k, int[] a) {
        int legalNum = 0;
        ArrayList<Integer> fuzzyNumList = new ArrayList<Integer>();
        boolean[] flag = new boolean[n + 1];
        // flag标记哪些数字已经存在
        for (int i = 0; i < n; i++) {
            if (a[i] != 0) {
                flag[a[i]] = true;
            }
        }
        // 统计排列中不存在的数字
        for (int i = 1; i <= n; i++) {
            if (flag[i] == false) {
                fuzzyNumList.add(i);
            }
        }
        // fuzzyNumLists 用来存模糊数字的全排列
        ArrayList<ArrayList<Integer>> fuzzyNumLists = new ArrayList<ArrayList<Integer>>();
        permutation(fuzzyNumLists, fuzzyNumList, 0);
        int curSortNum = 0;
        // 统计已有的排列的顺序对
        for (int i = 0; i < n - 1; i++) {
            if (a[i] != 0) {
                for (int j = i + 1; j < n; j++) {
                    if (a[j] != 0 && a[i] < a[j]) {
                        curSortNum++;
                    }
                }
            }
        }
        // 计算每个模糊数字排列的顺序对,加上已有的排列的顺序对,如果和k相等,则结果加1
        for (ArrayList<Integer> list : fuzzyNumLists) {
            int totalNum = curSortNum;
            int[] copyA = Arrays.copyOf(a, n);
            totalNum += fuzzySortNum(list, copyA);
            if (totalNum == k) {
                legalNum++;
            }
        }
        return legalNum;
    }

    // 计算添加模糊集到数列里面时增加的排序对
    public static int fuzzySortNum(ArrayList<Integer> list, int[] a) {
        int sortNum = 0;
        int count = 0;
        for (int i = 0; i < a.length; i++) {
            if (a[i] == 0) {
                a[i] = list.get(count++);// 每一个为0的位置 ,安插一个list中的模糊数字
                for (int j = 0; j < i; j++) {
                    if (a[j] != 0 && a[j] < a[i]) {
                        sortNum++;
                    }
                }
                for (int j = i + 1; j < a.length; j++) {
                    if (a[j] != 0 && a[j] > a[i]) {
                        sortNum++;
                    }
                }
            }
        }
        return sortNum;
    }

    // 计算全排列的函数(工具类)
    public static void permutation(ArrayList<ArrayList<Integer>> lists, ArrayList<Integer> list, int n) {
        if (n == list.size()) {
            lists.add(new ArrayList<Integer>(list));
        } else {
            for (int i = n; i < list.size(); i++) {
                Collections.swap(list, i, n);
                permutation(lists, list, n + 1);
                Collections.swap(list, i, n);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值