【劍指offer】2.4.2 查找和排序

面試題11:旋轉數組的最小數字

題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如,數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。

解答:和二分查找一樣,我們用兩個指針分別指向數組的第一個元素和最後一個元素。接着找到數組中間的元素。如果該中間元素大於或者等於第一個指針指向的元素,說明此時數組中最小的元素應該位於該中間元素的後面,可以把第一個指針指向該中間元素,從而縮小查找範圍。

    同樣,如果中間元素小於或者等於第二個指針指向的元素,則說明此時數組中最小的元素應該位於該中間元素的前面,可以把第二個指針指向該中間元素,從而縮小查找範圍。

    以此循環下去,最終第一個指針將指向前面子數組的最後一個元素,而第二個指針會指向後面子數組的第一個元素。也就是它們最終會指向兩個相鄰的元素,而第二個指針指向的剛好是最小的元素。

    還有一種特殊的情況,就是當兩個指針指向的數字及它們中間的數字三者相同的時候,我們無法判斷中間的數字是位於前面的子數組還是後面的子數組,也就無法移動兩個指針來縮小查找的範圍。此時不得不採用順序查找的辦法。實現代碼如下:

int MidInOrder(vector<int> rotateArray)
{
	if(rotateArray.size() == 0)
	{
		throw new std::exception("Invalid parameters");
	}

	int len = rotateArray.size();
	int result = rotateArray[0];

	for(int i = 1;i < len;i++)
	{
		if(result > rotateArray[i])
		{
			result = rotateArray[i];
		}
	}

	return result;
}

int minNumberInRotateArray(vector<int> rotateArray) 
{
	if(rotateArray.size() == 0)
	{
		throw new std::exception("Invalid parameters");
	}

	int left = 0;
	int right = rotateArray.size() - 1;
	int mid = left;//初始化爲第一個元素,若數組本身有序,可直接返回

	while(rotateArray[left] >= rotateArray[right])//若用left<right作爲判斷條件則會陷入死循環
	{
		if(right - left == 1)
		{
			mid = right;
			break;
		}
		
		mid = ((right - left) >> 1) + left;
                //若三數相等只能遍歷
		if(rotateArray[left] == rotateArray[mid] 
		&& rotateArray[mid] == rotateArray[right])
		{
			return MidInOrder(rotateArray);
		}
		if(rotateArray[mid] >= rotateArray[left])
		{
			left = mid;
		}
		else
		{
			right = mid;
		}
	}

	return rotateArray[mid];
}

 

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