数列还原-网易python

题目描述
牛牛的作业薄上有一个长度为 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 个)。
输出描述:
输出一行表示合法的排列数目。
示例1
输入

5 5
4 0 0 2 0
输出

2

解析:

# 数列还原
# 原理:参考实例[4,0,0,2,0]
# 1)第一步,计算已知数子的对数sum1,即[4,2],0种;复杂度n^2
# 第二步,前提,首先列举出所有的未知数字的排列组合,保存起来;
# 以上的例子为:[(1, 3, 5), (1, 5, 3), (3, 1, 5), (3, 5, 1), (5, 1, 3), (5, 3, 1)]
# 选取其中一个组合为例(1, 3, 5),分别将三个数中的一个插入原数组中[4,0,0,2,0]
# 例如,第一次插入的是1,原数组变为[4,1,0,2,0]通过分别计算将1,与1左边的和右边的数字进行比较(即[4]和[2])
# 2)计算出(1, 3, 5)相应的对数,然后进行累加的sum2
# 判断sum1+sum2 == k?

# itertools用于字符串/数字的全排列,itertools.permutations("abc",3),输出结果为abc, acb, bac, bca, cab和cba。
# copy用于复制数组,python采用的是:如果参数可变就为引用传递,否则则是值传递。(列表list可变[],元组tuple不可变())
import itertools
import copy

n, k = map(int, input().split())

array = list(map(int, input().split()))

# 计算第一个值sum1
firstNum = 0;
for i in range(len(array)):
    if array[i] != 0:
        for j in range(i, len(array)):
            if array[j] != 0 and array[i] < array[j]:
                firstNum += 1

# unknownNum存储未知的数字
unknownNum = []
tempArray = [0 for i in range(0, n + 1)]
for i in array:
    if i != 0:
        tempArray[i] = 1
for i in range(1,n + 1):
    if tempArray[i] == 0:
        unknownNum.append(i)

# 计算每一个未知排列,所对应的数量sum2
def calvalue(list, arr):
    sum = 0
    j = 0
    for i in range(len(arr)):
        if arr[i] == 0:
            arr[i] = list[j]
            j += 1
            # 分别计算左右
            for k in range(i):
                if arr[k] != 0 and arr[k] < arr[i]:
                    sum += 1
            for k in range(i + 1, len(arr)):
                if arr[k] != 0 and arr[k] > arr[i]:
                    sum += 1
    return sum


# 存储所有的未知数的排列情况
unknownArray = list(itertools.permutations(unknownNum, len(unknownNum)))

result = 0
for x in range(len(unknownArray)):
    total = 0;
    temp = unknownArray[x]
    temp = list(temp)
    # 由于传的是直接引用,数组array的值会改变,所以需要深度(完全复制,不共享内存)复制
    temparr = copy.deepcopy(array)
    total = calvalue(temp, temparr) + firstNum
    if total == k:
        result += 1

print(result)


# 全排列函数permutation,需要使用递归来列举,也是一个知识点(参考网络)
# 除了使用模块,当然可以自己写一个函数来实现:
# def permutation(xs):   #简化问题,假定形参xs是列表
#     if len(xs) == 0 or len(xs) == 1:
#         return [xs]
#     result = []
#     for i in xs:
#         temp_list = xs[:] #对xs进行切片操作,使得temp_list的值和xs一样 但是temp_list的改变不影响xs
#         temp_list.remove(i)
#         temp = permutation(temp_list) #使用递归 生成删掉一个元素的xs的全排列
#         for j in temp:   #对temp中的每一项再进行遍历
#             j[0:0] = [i]   #在index 0 的位置插入之前删去的i
#             result.append(j)
#     return result
#
# 这个函数就可以对列表内的元素进行全排列。
# permutation([0,1,2])得到[[0,1,2],[0,2,1],[1,0,2],[1,2,0],[2,0,1],[2,1,0]]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值