数组理论要点
- 数组是存放在连续内存空间上的相同类型数据的集合,下标从0开始
- 数组的元素不能删,只能覆盖
- C++中二维数组在地址空间上是连续的
- Java中没有指针,寻址操作完全交给虚拟机,暴露给程序员的并非真正的地址,更无所谓连续
704. 二分查找
题目链接:Leecode704. 二分查找
文档讲解:代码随想录—704. 二分查找
二分查找条件:有序、无重复元素
难点:区间定义,左闭右闭或左闭右开
第一种:左闭右闭
要点:
- left == right 有意义,因此 while 循环条件是 left <= right
- 当 nums[mid] > target 时,因为已经明确 mid 处并非 target值,因此 right 取到 mid - 1,把原来的 mid 踢出查找区间
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] < target) left = mid + 1;
else if (nums[mid] > target) right = mid - 1;
else return mid;
}
return -1;
}
};
时间复杂度:O(log n)
空间复杂度:O(1)
第二种:左闭右闭
要点:
- left == right 无意义,因此while循环条件是 left < right
- 当 nums[mid] > target 时,由于 right 处的值本身取不到,但 mid - 1 是有意义的,因此 right 只能取到 mid ,放 mid - 1 进入下一次循环
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] < target) left = mid + 1;
else if (nums[mid] > target) right = mid;
else return mid;
}
return -1;
}
};
时间复杂度:O(log n)
空间复杂度:O(1)
27. 移除元素
题目链接:Leecode27. 移除元素
文档讲解:代码随想录—27. 移除元素
暴力解法
需要两层 for 循环,时间复杂度非常高
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for (int i = 0; i < size; i ++ ) {
if (nums[i] != val) continue;
else {
for (int j = i + 1; j < size; j ++) {
nums[j - 1] = nums[j];
}
i --;
size --;
}
}
return size;
}
};
时间复杂度:O(n ^ 2)
空间复杂度:O(1)
双指针解法
要点:
- 快慢双指针,把两层循环放在一层里完成
- 慢指针指向新数组下标 :保证新数组中没有目标值元素
- 快指针指向原数组下标 :检查原数组元素是否为目标值元素,如果不是则更新到新数组,是则不更新
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0, fast = 0;
for (int fast = 0; fast < nums.size(); fast ++) {
if (nums[fast] != val) nums[slow ++] = nums[fast];
}
return slow;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
心得
之前做过一边这块内容,复习一遍感觉很轻松,数组部分还是很简单的。可能真正考试的时候会出现想不到哪种题用哪种方法的问题,因此平时需要总结各方法的使用条件。