目录
数组和矩阵问题,这些做得比较多。
未排序正整数数组中累加和为给定值的最长子数组长度
package Array;
/**
* Created by zdmein on 2017/8/30.
*未排序正整数数组中累加和为给定值的最长子数组长度
* 给定一个无需数组arr,其中元素为正,给定一个整数k。求arr的所有子数组中累加和为k的最长子数组的长度。
* arr=[1,2,1,1,1],k=3
* 结果返回3
*/
public class getMaxLength1 {
public static void main(String [] args){
int [] arr={1,2,1,1,1};
int k=3;
System.out.println(getMaxLength(arr,k));
}
public static int getMaxLength(int [] arr ,int k){
if(arr==null||arr.length<0||k<0){
return 0;
}
int right =0;
int left=0;
int len=0;
int sum=arr[0];
while (right<arr.length){
if(sum==k){
len=Math.max(len,right-left+1);
sum-=arr[left++];
}else if(sum<k){
right++;
if(right==arr.length){
break;
}
sum+=arr[right];
}else {
sum-=arr[left++];
}
}
return len;
}
}
数组partition调整使数组的左部分单调有序
给定一个有序数组arr,调整使得数组的左部分无重复元素且有序,右边部分不要求。如数组arr[]={1,2,2,2,3,3,4,5,6,9,9} ;调整过后可以为:[1, 2, 3, 4, 5, 6, 9, 2, 3, 2, 9] 。
思路:使用标记 u 其中arr[0…u] 表示已经处理过的没有重复元素且有序的区间,从arr[u+1…i-1]表示有重复元素的部分。则算法主要分为下面两部分。
1. 比较 arr[i] 与 arr[u] 是否相同如果不同,则将 arr[i] 的值赋给arr[u+1],u++;
2. i++遍历数组。
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
int[] arr = {1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9};
leftUnique(arr);
}
public static void leftUnique(int[] arr) {
if (arr.length == 0 || arr == null) {
return;
}
int u=0;
int i=1;
while (i!=arr.length){
if(arr[i++]!=arr[u]){
swap(arr,i-1,++u);
}
}
for( i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
}
public static int [] swap(int[] arr,int m, int n){
int temp= arr[m];
arr[m]=arr[n];
arr[n]=temp;
return arr ;
}
}
将正方形矩阵顺时针转动90度
题目:给定一个N*N的矩阵matrix,求把这个矩阵调整成顺时针转动90度后的形式。
例如:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
顺时针转动90度后为:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
要求:额外空间复杂度为O(1)
public class Main {
public static void main(String[] args) {
int[][] m = { {1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16} };
rotate(m);
}
public static void rotate(int[][] arr) {
int tR=0;
int tC=0;
int dR=arr.length-1;
int dC=arr[0].length-1;
while (tR<dR){
rotateEdge(arr,tR++,tC++,dR--,dC--);
}
for (int i=0;i<arr.length;i++) {
for (int j = 0; j < arr[0].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println(" ");
}
}
public static void rotateEdge(int [][] arr ,int tR,int tC ,int dR ,int dC){
int times=dR-tR;
int temp=0;
for(int i=0;i!=times;i++){
temp = arr[tR][tC+i];
arr[tR][tC+i]=arr[dR-i][tC];
arr[dR-i][tC]=arr[dR][dC-i];
arr[dR][dC-i]=arr[tR+i][dC];
arr[tR+i][dC]=temp;
}
}
}
找到无序数组中最小的K个数
给定一个无序的整型数组arr,找到其中最小的k个数。
时间复杂度:O(nlogk)
维护一个有k个数的大根堆,这个堆代表目前选出的k个最小的数。在堆的k个元素中堆顶元素是最小的k个数中最大的那个。
接下来要遍历整个数组,遍历的过程中看当前数是否比堆顶元素小。如果是,就把堆顶元素替换成当前数,然后调整堆。如果不是,则不做任何操作,继续遍历下一个数。在遍历完成后,堆中的k个数就是所有数组中最小的k个数。
public class Main {
public static void main(String[] args) {
int[] arr = {5 ,9,3,4,7,2,8,1,6};
int k=3;
int [] res= getMinKNumsByHeap(arr,k);
for(int i=0;i<res.length;i++){
System.out.println(res[i]);
}
}
public static int [] getMinKNumsByHeap(int[] arr,int k) {
if(k<1&&k>arr.length){
return arr;
}
int kHeap[]=new int [k];
for(int i=0;i!=k;i++){
heapInsert(kHeap,arr[i],i);
}
for(int i = k;i !=arr.length;i++){
if(arr[i]<kHeap[0]){
kHeap[0]=arr[i];
heapify(kHeap,0,k);
}
}
return kHeap;
}
public static void heapify(int [] arr, int index ,int heapsize){
int left= index*2+1;
int right=index*2+2;
int largest=index;
while(left<heapsize){
if(arr[left]>arr[index]){
largest=left;
}
if(right<heapsize && arr[right]>arr[largest]){
largest=right;
}
if(largest!=index){
swap(arr,largest,index);
}else {
break;
}
index=largest;
left= index*2+1;
right=index*2+2;
}
}
public static void heapInsert(int [] kHeap ,int arri ,int i){
kHeap[i]=arri;
while (i!=0){
int parent=(i-1)/2;
if(kHeap[parent]<kHeap[i]){
swap(kHeap,parent,i);
i=parent;
}else {
break;
}
}
}
public static void swap(int [] arr ,int m ,int n){
int temp=arr[m];
arr[m]=arr[n];
arr[n]=temp;
}
}
三数排序
给定一个数组,其中只有三个数0,1,2三个值,请实现arr排序。
三个颜色的球排序
用left和right标记数组头和尾,用index遍历,遇到该交换的交换,直到index==right为止。
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
int[] arr = {1,0,2,0,1,2,1,0 ,2, 2,0};
leftUnique(arr);
}
public static void leftUnique(int[] arr) {
if (arr.length <2 || arr == null) {
return;
}
int left=-1;
int index=0;
int right=arr.length;
while (index<right){
if(arr[index]==0){
swap(arr,++left,index++);
}else if(arr[index]==2){
swap(arr,--right,index);
}else {
index++;
}
}
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
}
public static int [] swap(int[] arr,int m, int n){
int temp= arr[m];
arr[m]=arr[n];
arr[n]=temp;
return arr ;
}
}
转圈打印矩阵
给一个整型矩阵matrix,按照转圈的方式打印它。
1 2 3
4 5 6
7 8 9
打印就是:1 2 3 6 9 8 7 4 5
public class CircleDynamic {
public static void main(String [] args){
int [][] m= {{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}};
spirOrderPrint(m);
}
public static void spirOrderPrint(int [][]matrix){
int tR = 0;
int tC = 0;
int dR=matrix.length-1;
int dC=matrix[0].length-1;
while (tR<=dR && tC<=dC){
printEdge(matrix,tR++,tC++,dR--,dC--);
}
}
public static void printEdge(int [][] matrix ,int tR ,int tC,int dR , int dC){
if(tR==dR){
for(int i=0;i<=dC;i++){
System.out.print(matrix[tR][i]+" ");
}
}else if(tC==dC){
for(int i=0;i<dR ;i++){
System.out.print(matrix[i][tC]+ " ");
}
}else {
int curC=tC;
int curR=tR;
while (curC != dC){
System.out.print(matrix[tR][curC]+" ");
curC++;
}
while (curR!=dR){
System.out.print(matrix[curR][dC]+" ");
curR++;
}
while (curC != tC){
System.out.print(matrix[dR][curC]+" ");
curC--;
}
while (curR!=tR){
System.out.print(matrix[curR][tC]+" ");
curR--;
}
}
}
}
"之"字形打印矩阵
- 上坐标(tR,tC)初始为(0,0),先向右走(tC++),再向下走tR++
- 下坐标类似
- 打印斜线方向用boolean判断
public class CircleDynamic {
public static void main(String [] args){
int [][] m= {{1,2,3, 4},
{5,6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}};
printMatrixZigZag(m);
}
public static void printMatrixZigZag(int [][] matrix){
int tR = 0;
int tC = 0;
int dR = 0;
int dC = 0;
int endR = matrix.length-1;
int endC = matrix[0].length-1;
boolean flag=false;
while (tR!=matrix.length){
printZigZag(matrix,tR,tC,dR,dC,flag);
tC=tC==endC?tC:tC+1;
tR= tC==endC ?tR+1:tR;
dR=dR==endR?dR:dR+1;
dC=dR==endR?dC+1:dC;
flag=!flag;
}
}
public static void printZigZag(int [][] matrix,int tR,int tC,int dR,int dC,boolean flag ){
if(flag){
while (tR!=dR+1){
System.out.print(matrix[tR++][tC--]+" ");
}
}else {
while (dR!=tC-1) {
System.out.print(matrix[dR--][dC++]+" ");
}
}
}
}
自然数数组的排序
给定一个长度为N的整型数组arr,其中有N个互不相等的自然数1~N,请实现arr的排序,但是不要把下标0~N-1位置上的数值通过直接赋值的方式替换成1~N。
要求:时间复杂度为O(N),额外空间复杂度为O(1)。
思路:
1.从左向右遍历arr,假设当前遍历到i位置。
2.if arr[i]==i+1,不需要调整,继续遍历。
3.if arr[i]!=i+1,进行调整。
根据调整功能的方法不同,可以有不同的实现过程。
public class CircleDynamic {
public static void main(String [] args){
int [] m= {1,2,5,3, 4};
m=sort(m);
for(int i=0;i<m.length;i++){
System.out.println(m[i]);
}
}
public static int [] sort(int [] matrix){
for(int i=0;i<matrix.length;i++){
while(matrix[i]!=i+1){
int temp=matrix[matrix[i]-1];
matrix[matrix[i]-1]=matrix[i];
matrix[i]=temp;
}
}
return matrix;
}
}
奇数下标都是奇数或偶数下标都是偶数
给定一个长度不小于2的数组arr,实现一个函数调整arr,要么使所有的偶数下标都是偶数,要么使所有的奇数下标都是奇数。
要求:时间复杂度为O(N),额外空间复杂度为O(1)。
算法解释:
最后位置的数是偶数,就替换前面的偶数下标,最后位置的是奇数,就替换前面的奇数下标,每替换一次,最后位置的数都是变化的,这样就都替换了。
public class CircleDynamic {
public static void main(String [] args){
int [] m= {1,8,3,2,4,6};
modify(m);
}
public static void modify(int [] matrix){
if(matrix==null || matrix.length<2){
return;
}
int even=0;
int odd=1;
int end=matrix.length-1;
while (even<=end && odd<=end){
if((matrix[end]&1)==0){
swap(matrix,even,end);
even+=2;
}else {
swap(matrix,odd,end);
odd+=2;
}
}
for(int i=0;i<matrix.length;i++){
System.out.println(matrix[i]);
}
}
public static void swap(int [] m,int index1,int index2){
int temp=m[index1];
m[index1]=m[index2];
m[index2]=temp;
}
}
子数组的最大累加和问题
给定一个数组,返回子数组的最大累加和。
例如:arr=[1,-2,3,5,-2,6,-1],所有子数组中,[3,5,-2,6]可以累加出最大的和12,return 12.
时间复杂度为O(N),额外空间复杂度为O(1)。
如果arr中没有正数,产生的最大累加和一定是数组中的最大值。
如果arr中有正数,从左向右遍历arr,用变量cur记录每一步的累加和,遍历到正数cur增加,遍历到负数cur减少。当cur<0时,舍弃当前部分,令cur=0,表示重新从下一个数开始累加。当cur>=0时,每一次的累加都可能是最大的累加和,所以,用另外一个变量max全程跟踪cur出现的最大值。
cur累加到负数就重新累加,max记录当前cur的最大值。
public class CircleDynamic {
public static void main(String [] args){
int [] m= {1,-2,3,5,-2,6,-1};
maxSum(m);
}
public static void maxSum(int[] m){
if(m==null||m.length==0){
return;
}
int cur=0;
int max=0;
for(int i=0;i<m.length;i++){
cur+=m[i];
if(max<cur){
max=cur;
}
if(cur<0){
cur=0;
}
}
System.out.println(max);
}
}
子矩阵的最大累计和问题
给定一个矩阵,其中的值有正、有负、有0。返回子矩阵的最大累计和。
如果一个矩阵一共有K行且限定必须含有K行元素的情况下,只要把矩阵中每一行的K个元素累加生成一个累加数组,然后求出这个数组的最大累加和,这个最大累加和就是必须含有K行元素的子矩阵中的最大累加和。
用i动态测试每一层往下累计的最大值,i+1实际上是把i层之上的全部不算。实现动态遍历
j和k是普通遍历
用s[k]存每次往下加的数字
cur加s[k]如果大就保存,如果不是最大就不存,如果小于0就清零。
public class Main {
public static void main(String[] args) {
int[][] m = {{-90, 48, 78},
{64, -40, 64},
{-81, -7, 66}};
maxSum(m);
}
public static void maxSum(int[][] m) {
if (m == null || m.length == 0 || m[0].length == 0) {
return;
}
int cur = 0;
int max = Integer.MIN_VALUE;
int []s=null;
for (int i = 0; i < m.length; i++) {
s = new int[m[0].length];
for (int j = i; j < m.length; j++) {
cur = 0;
for (int k = 0; k < m[0].length; k++) {
s[k] += m[j][k];
cur += s[k];
max = Math.max(max, cur);
if (cur < 0) {
cur = 0;
}
}
}
}
System.out.println(max);
}
}
在数组中找到一个局部最小的位置
定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]为局部最小。如果arr[N-1]<arr[N-2],那么arr[N-1]是局部最小。如果0<i<N-1,arr[i]<arr[i+1]&&arr[i]<arr[i-1],那么arr[i]是局部最小。
给定无序数组arr,已知arr中任何两个相邻的数不相等。写一个函数,只需返回arr中任何一个局部最小出现的位置即可。
利用二分查找可以做到时间复杂度O(logN)、额外空间复杂度为O(1)
public class Main {
public static void main(String[] args) {
int[] m = {90,78, 48, 78};
System.out.println(getLessIndex(m));
}
public static int getLessIndex(int[] arr) {
if(arr==null || arr.length==0){
return -1;
}
if(arr[0]<arr[1]){
return 0;
}
if(arr[arr.length-1]<arr[arr.length-2]){
return arr[arr.length-1];
}
int left = 1;
int right= arr.length-2;
int mid=0;
while (left<right){
mid=(right+left)/2;
if(arr[mid]>arr[mid-1]){
right=mid-1;
}else if(arr[mid]>arr[mid+1]){
left=mid+1;
}else {
return mid;
}
}
return left;
}
}
不包含本位置值的累乘数组
给定一个整型数组,返回不包含本位置的累乘数组。
例如:arr=[2,3,1,4],返回[12,8,24,6],即除自己外,其他位置的类乘。
1.时间复杂度为O(N).
2.除需要返回的结果数组之外,额外空间复杂度为O(1).
使用除法:
结果数组记为res,所有数的乘积记为all。如果数组中不含0,则设置res[i]=all/arr[i]。如果数组中有一个0,对唯一的arr[i]==0的位置令res[i]=all,其他位置都是0。如果数组中0的数量大于1,那么res所有位置上的值都是0。
不使用除法:
1.生成两个长度和arr一样的新数组lr[]和rl[],lr[i]=arr[0…i],rl[i]=arr[i…N-1]。
2.res[i]=lr[i-1]*rl[i+1]
3.res[0]=rl[1],res[N-1]=lr[N-2]
这里又额外使用了两个数组,可以通过res数组复用的方式省略掉这两个数组,先把res数组作为辅助计算的数组,然后把res调整成结果数组返回。
public class Main {
public static void main(String[] args) {
int[] m = {2,3, 1, 4};
m= product(m);
for(int i=0;i<m.length;i++){
System.out.println(m[i]);
}
}
public static int [] product(int[] arr) {
if(arr==null || arr.length==0){
return null;
}
int[] res=new int [arr.length];
res[arr.length-1]=1;
for(int i=arr.length-2;i>=0;i--){
res[i]=res[i+1]*arr[i+1];
}
int temp=1;
for(int i=0;i<arr.length;i++){
res[i]*=temp;
temp*=arr[i];
}
return res;
}
}
求最短通路值
用一个整形矩阵matrix表示一个网络,1代表有路,0代表没路,每一个位置只要不越界,都有上下左右4个方向,求从最左上角到最右下角的最短通路值。
例如:
1 0 1 1 1
1 0 1 0 1
1 1 1 0 1
0 0 0 0 1
通路只有1条,由12个1组成,所以返回12。
使用宽度优先遍历即可,如果矩阵大小为NM,时间复杂度为O(NM),
1.开始时生成map矩阵,map[i][j]的含义是从(0,0)位置走到(i,j)位置最短的路径值。然后将左上角位置(0,0)的行坐标和列坐标放入行队列rQ、列队列 cQ。
2.不断从队列弹出一个位置(r,c),然后看这个位置的上下左右四个位置哪些在matrix上的值是1,这些都是能走的位置。
3.将那些能走的位置设置好各自在map中的值,即map[r][c]+1。同时将这些位置加入到rQ和cQ的中,用队列完成宽度优先遍历。
4.在步骤3中,如果一个位置走过,就不要重复走,这个逻辑可以根据一个位置在map中的值来确定,比如map[i][j]!=0,就可以知道这个位置之前走过。
5.一直重复步骤2~步骤4。直到遇到右下角位置,说明已经找到终点,返回终点在map中的值即可,如果rQ和cQ已经为空都没有遇到终点位置,return 0。
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
int[][] m = { {1,0,1,1,1},
{1,0,1,0,1},
{1,1,1,0,1},
{0,0,0,0,1} };
System.out.println(minPathValue(m));
}
public static int minPathValue(int [][] m){
if(m==null || m.length==0|| m[0].length==0||m[0][0]!=1||m[m.length-1][m[0].length-1]!=1){
return 0;
}
int res=0;
int [][] map=new int [m.length][m[0].length];
map[0][0]=1;
Queue<Integer> rQ=new LinkedList<Integer>();
Queue<Integer> cQ=new LinkedList<Integer>();
rQ.add(0);
cQ.add(0);
int r=0;
int c=0;
while (!rQ.isEmpty()){
r=rQ.poll();
c=cQ.poll();
if( ( r==m.length-1 ) && ( c==m[0].length-1)){
//查map路径
for(int i=0;i<map.length;i++){
for (int j=0;j<map[0].length;j++){
System.out.print(map[i][j]+" ");
}
System.out.println(" ");
}
//输出结果
return map[r][c];
}
walkTo(map[r][c],r-1,c,m,map,rQ,cQ);
walkTo(map[r][c],r+1,c,m,map,rQ,cQ);
walkTo(map[r][c],r,c-1,m,map,rQ,cQ);
walkTo(map[r][c],r,c+1,m,map,rQ,cQ);
}
return res;
}
public static void walkTo(int pre,int toR,int toC ,int [][]m , int [][] map,Queue<Integer> rQ , Queue<Integer> cQ ){
if (toR < 0 || toR == m.length || toC < 0 || toC == m[0].length || m[toR] != 1 || map[toR][toC] != 0) {
return;
}
map[toR][toC]=pre+1;
rQ.add(toR);
cQ.add(toC);
}
}
---res:
1 0 7 8 9
2 0 6 0 10
3 4 5 0 11
0 0 0 0 12
12
最长的可整合数组的长度
如果一个数组再排序之后,每相邻两个数差的绝对值都为1,则该数组为可整合数组。例如,[5,3,4,6,2]排序之后为[2,3,4,5,6],符合每相邻两个数差的绝对值为1,所以这个数组为可整合数组。
给定一个整型数组,请返回其中最大可整合子数组的长度。例如,[5,5,3,2,6,4,3]的最大可整合子数组为[5,3,2,6,4],所以返回5.
一个数组中如果没有重复元素,并且如果最大值减去最小值,再加上1的结果等于元素的个数(max-min+1=元素个数),那么这个数组就是可整合数组。
这样,验证一个数组是否是可整合数组的时间复杂度可以从第一种方法的O(NlogN)减少至O(1),整个过程的时间复杂度为O(N^2)
无需排序,仅仅只需要遍历比较大小
public class Main {
public static void main(String[] args) {
int[] m = { 5,5,3,2,6,4,3};
System.out.println(getLIL(m));
}
public static int getLIL(int [] arr){
if(arr.length==0||arr==null){
return 0;
}
int max=0;
int min=0;
int len=0;
HashSet<Integer> set=new HashSet<Integer>();
for(int i=0;i<arr.length;i++){
max=Integer.MIN_VALUE;
min=Integer.MAX_VALUE;
for(int j=i;j<arr.length;j++){
if(set.contains(arr[j])){
break;
}
set.add(arr[j]);
max=Math.max(max,arr[j]);
min=Math.min(min,arr[j]);
if(max-min==j-i){
len=Math.max(len,j-i+1);
}
}
set.clear();
}
return len;
}
}
边界都是1的最大正方形大小
给定一个M*N的矩阵,在这个矩阵中,只有0和1两种值,返回边框全是1的最大正方形的边长长度。
例如:
[0, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 1, 1, 0, 1],
[0, 1, 1, 1, 1],
[0, 1, 0, 1, 1]
其中,边框全是1的最大正方形的大小为4。
解析:
1.正方形边长为0<=size<=Math.min(rows,cols);
2.边长为size时,左上角的坐标范围为 0<=i<=rows-size,0<=j<=cols-size;
3.使用预处理矩阵right和down,空间换时间,right[i][j]保存matrix[i][j]包括自己往右边有多少个1,同理down[i][j]。
3.对每一个左上角的边长为size的矩形判断边上是否全为1,发现有满足的直接返回当前size。
public class Main {
public static void main(String[] args) {
int[][] arr = { {0,1,1,1,1},
{0,1,0,0,1},
{0,1,0,0,1},
{0,1,1,1,1},
{0,1,0,1,1}};
System.out.println(getMaxSize(arr));
}
public static int getMaxSize(int [][]m){
int [][] right=new int [m.length][m[0].length];
int [][] down= new int [m.length][m[0].length];
setBorderMap(m,right,down);
for(int size=Math.min(m.length,m[0].length);size!=0;size--){
if(hasSizeOfBorder(size,right,down)){
return size;
}
}
return 0;
}
public static void setBorderMap(int [][] m,int [][]right ,int [][]down){
int r=m.length;
int c=m[0].length;
if(m[r-1][c-1]==1){
right[r-1][c-1]=1;
down[r-1][c-1]=1;
}
for(int i=r-2;i>=0;i--){
if(m[i][c-1]==1){
right[i][c-1]=1;
down[i][c-1]=down[i+1][c-1]+1;
}
}
for(int j=c-2;j>=0;j--){
if(m[r-1][j]==1){
right[r-1][j]=right[r-1][j+1]+1;
down[r-1][j]=1;
}
}
for(int i=r-2;i>=0;i--){
for (int j=c-2;j>=0;j--){
right[i][j]=right[i][j+1]+1;
down[i][j]=down[i+1][j]+1;
}
}
}
public static boolean hasSizeOfBorder(int size ,int [][]right ,int [][] down){
for(int i=0;i<right.length-size+1;i++){
for(int j=0;j<right[0].length-size+1;j++){
if(right[i][j]>=size&&down[i][j]>=size
&&right[i+size-1][j]>=size
&&down[i][j+size-1]>=size)
return true;
}
}
return false;
}
}
需要排序的最短子数组长度
package Array;
/**
* Created by zdmein on 2017/9/15.
* 需要排序的最短子数组长度
* 思路:
用noMin 记录从右到左,可以遍历的,最左边开始需要重新排的
用noMax 记录从左到右,可以遍历的,最右边需要重新排的
1, 5,3,4,2, 6,7
返回 4
*/
public class getMinLength1 {
public static void main(String args[]){
int []arr={1,5,3,4,2,6,7};
System.out.println(getMinLength(arr));
}
public static int getMinLength(int [] arr){
if(arr==null||arr.length<2){
return 0;
}
int min=arr[arr.length-1];
int noMin=-1;
for(int i=arr.length-2;i>=0;i--){
if(arr[i]>min){
noMin=i;
}else {
min=Math.min(arr[i],min);
}
}
if(noMin==-1)
return 0;
int max=arr[0];
int noMax=-1;
for(int i=1;i<arr.length;i++){
if(arr[i]<max){
noMax=i;
}else {
max=Math.max(max,arr[i]);
}
}
return noMax-noMin+1;
}
}