leetcode 169.Majority Element

这道题虽然简单,但适合用来练习各种解法。《剑指offer》5.2节 面试题29与此题一样,并且给出了leetcode官方题解未给出的快速选择的解法。

方法一、用哈希表解决

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int,int> count;
        int majority = 0;
        int cnt = 0;
        for(auto num:nums){
            count[num]++;
            if(count[num] > cnt){
                cnt = count[num];
                majority = num;
            }
        }
        return majority;
    }
};

方法二、先排序再取numsn/2

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int len = nums.size();
        srand(time(0));
        quick_sort(nums,0,len-1);
        return nums[len/2];
    }

    int partition(vector<int>& nums,int left,int right){
        if(left >= right)
            return left;
        int random = rand()%(right - left +1);
        swap(nums[left],nums[left + random]);
        int pivot = nums[left];
        while(left < right){
            while(left<right && pivot < nums[right]) right--;
            nums[left] = nums[right];  
            while(left<right && nums[left]<=pivot) left++;
            nums[right] = nums[left];
        }
        nums[left] = pivot;
        return left;
    }
    void quick_sort(vector<int>& nums,int left,int right){
        if(left>=right) return;
        int pivot_pos = partition(nums,left,right);
        quick_sort(nums,left,pivot_pos-1);
        quick_sort(nums,pivot_pos+1,right);
    }
};

方法三、快速选择

由于方法二可知,问题等价于求数组排好序后的第n/2个元素。那么由快速排序算法的思想,其实不用把整个数组排序结束,就可以找到排好序后的第n/2个元素,也就是快速选择算法。

这种解法,leetcode官方没有给出。

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        srand(time(0));
        return quick_select(nums,0,nums.size()-1,nums.size()/2);
    }

    int partition(vector<int>& nums,int left,int right){
        if(left >= right) return left;
        int random_pos = left + rand()%(right - left +1);
        swap(nums[left],nums[random_pos]);
        int pivot = nums[left];
        while(left<right){
            while(left<right && pivot <= nums[right]) right--;
            nums[left] = nums[right];
            while(left<right && nums[left] < pivot) left++;
            nums[right] = nums[left];
        }
        nums[left] = pivot;
        return left;
    }

    int quick_select(vector<int>& nums,int left,int right,int k){
        if(left>=right) return nums[left];
        int pivot_pos = partition(nums,left,right);
        if(pivot_pos == k)
            return nums[pivot_pos];
        else if(pivot_pos > k)
            return quick_select(nums,left,pivot_pos-1,k);
        else
            return quick_select(nums,pivot_pos+1,right,k);
    }
};

方法四、随机化方法

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        srand(0);
        int len = nums.size();
        int random = 0; 
        int cnt = 0;
        while(true){
            random = rand()%len;
            cnt = 0;
            for(auto num:nums){
                if(num == nums[random]){
                    cnt++;
                    if(cnt >len/2)
                        return num;
                }
            }
        }
    }
};

方法五、分治法

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        return divide_conquer(nums,0,nums.size()-1);
    }

    int divide_conquer(vector<int>& nums,int left,int right){
        if(left>=right)
            return nums[left];
        int mid = left + (right - left)/2;
        int majorityLeft = divide_conquer(nums,left,mid);
        int majorityRight = divide_conquer(nums,mid+1,right);
        if(majorityLeft == majorityRight)
            return majorityLeft;
        int cnt = 0;
        for(int i = left;i <= right;i++){
            if(nums[i] == majorityLeft){
                cnt++;
                if(cnt > (right - left +1)/2)
                    return majorityLeft;
            }
        }
        return majorityRight;
    }
};

方法六、Boyer-Moore投票法

《剑指offer》5.2节也给出了这种解法

cpp 复制代码
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int candidate = nums[0];
        int count = 1;
        for(int i = 1;i < nums.size();i++){
            if(nums[i] == candidate){
                count++;
            }else{
                count--;
                if(count == 0)
                {
                    candidate = nums[i];
                    count = 1;
                }
            }
        }
        return candidate;
    }
};
相关推荐
nvd115 小时前
LiteLLM 与 Redis 响应缓存机制:从精确哈希匹配到模型底层 KV-Cache 边界
redis·缓存·哈希算法
wabs6666 小时前
关于栈【力扣1047. 删除字符串中的所有相邻重复项的思考】
数据结构·c++·算法·leetcode··代码随想录
草莓熊Lotso9 小时前
【Redis 初阶】Hash 类型深度解析:结构化数据存储的最优解
linux·网络·数据库·redis·tcp/ip·缓存·哈希算法
evans在进步9 小时前
LeetCode 53 最大子数组和:一次遍历掌握 Kadane 算法
算法·leetcode·职场和发展
Nil20810 小时前
leetcode 230二叉搜索树中第k小的元素
算法·leetcode·职场和发展
旖旎夜光10 小时前
LeetCode 69:x 的平方根(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
学习星球10 小时前
【LeetCode算法题精讲】图算法精讲——从图遍历到拓扑排序
数据结构·算法·leetcode·图搜索
Nil2081 天前
leetcode 98验证二叉搜索树
算法·leetcode·职场和发展
时针滴滴答啊1 天前
最大子数组和
算法·leetcode·职场和发展
重生之后端学习1 天前
15. 三数之和[中等]✅
java·数据结构·算法·leetcode·职场和发展