所有问题的下标可能涉及到越界的,要么在循环的起始条件里就要搞好,要么就特判
(下面这种写法不要看了)
l=0
r=-1
while(r<n-1)
{
r++
//更新有关数据
while(r<n-1&&数据有效&&可以向右拓展........)
{
//注意此时也是合法窗口,因此也有必要更新答案
r++;//向右拓展
//更新有关数据
}
//更新l(这种更新方式有很多,可以l++,也可以l = r,也可以用循环while(l<=r)缩短窗口(注意必须l<=r,l==r当然有效)
//找到了合法窗口,更新答案
}
但是我随后在某些地方也看到的全新的维护,似乎更好理解:
int l = 0;
int r = -1;
while(r<n-1){
r++
//进窗口,处理有关数据
while(窗口不合法){
//l准备出窗口
l++;
}
//此时窗口合法,更新答案
}
或者变体
int l = 0;
int r = -1;
while(r<n-1){
r++
//进窗口,处理有关数据
while(窗口合法但是右移更优){
//如果“右移更优”这里需要更新答案,比如最小覆盖子串
//l准备出窗口
l++;
}
}
同时这种写法的价值是:
l=0
r=-1
while(r<n-1)
{
r++
//更新有关数据
while(r<n-1&&数据有效&&可以向右拓展........)
{
r++;//向右拓展
//更新有关数据
}
//找到了合法窗口,更新答案
l = r+1;
}
这种方式主要用来处理:一直向右拓展窗口,直到某个时候不合法。然后更新答案。如合并区间 这题
if (head ==null ||head.next==null) return head;(当然如果不好处理也可以不写,但最先想的就应该是这个)
复杂问题上哨兵
宁愿判(node!=null))也不判(node.next!=null)。当然有时两者都要判
测试数据过不去,可以直接通过判断if来处理一些边界情况
在写的过程当中,如果一些边界(比如链表末尾问题)尽量不要特判,除非你很有把握特判效果很好
首先复习一下背包问题就行。
首先一定是要写状态转移方程,然后看这个方程里涉及的下标是否可能越界,有越界的可能才可能需要扩充dp数组; 有时候dp数组的定义就是“第i个元素”这种,那i自然就是从1开始,进而需要扩充数组