// 給定一個非空整數數組,
// 1)除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。稍微拓展下,
// 2)加深一步:有兩個元素分別各出現一次,且兩個元素一個是奇數,一個是偶數又該如何找到這兩個數字。
// 3)更進一步:僅僅告訴你就是有兩個數不同,且各出現一次,如何找出這兩個數字
// 說明:
// 你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
//
// 示例 1:
// 輸入: [2,2,1]
// 輸出: 1
// 示例 2:
//
// 輸入: [4,1,2,1,2]
// 輸出: 4
//
// 來源:力扣(LeetCode)
// 鏈接:https://leetcode-cn.com/problems/single-number
// 著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
public class NumberOnce {
public int singleNumber(int[] nums) {
if (null == nums || nums.length == 0) {
throw new IllegalArgumentException();
}
return singleNumber(nums, nums.length);
}
/**
* 從指定長度的數組裏面找只出現一次的數
*
* @param nums
* @param length
* @return
*/
private int singleNumber(int[] nums, int length) {
int numOnce = nums[0];
if (length == 1)
return numOnce;
// 採用異或操作
for (int i = 1; i < length; i++) {
numOnce = numOnce ^ nums[i];
}
return numOnce;
}
// 描述進一步,如果告訴輸入裏面有兩個元素分別只出現一次,且兩個元素一個奇數一個偶數,
// 線下時間複雜度下能否找出這兩個數字
public int[] twoOddEvenNumber(int[] nums) {
if (null == nums || nums.length < 2) {
throw new IllegalArgumentException();
}
// 因爲兩個只出現一次的數分奇偶,所以可以按奇偶把元素重新分配
int oddNum = 0;
int evenNum = 0;
for (int tem : nums) {
// 偶數
if (tem % 2 == 0) {
evenNum = evenNum ^ tem;
} else {
oddNum = oddNum ^ tem;
}
}
int[] retArr = new int[2];
// i的值就是奇數數值的有效個數,j的值就是偶數數組的有效長度
retArr[0] = oddNum;
retArr[1] = evenNum;
return retArr;
}
// 描述進一步,如果告訴輸入裏面有兩個元素分別只出現一次,
// 線下時間複雜度下能否找出這兩個數字
public int[] twoNumber(int[] nums) {
if (null == nums || nums.length < 2) {
throw new IllegalArgumentException();
}
int orNum = singleNumber(nums);// 找出兩個不同數的異或結果
int offset = 0;
// 從低位開始找第一個爲零的bit位,以此作爲數組區分的依據,因爲是int,所以最多循環32次
for (int i = 0; i < 32; i++) {
// 說明最低位是1,最低位不同
if ((orNum ^ (orNum - 1)) == 1) {
break;
} else {
orNum = orNum >> 1;
offset++;
}
}
int bitOne = 0;
int bitZero = 0;
for (int tem : nums) {
// 先把tem左移 offset位賦值給臨時變量m
int m = tem >> offset;
//把位爲1的分組異或
if ((m ^ (m - 1)) == 1) {
bitOne = bitOne ^ tem;
} else {
bitZero = bitZero ^ tem;
}
}
int[] retArr = new int[2];
// i的值就是奇數數值的有效個數,j的值就是偶數數組的有效長度
retArr[0] = bitOne;
retArr[1] = bitZero;
return retArr;
}
public static void main(String[] args) {
int[] input = { 2, 2, 1, 1, 3,3,6, 4 };
int[] out = new NumberOnce().twoNumber(input);
System.out.println(out[0]+","+out[1]);
// System.out.println(10^9);
}
}