理论:
数组在内存中是一片连续的空间,下标都是从0开始的,所以在进行数组的增加或删除元素的时候,准确来说并不是单一的操控某个元素,而是对所有元素的操控,移动一个元素,就要考虑后续所有元素的影响。所以数组的删除操作准确来说并不是真正的删除,而是后续元素对这个元素的覆盖。
多维数组也同理,也是一片连续的空间,所以不同写法的时间复杂度才会出现不同,按行遍历跟按列遍历,在我们看来没有什么区别,但是实际上时间复杂度相差很大。因为按行遍历是按照顺序依次进行遍历的,而按列遍历则是跳着遍历的。
练题总结
以前做数组题的时候,思想并不打开,更多的是考虑暴力的算法,虽然也能解决问题,但是并不高效,经过代码随想录的学习,感觉自己大大的提升了对数组的掌控能力,特此记录一下心得。
数组最重要的一点:坚持循环的不变量,即每一次循环中,对于边界的处理,要坚持一开始自己定义的区间来执行。
二分法
前提:数组为有序数组,数组中无重复元素 【有重复返回的下标不唯一】
坚持循环不变量的经典应用,一开始就要定义好target 是在左闭右闭[left, right]区间内,还是左闭右开[left, right)区间内,根据区间定义的不同,middle的取值和循环判断的条件也不同。
双指针法 - 移除元素 - 有序数平方
双指针太好用了,链表和数组中间经常有用到。
简单来说就是定义两个指针,一个快指针,一个慢指针,通过这两个指针的操作实现在一个for循环里面完成两个for循环的工作。
要清楚快慢指针代表的含义,每道题目所代表的作用也不同。在移除元素这道题目中:
- 快指针:寻找数组的新元素,即不含目标值的元素
- 慢指针:指向更新 新数组下标的位置
所以使用双指针,可以一次性删除数组中所有与目标值重复的元素。
滑动窗口 - 长度最小的子数组
一般滑动窗口的题用暴力算法也能写吧,暴力算法是用两个for循环,一个代表窗口的起始位置,一个代表窗口的终止位置,用两个for循环完成一个区间不断的搜索过程,而滑动窗口的思想是利用双指针用一个for循环解决暴力算法两个for循环的工作,所以就得清楚滑动窗口的for循环代表的是暴力循环中的终止位置还是起始位置。否则滑动窗口很容易写成暴力算法。
滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。
写滑动窗口的时候,要明白三点:
1、窗口内是什么? 2、如何移动窗口的起始位置? 3、如何移动窗口的终止位置?
明白好这三点就清楚答题的大体框架了。
题目:209. 长度最小的子数组 - 力扣(LeetCode)
模拟行为 - 螺旋矩阵II
这个也是经典的遵循循环不变量的规则,边界判断特别多,如果不遵循一个统一的规则,那就会越写越乱,一入循环深似海。