re-arrange 数组问题汇总

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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值