• LeetCode 137. Single Number II


    37. Single Number II

    Description Submission Solutions

    • Total Accepted: 108884
    • Total Submissions: 269252
    • Difficulty: Medium
    • Contributors: Admin 

    Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.

    Note:
    Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

    Subscribe to see which companies asked this question.

    【题目分析】

    相比上一个题目,这个题目中每个元素出现了3次。该如何解决呢?

    【思路分析】

    1. 输入是int型数组,所以可以用32位来表达输入数组的元素。
    假设输入中没有single number,那么输入中的每个数字都重复出现了数字,也就是说,对这32位中的每一位i而言,所有的输入加起来之后,第i位一定是3的倍数。
    现在增加了single number,那么对这32位中的每一位做相同的处理,也就是说,逐位把所有的输入加起来,并且看看第i位的和除以3的余数,这个余数就是single numer在第i位的取值。这样就得到了single number在第i位的取值。这等价于一个模拟的二进制,接着只需要把这个模拟的二进制转化为十进制输出即可。
    为了完成上面的过程,需要使用一个数组 int a[ 32 ]来模拟位运算。
    可以看出来,这个做法对于功力的要求非常高,需要看到数字的时候,眼前展现的是数字背后的二进制组成,要不然很难想到可以逐位去处理。
    另外,这个做法可以扩展,如果有一堆输入,其中1个数字出现了1次,剩下的数字出现了K次,这样的问题全部可以使用这样的办法来做。

    【java代码1】

     1 public class Solution {
     2     public int singleNumber(int[] nums) {
     3         int[] count = new int[32];
     4         int result = 0;
     5         
     6         for(int i = 0; i < 32; i++) {
     7             for(int j = 0; j < nums.length; j++) {
     8                 count[i] += (nums[j] >> i) & 1;
     9             }
    10             count[i] = count[i] % 3;
    11             result |= count[i] << i;
    12         }
    13         
    14         return result;
    15     }
    16 }

    上面的做法从每一位来进行考虑,但是用到了额外的存储空间。discuss中的做法如下:

    public int singleNumber(int[] A) {
        int ones = 0, twos = 0;
        for(int i = 0; i < A.length; i++){
            ones = (ones ^ A[i]) & ~twos;
            twos = (twos ^ A[i]) & ~ones;
        }
        return ones;
    }

    2. The code seems tricky and hard to understand at first glance.

    However, if you consider the problem in Boolean algebra form, everything becomes clear.

    What we need to do is to store the number of '1's of every bit. Since each of the 32 bits follow the same rules, we just need to consider 1 bit. We know a number appears 3 times at most, so we need 2 bits to store that. Now we have 4 state, 00, 01, 10 and 11, but we only need 3 of them.

    In this solution, 00, 01 and 10 are chosen. Let 'ones' represents the first bit, 'twos' represents the second bit. Then we need to set rules for 'ones' and 'twos' so that they act as we hopes. The complete loop is 00->10->01->00(0->1->2->3/0).

    • For 'ones', we can get 'ones = ones ^ A[i]; if (twos == 1) then ones = 0', that can be tansformed to 'ones = (ones ^ A[i]) & ~twos'.

    • Similarly, for 'twos', we can get 'twos = twos ^ A[i]; if (ones* == 1) then twos = 0' and 'twos = (twos ^ A[i]) & ~ones'. Notice that 'ones*' is the value of 'ones' after calculation, that is why twos is
      calculated later.

    上面的解释还没有完全理解,先在这里mark一下。
     
  • 相关阅读:
    CentOS_关机与重启命令详解
    去除ArrayList重复的对象
    单项设计模式
    死循环的应用
    java学习心得-面向对象与面向过程
    计算机使用个人经验及日常维护
    linux操作系统简介
    集合
    项目学习4
    周末总结
  • 原文地址:https://www.cnblogs.com/liujinhong/p/6442816.html
Copyright © 2020-2023  润新知