1. 程式人生 > >劍指offer----旋轉陣列的最小數字----java實現

劍指offer----旋轉陣列的最小數字----java實現

把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列{3,4,5,1,2}{1,2,3,4,5}的一個旋轉,該陣列的最小值為1NOTE:給出的所有元素都大於0,若陣列大小為0,請返回0

如果直接遍歷陣列,時間複雜度為On,可以利用旋轉陣列的特性來解決此題;

思路:

(1)如果發生旋轉,前面的數至少去了一個放在陣列的後面;

     1)旋轉後,陣列分為兩個排序陣列,而且前一個數組中的數均大於等於後一個數組中的數,因為要查詢陣列中的最小數,也就是第二個陣列中的第一個數,可以採用二分查詢的思想;

2)設定兩個指標p1,p2

p1指向陣列的開始位置,也就是第一個陣列的開始位置,p2指向陣列的終止位置,也就是第二個陣列的結束位置。Mid=p1+p2/2;

   如果中間位置mid的數大於p1指向的數,則mid在第一個陣列中,讓p1指向mid所指向的數,p1指向的依然是陣列1的數;

   如果中間位置mid的數小於p2所指向的位置,則mid在第二個陣列中,p2指向mid指向的數,p2指向的依然是陣列2的數;

Mid不是指向陣列1的數,就是指向陣列2的數,指向陣列1的數,就讓p1移動到mid的位置,指向陣列2就讓p2陣列移動到mid的位置;直到p2移動到陣列1的結束的位置,p1移動到陣列2的開始的位置,此時p2p1挨著,而且

p1所指向的陣列2的起始位置中存放的就是最小數;

2如果中間位置的數既等於p1位置數,又等於p2位置的數,這時候,不能確定移哪個指標,就必須採用順序查詢的方法來尋找最小數;

總結:此題就是利用兩個指標,一個往後移,一個往前移,具體怎麼移,通過mid的大小控制;直到兩個指標的位置挨著,就可以找到最小數了!

還需要考慮:

如果陣列取0個放在了陣列的後面,也就是排序陣列沒有變,這時p1指向的數小於p2指向的數;直接是陣列的首元素是最小的數;

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) 
    {
          if(array == null || array.length == 0)
	   {
		   return 0;
	   }
	   int p1 = 0;//從前往後走
	   int p2 = array.length-1;//從後往前走
	   int min = array[p1];//如果沒發生旋轉,直接將array[0]的值返回,
	   int mid = 0;
	   //當陣列發生旋轉了,
	   while(array[p1] >= array[p2])
	   {
		   //當兩個指標走到挨著的位置時,p2就是最小數了
		   if(p2 - p1 == 1)
		   {
			   min = array[p2];
			   break;
		   }
		   mid = (p1 + p2)/2; 
		   //如果中間位置的數既等於p1位置的數又等於P2位置的數
		   if(array[p1] == array[mid]&&array[p2]==array[mid])
		   {
			  min = minInorder(array,p1,p2);
		   }
		 if(array[p1] <= array[mid])//若中間位置的數位於陣列1,讓p1走到mid的位置
		 {
			 p1 = mid;
		 }
		 else if(array[p2] >= array[mid])//若中間位置的數位於陣列2,讓p2走到mid的位置
		 {
			 p2 = mid;
		 }
	   }
	   return min;
   }
   private int minInorder(int[]array,int p1,int p2)
   {
	   int min = array[p1];
	   for (int i = p1 + 1; i <= p2; i++)
	{
		if(min > array[i])
		{
			min = array[i];
		}
	}
	   return min;
   }
    
}