学习目标:
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.对这个“模拟行为”相关的题目熟悉度低,对边界条件把握的不好。