re-arrange 数组问题汇总

来源:互联网 发布:淘宝上的司法拍卖电器 编辑:程序博客网 时间:2024/06/06 06:56

这类问题的特征就是重新组织数组元素

1排序

注意几种特殊的排序问题(主要就是key-indexed sort)

1)元素值范围和下标是对应的且连续且没有重复(即元素取值是[0,n))则直接桶排序in place、O(n) 就可以排好序。

2 )元素值范围是下标域的子集且连续,可以有重复(即元素取值是[0,k],连续,k<=n),是第一种情况的一般化。也可以桶排序思想+计数排序思想 in place, O(n)的排好序

思想是:用元素值的桶作为该值的计数器,即counting sort中 count 数组和 原数组合二为一,即是数据数组又是key indexed counting 数组。区分就计数器用负数,负数就是计数器,正数是key,0则表示这个位置上的数据已经count了所以清除了。


2 shuffle

思路一:不变式是[0, i-1]里的元素是均匀分布的,加进a[i]后,[0, i]里的元素也是均匀分布的,处理的方式是随机从[0, i]位置选一个,和a[i]上的数交换

思路二:不变式是原数组的每个元素在[0, i-1]中每个位置出现的概率是相同的,加进位置i后,原数组每个元素在i上出现的概率是相同的,处理的方式是等概率的从剩下的数[i, n)里选一个数放到位置i 

3 partition (2 way, 3 way, k way)

2 way:

逻辑: [0,i]是partition 1,(i, j) 是 partition 2, [j, end]是 未处理部分。

当一个新元素a[j]进来,如果属于partition 1 就和a[++i]交换,这样,partition 1增长了1,partition 2 shift了一下,(头放到尾后面);如果属于partition 2 则自然append在partition 2后面,什么也不用做。

3 way:

逻辑:[0,i]是partition 1,(i, j)是partition 2,[j, k)是未处理部分,[k, end]是partition 3。

当一个新元素a[j]进来,如果属于partition 1 则 和 a[++i]交换,j++处理下一个;如果属于partition 2则自然append到partition 2,不用做什么,j++处理下一个;如果属于partition 3则和a[--k]交换,第3情况相当于a[j]上又来了一个新的数,所以j不前进,继续处理这个数。循环终止条件是j 和 k相遇。

 k way:

桶排序思想和计数排序思想结合,即1. 2)问题

4 interleave (奇偶partition)

interleave就暗示了奇偶。问题的实质就是将一个partition放在偶数下标位,另一个partition放在奇数下标位。

先扫一遍以确定哪个partition在偶数下标位,哪个partition在奇数下标位 :个数多的那个partition在偶数下标位(先开始)。双指针,一个管偶数下标位,一个管奇数下标位,分别定位到不满足partition条件的位置,交换。步长都是2。

def rerange(self, A):        num, n =0, len(A)        for e in A:            if e<0: num += 1        i, j = (0, 1) if num >= n-num else (1, 0)        while i < n and j < n:            while i < n and A[i] < 0: i += 2            while j < n and A[j] > 0: j += 2            if i < n and j < n: A[i], A[j] = A[j], A[i]        return A


3 错排

输入是一个具体排列,求所有元素都不在自己起始位置上的排列总数。

递推公式:D(n) = (n-1) * (D(n-2) + D(n-1))

0 0