https://www.icourse163.org/learn/PKU-1001894005?tid=1450413466#/learn/content
程序设计与算法(二)算法基础
这里写目录标题
7617:输出前k大的数
# 7617:输出前k大的数
# http://noi.openjudge.cn/ch0204/7617
# 把a[left, right]中前k大的数放在右边
def FindMaxK(a, left, right, k):
if left - right + 1 == k:
return
key = a[left]
i = left
j = right
while i != j:
while (i < j and a[j] >= key): # 找到一个a[j]<key
j -= 1
a[i], a[j] = a[j], a[i]
while (i < j and a[i] <= key): # 找到一个a[i]>key
i += 1
a[i], a[j] = a[j], a[i]
if right - i + 1 == k: # 如果i及其右边的元素个数 == k
return
elif right - i + 1 > k: # 如果i及其右边的元素个数 > k
# 那么前k大的数在[i + 1, right]中
FindMaxK(a, i + 1, right, k)
else: # 如果i及其右边的元素个数 < k
# 那么前k大的数在[left, i - 1]中还有(k - (right - i + 1))个
FindMaxK(a, left, i - 1, k - (right - i + 1))
# 第一行包含一个整数n,表示数组的大小。n < 100000。
n = int(input())
# 第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。
# 每个整数的绝对值不超过100000000。
a = input().split()
for i in range(0, n):
a[i] = int(a[i])
# 第三行包含一个整数k。k < n。
k = int(input())
FindMaxK(a, 0, n - 1, k)
# print(a)
amaxk = a[n - k:]
amaxk.sort()
for item in reversed(amaxk):
print(item)
7622:求排列的逆序数
# 7622:求排列的逆序数
# http://noi.openjudge.cn/ch0204/7622/
# 如果左边>右边,那么就是一对逆序数
def Merge(Array, TempArray, left, middle, right):
#从大到小合并[left,middle], [middle+1,right]
ptmp = 0 # 从左开始归并
index1 = left # 左边子序列的起始位置
index2 = middle + 1 # 右边子序列的起始位置
while index1 <= middle and index2 <= right:
if Array[index1] > Array[index2]: # 取较大者插入合并数组中
TempArray[ptmp] = Array[index1]
ptmp += 1
index1 += 1
else:
TempArray[ptmp] = Array[index2]
ptmp += 1
index2 += 1
while index1 <= middle: # 只剩左序列,可以直接复制
TempArray[ptmp] = Array[index1]
ptmp += 1
index1 += 1
while index2 <= right:
TempArray[ptmp] = Array[index2]
ptmp += 1
index2 += 1
for i in range(0, right - left + 1): # 将数组暂存入临时数组
Array[left + i] = TempArray[i]
def Count(Array, left, middle, right):
# o(n)算有多少逆序是由左半边取一个数和右半边取一个数构成
# 要求[left,middle]和[middle+1,right]都是从大到小排列
result = 0
p1 = left
p2 = middle + 1
while (p1 <= middle and p2 <= right):
if (Array[p1] > Array[p2]): # 如果左边的 Array[p1] > 右边的 Array[p2]
result += (right - p2 + 1) # 那么左边的 Array[p1]和右边的[p2,right]都构成逆序数
p1 += 1
else:
p2 += 1
return result
# Array为待排序数组,left,right两端
def MergeSortAndCount(Array, TempArray, left, right):
result = 0
if left < right:
# 划为两个子序列[left,middle]和[middle+1,right]
middle = left + (right - left) // 2
result += MergeSortAndCount(Array, TempArray, left, middle) # 左
result += MergeSortAndCount(Array, TempArray, middle + 1, right) # 右
result += Count(Array, left, middle, right)
Merge(Array, TempArray, left, middle, right) # 对相邻的有序序列进行归并
return result
# 第一行是一个整数n,表示该排列有n个数(n <= 100000)。
n = int(input())
# 第二行是n个不同的正整数,之间以空格隔开,表示该排列。
Array = input().split()
for i in range(0, n):
Array[i] = int(Array[i])
print(MergeSortAndCount(Array, [0] * len(Array), 0, n - 1))