算法训练营第二天
滑动窗口:
209.长度最小的子数组
开始没啥思路。只知道两个for O(n*2) 得到结果。看到题目要用滑动窗口,双指针。但根本对滑动窗口没有任何记忆。
滑动窗口:滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
然后看了下 sliding window的定义在代码随想录上,然后再思考:
想到移动子序列对于这个题也就是 子数组。怎么更新子数组呢? start位置和end位置 要更新,这两个是指针,然后主数组就向右移动。有些思路:子数组终止位置时,子数组和大于target 就要尝试移动start位置。 这个移动是一个小的for,那时间复杂度是多少呢?有了这个想法就开始更新代码:
更新代码还是有问题,没搞对如何更新startPoint,以及子数组。先入僵局,测试没过。
那就完整的看下代码随想录:
(from 代码随想录)滑动窗口也可以理解为双指针法的一种!只不过这种解法更像是一个窗口的移动,所以叫做滑动窗口更适合一些。
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么? 子数组
- 如何移动窗口的起始位置?子数组的startPoint
- 如何移动窗口的结束位置?子数组的endPoint
我没有做出来的原因,是移动startPoint 想法有问题
我的是比较混乱的 判断滑动条件以及滑动。
根本不需要这么麻烦:直接
总结:209
这道理思路思路没问题,就是实现startPoint这儿出现问题。逻辑没考虑好!时间复杂度:每一个点都会经历一次endPoint,每一个点最多会经历一次startPoint。所以O(n) = n. 循环的细节需要注意!!! 注意startPoint移动!!!!! 自己的逻辑差在startPoint没控制
59.螺旋矩阵II
好像23年面试实习时,有人问过,螺旋打印。
初想法是:
把每个点设置一个 if_hit 来判断是否赋值过,如果当遍历到赋值过的,赋值方向改变。遍历就4个方向,
up down left right.想法没问题 就是要加强把想法变成 代码的能力。在看claude前,自己控制方向的方法不对,对边界控制还是差。
按照我的思路看了claude后:
里面我没做到的 使用%4来控制下一次的方向。其次就是使用nextX,nextY来表示下一次移动到哪,然后判断需要换方向吗,如果需要的话,在处理真正的x y!
看答案后:
代码随想录里提出要坚持循环不变量原则。所以什么是循环不变量?需要好好理解!
代码随想录的解法是 一次loop 就完成一圈的填数字,然后下一圈就在大圈里 x,y各加1开始的点开始。需要注意这样最小圈是3*3的圈,里面还有有一点 需要额外处理! 这个思路也不错,在这里循环不变量原则 就是在每次loop 中,每一圈的up down left right需要用一致的处理方法。
区间和
这个题是***的题,算是代码随想录的原创题。不是leetcode上的题:*************************************************
是ACM模式,很好的锻炼!
初思路:
做这个题 首先我得承认自己忘了 std in 在java里如何实现,所以我用了claude 查了下:
- scanner:
可以使用hasNext()或hasNextLine(): 来检测是不是到了eof
然后 复习下 java里类型转化:比如 string -> int: Integer.parserInt();
自己的想法使用暴力解法,for a 到 b累加,这时间复杂度 超了。但超了后,自己想起来 求 2 - 5 可以用 sum(5) - sum(1) 得到。
这个题难点不是思路,而是 std in std out。也就是 ACM模式!后面需要多练习下 ACM模式!!!
看了代码随想录后:
还是没有写对,因为 累加这儿出错了,实现逻辑出现问题。并且并没有处理 边界问题! 需要认真!
这个代码出现了 很多小问题。要多回看! 比如 怎么std in std out 以及关于 类型转化。
开发商购买土地:
还是***里的题,对ACM模式练习有帮助
初想法:
这个题要求 横 或者 竖切,其实就是 (n-1)*(m-1) 种切法。在这里面找最小?在 std in 的过程中 可以很方便的 得到 一行的sum,横切的话 就是 行的sum 直接的对比,那如果是 竖切呢? 然后我又进一步思考 这个面积差,其实就是总面积 z , A得到 x, B得到y,A B的价差 最小,就是| 2y-z| 最小,也就是要找 最接近 z/2的面积。(这里的面积指的是 加上权后的)。然后也就是记录下每一行和每一列的sum。初想法实践后 还是错的,感觉代码写太少,很多条件逻辑 不熟,需要多做题。
看完代码随想录:
觉得自己的初想法是正确的,其实和 代码随想录的一样,只是我太关注在 用复杂的方式表示前缀和,其实就是上下,或者左右的node权重和。可以直接用for(m){for(n)}来处理。其实和我的意思是一样的。最后发现自己只是一个在给前m列的总node和处理时,判断条件应该是i < m,搞成了 i < n! 需要长教训。并且以后 可以 先从简单的方法来 就是代码随想录里提到的。代码随想录里把每一个node 先得到,然后再从 行切 开始,用for(m){for(n)}处理,然后到 行的最后一个数 就可以进行比较了,不用专门再用 for 比较。这是一个很好的代码习惯格式。