从 JOIN 到 join-on-demand,深入理解 ABAP CDS Association 与 Composition
2026/10/8 14:29:04
给定一个大小为n nn的整数数组,找出数组中所有出现次数超过⌊ n / 3 ⌋ \lfloor n/3 \rfloor⌊n/3⌋的元素。
进阶约束:要求算法时间复杂度为O ( n ) O(n)O(n),空间复杂度为O ( 1 ) O(1)O(1)。
示例
nums = [3,2,3],输出:[3]nums = [1],输出:[1]nums = [1,2],输出:[1,2]结合题目要求与数学性质,提炼问题核心特征:
| 解法方案 | 时间复杂度 | 空间复杂度 | 弃选原因 |
|---|---|---|---|
| 哈希表统计 | O ( n ) O(n)O(n) | O ( n ) O(n)O(n) | 无法满足O ( 1 ) O(1)O(1)空间约束 |
| 排序遍历 | O ( n log n ) O(n\log n)O(nlogn) | O ( log n ) O(\log n)O(logn) | 排序带来非线性时间开销,效率更低 |
| 暴力枚举 | O ( n 2 ) O(n^2)O(n2) | O ( 1 ) O(1)O(1) | 时间复杂度过高,无法通过大数据量测试 |
本题属于固定比例众数查找题型,是摩尔投票法的标准应用场景,具备明确的题型模板:
触发信号:题目出现「固定比例众数+线性时间+常数空间」组合约束时,优先选择摩尔投票法。
摩尔投票法分为投票筛选候选和验证候选有效性两个核心阶段,缺一不可:
初始化两个候选值candidate1/candidate2、两个计数器count1/count2,初始计数器置为0。
遍历数组中的每个元素num,执行以下逻辑:
candidate1,对应计数器count1++;candidate2,对应计数器count2++;count1 == 0,将当前元素赋值给candidate1,并重置count1 = 1;count2 == 0,将当前元素赋值给candidate2,并重置count2 = 1;投票阶段仅能筛选出潜在候选,无法保证一定满足次数要求,因此需要二次遍历数组,统计两个候选值的真实出现次数,筛选出次数严格大于n / 3 n/3n/3的元素作为最终结果。
#include<vector>usingnamespacestd;classSolution{public:vector<int>majorityElement(vector<int>&nums){intn=nums.size();// 初始化候选值与计数器intcandidate1=0,candidate2=0;intcount1=0,count2=0;// 第一步:摩尔投票,筛选潜在候选元素for(inti=0;i<n;++i){intnum=nums[i];if(candidate1==num){count1++;}elseif(candidate2==num){count2++;}elseif(count1==0){// 替换空候选位candidate1=num;count1=1;}elseif(count2==0){// 替换空候选位candidate2=num;count2=1;}else{// 不同元素相互抵消计数count1--;count2--;}}// 重置计数器,统计候选值真实出现次数count1=0,count2=0;for(inti=0;i<n;++i){intnum=nums[i];if(candidate1==num)count1++;elseif(candidate2==num)count2++;}vector<int>ans;// 独立判断,支持同时存入两个有效结果if(count1>n/3)ans.push_back(candidate1);if(count2>n/3)ans.push_back(candidate2);returnans;}};if判断,支持同时返回两个符合条件的元素。算法对数组进行两次线性遍历,单次遍历时间开销为O ( n ) O(n)O(n),总时间复杂度为O ( n ) \boldsymbol{O(n)}O(n),n nn为数组长度。
仅使用常数个局部变量,无随输入规模增长的额外存储空间,结果集不计入算法空间复杂度统计,总空间复杂度为O ( 1 ) \boldsymbol{O(1)}O(1)。
else if,否则会丢失第二个有效结果;