剑指Offer面试题8旋转数组的最小数字(二分查找)附带快排和按年龄排序

面试题8:旋转数组的最小数字

把一个数组最开始的几个元素搬到数组末尾,我们称之为数组的旋转,输入一个递增的数组的旋转,输出它的最小元素。如{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,输出1。

思路:直观想法是从头到尾遍历就行,复杂度O(n),但是这个数组其实已经划分为两个排好序的子数组,前面一个子数组的元素都大于等于后边一个,并以最小元素为分界。

对于排好序的数组,推荐用二分查找复杂度为O(logn),做法是一个指针指首元素,一个指针指尾元素,若中间元素大于等于首元素,则它位于前一个子数组内,最小元素在中间元素之后。反之同理。

用二分方法处理此问题:

public class Min {
	//最简单的二分
	static Integer printMin(int array[]) {
		int low = 0 ;
		int high = array.length - 1;
		if(array.length == 0) return null;//判空
		while(low < high){
			int mid = (low + high)/2;
			if(array[mid] > array[high]){
				low = mid + 1;
			}else if(array[mid] == array[high]){
				high = high - 1;
			}else{
				high = mid;
			}
		}
		return array[low];
	}
	public static void main(String[] args) {
		int test[] = {3,4,5,1,2};//{2,2,2,1,2}
		System.out.println(printMin(test));
	}
}

快排的写法要很熟练:

import java.util.Arrays;

public class QSort {
	//快排
	private void qsort(int a[],int left,int right){
		if(a.length == 0) System.out.println("输入为空");
		if(left >= right) return;//代表快排完成一轮了
		int i = left;
		int j = right;
		int key = a[left];//以第一个元素为参照key
		while(i < j){
			while(i < j && key <= a[j]){
				j--;//从后往前找比key小的
			}
			a[i] = a[j];//把找到的比key小的数往前挪
			while(i < j && key >= a[i]){
				i++;//从前往后找比key大的值
			}
			a[j] = a[i];//把找到的比key大的数往后挪
		}
		//排完一轮后把参照key还原,现在a[i]是分界线,对左右两边递归
		a[i] = key;
		qsort(a,left,i-1);
		qsort(a,i+1,right);
	}
	public static void main(String[] args) {
		QSort test = new QSort();
		int array[] = {5,4,2,3,1};
		test.qsort(array,0,array.length-1);
		System.out.println(Arrays.toString(array));
	}
}

对员工按年龄进行排序的问题:

import java.util.Arrays;

public class SortAges {
	//按所有员工的年龄进行排序,要求复杂度O(n)。
	//此题特点是所有的数字大小在一个小范围内(年龄在0-99,使用辅助空间)
	private void sortAges(int ages[]){
		if(ages.length == 0) System.out.println("输入为空");
		int oldestAge = 99;//最大年龄99
		int timesOfAge[] = new int[oldestAge+1];//保存每个年龄出现的次数
		for(int i=0;i<=oldestAge;i++){
			timesOfAge[i] = 0;//初始化为0
		}
		for(int i=0;i<ages.length;i++){
			if(ages[i] < 0 || ages[i] > oldestAge){
				System.out.println("错误,年龄越界");
				return;
			}else{
				timesOfAge[ages[i]]++;//该年龄出现次数加1
			}
		}
		//开始按年龄排序
		int index = 0;
		for(int i=0;i<=oldestAge;i++){
			for(int j=0;j<timesOfAge[i];j++){
				ages[index] = i;
				index++;
			}
		}
	}
	public static void main(String[] args) {
		SortAges test = new SortAges();
		int a[] = {14,25,22,44,29,44,88};//输入所有员工的年龄
		test.sortAges(a);
		System.out.println(Arrays.toString(a));
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值