一、数组理论基础
数组的内存空间地址都是连续的,二维数组内存空间地址也是连续一条线的。
二、704. 二分查找
第一遍通过代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int mid;
int L=0;
int R=nums.size()-1;
while(L<R){
mid=(L+R)/2;
if(target<=nums[mid]){
R=mid;
}
if(target>nums[mid]){
L=mid+1;
}
}
if(target==nums[L]){
return R;
}else{
return -1;
}
return 0;
}
};
对于涉及的边界条件非常混乱,要理解两种不同的区间定义,左闭右闭即[left, right],和左闭右开即[left, right)。
左闭右闭
while (L <= R) 要使用 <= ,因为L == R是有意义的,所以使用 <=
class Solution {
public:
int search(vector<int>& nums, int target) {
int L=0;
int R=nums.size()-1;
while(L<=R){
int mid=(L+R)/2;
if(nums[mid]==target){
return mid;
}else if(nums[mid]>target){
R=mid-1;
}else{
L=mid+1;
}
}
return -1;
}
};
左闭右开
while (L < R) 要使用 < ,因为L == R是无意义的
class Solution {
public:
int search(vector<int>& nums, int target) {
int L=0;
int R=nums.size();//注意是左闭右开,则R应大1
while(L<R){
int mid=(L+R)/2;
if(nums[mid]==target){
return mid;
}else if(nums[mid]>target){
R=mid;
}else{
L=mid+1;
}
}
return -1;
}
};
三.27. 移除元素
暴力解
先尝试暴力解,全部遍历一遍即可,最开始用for循环时发现用erase删除nums中元素时后面元素会递补上来,则删除时不应该i自增,后面改成while循环(其实for也可以,没区别),时间复杂度为O(n)
我这里使用了erase()函数,使用了vector的特性,下面看看只用数组的暴力解。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int i=0;
while(i<nums.size()){
if(nums[i]==val){
nums.erase(nums.begin()+i);
}else{
i++;
}
}
return nums.size();
}
};
真正的暴力解
因为数组并不能真正的删除,只能覆盖,所以修改数组其实是把原来的元素用后面的元素覆盖掉。时间复杂度为O(n^2)
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;
}
};
双指针法
这里用快慢指针,其中快指针一直遍历指向原数组,慢指针一直指向新数组(没有val值相同的数组),
只有当快指针对应元素即原数组值不与val相等时,覆盖进入新数组。整个原理其实是因为原数组一定大于等于新数组,新数组实际上是原数组的子集,所以快指针遍历过的空间不再需要,于是写入新数组。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
四、总结
1、理解了区间边界再来写二分查找回更加清晰,选择一种区间定义才能在边界问题上不出错,注意“循环不变量规则”。
2、要知道数组并不能直接删除的,删除数组元素其实就是覆盖,并且长度减一。
(3小时)