LeetCode 674简单双指针/数组扫描
最长连续递增序列 图解题解
这道题到底在问什么
给定整数数组 nums,返回最长连续递增子数组(子段)的长度。子段必须是原数组里相邻的一串,且严格递增。
- 输入
- nums=[1,3,5,4,7]
- 输出
- 3 (最长递增段是 [1,3,5])
- 输入
- nums=[2,2,2,2]
- 输出
- 1 (相等不算递增,只能取单个)
最优解:一步一步想明白
- 3记住这套「比前一个大就 cur+1,否则 cur 归 1,每步刷新 best」,下面每一帧都在套它。
- 4开局:第 0 个元素 1 自己就是一段长度 1 的递增段(绿色),cur=1,best=1。
- 5看第 1 个 3,和前一个 1 比。绿色是目前正在生长的递增段(长度 1)。
- 63 比 1 大,段接着长,cur=2。比旧的 best 更长,刷新 best=2。
- 7看第 2 个 5,和前一个 3 比。绿色是目前正在生长的递增段(长度 2)。
- 85 比 3 大,段接着长,cur=3。比旧的 best 更长,刷新 best=3。
- 9看第 3 个 2,和前一个 5 比。绿色是目前正在生长的递增段(长度 3)。
- 102 不大于 5(断开),绿色段缩回从第 3 个重新开始,cur 归 1。best 仍是 3。
- 11看第 4 个 4,和前一个 2 比。绿色是目前正在生长的递增段(长度 1)。
- 124 比 2 大,段接着长,cur=2。还没超过 best=3,best 不变。
- 13看第 5 个 6,和前一个 4 比。绿色是目前正在生长的递增段(长度 2)。
- 146 比 4 大,段接着长,cur=3。还没超过 best=3,best 不变。
- 15看第 6 个 8,和前一个 6 比。绿色是目前正在生长的递增段(长度 3)。
- 168 比 6 大,段接着长,cur=4。比旧的 best 更长,刷新 best=4。
- 17看第 7 个 9,和前一个 8 比。绿色是目前正在生长的递增段(长度 4)。
- 189 比 8 大,段接着长,cur=5。比旧的 best 更长,刷新 best=5。
- 19看第 8 个 3,和前一个 9 比。绿色是目前正在生长的递增段(长度 5)。
- 203 不大于 9(断开),绿色段缩回从第 8 个重新开始,cur 归 1。best 仍是 5。
- 21看第 9 个 5,和前一个 3 比。绿色是目前正在生长的递增段(长度 1)。
- 225 比 3 大,段接着长,cur=2。还没超过 best=5,best 不变。
- 23看第 10 个 7,和前一个 5 比。绿色是目前正在生长的递增段(长度 2)。
- 247 比 5 大,段接着长,cur=3。还没超过 best=5,best 不变。
- 25看第 11 个 2,和前一个 7 比。绿色是目前正在生长的递增段(长度 3)。
- 262 不大于 7(断开),绿色段缩回从第 11 个重新开始,cur 归 1。best 仍是 5。
- 27扫完全程,最长的一段是绿色这 5 个(2→4→6→8→9),答案 5。其余灰掉的段都更短。
⚠️ 容易写错的地方
✗ 错:把「严格递增」当成「非递减」
✓ 对:相等要算断开,cur 归 1
题目要求严格大于,[2,2] 的最长段是 1 不是 2
✗ 错:断开时忘了重置 cur
✓ 对:不满足递增就 cur=1 重新数
不重置会把不相连的段错误地连起来计数
✗ 错:空数组返回 1
✓ 对:空数组返回 0
没有元素就没有段,长度为 0
完整代码(Python / C++ / Java)
Python
from typing import List
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
if not nums:
return 0
best = cur = 1
for i in range(1, len(nums)):
if nums[i] > nums[i - 1]:
cur += 1
else:
cur = 1
best = max(best, cur)
return bestC++
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
if (nums.empty()) return 0;
int best = 1, cur = 1;
for (int i = 1; i < (int)nums.size(); ++i) {
if (nums[i] > nums[i - 1]) ++cur;
else cur = 1;
best = max(best, cur);
}
return best;
}
};Java
import java.util.*;
class Solution {
public int findLengthOfLCIS(int[] nums) {
if (nums.length == 0) return 0;
int best = 1, cur = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) cur++;
else cur = 1;
best = Math.max(best, cur);
}
return best;
}
}复杂度
时间
O(n)
从头到尾扫一遍
空间
O(1)
只用 cur、best 两个变量
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 最长连续递增序列 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
和「最长递增子序列 LIS(LC300)」有什么区别?+
LC674 要求「连续」(原数组里相邻),所以一遍线性扫描 O(n) 即可;LC300 不要求连续,可以跳着选,需要 DP O(n²) 或贪心+二分 O(n log n)。一个连续、一个可跳,难度差很多。
能否一边扫一边记录最长段的起止位置?+
可以:每次刷新 best 时把当前 runStart 和 i 记下来,结束时即得最长段的区间。本动画最后一帧的绿色高亮就是这么标出来的。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 最长连续递增序列 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。