题目: 给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。
数学表达式如下:
如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1,
使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。
说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。
首先,新建两个变量 min和 mid ,分别用来保存题目要我们求的长度为 3 的递增子序列的最小值和中间值。
接着,我们遍历数组,每遇到一个数字,我们将它和 min 和 mid 相比,若小于等于 min ,则替换 min;
否则,若小于等于 mid,则替换 mid;否则,若大于 mid,则说明我们找到了长度为 3 的递增数组!
上面的求解过程中有个问题:当已经找到了长度为 2 的递增序列,这时又来了一个比 min还小的数字,
为什么可以直接替换 min 但是保留mid 呢?
比如: 2 3 1 5 min=2 mid=3 当遇到1的时候 min变为1 但是mid还是3,
继续往前遇到5, 5比mid=3 大 返回true 但是此时mid不在min后面 也正确吗?
因为: min遇到更小的更新 是为了尽量标识出更小的起始值
但是人家之前的2的位置和大小依然在哪 你找到比mid=3大的 自然可以 2 3 5 组成 没你新的min=1的事情
如果是2 3 1 2 5 这种情况: mid 遇到 第2个 2的时候 也会更新成2
那么这个三元序列的前两个值就从2 3 变成了1 2 ,
显然1 2 比 2 3能找到更多的满足条件的 三元序列的第三个值
public boolean increasingTriplet(int[] nums) {
if (nums.length < 3) return false;
int min = nums[0], mid = Integer.MAX_VALUE;
for (int i = 1; i < nums.length; ++i) {
if (nums[i] <= min) min = nums[i];
else if (nums[i] <= mid) mid = nums[i];
else if (nums[i] > mid) return true;
}
return false;
}