旋轉數組的最小數字(使用二分查找)

(一)題目:把一個數組最開始的若干的元素搬到數組的末尾,稱這樣的數組爲旋轉數組。例如,{3, 4, 5, 1, 2}, 最小值爲1.ios

旋轉後的數組能夠看做是兩個排序數組,並且前面子數組的元素都大於或等於後面子數組的元素,最小的元素剛好是兩個數組的分界線。排序數組中,咱們能夠使用二分查找來實現O(log N) 的查找。算法

    和二分算法同樣,能夠先使用兩個指針,分別指向數組的第一個元素和最後一個元素。按照題目中的旋轉規則,第一個元素應該大於或等於最後一個元素(數組正序的時候另加討論)。接着,咱們能夠找數組中間的元素。數組

        若是該中間元素位於前面的遞增子數組,那麼它應該大於等於第一個指針指向的元素。此時,數組的最小元素應該位於該中間元素的後面。能夠將第一個指針指向該中間元素,這樣能夠縮小查找範圍。移動以後前面的指針仍然位於前面的遞增的子數組中。spa

        一樣,若是該中間元素位於後面的遞增子數組時,它應該小於等於第二個指針指向的元素。此時,數組的最小元素應該位於該中間元素的前面(或是其自己)。能夠將第二個指針指向該中間元素。移動以後後面的指針仍然位於後面的遞增的子數組中。指針

按照上述的思路,第一個指針始終指向前一個遞增的子數組,第二個指針始終指向後一個遞增的子數組。最終,第一個指針將指向前一個遞增子數組的最後一個元素,而第二個指針將指向後面的遞增子數組的第一個元素(即數組的最小元素),也就是他們最終會指向兩個相鄰的元素【終止條件】。排序

 

//在旋轉數組中查找最小值
#include<iostream>
using namespace std;
索引

typedef int ElemType;input

int MinInOrder(int *number, int index1, int index2)
{
 int result = number[index1];
 for(int i = index1 + 1; i <= index2; i++)
 {
  if(number[i] < result)
   result = number[i];
 }
 return result;
}
int Min(int *number, int length)
{
 if(number == NULL || length <= 0)
  throw exception("Invalid input data!");
 int index1 = 0;
 int index2 = length - 1;
 int Midindex = index1; //若是輸入的數組就是一個正序的數組,即第一個元素就是最小的元素,則應直接返回第一個索引所指示的元素,所以,應將中間的索引初始化爲第一個索引所指的位置 
 while(number[index1] >= number[index2])
 {
  if(index2 - index1 == 1)  //當最後一個索引的位置位於第一個索引以後時,最後一個索引所指示的元素就是數組的最小值
  {
   Midindex = index2; 
   break;
  }
  Midindex = (index1 + index2) / 2;  //中間位置索引
  if(number[Midindex] >= number[index1]) //中間值大於第一個索引的值,能夠判斷,中間的值屬於第一個遞增數組
   index1 = Midindex;
  if(number[Midindex] <= number[index2]) //中間值小於等於最後一個索引的值,說明中間位置的值屬於後半部分的第二個遞增數組,且最小元素必定位於該元素以前,或者就是這個元素。
   index2 = Midindex;
  if(number[index1] == number[index2] && number[Midindex] == number[index1]) //第一個索引的值等於第二的索引的值等於中間索引的值,此時,沒法判斷中間索引的值屬於前一半的數組仍是後一半的數組,此時使用的是順序查找。例如:輸入的數據爲:{1111101}
   return MinInOrder(number, index1, index2);  //返回順序查找的結果
 }
 return number[Midindex];
}
io

int main()
{
 //int arr[10] = {3, 4, 5, 1, 2};
 //int arr[10] = {1, 1, 1, 1, 0, 1};
 int arr[10] = {1, 2, 3, 4, 5};
 int result;
 result = Min(arr, 5);
 cout << "The minimum is "<< result << endl;
效率

 system("pause");
 return 0;
}

(二)題目:實現一個排序算法,要求其時間複雜度爲O(N)。(如對公司全部員工的年齡進行排序(幾萬人),只容許使用常量大小的輔助空間,不得超過O(N)。)

不一樣的排序算法適用的場合也不盡相同。快速排序雖然整體的排序效果是最好的,可是也不是任什麼時候候都是最優的算法。好比,數組自己已經排好序了,而每一輪排序的時候都以最後一個數字做爲比較的標準,此時快速排序算法的效率只有 O(N^2)。

 

//對一個公司的全部員工的年齡進行排序(幾萬人),使用的輔助空間不得超過O(N)
#include<iostream>
using namespace std;

void AgeSort(int ages[], int length)
{
 if(ages == NULL || length <= 0)
  throw exception("Invalid input data!");
 const int oldestAge = 99;
 int timesOfAge[oldestAge + 1];  //該數組記錄每個年齡有多少人
 for(int i = 0; i <= oldestAge; i++)
  timesOfAge[i] = 0;
 for(int j = 0; j < length; j++)
 {
  int age = ages[j];
  if(age < 0 || age > oldestAge)
   throw exception("Age out of range!");
  ++timesOfAge[age];
 }
 int index = 0;
 for(int i = 0; i <= oldestAge; i++)
 {
  for(int j = 0; j < timesOfAge[i]; j++)
  {
   ages[index] = i;  //年齡 i 出現了多少次,就在原數組中設置多少次i
   ++index;
  }
 }
}

int main()
{
 int ages[10] = {12, 46, 35, 85, 32, 17, 95, 35, 75, 67};
 AgeSort(ages, 10);

 for(int i = 0; i < 10; i++)
  cout << ages[i] << " ";
 cout << endl;

 system("pause"); return 0;}

相關文章
相關標籤/搜索