两道位运算 / 摩尔投票经典题复盘:只出现一次的数字 & 多数元素

前言

今天复盘两道 LeetCode 上的经典 "简单题",它们看起来容易,但解法里藏着非常巧妙的算法思想:一道是位运算的经典应用 ,另一道是摩尔投票算法的入门模板。这两道题不仅是面试高频考点,更是理解算法优化思路的绝佳案例。


一、136. 只出现一次的数字(简单)

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 要求:线性时间复杂度、常数额外空间。

核心思路:异或运算的妙用

这道题的 "黑科技" 解法,核心是利用异或运算的三个性质:

  1. a ^ a = 0:相同的数异或结果为 0
  2. a ^ 0 = a:任何数和 0 异或,结果不变
  3. a ^ b ^ a = b:异或运算满足交换律和结合律

所以,我们只需要把数组里的所有数从头到尾异或一遍,最终的结果就是那个只出现一次的数字 ------ 所有成对出现的数都会异或为 0,最后剩下的就是那个单独的数。

完整代码(Java)

java

运行

复制代码
class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for (int num : nums) {
            res ^= num;
        }
        return res;
    }
}

复杂度分析

  • 时间复杂度:O (n),只遍历一次数组
  • 空间复杂度:O (1),只用了一个变量存结果

拓展思考

如果题目改成 "其余元素出现三次,只有一个元素出现一次",就不能直接用异或了,需要用位统计的方法,但核心思路依然是利用位运算的特性。


二、169. 多数元素(简单)

题目描述

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊n/2⌋ 的元素。 要求:线性时间复杂度、O (1) 空间复杂度。

核心思路:摩尔投票算法

这道题的最优解是摩尔投票算法,它的核心思想可以理解为 "正负抵消":

  • 维护一个候选元素 candidate 和它的票数 count
  • 遍历数组:
    • 如果 count == 0,把当前元素设为新的候选
    • 如果当前元素等于候选,count++;否则 count--
  • 因为多数元素的出现次数超过一半,它在和其他元素 "抵消" 后,最终一定会成为剩下的候选。

完整代码(Java)

java

运行

复制代码
class Solution {
    public int majorityElement(int[] nums) {
        int candidate = nums[0];
        int count = 1;
        for (int i = 1; i < nums.length; i++) {
            if (count == 0) {
                candidate = nums[i];
                count = 1;
            } else if (nums[i] == candidate) {
                count++;
            } else {
                count--;
            }
        }
        return candidate;
    }
}

复杂度分析

  • 时间复杂度:O (n),只遍历一次数组
  • 空间复杂度:O (1),只用了两个变量

拓展思考

摩尔投票算法还可以拓展到 "找出数组中出现次数大于 n/3 的元素",最多有两个候选元素,需要两轮遍历:第一轮投票找出候选,第二轮验证是否真的满足条件。


两道题对比总结

表格

题目 核心思想 时间复杂度 空间复杂度 关键考点
只出现一次的数字 异或运算的性质 O(n) O(1) 位运算、交换律结合律
多数元素 摩尔投票算法(正负抵消) O(n) O(1) 多数元素的定义、投票过程

这两道题都是 "看起来简单,解法很巧妙" 的典型,掌握它们的思路,不仅能解决原题,更能帮你理解算法优化的核心思想 ------ 利用问题的特性,用更高效的方式实现目标。

相关推荐
Navigator_Z7 小时前
LeetCode //C - 1252. Cells with Odd Values in a Matrix
c语言·算法·leetcode
语戚8 小时前
力扣 1621. 大小为K的不重叠线段的数目:动态规划(Java 实现)
java·算法·leetcode·动态规划·力扣·dp
青山木8 小时前
Hot 100 --- 最长有效括号
java·数据结构·算法·leetcode·动态规划
这料鬼有毒10 小时前
二刷hot100-1143.最长公共子序列
算法·leetcode·动态规划
政企项目老覃11 小时前
边缘 AI 推理部署:安防零售场景下的模型裁剪与端侧落地实践
人工智能·程序人生·算法·性能优化·vllm
爱吃苹果的日记本11 小时前
数据结构第五课
数据结构·学习
Logic10112 小时前
C语言/数据结构贪心算法题解:买卖股票的最佳时机——一次交易最大利润(O(n)时间O(1)空间)
c语言·数据结构·贪心算法·数组·时间复杂度·算法题·股票交易
Logic10112 小时前
C语言/数据结构位运算题解:异或XOR找出货币交易中的“独特面值“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
ctlover12 小时前
数据结构:树
数据结构·python
GreenTea12 小时前
发布 3 天登顶 HN:不生成一个字的模型 Jev,我把它的源码和黑料都扒了一遍
前端·后端·算法