【leetcode】136. 只出現一次的數字-java

//	給定一個非空整數數組,
//   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);


	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章