数组
数组是存放在连续内存空间上的相同类型数据的集合。
- 使用C++时,要注意vector和array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
- 对于二维数组,C++中按行展开后是连续的,而Java中只有第一维是连续的。由此可以看出,不同语言具有不同的内存管理机制。
704. 二分查找
思路:将目标值同有序数组中间位置的元素进行比较,如果目标值更大则二分查找后半个数组,反之二分查找左半个数组。
- 我首先想到的是采取递归的方法每次传入一个新的切割后的数组,而不是对数组的下标进行操作。这样会产生额外的空间开销,又不能提高效率。所以在处理数组问题时,可能应该优先考虑对数组的下标进行操作。
- 代码实现中边界的判断:最简单直接的想法是让每次收窄后区间边界等于中间值+1/-1。这时考虑两种最终情况,一种是在二分法区间收窄的过程中恰好某个中间值为目标值(最差情况是缩减到三个元素区间的中间值)则此时直接返回中间元素下标;第二种是区间收窄后左右端点中的一个恰好为目标值,此时的区间必然会最终收窄到两个元素的大小。这时,如果目标值是左端点值,则取中间值恰好返回左端点值,任务完成。如果目标值是右端点值,则取中间值为左端点值,目标值大于左端点值,因此左端点右移,等于右端点,需要进入下一次循环完成对右区间端点的判断,因此循环判断中需要写“left<=right”。
- 直接从左闭右闭区间的角度来考虑,[left,right]当left=right时是合法区间,因此判断条件中需要加入等于的情况。
- 为什么要“左闭右开”?在网上搜索了一些资料,主要有以下几个好处:
- 便于获取区间大小:区间长度=区间右端点索引-区间左端点索引;
- 对于自然数集来说,不会因为采取左开而导致-1的出现;
- 当区间缩减为0时,便于空集的表示:[x,x);
- 进一步地,长度为n的数组的所有下标可由左开右闭区间[0,n)来表示,也可以由[1,n+1]表示,前者比后者更加直观,这是数组第一个元素的下标取为0的(部分?)原因。
- 在搜索资料的时候,遇到了这篇博文,详细地解释了二分法中使用左闭右开区间的优势,留待后续学习。
27. 移除元素
- 暴力解法思路:在每次发现目标元素之后,对后续的数组元素整体逐步地向前平移;
- 双指针思路:通过两个指针对数组进行定位,一步到位地把每个元素丢到新数组的对应位置上去。时间复杂度的降低是因为采用两个指针直接获取了元素移动的原始位置和目标位置。
C++语法
- 获取数组长度:.size()
- 从容器中删除某项:.erase() 时间复杂度为O(n)
- “/”是整除符号,相当于python中的“//”,有时使用位运算“>>n”对2的n次幂的除法进行优化。
总结
第一天比较生疏,只做了基础题,遇到问题上手时思路不够清晰,C++语法还需进一步熟悉。