leetcode136-137:single number

LC136:Given an array of integers, every element appears twice except for one. Find that single one.
LC137:
Given an array of integers, every element appears three times except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
LC136和LC137这两个题很像,前者是一整数数组中,仅有一个元素出现一次,其余均出现两次,后者是仅有一个元素出现一次,其余均出现三次,都要求找到仅出现一次的那个元素。而且要求都在线性时间O(n)以及不要创建额外的数组实现。

思路:
如果可以使用额外的空间,我们可以创建一个数组filter,通过遍历一次原始数组,保存所有不相同元素出现次数,然后在遍历一次filter,就可以找到出现一次的元素,这样的时间复杂度为O(3n)。甚至我们可以把原始数组的数据放到hashmap中去,直接就可以统计出不同元素出现的次数,但如果看过hashmap源码的同学,就会知道时间复杂度就不是O(n)了,而是O(log)级别的。其实对于这种找元素出现次数的问题,我们可以采用位运算实现。

LC136:

位运算有4种:与&、或|、非~、异或^,而且位运算通常针对二进制运算符。对于异或我们应该记住以下公式:
a^b=b^a
a^b^c=a^(b^c)=a^(c^b)
a^a=0
0^a=a
a^a^b^b^c^d^c=d
相同元素异或为0,扩展为偶数个相同元素异或为0; 0和任何元素异或为任何元素。

对于LC136:数组所有元素取异或,出现两次的元素异或后为0,那么最终异或结果就是只出现一次的元素。测试通过代码如下:

public class Solution {
    public int singleNumber(int[] nums) {
        int result=nums[0];
        for(int i=1;i<nums.length;i++){
            result=(result^nums[i]);
    }
        return result;
}
}

LC137:
这题相对麻烦些,对于出现奇数次+1次的,不能直接用异或来实现。这里可以结合 的概念。
1与任何元素与运算都是任何元素;0与任何元素或运算都是任何元素。
除一个元素出现一次外,其余元素均出现三次。这里也有几个共识需要大家掌握:

  • 十进制运算可以转换为二进制运算
    以3+5+6=14为例,我们把每个十进制数转换为二进制数进行相加运算,最终的伪二进制为222,转换为十进制为2+2 2 1 +2 2 2 =14,恰恰等于以十进制方式相加的结果。
    0 1 1
    1 0 1
    1 1 0
    ————
    2 2 2

将每个元素考虑为一个32位的二进制数,这样每一位上出现要么为1 ,要么为0。统计数组每一位上1 出现的次数count,必定是3N或者3N+1 次。让count对3取模,能够获得到那个只出现1次的元素该位是0还是1。

代码:
public class Solution {
    public int singleNumber(int[] nums) {
        int length = nums.length;  
        int result = 0;  
        for(int i = 0; i<32; i++){  
            int count = 0;   
            int temp = 1<< i;  
            for(int j=0; j<length; j++){  
                if((nums[j] & temp[)!=0)  
                    count++;  
            }  
          if(count %3==1)  
                result |= temp;  
        }  
        return result;  
    }
}

附上java进制转换:java中进行二进制,八进制,十六进制,十进制间进行相互转换

十进制转成十六进制:
Integer.toHexString(int i)
十进制转成八进制
Integer.toOctalString(int i)
十进制转成二进制
Integer.toBinaryString(int i)
十六进制转成十进制
Integer.valueOf(“FFFF”,16).toString()
八进制转成十进制
Integer.valueOf(“876”,8).toString()
二进制转十进制
Integer.valueOf(“0101”,2).toString()

你可能感兴趣的:(leetcode136-137:single number)