题目及测试
package pid334;
/*递增的三元子序列
给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。
数学表达式如下:
如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1,
使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。
说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。
示例 1:
输入: [1,2,3,4,5]
输出: true
示例 2:
输入: [5,4,3,2,1]
输出: false
*/
public class main {
public static void main(String[] args) {
int[][] testTable = {{2,5,3,4,5},{1,1,1,1,1},{5,1,5,5,2,5,4},{1,1,-2,6}};
for (int[] ito : testTable) {
test(ito);
}
}
private static void test(int[] ito) {
Solution solution = new Solution();
boolean rtn;
long begin = System.currentTimeMillis();
System.out.print("ito=");
for(int num:ito){
System.out.print(num+" ");
}
System.out.println();
//开始时打印数组
rtn= solution.increasingTriplet(ito);//执行程序
long end = System.currentTimeMillis();
System.out.println("rtn=" );
System.out.print(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,8ms,超慢)
速度o(n) 空间o(1)
使用两个数组,共2个*2,记录3元数组的前两个,总体思路就是找到小的塞到数组,如果有数比数组第二个元素大的,则成功
package pid334;
import java.util.Arrays;
public class Solution {
public boolean increasingTriplet(int[] nums) {
boolean result=false;
int length=nums.length;
if(length<=2){
return result;
}
Integer[] prev=new Integer[2];
Integer[] next=new Integer[2];
for(int i=0;i<length;i++){
int now=nums[i];
//next为空
if(next[0]==null){
//初始化
if(prev[0]==null){
prev[0]=now;
continue;
}
//到这里prev【0】一定存在
//第二个数没有且比第一个大
if(prev[1]==null&&prev[0]<now){
prev[1]=now;
continue;
}
//第二个数没有且比第一个小,则第一个为now
if(prev[1]==null&&prev[0]>=now){
prev[0]=now;
continue;
}
//到这里prev【1】一定存在
//now>prev[1],成功
if(now>prev[1]){
result=true;
break;
}
//比现在的prev1小,比prev0大,prev1=now,开启next
if(now<prev[1]&&now>prev[0]){
prev[1]=now;
next[0]=now;
continue;
}
//比现在的prev0小,开启next
if(now<prev[0]){
next[0]=now;
continue;
}
}
//next0存在
else{
//前置成功条件
if(now>prev[1]){
result=true;
break;
}
//next1不存在
if(next[1]==null){
//now比next0小,则next0为now
if(now<=next[0]){
next[0]=now;
continue;
}
//now比next0大,则next1为now
else{
next[1]=now;
}
}
//next1存在
else{
//next成功条件
if(now>next[1]){
result=true;
break;
}
//now比next0小,重置next
if(now<next[0]){
prev[0]=next[0];
prev[1]=next[1];
next[0]=now;
next[1]=null;
continue;
}
}
}
}
return result;
}
}
解法2(成功,2ms,极快)
3个连续递增子序列
有3个槽位,a,b,c
满足条件 a < b < c,即可
需要将合适的元素填入这3个槽位
比如说:
one=10,two=20,
如果现在n>20,直接成功,
10<n<=20,two=n,
n<10,one=n (这里是重点),假设n=5,此时one=5,two=20,然后下一步,
如果n<5,与之前一样,设置one=n,
如果20>n>5,设置two=n,此时递增数列是顺序的,one=5,two=15,比之前的10和20都小,而且是two在one后面
如果n>20,成功,因为尽管现在的one在two的后面,但是n比在前面的two大,
而每一个two都有一个比它小的,而且在two前面的one(在这里的一开始的10),(这句话很重要!!!!)
此时10,20,n,成为递增序列
public boolean increasingTriplet(int[] nums) {
int length=nums.length;
if(length<=2){
return false;
}
int first = nums[0];
int second = Integer.MAX_VALUE;
for(int i=1;i<length;i++) {
int now = nums[i];
if(now <= first) {
first = now;
continue;
}
if(now <= second) {
second = now;
continue;
}
return true;
}
return false;
}