题目链接及描述
334. 递增的三元子序列 - 力扣(LeetCode)
300. 最长递增子序列 - 力扣(LeetCode)
题目分析
300. 最长递增子序列 - 力扣(LeetCode)
最长递增子序列作为一道经典的动态规划题目,定义dp[i] 表示下标 i 时数组中存在的最长递增子序列,则可以确定递推公式:
if(nums[i] < nums[i]){
dp[i] = Math.max(dp[i], dp[j] + 1);
}
此题之前自己写过很多遍,对于这个思想比较熟悉,就不再赘述了。写这道题目的目的,是和334题的题目进行对比。 此题参考如下:
class Solution {public int lengthOfLIS(int[] nums) {int ans = Integer.MIN_VALUE;int len = nums.length;int[] dp = new int[len];for(int i = 0; i < len; i++){for(int j = 0; j < i; j++){if(nums[j] < nums[i]){dp[i] = Math.max(dp[i], dp[j] + 1);}}ans = Math.max(ans, dp[i]);}return ans + 1;}
}
334. 递增的三元子序列 - 力扣(LeetCode)
对于334题,今天这是第一次写,首先想的一种做法是,采用回溯的思想,遍历构造所有长度对的3的数组,并且在构造的过程中验证是否满足nums[i] < nums[j] < nums[k] 如果不满足直接返回false,如果满足并且得到长度为3时终止循环,并且返回ture。
感觉使用回溯的做法有些许复杂,随后下班回到出租屋后又打开电脑,联想到【最长递增子序列】上面的那道题。本次无非就是寻找长度为3的最长递增子序列。于是乎使用上面的思路编写代码如下:
class Solution {public boolean increasingTriplet(int[] nums) {int n = nums.length;int[] dp = new int[n];Arrays.fill(dp, 1);for(int i = 0; i < n; i++){for(int j = 0; j < i; j++){if(nums[j] < nums[i]){dp[i] = Math.max(dp[i], dp[j] + 1);if(dp[i] == 3){return true;}}}}return false;}
}
不幸的是,使用这种解法超时了,无法通过所有测试用测,将这个方法写出来就是为了扩展做题思路。
随后参考答案的写法看到一种贪心的做法,非常巧妙,由于题目是寻找到长度为3的递增数组,所有设置两个阈值first、second。参考图示如下:
遍历数组nums中的每一个数,如果num在(-oo,first] 之间,说明遇到比当前得到的最小的数更小的数,此时将num 赋值给first,如果num在(first,second] 之间,说明遇到了比当前第二小更小的数,此时将num 赋值给second。如果num 在(second,+oo)之间,说明遇到了第三大的数,此时返回true。终止循环。
需要将 first 和 second 初始化为Integer.MAX_VALUE。
代码编写
class Solution {public boolean increasingTriplet(int[] nums) {int first = Integer.MAX_VALUE, second = Integer.MAX_VALUE;if(nums.length < 3){return false;}for(int num : nums){if(num <= first){first = num;}else if(num <= second){second = num;}else{return true;}}return false;}
}