剑指offer----旋转数组的最小数字----java实现

版权声明:转载请标明出处 https://blog.csdn.net/snow_7/article/details/51909764

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}{1,2,3,4,5}的一个旋转,该数组的最小值为1
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0

如果直接遍历数组,时间复杂度为On,可以利用旋转数组的特性来解决此题;

思路:

(1)如果发生旋转,前面的数至少去了一个放在数组的后面;

     1)旋转后,数组分为两个排序数组,而且前一个数组中的数均大于等于后一个数组中的数,因为要查找数组中的最小数,也就是第二个数组中的第一个数,可以采用二分查找的思想;

2)设置两个指针p1,p2p1指向数组的开始位置,也就是第一个数组的开始位置,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;
   }
    
}


展开阅读全文

没有更多推荐了,返回首页