给定任意一维数组,如{1, 4, 3, 5, 9, 12, 11, 14, 17}。该数组可能是有序的,也可能是无序的。请写一个函数,求出将该数组变成有序数组时,最少需要重新排序的元素个数。例如{1, 4, 3, 5, 9, 12, 11, 14, 17},输出结果为:6,需要对{4, 3, 5, 9, 12, 11}重新排序。
最佳要求:时间复杂度O(N),空间复杂度O(1)。
算法+分析:
import java.util.Scanner;
/**
* 试题三
* @author: Mr.Hu
* @create: 2019-03-14 19:59
* 元素前面都小于元素自身,后面的都大于元素自身,则不需要排序。
* 因此我们记录前面的最大值,后面的最小值。两次遍历即可
* 分情况:无序数组在中间,在边上和全部有序。
* 全部有序输出0,在边上4 1 2 3 输出数组的lenth,在中间安上面思路计算。
* 总体时间复杂度为O(n),
* 输入样例:
* 9
* 1 4 3 5 9 12 11 14 17
*/
public class Main{
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
while (sc.hasNextInt()){
int n=sc.nextInt();
int[] a=new int[n];
for (int i = 0; i < n; i++) {
a[i]=sc.nextInt();
}
System.out.println( max(a));
}
}
public static int max(int[] num){ //
int preMax=0,bacMin=Integer.MAX_VALUE;
int start=num.length,end=-1;
for (int i = 0; i < num.length; i++) {
if (preMax > num[i] ) {
start=start>i?i:start;
end=end<i?i:end;
}
else preMax = num[i];
}
for (int i = num.length-1; i >=0 ; i--) {
if (bacMin< num[i]) {
start=start>i?i:start;
end=end<i?i:end;
}
else bacMin=num[i];
}
if(preMax==num[0] || bacMin==num[num.length-1]) return num.length; //无序的在两边
return end==-1?0:end-start+1; //有序和无序的在中间的情况
}
}