LeetCode刷题笔记(八)--- topK与简单动规

文章内容为LeetCode刷题笔记,如发现错误请多多指教

23、数组中出现次数超过一半的数字:数组使用,简单算法的设计

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
在这里插入图片描述
这个题是比较简单的,可以有三种思路:
1、定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数。
2、将数组排序,那么超过数组大小一半的数字肯定在数组中间位置,然后统计该数字的次数是否符合要求
3、目标条件:目标数据超过数组长度的一半,那么对数组,我们同事去掉两个不同的数字,到最后剩下的一个数就是该数字,如果剩下两个,那么这两个也是一样的,就是结果,在其基础上把最后剩下的一个数字或者两个返回到原来数组中,遍历数组检查该数字出现的次数进行最终判断。

//思路一:使用hash表
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int,int> map;
        int half=nums.size()/2;
        for(int i=0;i<nums.size();i++){
            auto it=map.find(nums[i]);
            //如果找到了,那么就进行自增,如果不在那么就是首次出现,插入
            if(it!=map.end()){
                map[nums[i]]++;
            }
            else map.insert(make_pair(nums[i],1));
            //走到这里说明对应的key值一定存在,进行判定
            if(map[nums[i]]>half){
                return nums[i];
            }
        }
        return 0;
    }
};
//思路二,排序方式
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int size=nums.size();
        int count=0;
        sort(nums.begin(),nums.end());
        for(int i=0;i<size;i++){
            if(nums[i]==nums[size/2]){
                count++;
            }
        }
        if(count>(size/2)){
            return nums[size/2];
        }
        return 0;
    }
};
//思路三:不同数字抵消方式求解
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        if(nums.size()<0) return 0;
        int time =1;//time决定了当前number可以抵消几次不同数字
        int number=nums[0];
        for(int i=1;i<nums.size();i++){
            //当time等于0的时候,说明两个数字不同且都抵消了
            if(time==0){
                number=nums[i];
                time=1;
            }
            //如果相同就让当前number与后面数字多抵消一次
            else if(nums[i]==number){
                time++;
            }
            else{
                time--;
            }
        }
        //到这一步,number就是我们要找的数字,但是还需要验证一下他出现的次数是否符合条件
        int count=0;
        for(int i=0;i<nums.size();i++){
            if(nums[i]==number){
                count++;
            }
        }
        return count>nums.size()/2 ? number:0;
    }
};

24、最小的K个数:topK问题

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
在这里插入图片描述
这个问题有多种思路,首先可以先排序,然后输出k个数,但是这个可能会比较慢,我们可以选择最大堆的方法来解决这个问题,具体思路是:首先建立一个最大堆,采用优先队列的容器来实现这个最大堆,那么我们先输入k个数,这k个数会在堆里降序排列(因为最大堆根节点是最大的嘛),当再有数来时,让它和队头进行比较,如果比队头的元素值小,那么pop(队头),push(该值),遍历一遍数组,就完成了对比arr[k]值大的元素的提出,剩下的就是前topK个元素

struct comp{
    bool operator()(const int &a,const int &b){
        return a<b;//我们需要最大堆,所以选择降序排序
    }
};
class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        vector<int> list;
        if(arr.size()==0||k<=0||k>arr.size()){
            return list;
        }
        priority_queue<int,vector<int>,comp> queue;//采用容器优先级队列实现最大堆
        for(int i=0;i<arr.size();i++){
            if(i<k){
                queue.push(arr[i]);
            }
            else{
                if(arr[i]<queue.top()){
                    queue.pop();
                    queue.push(arr[i]);
                }
            }
        }
        for(int i=0;i<k;i++){
            list.push_back(queue.top());
            queue.pop();
        }
        return list;
    }
};

25、连续数组的最大和:简单动规问题

输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。
在这里插入图片描述
这个题我们可以用动规的方法来解决,让输入的数组每个值为以这个值结尾的连续数组的最大值,举个例子,就拿上面的数组来说,nums[1]=1,转换完成之后nums[1]还为1,因为以nums[1]结尾的最大连续数组值为一。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int maxNum=nums[0];
        for(int i=1;i<nums.size();i++){
            //让nums[i]永远是以nums[i]结尾的连续数组的最大值
            if(nums[i-1]+nums[i]>nums[i]){
                nums[i]=nums[i-1]+nums[i];
            }
            maxNum=max(maxNum,nums[i]);
        }
        return maxNum;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值