给定一组数组,含有n种偶数个数字和2种奇数个数字,求这两种出现奇数次的数字

先看简单的情况

给定一组数组,含有n种偶数个数字和1种奇数个数字,求这种出现奇数次的数字

可以通过异或运算解决,相同的数异或为0,就保留下了奇数个的数字

#给定一组数组,含有n种偶数个数字和一种奇数个数字,求该种出现奇数次的数字
def getOddNum1(data):
    eor = 0
    for i in data:
        eor = eor ^ i
    print(eor)

给定一组数组,含有n种偶数个数字和2种奇数个数字,求这两种出现奇数次的数字

思路
假设这两种数是a和b
先对数组进行一遍异或运算,得到的结果是a^b
因为a和b是两种不同的数,那么a^b!=0,计作eor
说明a^b中至少存在某一位为1,假设这一位置是第x位
那么就可以把数组分为两组,x位不为0和x位不为1,计作A组和B组
在其中一组中作异或运算,那么就可以得到a|b,计作eor_p
这一步比较难理解,可以这样思考,我把数分为了a,b和其他,因为其他的异或结果必然是0(因为偶数个相同数字),所以在计算第x位上的异或结果时,其他数字在该x位上存在偶数个0或者偶数个1,因此不会影响分组结果,因为分组后作异或运算,其他数字必然等于0,只会剩下a或者b
然后得到另一个数字就是eor ^ eor_p

#给定一组数组,含有n种偶数个数字和2种奇数个数字,求这两种出现奇数次的数字
def getOddNum2(data):
    eor = 0
    for i in data:
        eor = eor ^ i
    # eor = a ^ b
    right = eor & (~eor + 1) # 获得最右侧的1,取补码进行与运算可得
    eor_p = 0
    # 将数分为该位为0和1的两组,得到a|b
    for i in data:
        if right & i == 0:
            eor_p = eor_p ^ i
    print(eor_p, eor_p^eor)

测试

if __name__ == '__main__':
    data1 = [1,1,1,2,2,3,3,4,4,4,5,5,6,6]
    getOddNum2(data1)

输出

4 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于给定的整型数组n,将数组中的值组合成x,有多方法可以实现。 一常见的方法是使用递归。我们可以定义一个递归函数,该函数接受数组、目标值x和当前索引作为参数。在每一递归调用中,我们有两种选择:要么将当前索引的元素包含在组合中,要么不包含。如果选择包含当前索引的元素,则目标值x减去该元素的值,并将索引加1。如果选择不包含当前索引的元素,则只需将索引加1。递归终止条件是当目标值x等于0时,说明找到了一组合方式;当索引超过数组长度时,说明已经遍历完所有元素。 以下是一个示例代码实现: ```cpp #include <iostream> #include <vector> int countCombinations(std::vector<int>& nums, int x, int index) { if (x == 0) { // 找到一组合方式 return 1; } if (index >= nums.size()) { // 已经遍历完所有元素 return 0; } // 不包含当前索引的元素 int count = countCombinations(nums, x, index + 1); // 包含当前索引的元素 count += countCombinations(nums, x - nums[index], index + 1); return count; } int main() { std::vector<int> nums = {1, 2, 3}; int x = 4; int count = countCombinations(nums, x, 0); std::cout << "有 " << count << " 组合方式" << std::endl; return 0; } ``` 在以上示例中,数组`nums`为`{1, 2, 3}`,目标值`x`为4。程序输出结果为"有 4 组合方式",即数组元素的组合方式为{1, 3}、{2, 2}、{1, 2, 1}和{3, 1}。 希望以上解答能够对你有所帮助!如有任何疑问,请随时提出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值