算法练习day2
#数据结构 算法练习
2024-04-18
有序数组的平方
(用时:0.3小时)
这道题很简单,可以用双指针法或者暴力破解。
双指针法
本题允许新构建数组,然后返回值可以是新的数组,因此个人认为才会比较简单。但如果不允许构建数组呢?
- 题目提供的是一个有序的升序数组,数组中也会有负数和零。整个数组都平方后,数组的大小趋势应该是从两头向中间递减的,如图:

- 指针head和tail顾名思义,分别从数组的头和尾开始遍历。
- 在遍历的时候,比较头和尾的平方大小,大的放入新数组的尾部,不断比较放入,即可得到一个新的升序的平方数组。
- 注意一下新数组是从后往前赋值的,因此新数组的下标初始值应为数组长度-1.
暴力破解
暴力破解就更简单了。
- 将原数组按顺序平方后的值放入新数组中。
- 再对新数组排序既可。
代码实现
暴力破解:
1 | /// <summary> |
双指针法:
1 | /// <summary> |
长度最小的子数组
(用时:0.5小时)
这道题其实难度不高,但是引入了滑动窗口的思想。
滑动窗口
滑动窗口是一个抽象的概念,在不同地方具体是什么都不太也一样。
- 个人认为窗口其实就是一块“区域”,像是数学的“区间”。
- 所谓滑动,个人认为是这块区域的起始和终点是可变意思,但是起点和终点始终会保持着起点<=终点这个条件(起点和终点的意义也是这样固定了)。
- 合起来,滑动窗口可以认为就是一段可变的区间,变化的条件、区间要满足的要求都是人定的。利用这个思想,可以解决一些计算机的问题。
(题外话:滑动窗口也让我想起来计网中的那个滑动窗口hhhh,思想都是很互通呢。)
滑动窗口法
本题本质其实就是要找数组中连续的数字,这些数字连在一起,可以看成一片“区域”。
- 程序中,可以用两个指针(也不一定是真的指针)表示窗口的起点和终点。让起点和终点按照我们的要求改变,就可以实现查找区域的想法。
- end指针先向后探索,从start到end这块区域的数相加如果>=target,那么就说明这块区域是符合要求的“子列”。
- 由于要找最小子列长度,那么单单符合要求并不够,还得比较符合要求的所有子列的长度。此时可以靠start,从目前已经符合要求的start到end的区间中,后移减短子列长度。
start和end配合操作,总结来说:
1.先找到符合要求的子列
2.数一定要连续。依次让起点往后挪,尝试是否有更加“完美”的子列。
重点思考
写的时候,需要重点考虑以下问题:
- 窗口的start如何定义和改变?
- 窗口的end如何定义和改变?
个人的一些理解:
窗口的start如何定义和改变?
start指针主要是用来在现有符合条件的子列上,缩短“优化”子列长度。
start只有在 s(当前子列和)>=Target时,才能start++以后移
start能够一直后移,一定是start++后,s(当前子列和)>=Target依旧成立。(不用担心出现start>end而条件还成立的情况。因为s-nums[start]和start++是先后进行的,s的初值是0,target和数组都是正整数,0<正整数。)窗口的end如何定义和改变?
end指针主要是用于寻找符合条件的子列,不负责“优化”。
end只有在找到s(当前子列和)>=Target时,才会停下来,让start“优化”。
end的边界条件是数组长度。
错误思考
- 本题写的时候,思路上没有什么阻碍,实现上也是。
- 但在一个地方出了问题:int的最大值。
- 以前写习惯了,int的最大值直接定成65535,其实不是。
- C#中可以用int.MaxValue来替代。
暴力破解法
暴力破解就是双层循环,遍历出所有的可能。
代码实现
滑动窗口法:
1 | /// <summary> |
拓展思考
如果Target不一定是正整数或数组里包含负数或0呢?