上海金桥建设监理有限公司网站,网站开发在哪个科目核算,网站icp备案证明文件,内容营销平台有哪些代码随想录算法训练营第52天 || 300.最长递增子序列 || 674. 最长连续递增序列 || 718. 最长重复子数组
300.最长递增子序列
题目介绍
给你一个整数数组 nums #xff0c;找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列#xff0c;删除#xff08;或…代码随想录算法训练营第52天 || 300.最长递增子序列 || 674. 最长连续递增序列 || 718. 最长重复子数组
300.最长递增子序列
题目介绍
给你一个整数数组 nums 找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列删除或不删除数组中的元素而不改变其余元素的顺序。例如[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例 1
输入nums [10,9,2,5,3,7,101,18]
输出4
解释最长递增子序列是 [2,3,7,101]因此长度为 4 。示例 2
输入nums [0,1,0,3,2,3]
输出4示例 3
输入nums [7,7,7,7,7,7,7]
输出1思路解析
本题的一个难点在于子序列可以不连续那么我们如何能够确定这个子序列呢
动规五部曲 确定dp数组及其下标含义 dp[i]表示以第i个元素为结尾的严格递增子序列必须包括第i个 递推公式 for (int j 0; j i; j) { //[0,j]i部分的区域j、i必取if (nums[i] nums[j])dp[i] Integer.max(dp[i], dp[j] 1);
}这里的关键之处要遍历以下标j为结尾的前区间如此循环遍历最终即可得到以下标i结尾的最长严格子序列。 结果不是最后一位dp数值所以我们需要记录过程中的最大值 初始化dp数组 Arrays.fill(dp,1);每个位置保底为1对应它本身 确定遍历顺序 正序遍历即可 打印dp数组检验
本题关键要确定dp数组及其下标含义还要想到循环遍历得到结果复杂度O(n2)O(n^2)O(n2)
class Solution {int result 1;public int lengthOfLIS(int[] nums) {int[] dp new int[nums.length];//以第i个元素为结尾的最长严格递增子序列Arrays.fill(dp,1);for (int i 1; i nums.length; i) {for (int j 0; j i; j) { //[0,j]i部分的区域j、i必取if (nums[i] nums[j])dp[i] Integer.max(dp[i], dp[j] 1);}result Integer.max(dp[i], result);}return result;}
}674. 最长连续递增序列
题目介绍
给定一个未经排序的整数数组找到最长且 连续递增的子序列并返回该序列的长度。
连续递增的子序列 可以由两个下标 l 和 rl r确定如果对于每个 l i r都有 nums[i] nums[i 1] 那么子序列 [nums[l], nums[l 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。
示例 1
输入nums [1,3,5,4,7]
输出3
解释最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的因为 5 和 7 在原数组里被 4 隔开。 示例 2
输入nums [2,2,2,2,2]
输出1
解释最长连续递增序列是 [2], 长度为1。个人思路
本题相比于上一题简单不少因为它有个连续的限制我们不需要再遍历就可以直接确定dp数组的每个元素
直接上代码了
class Solution {public int findLengthOfLCIS(int[] nums) {int result 1;int[] dp new int[nums.length];dp[0] 1;for (int i 1; i nums.length; i) {dp[i] nums[i] nums[i - 1] ? dp[i - 1] 1 : 1;result Integer.max(result, dp[i]);}return result;}
}718. 最长重复子数组
题目介绍
给两个整数数组 nums1 和 nums2 返回 两个数组中 公共的 、长度最长的子数组的长度 。
示例 1
输入nums1 [1,2,3,2,1], nums2 [3,2,1,4,7]
输出3
解释长度最长的公共子数组是 [3,2,1] 。示例 2
输入nums1 [0,0,0,0,0], nums2 [0,0,0,0,0]
输出5个人思路
本题相较于前两题难点在于这里给了两个数组所以我们考虑使用二维dp数组来记录一些中间状态。注意到本题要求连续子序列所以这道题其实就是上一题的二维升级版
不难得出递推公式dp[i][j] nums1[i] nums2[j] ? dp[i - 1][j - 1] 1 : 0;
由此可以推出初始化操作必须把0下标位置初始化好避免越界问题
动规五部曲 确定dp数组及其下标含义 int[][] dp new int[nums1.length][nums2.length];dp[i][j]表示下标[i]、[j]位置为结尾的两子串符合条件的最大长度 递推公式的确定 dp[i][j] nums1[i] nums2[j] ? dp[i - 1][j - 1] 1 : 0;初始化dp数组 for (int i 0; i nums1.length; i) {dp[i][0] nums1[i] nums2[0] ? 1 : 0;result Integer.max(result, dp[i][0]);
}
for (int i 0; i nums2.length; i) {dp[0][i] nums1[0] nums2[i] ? 1 : 0;result Integer.max(result, dp[0][i]);
}由递推公式推出 确定遍历顺序 两层for循环正序遍历即可 打印dp数组检验
class Solution {public int findLength(int[] nums1, int[] nums2) {int result 0;int[][] dp new int[nums1.length][nums2.length];//以i.j为结尾的符合条件的子数组最长长度for (int i 0; i nums1.length; i) {dp[i][0] nums1[i] nums2[0] ? 1 : 0;result Integer.max(result, dp[i][0]);}for (int i 0; i nums2.length; i) {dp[0][i] nums1[0] nums2[i] ? 1 : 0;result Integer.max(result, dp[0][i]);}for (int i 1; i nums1.length; i) {for (int j 1; j nums2.length; j) {dp[i][j] nums1[i] nums2[j] ? dp[i - 1][j - 1] 1 : 0;result Integer.max(result, dp[i][j]);}}return result;}
}