【劍指offer】-數組中只出現一次的數字-35/67

1. 題目描述

一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

2.題目分析

  1. 這題類似於【劍指offer】- 第一個只出現一次的字符位置-33/67
  2. 我們需要了解一些關於二進制的符號:
一)按位與&

兩位全爲1,結果才爲1

0&0=00&1=01&0=01&1=1

(二)按位或 |

只要有一個爲1,結果就爲10|0=00|1=11|0=11|1=1;

(三)異或 ^

兩個相應位爲“異”(值不同),則該位結果爲1,否則爲0

0^0=0; 0^1=1; 1^0=1; 1^1=0;

四)取反與運算~

對一個二進制數按位取反,即將0變爲110

~1=0~0=1

(五)左移<<

將一個運算對象的各二進制位全部左移若干位(左邊的二進制位丟棄,右邊補0)

例如: 2<<1 =4 10<<1=100

若左移時捨棄的高位不包含1,則每左移一位,相當於該數乘以2。

例如:

11(1011)<<2= 0010 1100=22

11(00000000 00000000 00000000 1011)整形32bit

(六)右移>>

將一個數的各二進制位全部右移若干位,正數左補0,負數左補1,右邊丟棄。若右移時舍高位不是1(即不是負數),操作數每右移一位,相當於該數除以2。

左補0還是補1得看被移數是正還是負。

例如:4>>2=4/2/2=1

-14(即1111 0010>>2 =1111 1100=-4

(七)無符號右移運算>>>

各個位向右移指定的位數,右移後左邊空出的位用零來填充,移除右邊的位被丟棄。

例如:-14>>>2

(即11111111 11111111 11111111 11110010>>>2

=(00111111 11111111 11111111 11111100)=1073741820

  1. 還有另外一種做法,將所有的數字進行異或操作,最後得出到的數字,一定是這兩個數字進行異或的結果sum,因爲兩個數字不一樣,所以我們得到的sum(二進制)必定有爲1的位,我們根據這一位來進行區分;

3. 題目代碼

1. hashmap

	public static void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
		HashMap<Integer, Integer> map = new HashMap<>();
		for (int i = 0; i < array.length; i++) {
			if (map.containsKey(array[i])) {
				map.remove(array[i]);
			} else {
				map.put(array[i], 1);
			}
		}
		for (Integer key : map.keySet()) {
			System.out.println(key);
		}
		boolean f = true;
		for (Integer key : map.keySet()) {
			if (f) {
				num1[0] = key;
				f = false;
			} else {
				num2[0] = key;
			}
		}
		System.out.println(num1[0]);
		System.out.println(num2[0]);
	}

2. 二進制

public static int[] singleNumbers(int[] nums) {
		int sum = nums[0];
		for (int i = 1; i < nums.length; i++) {
			sum = sum ^ nums[i];
		}
		int div = 1;
		while ((div & sum) == 0) {
			div = div << 1;
			System.out.println(div);
		}
		int[] a = new int[2];
		for (int i = 0; i < nums.length; i++) {
			if ((div & nums[i]) == 0) {
				a[0] = a[0] ^ nums[i];
			} else {
				a[1] = a[1] ^ nums[i];
			}
		}
		return a;
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章