首页 > 其他分享 >剑指offer——Day23 数学(简单)

剑指offer——Day23 数学(简单)

时间:2023-02-05 12:34:22浏览次数:34  
标签:votes nums int 题解 offer Day23 数学 数组 dp

Day23 2023.2.5 数学(简单)

剑指Offer 39. 数组中出现次数超过一半的数字

自己实现

因为考虑到这个数字起码有数组长度的一般那么多,那么如果把所有该数字放在一起,它势必会占据数组的中点,因此自己实现的方法就是将数组进行排序,然后直接返回排序后的数组中点即可

代码如下:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        return nums[nums.size()/2];
    }
};

代码表现

用排序就肯定有点慢了,看看题解

题解

方法一:数组排序法(就是自己实现的方法)
方法二:哈希表统计法:遍历数组,用HashMap统计各数字数量即可
方法三:摩尔投票法(下面详述)

摩尔投票法核心理念为票数正负抵消。此方法是本题的最佳解法

设输入数组nums的超过一半数量以上的数为x,数组长度为n

推论一:若记x的票值为+1,非x的票值为-1,则一定所有数字的票值和 > 0

推论二:若数组的前a个数字的票值和 = 0,则数组剩余(n-a)个数字的票值和一定仍然 > 0,即后(n-a)个数字的数量最多的数字仍为x

算法流程

  1. 初始化:票数统计votes=0,众数x
  2. 循环:遍历数组nums中的每个数字num
    1. 当票数votes等于0,则假设当前数字num是超过一半数量的数
    2. num=x时,票数votes自增1;反之,自减1
  3. 返回值:返回x即可

代码如下:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int x, votes=0;
        for(int num:nums){
            if(votes==0)x=num;
            votes+= (num==x?1:-1);
        }
        return x;
    }
};

代码表现

要快多了

hint

  • 其实这个还是用的一个排除的方法,将众数和非众数通过票数进行不断地抵消,最后剩下的一定就是那个众数。这样的思路可以用在占据超过一半容量的情况下,当然,也仅限于超过一半的情况下

剑指Offer 66. 构建乘积数组

自己实现

这个题目最难的要求就是不能使用除法,目前想到的方法就是直接暴力求解,这个肯定是不行的,直接看题解了

题解

题解给了一张图如下,看了就恍然大悟了

其实这就有动态规划的味道了,只是将动态规划蕴藏在了这个逐乘的过程中,而且其中包含了两个dp数组,分开维护最后再乘起来即可

题解用的是两个循环来做,自己参考这个表试试能不能一个循环做出来

但是必须要同时使用两个dp在同一个下标的结果才能得到B对应下标的值,一个循环好像有点勉强,看看参考

但其实一个循环和两次循环的时间消耗都是一样的,傻子……

只是一次循环的想法是,每一个下标的B值不是一次就要乘到位,先乘一边再等着乘另一边,给循环部分的代码作为参考:

for(int i = 0; i < len; i++){
        b[i] *= left;
        left *= a[i];           // 持有左边的所有数的乘积
        b[len - i - 1] *= right;
        right *= a[len -i - 1];  // 持有右边的所有数的乘积
}

而两次循环的代码如下:

class Solution {
public:
    vector<int> constructArr(vector<int>& a) {
        int len=a.size();
        vector<int> B(len,1);
        if(len==0)return B;
        int tmp=1;
        for(int i=1;i<len;i++){
            B[i]=B[i-1]*a[i-1];
        }
        for(int i=len-2;i>=0;i--){
            tmp*=a[i+1];
            B[i]*=tmp;
        }
        return B;
    }
};

代码表现

hint:

  • 还是用到了dp的思想,这种逐乘逐加的通常适配dp,当然,这个地方的另一要点就是将dp过程划分出两个dp数组来进行。
  • 其实dp很多时候需要的是二维的图示,光是看某一条(某个一维情况)很能看出来怎么用dp,就像这个题的题解,列出一个表,一看就知道是dp了,再结合这个地方被分裂成两个dp来做,就ok的。多沉淀

标签:votes,nums,int,题解,offer,Day23,数学,数组,dp
From: https://www.cnblogs.com/cspzyy/p/17093184.html

相关文章

  • 深度学习数学基础-概率与信息论
    前言概率论学科定义概率论是用于表示不确定性声明的数学框架。它不仅提供了量化不确定性的方法,也提供了用于导出新的不确定性声明(statement)的公理。概率论的知识在机器学......
  • 算法竞赛基础数学知识
    1、异或相同的数,异或结果为0,不同的数,异或结果为1.异或会用在nim博弈和一些数学中。可以找出n+1个数中,唯一一个与其他的数不同的数异或有个性质:一个数对另一个数异或两次,......
  • 【YBT2023寒假Day5 C】路径计数(数学)(生成函数)
    路径计数题目链接:YBT2023寒假Day5C题目大意有一个h*w的网格,你要从左上角走到右下角,每次可以向右或者向下,定义一条路径的分数是它经过的位置的权值和。每次会选择权......
  • 《剑指Offer》-58-Ⅱ-左旋字符串
    stringreverseLeftWords(strings,intn){ stringres; for(inti=n;i<s.size();i++)res.push_back(s[i]); for(inti=0;i<n;i++)res.push_back......
  • 《剑指Offer》-5-替换空格
    因为C++中的string本质上是一个静态数组,所以不能直接将长度1的空格直接替换为长度3的指定字符串也就是说要准备一个新的字符串才行 stringreplaceSpace(string......
  • 力扣-138-复杂链表的复制/剑指Offer-35-复杂链表的复制
    与复制普通链表的区别在于:多出了一个随机指针我们考虑下复制一个普通链表:遍历并复制节点i,让构造的他的上一个节点指向i看起来只需要2个指针,指针1指向当前构造的节点,指......
  • 剑指offer——Day22 位运算(中等)
    Day222023.2.4位运算(中等)剑指offer56-Ⅰ.数组中数字出现的次数自己实现就直接结合set进行遍历,然后出现重复就从set里面删除掉,最后就能得到只包含出现过一次的set......
  • codeforces 1047C. Enlarge GCD(数学)
    题意:给出n个数,求出最少删除几个数可以扩大最大公因子。AC代码:#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<set>#include<map>#includ......
  • 数学建模 —— 论文排版
    论文整体排版各级标题与正文层次分明一般标题级别不超过三级正文中文字体设置宋体,英文设置TimesNewRoman正文排版紧凑,看起来充实,没有大片空白避免图片过大导致......
  • 数学分析笔记【7】 实数完备性
    实数完备性实数完备性由六个等价的命题阐述。它们分别是:确界原理、单调有界定理、区间套定理、有限覆盖定理、聚点定理以及柯西收敛准则。证明它们等价的方法如下图:......