leetcode_137 Single Number II

本文介绍了三种高效算法来找出数组中仅出现一次的数,其他数均出现三次。通过使用哈希映射、位运算统计及二进制位状态追踪等方法,实现了C++与Java两种语言的解决方案。

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

  • 题目分析:

    给定一个数组,里面只有一个数只出现一次,其他的数均出现三次,请找出这个只出现一次的数。

  • 解题思路:

    • 方法1 利用map实现

      1)遍历整个数组,统计数组中每个数出现的次数,并将其保存在map种

      2)遍历数组中元素,查看map中对应元素出现的次数,如果出现只出现一次,则返回次元素,并结束程序即可。

    • 方法2 统计数组数的各个位之和

      1)int类型是32位数,对数组中所有数(32位int类)的各个位进行求和

      2)将就和的结果进行模3操作,放在结果的对应位置上即可。

    • 方法3 统计出现1次,2次,3次的数

      整体思想:利用3个变量分别保存各个二进制位上1出现一次、两次、三次的分布情况,最后只需要返回变量1就可以了。

      1)每次循环先计算twos,即出现两次的1的分布;

      2)然后计算出现一次的1的分布;

      3)接着二者进行与操作,得到三次出现1的分布;

      4)然后多three取反,在与ones、twos进行与操作,目的是将出现三次的位置清零。

  • 实现程序

    • C++版本

      // 方法1实现
      int singleNumber(vector<int> nums)
      {
          map<int, int> mp;
          for (int i = 0; i < nums.size(); i++)
          {
              mp[nums[i]]++;
          }
          for (int i = 0; i < nums.size(); i++)
          {
              if (mp[nums[i]] == 1)
                  return nums[i];
          } 
          return 0;
      }
      //方法2实现 
      int singleNumber1(vector<int> &nums)
      {
          int bitnum[32] = {0};
          int result = 0;
          for (int i = 0; i < 32; i++)
          {
              // 统计所有数对应第i位数的所有和 
              for (int j = 0; j < nums.size(); j++)
              {
                  bitnum[i] += (nums[j] >> i) & 1;
              }
              // 获取最后结果中第i位数对应的值 
              result |= (bitnum[i] % 3) << i;
          }
          return result;
      }
      //方法3实现
      int singleNumber1(vector<int> nums)
      {
          int one = 0;
          int two = 0;
          int three = 0;
          for (int i = 0; i < nums.size(); i++)
          {
              two |= one & nums[i];
              one ^= nums[i];
              three = one & two;
              one &= ~three;
              two &= ~three;
          }
          return one;
      }
      
    • Java版本

      // 方法1实现
      public int singleNumber1(int[] nums){
          Map<Integer, Integer> mp = new HashMap<Integer, Integer>();
          // 统计每个数出现的次数
          for (int i = 0; i < nums.length; i++){
              if (mp.containsKey(nums[i])){
                  int count = mp.get(nums[i]);
                  mp.put(nums[i], count + 1);
              }
              else
              {
                  mp.put(nums[i], 1);
              }
          }
          // 遍历map,取出只出现1次的数
          Set<Integer> keys = mp.keySet();
          for (int key : keys){
              if (mp.get(key) == 1)
                  return key;
          }
          return 0;
      }
      // 方法2实现
      public int singleNumber2(int[] nums){
          int[] bitnum = new int[32];
          for (int i = 0; i < bitnum.length; i++){
              bitnum[i] = 0;
          }
          int result = 0;
          for (int i = 0; i < 32; i++){
              for (int j = 0; j < nums.length; j++){
                  bitnum[i] += (nums[j] >> i) & 1;
              }
              result |= (bitnum[i] % 3) << i;
          }
          return result;
      }
      // 方法3实现
      public int singleNumber(int[] nums){
          int one = 0;
          int two = 0;
          int three = 0;
          for (int i = 0; i < nums.length; i++){
              two |= one & nums[i];
              one ^= nums[i];
              three = one & two;
              one &= ~three;
              two &= ~three;
          }
          return one;
      }
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值