1. 程式人生 > >劍指offer50 陣列中重複的數字(java)

劍指offer50 陣列中重複的數字(java)

題目

在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字2。

思路1

把當前序列當成是一個下標和下標對應值是相同的陣列,遍歷陣列,判斷當前位的值和下標是否相等

  • 若相等,則遍歷下一位;
  • 若不等,則將當前位置i上的元素和a[i]位置上的元素比較:
    • 若它們相等,則找到了第一個相同的元素;
    • 若不等,則將它們兩交換。換完之後a[i]位置上的值和它的下標是對應的,但i位置上的元素和下標並不一定對應;重複2的操作,直到當前位置i的值也為i,遍歷下一位。

程式碼1

/**
 * 重複的數字交給a[0]
 */
public static boolean duplicate(int[] a, int length) {
	if (length == 0)
		return false;
	for (int i = 0; i < length; i++)
		if (a[i] > length)
			return false;
	for (int i = 0; i < length; i++) {
		while (i != a[i]) {
			if (a[i] == a[a[i]]) {
				a[0] = a[i];
				return true;
			}
			int tem = a[i];
			a[i] = a[tem];
			a[tem] = tem;
		}
	}
	return false;
}

思路2(很巧妙,思路源於作者

題目裡寫了數組裡數字的範圍保證在0 ~ n-1 之間,所以可以利用現有陣列設定標誌,當一個數字被訪問過後,可以設定對應位上的數 + n,之後再遇到相同的數時,會發現對應位上的數已經大於等於n了,那麼直接返回這個數即可

程式碼2

/**
 * 重複的數字交給a[0]
 */
public static boolean duplicate2(int[] a, int length) {
	if (length == 0)
		return false;
	for (int i = 0; i < length; i++)
		if (a[i] > length)
			return false;
	for (int i = 0; i < length; i++) {
		int index = a[i];
		if (index >= length)
			index -= length;
		if (a[index] >= length) {
			a[0] = index;
			return true;
		}
		a[index] += length;
	}
	return false;
}