旋转数组的最小数字:
*把一个数组最开始的若干位搬到数组的末尾,我们称子为旋转数组。输入一个递增排序的旋转,输出旋转数组中的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,最小元素是1.
直接遍历也能够找到最小值,但是这样没有用到旋转的特性,其时间复杂度为O(n),不是优解。
可以把旋转数组看成是两个有序的子数组,那么可以用二分查找的思想的来解决,用两个指针来分别指向数组第一个元素和最后一个元素,第一个元素的值一定大于等于最后一个元素的值(也不完全是,特殊情况是如果把0个元素向后面移动,即还为数组本身)。
接着我们可以找到中间元素,如果中间元素大于一个元素,那么中间元素属于第一个子数组,那么最小值一定在中间值后面,让第一个指针指向中间元素,但任然还 是属于第一个数组,那么这样就缩小了搜索范围;如果中间元素小于最后一个元素,那么中间元素属于第二个数组,最小值一定在其前面,让第二个指针指向中间元素,依然还是属于第二个数组的;通样瘦小了搜索范围,重复进行新的一轮查询,直到两个指针相邻,此时第二个指针指向的元素为最小的元素。、
注意:
1、如果把0个元素向后移动,则还为原数组本身,最小元素为第一个元素。
2、如果第一个指针、中间元素、第二个指针指向是值相同,则只能进行顺利查询了。*
代码如下:
//找出旋转数组的最小元素,应用二分查找的思想
static int min(int a[],int len) {
//利用中间点去确定最小的元素
if(a == null || len <= 0) {
return -1;
}
int index1 = 0;
int index2 = len - 1;
//如果有序数列把0个元素移到到后面去,即旋转数列为本数列,那么第一个元素即为最小
int mid = index1;
while(a[index1] >= a[index2]) {
//当index2 - index1 = 1时index2所指元素是最小值
if(index2 - index1 == 1) {
mid = index2;
break;
}
//平分为两个序列
mid = (index1 + index2)/2;
//如果三个的值都相同的,那就只能顺利查找了
if(a[index1] == a[mid] && a[index2] == a[mid]) {
return minByOrder(a,index1,index2);
}
//mid属于第一个数列,index1指向mid
if(a[index1] < a[mid]){
index1 = mid;
}else if(a[index2] > a[mid])
//mid属于第二个数列
index2 = mid;
}
return a[mid];
}
static int minByOrder(int[] a, int index1,int index2) {
int min = a[index1];
for(int i=index1+1;i<index2;i++) {
if(min > a[i])
min = a[i];
}
return min;
}
排序方法
二分查找
非递归实现
static int binSearch(int a[],int start,int end,int key) {
if(a == null || start > end) {
return -1;
}
int mid = 0;
while(start <= end) {
mid = (start + end)/2;
if(a[mid] == key)
return mid;
else if(a[mid] > key)
end = mid - 1;
else
start = mid + 1;
}
return -1;
}
递归实现:
static int binSearchByBack(int a[],int start,int end ,int key) {
if(a == null || start > end ){
return -1;
}
int mid = (start + end)/2;
if(a[mid] == key)
return mid;
else if(a[mid] > key)
return binSearchByBack(a,start,mid-1,key);
else
return binSearchByBack(a, mid+1, end, key);
}
快速排序
static int partition(int a[],int low,int high) {
if(a==null || low > high)
return -1;
int key = a[low];
while(low<high) {
while(low < high && a[high] > key)
high--;
a[low] = a[high];
while(low < high && a[low] < key)
low++;
a[high] = a[low];
}
a[low] = key;
return low;
}
递归实现:
static void quickSort(int a[],int low,int high) {
if(a!=null && low < high) {
int m = partition(a,low,high);
quickSort(a,low,m-1);
quickSort(a,m+1,high);
}
}
非递归算法
static void quickSortLoop(int[] a,int low,int high) {
if(a == null && low > high) {
return ;
}
Stack s = new Stack();
int m = partition(a,low,high);
if(low < m-1) {
s.push(m-1);
s.push(low);
}
if(m+1 < high) {
s.push(high);
s.push(m+1);
}
//其实就是用栈保存每一个待排序子串的首尾元素下标,下一次while循环时取出这个范围,对这段子序列进行partition操作
while(!s.empty()) {
int first = (Integer)s.pop();
int end = (Integer) s.pop();
m = partition(a,first,end);
if(first < m-1){
s.push(m-1);
s.push(first);
}
if(end > m+1) {
s.push(end);
s.push(m+1);
}
}
}