其他:
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);
}
}
总结
练习了递增子序列,连续递增子序列,公共子序列问题.