刷题笔记:力扣第169题-多数元素

1.本题最不动脑子的做法便是设置一个哈希表,遍历数组的同时给元素对应位置的哈希表值+1,同时判断该值是否大于numsSize / 2,可写出完整代码如下:

cpp 复制代码
 1. int majorityElement(int* nums, int numsSize) {
 2.     int hash[2000000001] = {0};
 3.     for (int i = 0; i < numsSize; i++){
 4.         hash[nums[i] + 1000000000]++;
 5.         if (hash[nums[i] + 1000000000] > numsSize / 2){
 6.             return nums[i];
 7.         }
 8.     }
 9.  
10.     return nums[0];
11. }

该算法在逻辑上完全没有问题,但因为要考虑题目给出的元素数据范围为"-10^9 ~ 10^9",设置的哈希表范围也非常大,在该函数的栈上存不下这么多数据,会导致栈溢出,无法通过力扣的本地测试。该算法时间复杂度为O(n),空间复杂度为O(m),m为数据范围。

2.当题目保证一定存在出现次数大于n/2的元素时,就可以使用摩尔投票法。记录当前元素的值num_cur,这个值可以理解为擂主,出现一次相同的值就将计数值+1,反之则-1。当计数值减为负数,擂主就换成当前元素,因为最终出现次数大于n/2的元素一定会站在擂台最后,其他所有元素的出现次数和都小于它的次数。

3.基于以上思想,可写出完整代码如下:

cpp 复制代码
 1. int majorityElement(int* nums, int numsSize) {
 2.     // cur_num:摩尔投票的候选数;cnt:候选的计票
 3.     int cur_num = nums[0];
 4.     int cnt = 1;
 5.     // 从第2个元素开始遍历数组
 6.     for (int i = 1; i < numsSize; i++){
 7.         if (nums[i] == cur_num){
 8.             // 当前元素等于候选,票数+1
 9.             cnt++;
10.         } else {
11.             // 当前元素不等于候选,票数抵消-1
12.             cnt--;
13.             // 票数小于0,说明候选被抵消完,更换新候选,新候选票数初始化为1
14.             if (cnt < 0){
15.                 cnt = 1;
16.                 cur_num = nums[i];
17.             }
18.         }
19.     }
20.     return cur_num;
21. }

该算法时间复杂度为O(n),空间复杂度为O(1)。

4.非常神奇的一点是,如果将票数判断条件从cnt < 0改为cnt == 0,本题依然是正确的。按照正常的理解来说,这会导致新的元素被多算了一次,但实际上的逻辑为:

(1)如果是虚假的多数元素被推翻,那么真正的多数元素即使多加了1次仍然是多数,不影响。

(2)如果是真正的多数元素被暂时推翻,少数元素多加了1次,但因为多数元素一定严格大于其他所有元素的次数和,也就是至少大于1,所以它一定能卷土重来,推翻现在的少数元素擂主,之后它也多加了1次,将这个差距补回来了。

本质上只是凑巧对了,实际解题过程中还是应该使用cnt < 0这种正常逻辑。

5.本题题解给了非常多的解法,包括但不限于:

(1)哈希表

(2)摩尔投票法

(3)排序法,下标为n/2的元素一定是答案

(4)随机化法,随机挑选一个元素来验证它是不是答案

(5)分治法

从复杂度角度来说,还是摩尔投票法是本题最优解。

相关推荐
罗湖老棍子9 小时前
【例 1】Sightseeing Trip(信息学奥赛一本通- P1494)(洛谷-P10927)
数据结构·算法·图论·最短路·floyd·最小环
文丑颜不良啊10 小时前
LeetCode201~225题目解析
java·leetcode
stsdddd12 小时前
YOLO算法建筑工地安全帽目标检测数据集16881张:标注核对笔记
算法·yolo·目标检测
CV爱数码12 小时前
论文精读|Learned Primal-Dual:把原始–对偶算法展开成网络
图像处理·算法·计算机视觉·ct·重建·断层扫描
yuniko-n13 小时前
【算法】约瑟夫环问题
java·算法
l1t13 小时前
测试DuckDB v2.1.0-alpha49002的bignum乘法
数据库·sql·算法·duckdb
Swilderrr13 小时前
论文精读:《Directory-Aware Query and Maintenance in Vector Databases》
笔记·学习
SatanII13 小时前
K8s 存储与配置管理|Volume、ConfigMap、Secret 核心笔记
笔记·rpc·kubernetes
Nil20813 小时前
LeetCode 283移动零
数据结构·算法·leetcode
CQU_JIAKE13 小时前
10.18【A】
算法