【剑指 Offer】第 23 天

132 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、前言

刷题啊!!!

开始刷 “剑指 Offer” 31天。刷完时间:2022.3.6 ~ 2022.3.20。



二、题目

题目:

  • 数组中出现次数超过一半的数字
  • 构建乘积数组

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

题目描述


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

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2

限制:1 <= 数组长度 <= 50000

题解


这种方法蛮多的:

  1. 辅助 HashMap 来记录出现次数
  2. 排序
  3. 摩尔投票法:核心理念为:票数正负抵消

那么主要讨论摩尔投票法。

思路:若为众数,则 + 1; 若不为众数,则 -1;

因为众数,票数最后一定 > 0。

步骤如下:

  1. 若票数 votes 为 0, 则更新众数 x
  2. 若当前数等于 众数 x,则 +1; 反之 -1
  3. 最后找到了 x,但还要判断下这个 x 是否占大多数

AC 代码如下:

class Solution {
    // Time: O(n), Space: O(1), Faster: 99.97%
    public int majorityElement(int[] nums) {
        int x = 0, votes = 0;
        // 1. 找到 x
        for (int num : nums) {
            if (votes == 0) x = num;
            votes += num == x ? +1 : -1;
        }
        
        // 2. 判断是否众数
        int cnt = 0;
        for (int num : nums) {
            if (num == x) ++cnt;
        }
        
        return cnt > nums.length / 2 ? x : -1;
    }
}


(2)剑指 Offer 66. 构建乘积数组

题目描述


给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

示例:

输入: [1,2,3,4,5]
输出: [120,60,40,30,24]

提示:

  • 所有元素乘积之和不会溢出 32 位整数
  • a.length <= 100000

题解


思路:

  1. 初始化数组 BB[0] = 1, 辅助变量 tmp = 1
  2. 计算 B[i] 的下三角各元素的乘积
  3. 计算 B[i] 的上三角各元素的乘积,记为 tmp,同时乘入 B[i]

AC 代码如下:

class Solution {
    public int[] constructArr(int[] a) {
        int len = a.length;
        if(len == 0) return new int[0];
        int[] b = new int[len];
        b[0] = 1;
        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;

    }
}