leetcode典型算法题解析(虽然简单,绝对不凡)

1588. 所有奇数长度子数组的和

给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。

子数组 定义为原数组中的一个连续子序列。

请你返回 arr 中 所有奇数长度子数组的和 。

int sumOddLengthSubarrays(vector<int>& arr) {
    int res = 0;
    for(int i = 0; i < arr.size(); i ++){
        int left = i + 1, right = arr.size() - i,
        left_even = (left + 1) / 2, right_even = (right + 1) / 2,
        left_odd = left / 2, right_odd = right / 2;
        res += (left_even * right_even + left_odd * right_odd) * arr[i];
    }
    return res;
}

非常神奇,虽然我也知道不需要直接去统计每个序列的和,再求和,应该直接去计算元素出现的次数。但是始终没找到合适的算法公式来实现。

很简单的想法,把数组分成两个部分,前部分0~i-1,后部分i+1到最后。既然是奇数和,那前部分出现的序列长度的奇偶性跟后部分的奇偶性应该一样,这样(奇+奇)+1或者(偶+偶)+1的长度才是奇数,这样就统计了i出现的总的次数,一次遍历,求和,搞定,妙啊。

面试题 17.10. 主要元素

数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。

你有办法在时间复杂度为 O(N),空间复杂度为 O(1) 内完成吗?

想用排序的办法去解决的闷逼了吧,排序最快的也要nlogn,空间复杂度也有限制O(1),意味着你别想用字典来计数,哈哈。。

摩尔投票法:

    int majorityElement(vector<int>& nums) {
        if (nums.size() == 0) return -1;
        if (nums.size() == 1) return nums[0];
        int count = 0, num = -1;
        for (int c : nums) {
            //投票清零,统计新牛郎
            if (count == 0) {
                num = c;
                count++;
            }else {
                //“我”得一票
                if (c == num) count++;
                //我以外得一票(我减一票)
                else count--;
            }
        }

        count = 0;
        for (int c : nums) {
            if (c == num){
                count++;
            }
        }
        return count < nums.size()/2+1 ? -1 : num;
    }

话说世界上只有两种人,候选人摩尔跟其他人,只有摩尔超过半数才能得选。

摩尔得一票则加1,别人得一票则摩尔的票减1,如果摩尔的最终票数>0,则摩尔当选。注意问题是我并不知道摩尔是谁?

得票候选人数组里面去猜?如果默认票数为0,那就假定这个人是摩尔。如果票数归0了,意味着摩尔需要换人了,也可能是同一个人(得票数组有重复候选人,意味着得票多张)。

最终得到的摩尔是不是一定就超过半数呢?

不一定!

需要再统计一次,哈哈,第一次遍历只能证明,假如有人超过半数那一定是摩尔,但是不保证。

再次计数就能得出摩尔的真正票数。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值