牛客刷题日记【数组中出现次数超过一半的数字|数组中只出现一次的两个数字|缺失的第一个正整数】

BM51 数组中出现次数超过一半的数字

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

思考:

这道题目有多种处理方式,

  1. 用空间换时间的方法,
  2. 先排序,然后直接返回中位数
  3. 用投票法,进行两两抵消

代码:

空间换时间

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型vector 
     * @return int整型
     */
    int MoreThanHalfNum_Solution(vector<int>& numbers) {
        // write code here

        int a[50001];

        for (int i = 0;i < numbers.size();i++) a[numbers[i]]++;

        for (int i = 0;i < 50001;i++)   if (a[i] > numbers.size()/2) return i;

        return 0;
    }
};

排序

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型vector 
     * @return int整型
     */
    int MoreThanHalfNum_Solution(vector<int>& numbers) {
        // write code here

        sort(numbers.begin(), numbers.end());

        return numbers[numbers.size()/2];
    }
};

投票法

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型vector 
     * @return int整型
     */
    int MoreThanHalfNum_Solution(vector<int>& numbers) {
        // write code here

        int num = 0;
        int cond = -1;

        for (int i = 0;i < numbers.size();i++)
        {
            if (num == 0) {
                cond = numbers[i];
                num = 1;
            }
            else {
                if (numbers[i] == cond) num++;
                else num--;
            }
        }

        return cond;
    }
};

BM52 数组中只出现一次的两个数字

一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思考:

这次给的数组大小是1000000,用空间换时间会炸内存,所以用其他两种解法。

  1. 排序法
  2. 异或运算法

代码:

排序后处理

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型vector
     */
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        // write code here

        sort(nums.begin(), nums.end());

        int d = nums[0];
        vector<int> res;
        if (nums[0] != nums[1]) res.push_back(nums[0]);

        for (int i = 1;i < nums.size()-1;i++)
        {
            if (nums[i] != nums[i+1] && nums[i] != nums[i-1]) {
                res.push_back(nums[i]);
            }
        }

        if (res.size() == 1) res.push_back(nums[nums.size()-1]);

        return res;

    }
};

异或运算法

对于异或运算,

https://blog.youkuaiyun.com/cuixianlong/article/details/90064348
这篇博客简单介绍了基础的性质和用法

因为a ^ b ^ c ^ b ^ c = a ,所以我们试着将整个数组拆分为两段,即满足a ^ b ^ c ^ b ^ c = a, e ^ b ^ c ^ b ^ c = e,这样就得到了两个不同的元素

对于整段运算,结果为a ^ e,只需要明白二者从哪一位开始不同,就能将其拆分为两段

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @return int整型vector
     */
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        // write code here

        vector<int> res(2, 0);

        int ab = 0;
        for (int i = 0;i < nums.size();i++) ab ^= nums[i];

        int k = 1; // 数位检测器
        while ((ab & k) == 0) {
            k <<= 1; // zuo移
        }

        for (int i = 0; i < nums.size();i++) {
            if (
                (nums[i] & k) == 0 
            ) res[0] ^= nums[i];
            else res[1] ^= nums[i];
        }

        sort(res.begin(),res.end());

        return res;
    }
};  

BM53 缺失的第一个正整数

给定一个无重复元素的整数数组nums,请你找出其中没有出现的最小的正整数

思路:

2^(31)−1不能开数组了,用map实现哈希表

代码:

class Solution {
public:
    int minNumberDisappeared(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int, int> mp;
        for(int i = 0; i < n; i++) 
            mp[nums[i]]++;
        
        
        int res = 1;
        while(mp.find(res) != mp.end()) 
            res++;
        
        return res;
    }
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值