对于一个无序数组A,请设计一个算法,求出需要排序的最短子数组的长度。
给定一个整数数组A及它的大小n,请返回最短子数组的长度。
测试样例:
[1,5,3,4,2,6,7],7
返回:4
class ShortSubsequence { public: int findShortest(vector<int> A, int n) { // write code here int k = -1; int max = A[0]; for(int i=1;i<n;i++){ if(max > A[i]) k = i; else max = A[i]; } if(k==-1)return 0; int m = -1; int min = A[n-1]; for(int i=n-2;i>=0;i--){ if(min < A[i]) m = i; else min = A[i]; } return k-m+1; } };
class ShortSubsequence:
def findShortest(self, A, n):
B, start, end, canEnd = sorted(A), 0, -1, False
for i, v in enumerate(A):
if v != B[i]:
if not canEnd:
start = i
canEnd = True
else:
end = i
return end - start + 1
//两次遍历,题目中[1,5,3,4,2,6,7],7,我们要找到5和2的位置,怎么找呢?
他们2个有什么特征呢?他们都阻碍了单调性,而2是从左到右最后一个阻碍单调性的元素
而5是从右到左最后一个阻碍单调性的元素,知道之后我们需要两次遍历,一次从左到右,一次从右到左,具体怎么找看下面代码注释把!
};
//测试数据{1,2,10,1,8,9} 结果是4//但是这个测试明明就是5才对啊,所以测试用例错了classShortSubsequence {public:intfindShortest(vector<int> A, intn) {// write code hereintlen=n;intmin=A[len-1];intminIndex=-1;for(inti=len-2;i>=0;i--){if(A[i]>min)minIndex=i;elsemin=A[i];}if(minIndex==-1)return0;intmax=A[0];intmaxIndex=-1;for(inti=1;i<len;i++){if(A[i]<max)maxIndex=i;elsemax=A[i];}returnmaxIndex-minIndex+1;}};
import java.util.*; public class ShortSubsequence { public int findShortest(int[] A, int n) { // write code here int[] B=new int[n]; for(int i=0;i<n;i++) B[i]=A[i]; Arrays.sort(B); int indexStart=0; for(int i=0;i<n;i++){ if(A[i]!=B[i]){ indexStart=i; break; } } int indexEnd=0; for(int j=n-1;j>=0;j--){ if(A[j]!=B[j]){ indexEnd=j+1; break; } } return (indexEnd-indexStart)>0?(indexEnd-indexStart):0; } }
class ShortSubsequence: def findShortest(self, A, n): i, j = 0, n-1 while min(A[i + 1:]) >= A[i]: i += 1 if i >= n-1: return 0 while A[j] >= max(A[i:j]): j -= 1 return j-i+1
class ShortSubsequence { public: int findShortest(vector<int> A, int n) { // write code here vector<int> B(A.begin(),A.end()); sort(B.begin(),B.end()); int i=0,j=A.size()-1; for(;i<A.size();i++) if(A[i]!=B[i]) break; for(;j>=0;j--) if(A[j]!=B[j]) break; return -(j-i+1)==A.size()?0:(j-i+1); } };
class ShortSubsequence { public: int findShortest(vector<int> A, int n) { int k=-1,Max=A[0]; for(int i=1;i<n;i++) { if(Max > A[i]) k = i; else Max = A[i]; } if(k==-1) return 0; int m = -1; int Min = A[n-1]; for(int i=n-2;i>=0;i--) { if(Min < A[i]) m = i; else Min = A[i]; } return k-m+1; } };
class ShortSubsequence { public: // Left 左边第一个不等的位置 // Right 右边第一个不等的位置 int findShortest(vector<int> A, int n) { // write code here int t[n],res = 0; for(int i = 0; i < n; ++i) t[i] = A[i]; sort(A.begin(),A.end()); int Left = -1,Right = -1 ; for(int i = n - 1; i >= 0; --i){ if(t[i] != A[i]){ Right = i; break; } } for(int i = 0; i < n;++i){ if(t[i] != A[i]){ Left = i; break; } } if(Left == Right && Left == -1) return 0; else return Right - Left + 1; } };
分两部分进行,第一步寻找起始地最小位置,第二部寻找最后的最大位置,两者相减便是最小子串的长度。 public class ShortSubsequence { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int A[] = { 1, 2, 10, 1, 8, 9 }; new ShortSubsequence().findShortest(A, 6); } public int findShortest(int[] A, int n) { // write code here int size = 1; int begin = 0; int end = n - 1; for (int i = 0; i < n - 1; i++) { int j = i + 1; for (; j < n; j++) { if (A[i] > A[j]) { break; } } if (j == n) { begin++; } else { break; } } for (int i = n - 1; i >= 1; i--) { int j = i - 1; for (; j >= 0; j--) { if (A[i] < A[j]) { break; } } if (j == -1) { end--; } else { break; } } System.out.println(end - begin + 1); if (end - begin + 1 < 0) return 0; return end - begin + 1; } }
//我觉得是不是答案错了,答案的一个示例:{1,2,10,1,8,9} 结果是4 //我的代码运行结果是5,直观看来,答案就是5啊 import java.util.*; public class ShortSubsequence { public static void main(String[] args){ int[] A={1,5,3,4,2,6,7}; findShortest(A,A.length); } public static int findShortest(int[] A, int n) { // write code here int s=0; while(s<n-1){ if(A[s+1]<A[s]) break; else s++; } if(s==(n-1)) return 0; int min=A[s+1]; for(int j=n-1;j>s+1;j--){ if(A[j]<min){ min=A[j]; } } while(s>=0){ if(A[s]>min) s--; else break; } int end=n-1; while(end>s){ if(A[end-1]>A[end]) break; else end--; } int max=0; for(int i=s+1;i<end;i++){ if(A[i]>max){ max=A[i]; } } while(end<n){ if(A[end]<max) end++; else break; } return end-s-1; } }
思路:1.先判断依次最小值是否在正确位置,直到找到不在正确位置最小值的应该在的位置,作为最小需排序的起始点
2.依次判断最大值是否在正确位置,直到找不到正确位置最大值应该在的位置,作为最小需排序的末尾点
3.计算首末位点间的整数个数,即为需要排序的最短子数组长度
import java.util.*;
public class ShortSubsequence {
public int findShortest(int[] A, int n) {
int maxIndex = n-1;
int i=0;
for(;i<n;i++){
//判断当前子串最小值是否位置正确,若正确继续判断剩余子串最小值是否正确;
//若不正确,判断子串最大值位置是否正确
if(maxIndex==n-1){//
int tmp = findMin(A,i,n);
if(tmp==i){
continue;
}
}
int tmp = findMax(A,i,maxIndex+1);
if(maxIndex==tmp){//若子串最大值位置正确,更新子串最大值位置
maxIndex--;
i--;
continue;
}else{//若子串最大值位置不正确,结束循环
break;
}
}
return maxIndex-i+1;
} //寻找子串中的最小值的下标 public int findMin(int[] sub,int start, int n){
int min = sub[start];
int index = start;
for(int i=start+1;i<n;i++){
if(min>sub[i]){
min=sub[i];
index = i;
}
}
return index;
}
//寻找子串中的最大值的下标
public int findMax(int[] sub,int start, int n){
int max = sub[start];
int index = start;
for(int i=start+1;i<n;i++){
if(max<sub[i]){
max=sub[i];
index = i;
}
}
return index;
}
}
class ShortSubsequence { public: int findShortest(vector<int> A, int n) { // write code here int ans = 0; vector<int>Max(n,0); vector<int>Min(n,0); // 每个元素左侧的最大值 for(int i=1;i<n;++i) { if(i==1) Max[i]= A[0]; else Max[i] = max(A[i-1],Max[i-1]); } // 每个元素右侧最小值 for(int i=n-2;i>=0;--i) { if(i==n-2) Min[i]=A[n-1]; else Min[i] = min(Min[i+1],A[i+1]); } int i = 0; int j = n-1; while(i<n && A[i]<=Min[i]) ++i; while(j>=0 && A[j]>=Max[j]) --j; if(i>=n || j<=0) return 0; return j-i+1; } };
# -*- coding:utf-8 -*- class ShortSubsequence: def findShortest(self, A, n): # write code here list1=A list1=sorted(list1) re=[] for i in range(n): if list1[i]!=A[i]: re.append(i) if len(re)!=0: return max(re)-min(re)+1 else: return 0 找到与排好序的列表的不同的段,用最后的减去最前的位置加一就行了
//思路1:简单暴力,时间复杂度O(NlogN)+O(N),空间复杂度O(N) class ShortSubsequence { public: int findShortest(vector<int> A, int n) { vector<int> B(A);//额外开辟一个数组复制A数组并且排序 sort(B.begin(),B.end()); int left=0,right=n-1; while(left<=right && A[left]==B[left]) ++left; while(left<=right && A[right]==B[right])--right; //A从左到右不在最终位置的元素就是最短子数组长度 if(left>right) return 0; return right-left+1; } }; //思路二:参考楼上大佬的代码,时间复杂度O(N) 空间复杂度O(1) //根据样例模拟画个折线图会更好理解点 class ShortSubsequence { public: int findShortest(vector<int> A, int n) { int right=0,max=A[0]; for(int i=1;i<n;++i) if(A[i]>=max) max=A[i];//若第i个数A[i]大于等于前面的最大值,说明从前面看过来不用排序 else right=i;//否则,需要排序的子数组最右边界是i(i不断更新向右) if(right==0) return 0;//right==0说明数组已经全局有序了 int left,min=A[n-1];//因为right不为0所以说明数组非全局有序,left一定会有值,所以不用赋初值 for(int i=n-1;i>=0;--i) if(A[i]<=min)//同理,若第i个数A[i]小于等于后面的最小值,说明从后面看过来不用排序 min=A[i]; else left=i;//否则,需要排序的子数组最是左边的边界是i(i不断更新向左) return right-left+1; } };