LeetCode题目:
- 300. 最长递增子序列
- 674. 最长连续递增序列
- 718. 最长重复子数组
- 2918. 数组的最小相等和(每日一题)
其他:
今日总结
往期打卡
300. 最长递增子序列
跳转: 300. 最长递增子序列
学习: 代码随想录公开讲解
问题:
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的子序列。
思路:
dp[i]代表长度为n的串中末尾值,如果下一个数大于当前最大长度情况下的末尾值,就说明可以再加一个数.不然就看看是否更新其他位置,更新的原则是尽量让每个位置的值都更小.
要保证这个"插入位置"是比最后一个末尾比当前小的位置的下一个.
查询位置的过程可以使用二分查找降低复杂度到logn
复杂度:
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
- 空间复杂度: O ( n ) O(n) O(n)
代码:
class Solution {public int lengthOfLIS(int[] nums) {int[] dp = new int[nums.length];int count = 0;for(int i:nums){int left = -1,right = count;while(left+1<right){int mid = (left+right)/2; if(dp[mid]>=i){right = mid;}else left = mid;}dp[right] = i;if(right==count) count++;}return count;}
}
674. 最长连续递增序列
跳转: 674. 最长连续递增序列
学习: 代码随想录公开讲解
问题:
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l
和 r
(l < r
)确定,如果对于每个 l <= i < r
,都有 nums[i] < nums[i + 1]
,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]
就是连续递增子序列。
思路:
如果递增就+1,不然就归零,统计历史最大值.
因为还要加上当前值,所以每次归零初始化为1.
可以看成条件递推,如果递增dp[i] = dp[i-1]+1;
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
代码:
class Solution {public int findLengthOfLCIS(int[] nums) {int ans = 1;int num = 1;for (int i = 1; i < nums.length; i++) {if (nums[i] > nums[i - 1])num++;else {if (num > ans)ans = num;num = 1;}}return Math.max(ans, num);}
}
718. 最长重复子数组
跳转: 718. 最长重复子数组
学习: 代码随想录公开讲解
问题:
给两个整数数组 nums1
和 nums2
,返回 两个数组中 公共的 、长度最长的子数组的长度 。
思路:
顺序遍历一个数组,逆序找结尾看看能否匹配上次匹配到的部分
(为了防止基于当前更新过的匹配,所以需要逆序,因为是子数组,要保证连续,所以到位置不匹配及时覆盖为0)
动态规划就是
if (nums1[i - 1] == nums2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;
}
复杂度:
- 时间复杂度: O ( n m ) O(nm) O(nm)
- 空间复杂度: O ( n ) O(n) O(n)
代码:
class Solution {public int findLength(int[] nums1, int[] nums2) {int ans = 0;int m = nums1.length;int n = nums2.length;int[] fn = new int[n+1];for (int i = 0; i < m; i++)for (int j = n - 1; j >= 0; j--) {fn[j + 1] = nums1[i] == nums2[j] ? fn[j] + 1 : 0;ans = Math.max(ans, fn[j + 1]);}return ans;}
}
2918. 数组的最小相等和(每日一题)
跳转: 2918. 数组的最小相等和
问题:
给你两个由正整数和 0
组成的数组 nums1
和 nums2
。
你必须将两个数组中的 所有 0
替换为 严格 正整数,并且满足两个数组中所有元素的和 相等 。
返回 最小 相等和 ,如果无法使两数组相等,则返回 -1
。
思路:
0可以变成任意值,只要都有0就一定能一样,只有在算上0变1小的一方没有0的情况下才无解.
解就是0算作1加起来的最大那个和.
复杂度:
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
代码:
class Solution {public long minSum(int[] nums1, int[] nums2) {long n=0,m=0;boolean a,b;a=b=true;for (int i : nums1) {if (i > 0)n += i;else{n++;a=false;}}for (int i : nums2) {if (i > 0)m += i;else{m++;b=false;}}if(m>n&&a||m<n&&b){return -1;}else return Math.max(m,n);}
}
总结
练习了递增子序列,连续递增子序列,公共子序列问题.
往期打卡
代码随想录算法训练营第三十五&三十六天
代码随想录算法训练营第三十四天
代码随想录算法训练营第三十三天(补)
代码随想录算法训练营第三十二天
代码随想录算法训练营第三十一天
代码随想录算法训练营第三十天(补)
代码随想录算法训练营第二十九天
代码随想录算法训练营第二十八天
代码随想录算法训练营第二十七天(补)
代码随想录算法训练营第二十六天
代码随想录算法训练营第二十五天
代码随想录算法训练营第二十四天
代码随想录算法训练营第二十三天
代码随想录算法训练营周末四
代码随想录算法训练营第二十二天(补)
代码随想录算法训练营第二十一天
代码随想录算法训练营第二十天
代码随想录算法训练营第十九天
代码随想录算法训练营第十八天
代码随想录算法训练营第十七天
代码随想录算法训练营周末三
代码随想录算法训练营第十六天
代码随想录算法训练营第十五天
代码随想录算法训练营第十四天
代码随想录算法训练营第十三天
代码随想录算法训练营第十二天
代码随想录算法训练营第十一天
代码随想录算法训练营周末二
代码随想录算法训练营第十天
代码随想录算法训练营第九天
代码随想录算法训练营第八天
代码随想录算法训练营第七天
代码随想录算法训练营第六天
代码随想录算法训练营第五天
代码随想录算法训练营周末一
代码随想录算法训练营第四天
代码随想录算法训练营第三天
代码随想录算法训练营第二天
代码随想录算法训练营第一天