这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战
题目
解析
两个数相乘有以下几种情况:
- 任何数和0相乘:得0
- 任何乘负数得相反值
- 任何乘正数性质不变
那么,至少可以得出第一个边界条件:
- 只要遇到0,那么就中断了,因为要求的是连续的长度。
而两个负数相乘,得到的是正数;那么可以维护一个二维dp数组,来记录:到这个位置为止,连续的相乘为正数序列多长,连续的相乘为负数序列多长。
dp[i]:0为正数,1为负数
那么,如果我们读下一个数,就可以做出判断:
-
如果是0:总结状态,重新开始
-
如果是正数:
//当前正数序列长度+1 dp[i+1][0] = dp[i][0]+1; //如果当前负数序列长度为0,那么维持为0;否则,+1 dp[i+1][1] = dp[i][1]==0?0:dp[i][1]+1; -
如果是负数:
//如果当前负数序列长度>0,那么正数长度=负数长度+1;否则正数序列长度为0 dp[i+1][0] = dp[i][1]>0?dp[i][1]+1:0; //负数序列长度为之前的正数序列长度+1 dp[i+1][1] = dp[i][0]+1;
为了编码方便,将dp数组长度变为n+1(否则索引0位置获取不到),也就是说数组中对应位置的状态,在dp数组中的索引需要+1.
public static int getMaxLen(int[] nums) {
int[][] dp = new int[nums.length+1][2];
int max = 0;
for (int i = 0; i < nums.length; i++) {
if(nums[i]==0){
continue;
}
if(nums[i]<0){
dp[i+1][0] = dp[i][1]>0?dp[i][1]+1:0;
dp[i+1][1] = dp[i][0]+1;
}else{
dp[i+1][0] = dp[i][0]+1;
dp[i+1][1] = dp[i][1]==0?0:dp[i][1]+1;
}
max = Math.max(dp[i+1][0],max);
}
return max;
}
AC了,但是成绩垃圾:
执行用时:16 ms, 在所有 Java 提交中击败了5.14%的用户
内存消耗:57.3 MB, 在所有 Java 提交中击败了5.06%的用户
改进
空间上,显然dp数组只用到了前后两个位置的4个数,那么用4个数即可;同时注意到相互之间的关系,那么其实用2个数就可以替代dp数组了。
public static int getMaxLen(int[] nums) {
int lastP = 0,lastM = 0;
int max = 0;
for (int i = 0; i < nums.length; i++) {
if(nums[i]==0){
lastP = 0;
lastM = 0;
continue;
}
if(nums[i]<0){
int tmp = lastP;
lastP = lastM >0?lastM+1:0;
lastM = tmp+1;
}else{
lastP = lastP+1;
lastM = lastM==0?0:lastM+1;
}
max = Math.max(lastP,max);
}
return max;
}
执行用时:3 ms, 在所有 Java 提交中击败了99.70%的用户
内存消耗:54.8 MB, 在所有 Java 提交中击败了71.81%的用户
时间上,思考一下:是否我们需要读到每一个数都做一次max?
事实上我们可以只在lastP更新到更大值的时候做就可以。
public static int getMaxLen(int[] nums) {
int lastP = 0,lastM = 0;
int max = 0;
for (int i = 0; i < nums.length; i++) {
if(nums[i]==0){
lastP = 0;
lastM = 0;
continue;
}
boolean calMax = false;
if(nums[i]<0){
int tmp = lastP;
if(lastM >0){
calMax = true;
lastP = lastM+1;
}else lastP = 0;
lastM = tmp+1;
}else{
lastP = lastP+1;
calMax = true;
lastM = lastM==0?0:lastM+1;
}
if(calMax) max = Math.max(lastP,max);
}
return max;
}
执行用时:3 ms, 在所有 Java 提交中击败了99.70%的用户
内存消耗:54.7 MB, 在所有 Java 提交中击败了86.96%的用户