334. Increasing Triplet Subsequence

  不定期更新leetcode解题java答案。

  采用pick one的方式选择题目。

  题意为检测一个无序数组中是否存在三个递增序列(可不连续)。

  Return true if there exists i, j, k 
  such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.

  要求尽量时间复杂度在O(n),空间复杂度在O(1)。

  主要考虑几种情况,将可能出现的三个递增序列依次命名为leftNum,midNum,rightNum,在遍历检测数组时,一共有两种可能出现的情况(除了在检测数组第一个数字前leftNum是空值,其他过程中leftNum均为存在的值):

  1、我们检测新数字之前只有leftNum存在,前面不存在递增序列,midNum还无法添加;

  2、前面已有递增序列,midNum已经添加完,只求能有更大值填入rightNum,最后返回true。

  由于有两种情况,我们需要一个控制变量来标志midNum是否已经被填入。我们依次分析这两种情况:

  情况1,如果出现数比leftNum大,则填入midNum,进入情况2;否则替换leftNum,仍处于情况1。

  情况2,如果出现数比midNum大,则返回true。如果比leftNum大比midNum小,则将新数字替换为midNum;然而,当数字比leftNum小,问题则出现,由此可看出我们仍需要一个变量minNum(请仔细看清minNum和midNum)来存储数组最小值。

  这时我们重新将上述问题分析一遍,过程变成了这样:

  情况1,如果出现数比minNum大,则填入midNum,进入情况2;否则替换minNum,仍处于情况1(这里minNum与leftNum实际是等价的)。

  情况2,如果出现数比midNum大,则返回true。如果比minNum小,则替换minNum(逻辑是这样,因为minNum记录的就是数组已经遍历的最小值);如果出现数在minNum和midNum之间,那么无论与leftNum大小关系如何,我们应该将minNum替换为leftNum,将出现数替换为midNum,这样是利用贪心法取局部最优解,后面的情况依旧处于情况2,继续进行遍历。这里我们发现经过我们的分析,所有情况都没有使用到leftNum这个变量,因此没有必要去定义这个变量。

  当然,如果遍历完整个数组依旧没有返回true,则返回false。时间复杂度为O(n),空间复杂度为O(1)。

  具体代码如下:

 1 public class Solution {
 2     public boolean increasingTriplet(int[] nums) {
 3         if(nums.length < 3)
 4             return false;
 5         int minNum = nums[0]/*, leftNum = nums[0]*/, midNum = 0;
 6         boolean getMidNum = false;
 7         for(int i = 1; i < nums.length; i++){
 8             if(getMidNum){
 9                 if(nums[i] <= midNum){
10                     if(nums[i] <= minNum)
11                         minNum = nums[i];
12                     else{
13                         // leftNum = minNum;   //actually need not, no use for leftNum
14                         midNum = nums[i];
15                     }
16                 }else
17 return true; 18 }else{ 19 if(nums[i] > minNum){ 20 getMidNum = true; 21 midNum = nums[i]; 22 }else 23 minNum = nums[i]; 24 } 25 } 26 return false; 27 } 28 }

  局部代码9~17行,如用这种方式替换,运行时间在leetcode上会从2ms变成1ms,可能和测试用例有关,具体代码如下:

1                if(nums[i] < midNum){
2                     if(nums[i] < minNum)
3                         minNum = nums[i];
4                     else if(nums[i] > minNum){
5                         // leftNum = minNum;   //actually need not, no use for leftNum
6                         midNum = nums[i];
7                     }
8                 }else if(nums[i] > midNum)
9                     return true;            

 

posted @ 2016-11-03 16:24  zslhq~  阅读(319)  评论(0编辑  收藏  举报