2016阿里巴巴java筆試題

題目:

一個整形數組裏除了一個數字出現3次以外,其他數字都出現2次.請寫程序找出這個出現3次的數字.

要求使用輔助空間O1,時間複雜度Onlogn.


1.使用堆排序.(堆排序的時間複雜度爲Onlogn)

因爲堆排序每次取到的都是最大(或是最小)的數字,三個相同的數字肯定是緊挨着被取出的.

所以在原先的堆排序算法上,加2個標記記錄即可.


代碼:

// 使用堆排序,每次取最大的,連續取到3個相同的,那說明就是
	public static int find2(int[] array) {

		// 堆排序的:形成堆結構,
		// 從最後一個有葉子節點的節點開始,
		// 也就是最後一個節點的父節點
		for (int i = (array.length >> 1) - 1; i >= 0; i--) {
			refactor(array, i, array.length);

		}

		// 2個分別用來記錄前以及前前
		Integer pre = null;
		Integer prePre = null;
		for (int i = 1; i <= array.length; i++) {

			// 如果相同,返回
			if (pre != null && pre == prePre && array[0] == pre) {
				return array[0];
			}
			if (pre == null) {
				pre = array[0];
				swap(array, 0, array.length - i);
				refactor(array, 0, array.length - i);
				continue;
			}
			prePre = pre;
			pre = array[0];
			swap(array, 0, array.length - i);
			refactor(array, 0, array.length - i);
		}
		// 如果沒找到,說明輸入數組有問題,拋異常
		throw new RuntimeException();
	}

	static void refactor(int[] array, int root, int length) {
		int left = (root << 1) + 1;
		int right = (root + 1) << 1;

		if (left == length - 1 && array[left] > array[root]) {
			swap(array, root, left);
			return;
		}
		if (right < length) {
			if (array[left] >= array[right] && array[left] > array[root]) {
				swap(array, root, left);
				refactor(array, left, length);
				return;
			}
			if (array[right] > array[left] && array[right] > array[root]) {
				swap(array, root, right);
				refactor(array, right, length);
				return;
			}
		}

	}

	private static void swap(int[] array, int a, int b) {
		int tmp = array[a];
		array[a] = array[b];
		array[b] = tmp;
	}


2.這裏有個非常簡單的方法:


那就是異或:

一個數異或他本身得到0,那麼把所有的數異或得到的最後的結果肯定就是出現3次的那個數了.


public static int find1(int[] array) {
		int target = array[0];
		// 遍歷,異或所有
		for (int i = 1; i < array.length; i++) {
			target ^= array[i];
		}
		// 最後的值就是本身
		return target;
	}


升級版:

劍指offer面試題40-數組中只出現一次的數字


發佈了91 篇原創文章 · 獲贊 18 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章