Task 03:数组排序(day4)

Task 03: 数组排序

第7天打卡,附上学习链接

1 学习内容

1.1 计数排序(Counting Sort)

使用一个额外的数组counts,其中第i个元素count[i]是待排序数组arr中值等于i的元素个数,然后根据数组counts来将arr中的元素排到正确的位置。

算法步骤:

  • (1)找出待排序数组中最大值元素和最小值元素;

  • (2)统计数组中每个值为i的元素出现的次数,存在数组的第i项;

  • (3)对所有计数累加(从counts中的第一个元素开始,每一项和前一项累加);

  • (4)反向填充目标数组:将每个元素i放在新数组的第counts[i]项,每放一个元素就要将counts[i] -= 1。

算法分析:

  • 当输入元素是n个0~k之间的整数时,计数排序的时间复杂度为O(n+k);

  • 由于用于计数的数组counts的长度取决于待排序数组中数据的范围(等于待排序数组最大值减去最小值再加1),所以计数排序对于数据范围很大的数组,需要大量的时间和内存;

  • 计数排序一般用于排序整数,不适用于按字母顺序排序人名;

  • 计数排序时稳定排序算法。

代码实现:

def countingSort(arr):
    arr_min, arr_max = min(arr), max(arr)
    size = arr_max - arr_min + 1
    counts = [0 for _ in range(size)]
    
    for num in arr:
        counts[num - arr_min] += 1
    for j in range(1, size):
        counts[j] += counts[j - 1]
    
    res = [0 for _ in range(len(arr))]
    for i in range(len(arr) - 1, -1, -1):
        res[counts[arr[i] - arr_min] - 1] = arr[i]
        counts[arr[i] - arr_min] -= 1
    
    return res  
1.2 桶排序(Bucket Sort)

将未排序的数组分到若干个桶中,每个桶的元素再进行单独排序。

算法步骤:

  • (1)将区间划分为n个相同大小的子区间,每个区间称为一个桶;

  • (2)遍历数组,将每个元素装入对应的桶中;

  • (3)对每个桶内的元素单独排序(使用插入、归并、快排等算法);

  • (4)最后按照顺序将桶内的元素合并起来。

算法分析:

  • 桶排序可以在线性时间内完成排序,当输入元素个数为n,桶的个数是m时,桶排序时间复杂度为O(m+n);

  • 由于桶排序使用了辅助空间,所以空间复杂度是O(n+m);

  • 如果桶内使用插入排序等稳定排序算法,则桶排序也是稳定排序算法。

代码实现:

def insertionSort(arr):
    for i in range(1, len(arr)):
        temp = arr[i]
        j = i
        while j > 0 and arr[j - 1] > temp:
            arr[j] = arr[j - 1]
            j -= 1
        arr[j] = temp
        
    return arr
    
    
def bucketSort(arr, bucket_size = 5):
    arr_min, arr_max = min(arr), max(arr)
    bucket_count = (arr_max - arr_min) // bucket_size + 1
    buckets = [[] for _ in range(bucket_count)]
    
    for num in arr:
        buckets[(num - arr_min) // bucket_size].append(num)
        
    res = []
    for bucket in buckets:
        insertionSort(bucket)
        res.extend(bucket)
    
    return res 
1.3 基数排序(Radix Sort)

将整数按位数切割成不同的数字,然后按每个位数分别比较进行排序。

算法步骤:基数排序算法可以采用最低位优先法(Least Significant Digit First)或者最高位优先法(Most Significant Digit first),最常用的是前者。

  • (1)遍历数组元素,获取数组最大值元素,并取得位数;

  • (2)以个位元素为索引,对数组元素排序;

  • (3)合并数组;

  • (4)之后依次以十位、百位...,直到最大值元素的最高位处值为索引,进行排序,并合并数组,最终完成排序。

算法分析:

  • 基数排序的时间复杂度是O(k*n),其中n是待排序元素的个数,k是数字位数。k的大小取决于数字位的选择(十进制位、二进制位)和待排序元素所属数据类型全集的大小;

  • 基数排序的空间复杂度是O(n+k);

  • 基数排序是稳定排序算法。

代码实现:

def radixSort(arr):
    size = len(str(max(arr)))
    
    for i in range(size):
        buckets = [[] for _ in range(10)]
        for num in arr:
            buckets[num // (10**i) % 10].append(num)
        arr.clear()
        for bucket in buckets:
            for num in bucket:
                arr.append(num)
            
    return arr

2 练习题目

2.1 1122 数组的相对排序 *

题目描述:给出两个数组arr1和arr2,arr2中的元素各不相同,arr2中的每个元素都出现在arr1中,对arr1中的元素进行排序,使arr1中项的相对顺序和arr2中的相对顺序相同。未在arr2中出现过的元素需要按照升序放在arr1的末尾。 样例1:输入为arr1=[2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19], arr2=[2, 1, 4, 3, 9, 6],输出为[2, 2, 2, 1, 4, 3, 3, 9, 6, 7, 19]。

解题思路:自定义排序。

class Solution:
    def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
        def mycmp(x: int) -> (int, int):
            return (0, rank[x]) if x in rank else (1, x)
        
        rank = {x: i for i, x in enumerate(arr2)}
        arr1.sort(key=mycmp)
        return arr1

时间复杂度:O(mlogm+n); 空间复杂度:O(logm+n)。

2.2 0908 最小差值I *

题目描述:一个整数数组nums,给每个元素都加上一个任意数字x(-k<=x<=k),从而得到一个新数组result。返回数组result的最大值和最小值之间可能存在的最小差值。 样例1:输入为nums=[1], k=0,输出0; 样例2:输入为nums=[0, 10],k=2,输出为6; 样例3:输入为num=[1, 3, 6],k=3,输出为0。

解题思路:求B最大与最小之间的最小差值,希望的是max(B)更小,min(B)更大。max(B)最小的极 限值是max(A)-k,min(B)最大的极限值是min(A)+k,所以最小差值至少为(max(A)-k) - (min(A)+k)。

class Solution:
    def smallestRangeI(self, nums: List[int], k: int) -> int:
        return max(0, max(A)-min(A) - 2*k)

时间复杂度:O(n); 空间复杂度:O(1)。

2.3 0164 最大间距 ***

题目描述:给一个无序数组nums,要找出数组在排序之后,相邻元素之间最大的差值。如果数组元素个数小于2,则返回0。 样例1:输入为arr=[3, 2, 1], k=2,输出为[1, 2]或[2, 1]; 样例2:输入为arr=[0, 1, 2, 1], k=1,输出为[0]。

解题思路:基数排序,元素个数小于2的单独处理。

class Solution:
    def radixSort(arr):
        size = len(str(max(arr)))

        for i in range(size):
            buckets = [[] for _ in range(10)]
            for num in arr:
                buckets[num // (10**i) % 10].append(num)
            arr.clear()
            for bucket in buckets:
                for num in bucket:
                    arr.append(num)

        return arr
    
    def maximumGap(self, nums: List[int]) -> int:
        if len(nums) < 2:
            return 0
        arr = self.radixSort(nums)
        return max(arr[i] - arr[i-1] for i in range(1, len(arr)))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容