704.二分查找
·这是三个数的故事
left,middle,right
前提:数组有序 小->大
数组无重复数
使用语言:c++
寻找目标:target
思考路线:l--m--r
m找target
大小决定m
向左or向右
方法一:左闭右闭式 [l,r]
时间复杂度O(log(n));
空间复杂度O(1);
class Solution {
public:
int search(vector<int>& nums, int target) {
int m;
int l=0;
int r=nums.size()-1;
while(l<=r){
m=(l+r)/2;
if(target<nums[m]){
r=m-1;//注意!
}
else if(target>nums[m]){
l=m+1;//注意!
}
else if(target==nums[m]){
return m;
}
}
return -1;
}
};
困难笔记:
r=m和l=m造成了跳不出循环的问题
原因:重复计算,陷入死循环
理解:左闭右闭的形式下,左右边界值必定不包含前一次循环的中间值,因为前一次循环的中间值已经被判断过了。
方法二:左闭右开式 [l,r)
时间复杂度O(log(n));
空间复杂度O(1);
class Solution {
public:
int search(vector<int>& nums, int target) {
int m;
int l=0;
int r=nums.size();//区别
while(l<r){//因为[l,r)中l与r不能相等
m=(l+r)/2;
if(target<nums[m]){
r=m;//区别
}
else if(target>nums[m]){
l=m+1;//区别
}
else if(target==nums[m]){
return m;
}
}
return -1;
}
};
区别笔记:这里的r应该是右边的数+1位
收获摘要:此题需要区分好查找时判断的边界问题,注意当次循环和下一次循环中三个数的联系。
越界问题:m=(l+r)/2
int相加可能造成越界。
可以用如下公式:
m=l+(r-l)/2;
学习的文章链接:
学习的视频链接:
27、移除元素
·无序好耶!doge
不容于nums数组的val
前提:O(1)额外空间
元素顺序可以改变
不需要考虑超出新长度的数组元素
想要知道:没有val数组有多长?
思考路线:是val就往后靠,让后边的上来
方法一:看到题目的第一想法,AC
时间复杂度O(n);
空间复杂度O(1);
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int l=nums.size();
int i=0;
while(i<l){
if(nums[i]==val){
nums[i]=nums[l-1];
l--;
}
else{
i++;
}
}
return i;
}
};
思考笔记:应该也是暴力解法(本人最擅长暴力解doge),鉴于本题条件中输出数组是无序的,所以没有进行方法二中的覆盖操作。
方法二:暴力算法
时间复杂度O(n^2);
空间复杂度O(1);
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int l=nums.size();
int i=0;
int j;
for(i=0,i<l;i++){
if(nums[i]==val){
for(j=i+1;j<l;j++){//进行覆盖
nums[j-1]=nums[j];
}
i--;//下一个数组元素也可能是val
l--;//数组长度-1
}
}
return l;
}
};
方法三:双指针法
时间复杂度O(n);
空间复杂度O(1);
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int l=nums.size();
int i=0;
int slow=0;
for(int fast=0;fast<l;fast++){
if(nums[fast]!=val){//快指针指向的不是val就可以对慢指针指向的数组元素进行覆盖
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
};
感悟笔记:双指针好快!
摘要笔记:双指针妙啊~~
学习的文章链接:
学习的视频链接:
今日学习时长:4h30min
Day01:好的开始,继续努力!