第40题——数组中只出现一次的两个数

123 阅读3分钟

题目;

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路:

  • 思路一:利用hash,较简单。
  • 思路二:利用位运算。
  • 考虑题目的特殊性,“一个整型数组里除了两个数字之外,其他的数字都出现了两次”,那么自然想到异或运算,相同数异或得0,而不同数异或的结果二进制中至少有一个为1。但,这样将所有数都异或得到的只是出现一次的两个数异或的结果,并不能得到题目要求的这两个数。那么,就将问题转换为将这两个出现一次的数放在两个不同的子数组中。
  • 在每个子数组中,包含一个只出现一次的数字,而其它数字都出现两次。如果能够这样拆分原数组,按照前面的办法就是分别求出这两个只出现一次的数字了。
  • 我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其它数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。我们在结果数字中找到第一个为1的位的位置,记为第N 位。现在我们以第N位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第 N位都为1 ,而第二个子数组的每个数字的第N位都为0 。

Java 思路一

package nowcoder;

import java.util.HashMap;

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class S40_FindNumsAppearOnce {
    public void findNumsAppearOnce(int[] array, int[] num1, int[] num2){
        HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
        for (int i=0;i<array.length;i++){
            if (hashMap.containsKey(array[i])){
                int count = hashMap.get(array[i]);
                hashMap.put(array[i], count+1);
            }
            else hashMap.put(array[i], 1);
        }
        for (int i=0;i<array.length;i++){
            if (hashMap.get(array[i]) == 1) {
                if (num1.length == 0)
                    num1[0] = array[i];
                else {
                    num2[0] = num1[0];
                    num1[0] = array[i];
                }
            }
        }
        System.out.println(num1[0]+","+num2[0]);
    }
    public static void main(String[] args){
        S40_FindNumsAppearOnce s40 = new S40_FindNumsAppearOnce();
        int[] array = {1, 2, 1, 2, 3, 3, 4, 5, 6, 4, 7, 6, 8, 7};
        int[] num1 = new int[1];
        int[] num2 = new int[1];
        s40.findNumsAppearOnce(array, num1,num2);
    }
}

Java 思路二

package nowcoder;

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class S40_FindNumsAppearOnce_new {
    public void findNumsAppearOnce(int[] array, int[] num1, int[] num2){
        if (array.length == 2){
            num1[0] = array[0];
            num1[1] = array[1];
        }
        int bitResult = 0;
        for (int i=0;i<array.length;i++){
            bitResult ^= array[i];
        }
        int index = findFirst1(bitResult);
        for (int i=0;i<array.length;i++){
            if (isBit1(array[i], index))
                num1[0] ^= array[i];
            else num2[0] ^= array[i];
        }
        System.out.println(num1[0]+","+num2[0]);
    }
    //找到所有树异或后最后一个数的二进制的第一个1的位置
    public int findFirst1(int bitResult){
        int index = 0;
        while ((bitResult & 1) == 0 && index< 32){
            index++;
            bitResult >>= 1;
        }
        return index;
    }
    public boolean isBit1(int target, int index) {
        return (target >> index & 1) == 1;
    }
    public static void main(String[] args){
        S40_FindNumsAppearOnce_new s40 = new S40_FindNumsAppearOnce_new();
        int[] array = {1, 2, 1, 2, 3, 3, 4, 5, 6, 4, 7, 6, 8, 7};
        int[] num1 = new int[1];
        int[] num2 = new int[1];
        s40.findNumsAppearOnce(array, num1,num2);
    }
}

Python 思路一

class FindNumsAppearOnce:
    #hash法
    def findNumsAppearOnce(self, array):
        hashMap = {}
        for i in array:
            if str(i) in hashMap:
                hashMap[str(i)] += 1
            else:
                hashMap[str(i)] = 1
        res = []
        for i in hashMap.keys():
            if hashMap[i] == 1:
                res.append(int(i))
        print(res)
if __name__ == '__main__':
    test = FindNumsAppearOnce()
    array = [1, 2, 1, 2, 3, 3, 4, 5, 6, 4, 7, 6, 8, 7]
    test.findNumsAppearOnce(array)

Python 思路二

class FindNumsAppearOnce_new:
    def findNumsAppearOnce(self, array):
        if not array:
            return []
        bitResult = 0
        for i in array:
            bitResult ^= i
        print(bitResult)
        index = self.findFirst1(bitResult)
        a = b = 0
        for i in array:
            if self.isBit1(i, index):
                a ^= i
            else:
                b ^= i
        print([a, b])
        return [a, b]
    def findFirst1(self, bitResult):
        index = 0
        while (bitResult & 1) == 0:
            bitResult >>= 1
            index += 1
        return index
    def isBit1(self, target, index):
        target = target >> index
        return target & 1
if __name__ == '__main__':
    test = FindNumsAppearOnce_new()
    array = [2, 4, 3, 6, 3, 2, 5, 5]
    test.findNumsAppearOnce(array)