1. 数据结构与算法-计算排行榜和礼物数量
实际问题
问题:某个时间段内,直播间礼物数前十的房间获得奖励,需要在每个房间展示礼物数排行榜。
解决方法: 礼物数量存储在 Redis-zset 中,使用skiplist 使得元素整体有序;使用Redis 集群,避免单机压力过大,使用主从算法、分片算法; 保证集群原信息的稳定,使用一致性算法; 后端使用 缓存算法(LRU)降低Redis 压力,展示房间排行榜;
排序算法
最快的排序算法:
Python-timsort C++-introsort Rudst-pdqsort
Go: Go(<=1.18)-introsort
Go 1.19:
2. 经典排序算法
1)插入排序 Insertion Sort
将元素不断插入已经排序好的array 中;起始只有一个元素5,其本身就是一个有序序列,后续元素插入到有序序列中,即不断交换,直到找到第一个比其小的元素;
class Solution: def sortArray(self, nums: List[int]) -> List[int]: n = len(nums) if not nums or n==0: return [] for i in range(1,n): preIndex = i-1 current = nums[i] while preIndex >= 0 and nums[preIndex] > current: nums[preIndex + 1] = nums[preIndex] preIndex = preIndex - 1 nums[preIndex + 1] = current return nums
算法特性
时间复杂度(最好): O ( n ) O(n) O(n); 时间复杂度(最坏): O ( n 2 ) O(n^2) O(n2); 时间复杂度(平均): O ( n 2 ) O(n^2) O(n2); 空间复杂度: O ( 1 ) O(1) O(1); 稳定性:稳定;
最佳情况:T(n) = O(n) 最坏情况:T(n) = O(n2) 平均情况:T(n) = O(n2);
一般来说,插入排序都采用in-place在数组上实现。 具体算法描述如下:
从第一个元素开始,该元素可以认为已经被排序; 取出下一个元素,在已经排序的元素序列中从后向前扫描; 如果该元素(已排序)大于新元素,将该元素移到下一位置; 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置; 将新元素插入到该位置后; 重复步骤2~5。
2)快速排序 Quick Sort
分治思想,不断分隔序列知道序列整体有序;选定一个 pivot (轴点),使用 pivot 分割序列,分成元素比 pivot 大和元素比 pivot 小的两个序列;
快速排序(Quicksort)是对冒泡排序的一种改进算法。由C. A. R. Hoare在1960年提出。该算法使用广泛、效率很高,是最重要的排序算法之一;
实现方法:
在数组中选一个基准数(通常为数组第一个);将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边;对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序;
也就是:
通过多次比较和交换来实现排序,在一趟排序中把将要排序的数据分成两个独立的部分,对这两部分进行排序使得其中一部分所有数据比另一部分都要小,然后继续递归排序这两部分,最终实现所有数据有序。
首先设置一个分界值也就是基准值也称为监视哨,通过该分界值将数据分割成两部分;将大于或等于分界值的数据集中到右边,小于分界值的数据集中到左边;一趟排序过后,左边部分中各个数据元素都小于分界值,而右边部分中各数据元素都大于或等于分界值,且右边部分各数据元素皆大于左边所有数据元素;然后,左边和右边的数据可以看成两组不同的部分,重复上述1和2步骤,当左右两部分都有序时,整个数据就完成了排序;
3)堆排序 Heap Sort
利用堆的性质形成的排序算法;构造一个大顶堆,将根节点(最大元素)交换到最后一个位置,调整整个堆,如此反复;
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字;对于一个小顶堆,若在输出堆顶的最小值之后, 使剩余n-1个元素的序列再次筛选形成一个堆,再输出次小值,由此反复进行,便能得到一个有序的序列,这个过程就称之为堆排序。
4)Benchmark
根据序列元素排列情况划分:
完全随机的情况 (random) ;
有序/逆序的情况 (sorted/reverse) ;
元素重复度较高的情况 (mod8) ;
在此基础上,还需要根据序列长度的划分 (16/128/1024)