这道题目的思路我们使用滑动窗口的方式,通过不断滑动的窗口来确定最小的长度是多少
以示例为例子,分析过程如下
通过不断地滑动窗口就可以尝试获取到最小子数组的长度
那么具体的代码思路我们首先要确立三个目标:
1.怎么样来保证窗口的滑动
我们定义一个for循环,for循环的变量就是用来保证我们的窗口不断的移动的,这个变量相当于窗口的右边
2.怎么样来保证窗口的收缩
我们在一开始就应该定义一个变量来控制我们窗口的左边,当我们记录到的窗口内元素和大于或者等于目标值时,我们就应该进行收缩操作了。这个变量向后移动一位就相当于收缩了一个格子的窗口
3.怎么样来记录窗口的长度
我们在进入到for循环里面的时候就使用一个result来进行记录我们的数组的长度,如果进行收缩操作了此时就对数组长度进行记录。
最后贴上我们的代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int ans = Integer.MAX_VALUE;
int sum = 0;
for(int right = 0;right < nums.length;right++){
sum += nums[right];
while(sum >= target){
ans = Math.min(ans,right - left + 1);
sum = sum - nums[left];
left++;
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}
这道题的思路其实就是不断地模拟这个过程旋转的
不断的进行循环填充的过程,并且根据这个过程选择合适的取值范围(左闭右开?左闭右闭?)
分析完大体的解题过程过程我们再继续分析细节
由于我们的n是不确定的,不能准确地知道系统给我们的n究竟是奇数还是偶数
所以我再对n是奇数还是偶数具体进行分析
由于我们是循环填充,所以说如果n是偶数的话刚好可以使用n/2圈的填充就可以将二维数组填充完毕,但是如果n是奇数的话,使用n/2圈的填充以后还是会剩下一个中心点需要单独处理
所以代码上我们使用来进行处理
if((n % 2) == 1){
nums[x][x] = count; //填充中心点
}
分析完主要的难点以后我们直接上代码,并且使用注释的形式来解释每段代码的含义
class Solution {
public int[][] generateMatrix(int n) {
int[][] nums = new int[n][n];//创建二维数组
int startX = 0;//控制左右移动的变量
int startY = 0;//控制上下移动的变量
int count = 1;//控制需要进行填充的数字
int offset = 1;//控制边界
int loop = n / 2;//确认需要循环的圈数
while(loop > 0){
//上左到上右
for(;startX < n - offset;startX++){
nums[startY][startX] = count++;
}
//左上到左下
for(;startY < n - offset;startY++){
nums[startY][startX] = count++;
}
//下右到下左
for(;startX >= offset;startX--){
nums[startY][startX] = count++;
}
//右下到右上
for(;startY >= offset;startY--){
nums[startY][startX] = count++;
}
startX++;//操作下一圈循环
startY++;
offset++;//控制边界也需要向后移动一位
loop--;//循环一圈结束以后自减一次
}
//填充中心点
if((n % 2) == 1){
nums[startX][startY] = count;
}
return nums;
}
}
关于代码中的offset这个变量我再次具体进行分析
这道题的思路其实就是使用一个指针来不断的遍历该节点的下一个节点的值是否是需要删除的元素如果是的话就需要修改指向,具体如图所示
为了统一操作,避免头节点就是需要删除的元素我们使用了一个虚拟头节点来指向头节点,然后我们从虚拟头节点开始遍历
ListNode cur = Dhead;
由于我们需要不断的遍历链表,所以我们使用while循环来进行遍历,由于我们需要操作cur.next,所以为了避免空指针异常,那么while循环的条件就是
while(cur.next != null)
每当我们需要删除元素的时候就修改指向,所以我们使用 if-else 语句来进行控制
if(cur.next.val == val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
为什么需要一个else语句来控制cur的移动?而不是将代码写成
if(cur.next.val == val){
cur.next = cur.next.next;
}
cur = cur.next;
原因在于,当我们在修改倒数第二个元素的指向的时候,如果修改完成后直接移动cur,那么此时cur为空,再次进入到while循环时就会出现空指针异常(cur == null 所以无法操作cur.next)
可以参考上图来进行模拟操作!
所以具体的代码如下:
public ListNode removeElements(ListNode head, int val) {
ListNode Dhead = new ListNode();
Dhead.next = head;
ListNode cur = Dhead;
while(cur != null && cur.next != null){
if(cur.next.val == val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return Dhead.next;
}