Leetcode Single Number 扩展

本文提供了一种算法,用于解决LeetCode中的问题,即在一个数组中找出仅出现特定次数的数字。文章详细介绍了解题思路、代码实现及验证方法,并提供了测试数据进行验证。

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

问题描述

Leetcode 137 Single Number II 仅出现一次的数字 中提出了一个更一般的问题:有一个数组,其中有一个元素出现了x次,其余所有元素都出现了y次(x < y),找出这个出现了x次的元素,要求时间复杂度O(n),空间复杂度O(1)

解题思路

实际上,Leetcode 136 Single Number 仅出现一次的数字Leetcode 137 Single Number II 仅出现一次的数字 都是这个一般问题的特例。136是最特殊的一个例子,我们从中可以找到的规律不是很明显;在137中我们已经给出使用one two three作为掩码来统计每一位上1的出现次数的方法,对于我们解决此题很有启发。出现x次的情况下,我们用一个大小为x的动态数组来存储各掩码即可,然后在每次获取到一个数字后,循环更新所有的掩码,最终第y个掩码所代表的数字就是只出现了y次的元素。

为了统一处理,我们掩码数组大小设为x+1,用times[x+1]来表示,其中times[i]表示出现i次的位。

具体逻辑请看后面的代码。

代码

/**
 * 返回特殊的数字
 * 特殊数字仅出现y次,其余数字均出现x次,x>0,y>0,x>y
 * @param nums 数字集合
 * @param numsSize 集合大小
 * @param x 普通数字出现次数
 * @param y 特殊数字出现次数
 */
int specialNumber(int *nums, int numsSize, int x, int y) {
    int num, change, i;
    int* times = (int*)malloc(sizeof(int) * (x + 1));
    for (i = 1; i <= x; ++i) *(times + i) = 0;
    while (numsSize) {
        *times = ~0; // 置全1,保证*(times+1)结果的正确性
        // 获取当前要统计的数字
        num = *(nums + --numsSize); 
        for (i = x; i > 0; --i) { // 更新每一位掩码
            change = *(times + i - 1) & num; // 获得更新位
            *(times + i) |= change;  // 更新
            num &= ~change;          // 清空更新位
            *(times + i - 1) &= ~change;
        }
    }
    num = *(times + y);
    free(times);
    return num;
}

有了这个方法以后,我们在 Leetcode 136 Single Number 仅出现一次的数字 中的方法就可以如下实现:

/**
 * 返回仅出现一次的数字
 * 特殊数字仅出现1次,其余数字均出现2次
 * @param nums 数字集合
 * @param numsSize 集合大小
 */
int singleNumber(int* nums, int numsSize) {
    int specialNumber(int*, int, int, int);
    return specialNumber(nums, numsSize, 2, 1);
}

同样, 在Leetcode 137 Single Number II 仅出现一次的数字 中的方法就可以如下实现:

/**
 * 返回仅出现一次的数字
 * 特殊数字仅出现1次,其余数字均出现3次
 * @param nums 数字集合
 * @param numsSize 集合大小
 */
int singleNumber(int* nums, int numsSize) {
    int specialNumber(int*, int, int, int);
    return specialNumber(nums, numsSize, 3, 1);
}

在leetcode上进行了验证,136和137均Accept。

完整代码 https://github.com/Orange1991/leetcode/blob/master/137/c/more.c

测试数据

[1,2,3,4,1,2,3,1,2,3] : each number appears 3 times expect for the special one appears 1 times, the special number is 4
[1,1,2,2,3,4,4,5,5,66,66] : each number appears 2 times expect for the special one appears 1 times, the special number is 3
[1,1,1,3,3,3,44,44,55,55,55,111,111,111] : each number appears 3 times expect for the special one appears 2 times, the special number is 44
[1] : each number appears 3 times expect for the special one appears 1 times, the special number is 1

2015/8/18

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值