代码随想录算法训练营第二天_数组结束 _ 977.有序数组的平方 、209.长度最小的子数组、2760. 最长奇偶子数组、59.螺旋矩阵II。

学习目标:

60天训练营打卡计划!

学习内容:

977.有序数组的平方

  • 977题,为什么会想到双指针法呢?
    因为最大的值一定出现在平方后数组的两侧,左右各放一个指针一定可以取到最大值。
  • 能给什么启示呢?
    用双指针是为了解决问题的,没有特定的形式,只要保证实现的效果满足1+1>2就行。多积累双指针法的使用场景。
		int size = nums.length;
        int left = 0;
        int right = size - 1;
        int j = size - 1;
        int[] result= new int[size];
        while(left <= right){
            if(nums[left]*nums[left] < nums[right]*nums[right]){
                result[j] = nums[right]*nums[right];
                right--;
                j--;
            }
            else{
                result[j] = nums[left]*nums[left];
                left++;
                j--;
            }
        }
        return result;

209.长度最小的子数组

实操时心得:

  • 暴力求解法
    相当于是阶梯式求解,第一层循环确定起始的节点,第二层循环是从起始点一直加和到终止点,第一个超过s的字符长度就是本段的最短字符。
  • 滑动窗口(双指针法的引申)
    窗口里放的是和大于s的子字符串。若当前窗口大于s,则起始指针前移。若不满足大于s,则终止指针后移直到满足大于s。妙!实际完成时,要注意指针前移时要从sum里减掉删除的前数值。对于Java语言不满足for的cpp语法,需要自适应改变。
	int size = nums.length;
    int sum = 0;
    int start = 0;
    int result = size + 1;
    for(int end = 0; end < size; end++){
        sum += nums[end];
        while(sum >= target){
            result = Math.min(result, end - start + 1);
            sum -= nums[start++];
        }
    }
    return result == size + 1 ? 0 : result;
}
  • 有些奇怪的人生感悟,不一定要找到最好的选择,最适合自己的就是最好的;要懂得知足,避免捡了芝麻丢了西瓜。

补充一个滑动窗口

2760. 最长奇偶子数组

不知道为什么我写就全是报错。。。妈的

  • 根本没想到用一个循环来解决这个题,其实i就是滑动窗口结束的位置。
  • 还有个比较容易错的位置,结束窗口处的指针越界的问题。
  • 关键是分别来找头和尾,这和209的处理是很相似的,但是本题的限制条件实在是太多了。有一种使用一个变量实现了双重遍历的效果!
class Solution {
    public int longestAlternatingSubarray(int[] nums, int threshold) {
        int ret = 0;
        int start = 0;
        int length = nums.length;
        // i是滑动窗口的end
        for(int i = 0; i < length; i++){
            // 1.遍历数组判断数字是否小于threshold并且为偶数找到子数组的开头。
            if(nums[i] %2 ==1 || nums[i] > threshold){
                continue;
            }
            start = i;
            // 2.找到子数组的开头后继续往后遍历出子数组。
            // 条件为:不超过数组长度、
            // 数字为奇偶交替排序、数字不大于threshold
            while(i < length-1 && (nums[i]%2 != nums[i+1]%2) && nums[i+1] <= threshold){
                i++;
            }
            // 3.比较出最大子数组
            ret = Math.max(ret,i - start + 1);
        }
        return ret;
    }
}

59.螺旋矩阵II

  • 看完视频讲解之后是比较懵的,第一次实现果然报错了。。
  • 起始位置👉start确定,终止的位置由offset确定。而且仅需要循环n/2圈,这样每循环一圈时,就可以令start和offset都加1,这样可以实现精准的控制数组遍历的位置。
  • 其中的offset = start + 1
  • 最后填充的奇数中间节点是res[start][start] = count;
  • 从小到大的停止条件是 < n - offset
  • 从大到小时的停止条件是 >= offset
  • 牢记边界条件!!
  • 在以后要加强对“循环不变量”理解和把握。处理的规则是一致的,便于简化问题的分析处理。
int start = 0;
    int[][] res = new int[n][n];
    int offest = 0;
    int count = 1;
    int i,j;

    while(offest++ < n/2){
        for(j = start; j < n - offest; j++){
            res[start][j] = count++;
        }
        for(i = start; i < n - offest; i++){
            res[i][j] = count++;
        }
        for(; j >= offest; j--){
            res[i][j] = count++;
        }
        for(; i >= offest; i--){
            res[i][j] = count++;
        }
        start++;
    }
    if(n % 2 == 1){
        res[start][start] = count;
        // res[start][start] = count;
    }
    return res;

学习时间:

  • 上午一小时,下午一小时,整理文档半小时
  • 12月5日复习刷!59和2760题非常不熟悉。

数组的总结:

  • 问题:
    1.双指针法会使用,但是不会轻易的识别出双指针法使用的场景。
    2.对这个“模拟行为”相关的题目熟悉度低,对边界条件把握的不好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值