题目;
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路:
- 思路一:利用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)