面试题11:旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:
- 数组长度为0:返回0
- 起始的时候,数组第一个元素小于最后一个元素:则直接返回第一个元素,也是indexMid初始值设为index1的原因
- index1元素大于等于index2的情况:(index1必定指向较大的递增数组,index2必定指向较小的递增数组,注意交界处即是最小元素)
1)index1和index2相邻时,直接返回index2
2)当index1 = index 2 = indexMid时,无法分辨,存在相同元素,所以调用顺序扫描(index1,index2)
3) 当indexMid>=index1的时候,index1 = indexMid,当indexMid<=index2时,index2 = indexMid
1 public int minNumberInRotateArray(int [] array) { 2 if(array.length < 0) return 0; 3 int index1 = 0,index2 = array.length - 1; 4 int indexMid = index1;
5 while(array[index1] >= array[index2]){ 6 if(index2-index1 == 1) return array[index2]; 7 indexMid = (index1 + index2)/2; 8 if(index1 == index2 && index1 == indexMid) 9 return minInOrder(array,index1,index2); 10 if(array[indexMid] >= array[index1]) index1 = indexMid; 11 else if(array[indexMid] <= array[index2]) index2 = indexMid; 12 } 13 return array[indexMid];//若index1>index2时,不进入while循环,直接跳出,返回index1 14 } 15 int minInOrder(int[] a,int index1,int index2){ 16 int result = a[index1]; 17 for(int i = index1;i <= index2;++i){ 18 if(result > a[i]) result = a[i]; 19 } 20 return result; 21 }
}
面试题39:数组中出现次数超过一半的数字O(n)
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路:分为两个步骤
- 使用num记录数组中的一个数字,count记录该数字的次数,对比num和array【i】,分为三种情况
1)如果次数为0,则将num设为当前数字
2)如果当前数字与num不相同,则次数减1
3)如果当前数字与num相同,则次数加1
2. 检验得到的num重复次数是否超过一半,扫描一遍数组(eg:123455,count = 2,但不符合条件),所以得到的num有两种可能(重复次数超过一半或者重复次数不超过一半)
1 public int MoreThanHalfNum_Solution(int [] array) { 2 if(array.length == 0) return 0; 3 int count = 1,num = array[0]; 4 for(int i = 1;i < array.length;i++){ 5 if(count == 0) { 6 num = array[i]; 7 count = 1; 8 } 9 else if(array[i] != num) count--; 10 else count++; 11 } 12 if(count >=1 ){ 13 count = 0; 14 for(int i = 0;i < array.length;i++){ 15 if(array[i] == num) count++; 16 if(count > array.length/2) return num; 17 } 18 } 19 return 0; 20 }