数组
数组是存放在连续内存空间上的相同类型数据的集合。数组的下标或者索引是从0开始的.
数组的优点
- 快速访问:通过索引可以在常数时间内(O(1))访问数组中的任意元素。
- 顺序存储:数组中的元素在内存中是连续的,方便进行批量处理。
数组的缺点
- 固定大小:一旦定义了数组的大小,就无法更改,可能导致内存浪费或容量不足。
- 插入和删除操作效率低:正是因为数组的内存空间地址是连续的,在数组中间插入或删除元素需要移动其他元素,导致插入和删除操作的时间复杂度为O(n)。
时间复杂度分析
- 访问数组元素的时间复杂度:O(1)
- 插入/删除元素的时间复杂度(在最坏情况下):O(n)
- 查找元素的时间复杂度:O(n)(线性查找),O(log n)(如果数组有序并使用二分查找)
二分查找,主要思路是,确认一个中间下标并用其值进行和目标值进行比较,如果中间值大于目标值就,说明目标值在中间值的左边,我们需要将右边界进行缩小,反之我们需要增大左边界,当值相等时我们进行return 中间值下标。但在while的循环条件中我们需要考虑一些事情,左边界到底是小于还是小于等于右边界。首先如果是小于等于,那我们在对右边界取值时就说明我们左右边界是可以相等的,
重点:left = mid + 1 和 right = mid - 1
- 为什么是 left = mid + 1?
- 当目标值比中间值大时,当前 mid 已经检查过了,不可能是目标值,因此下一次查找时可以排除掉 mid,所以 left 被设置为 mid + 1。
- 为什么是 right = mid - 1?
- 同理,当目标值比中间值小时,当前 mid 也被检查过了,不可能是目标值,所以 right 被设置为 mid - 1。
如果while中只有小于时,这时我们就要改变right的取值,他是开区间,说明他并不会取到最后一个值,我们在给right赋值时就需要使用right = nums.Length而没有减一。其实原理时一样的,在小于等于时是取的减一但当时的right是可以包含最大的一位数,还有就是当中间值大于目标值时,我们也需要改变right的赋值,因为它并不包含最大值,所以right取等于mid而不需要减一,其实这里的mid是比小于等于时的mid大一的,因为我们在一开始赋值时使用right = nums.Length而没有减一,所以在计算mid值时也会大1。然后我们right取mid的值就比循环条件大于等于时大一位。right又不能取最后一位,所以其实和上面的是一个道理。