LeetCode137_只出现一次的数字 II

本文介绍了解决137.只出现一次的数字II问题的三种方法,包括数学法、位操作法及一种复杂方法。数学法利用集合求和的特性;位操作法通过位运算巧妙解决;复杂方法通过对每位上1的数量计数再取余实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 题目

137. 只出现一次的数字 II
给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

示例 1:
输入:nums = [2,2,3,2]
输出:3

示例 2:
输入:nums = [0,1,0,1,0,1,99]
输出:99
 
提示:
1 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
 
进阶:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

2. 题解

2.1 解法1 (数学法)
from typing import List

# 数学法
# 假设 nums = [a, a, a, b, b, b, c]
# 结果为 3 * (a + b + c) - (a + a +a + b + b +b + c) = 2c
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        return (3 * (sum(set(nums))) - sum(nums)) // 2


if __name__ == "__main__":
    s = Solution()
    a = s.singleNumber([2,2,1])
    print(a)

2.2 解法2 (复杂)
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        counts = [0] * 32
        for n in nums:
            for j in range(32):
                counts[j] += n & 1
                n >>= 1                 # 进行右移
        res, m = 0, 3                   # m表示 3的次数
        # 对每一位上的1个数取余
        for i in range(32):
            res <<= 1
            res |= counts[31 - i] % m
        
        return res if counts[31] % m == 0 else ~(res ^ 0xffffffff)
2.3 解法3 (位方法)
from typing import List


class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        one, two = 0, 0
        for n in nums:
            one ^= n
            two |= (one & n)
            three = (one & two)

            # 如果相应的位出现3次,则将改为重置位0
            two &= ~three
            one &= ~three
        return one


if __name__ == "__main__":
    s = Solution()
    a = s.singleNumber([2,2,1])
    print(a)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值