今日主要完成数组理论的学习、二分法查找和双指针法。
1.基础知识
数组是存放在连续内存空间上的相同类型数据的集合.
需要两点注意的是
- 数组下标都是从0开始的。
- 数组内存空间的地址是连续的
而且大家如果使用C++的话,要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
(TODO:这部分后续补充)
2.题目
2.1 二分查找
解题思路:
对于一个有序的不重复数组的查找,首先想到使用二分法进行查找,二分法在写的时候,需要注意有两种写法,一种是左闭右闭,另一种是左闭右开。
对于以下两种方法,区别主要在于初始right和right在迭代时的变化,举一个例子就能够直接清楚了解
假如nums = [1] target = 1
如果是左闭右闭方法,由于能够出现left =right 的情况,所以初始的right = nums.size()-1
如果是左闭右闭的方法,由于left = right时跳出循环,所以初始的right = nums.size(),以保证能够正常进入循环。
同样,对于right的迭代操作,只需要记住如果时右开的区间,因为是开区间,下次会对[left,middle)这个区间进行判断,因此不需要进行-1操作。
对于右闭区间,如果没有middle-1的操作,则会因为left = right 不会退出循环,而导致无限循环的问题。
例如:nums = [1, 2, 4, 5, 6] target =3
左闭右闭:
class Solution{
public:
int search(vector<int>& nums,target){
int left = 0;
int right = nums.size() - 1;
while(left <= right){
int middle = left + (right - left)/2; // 避免right + left越界,不过应该一般不会出现
if(nums[middle] > target){
right = middle - 1;
} else if (nums[middle] < target>){
left = middle + 1;
} else {
return middle;
}
}
return -1;
}
};
左闭右开:
class Solution{
public:
int search(vector<int>& nums,target){
int left = 0;
int right = nums.size();
while(left < right){
int middle = left + (right - left)/2; // 避免right + left越界,不过应该一般不会出现
if(nums[middle] > target){
right = middle;
} else if (nums[middle] < target>){
left = middle + 1;
} else {
return middle;
}
}
return -1;
}
};
2.2 移除元素
方法一:暴力法
通过两层循环来暴力将元素移除,需要注意的是,当第二层循环将后续元素移动后,需要将i--和size--,数组也向前移动一位,否则会遗漏数据未处理。
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
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){
for(int j = i + 1;j<size;j++){
nums[j-1] = nums[j];
}
i--;
size--;
}
}
return size;
}
};
方法二:双指针法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
int fastIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size();fastIndex++){
if(nums[fastIndex]!=val){
nums[slowIndex] = nums[fastIndex];
slowIndex ++;
}
}
return slowIndex;
}
};
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
int fastIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size();fastIndex++){
if(nums[fastIndex]==val){
continue;
}else{
nums[slowIndex] = nums[fastIndex];
slowIndex ++;
}
}
return slowIndex;
}
};