目录
数组理论基础
二维数组在c++的地址空间是连续的,假设我们建立一个int array[2][3],输入&array[0][0]和&array[0][1] 返回的都是里面存储的整数型数据指向内存的起始地址,这两个相邻地址的十六进制内存大小会差4,因为存储的整数型int数据是4个字节。
704.二分查找
题目链接:
底层逻辑:在数组中寻找target,没有找到就返回-1
看完楼上的视频,按照自己的思路顺了一遍,然后和老师的板书一对没问题,那看来是懂了
左闭右闭
left = 0
right = num.size-1
while(left < = right )//如果是一个闭区间,那么左右都是相同的值是合理的,比如[1,1]代表的是从1到1闭区间
middle = (left + right) /2
if(middle > target)//target在middle的左面,需要更换右边界
right = middle - 1 //闭区间的话就不包含已经大了的middle
elseif(middle < target)//target在middle的y右面,需要更换左边界
right = middle + 1 //闭区间的话就不包含已经小了的middle
else return middle
左闭右开
left = 0
right = num.size //需要比最后一位的位置高1,不然无法取到最后一位
while(left < right )//如果是一个右开区间,那么左右都是相同的值不再是合理的,比如[1,1)
middle = (left + right) /2
if(middle > target)//target在middle的左面,需要更换右边界
right = middle //开区间因为取不到middle,所以可以设置成middle
elseif(middle < target)//target在middle的右面,需要更换左边界
right = middle + 1 //闭区间的话就不包含已经小了的middle
else return middle
我写的错误代码和分析:
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while (left <= right){
int middle = (left+right)/2;
if(middle < target){
left = middle + 1;
}else if(middle > target){
right = middle -1;
}else if(middle == target){
return middle;
}else{
return -1;
}
}
return -1;
}
};
1.不应该用middle和target比大小,应该是用下标为middle的数组里面的数
2.我混淆了输出的概念,如果在while循环里面,最后一种情况是nums[middle] == target,也就是else,我把这两个混淆成了一个概念,如果相等就return nums[middle]
3.左闭右闭是nums.size()-1,在笔记里写的挺好,一写真代码就有问题
4.如果在while循环中没有找到相应的数据,那么需要在外面写return -1;
一开始没写的时候,有这样的错误
non-void function does not return a value in all control paths
这是一个编程错误,表示非空函数在所有控制路径上都没有返回值。这意味着在函数的所有执行分支中都没有返回语句。应该在每个分支中添加一个返回语句,以确保在所有情况下都返回值。
对的结果:左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while (left <= right){
int middle = (left+right)/2;
if(nums[middle] < target){
left = middle + 1;
}else if(nums[middle] > target){
right = middle -1;
}else{
return middle;
}
}
return -1;
}
};
27.移除元素
数组是一个连续的类型相近的数据的集合,删除数组中的元素是不可行的,只能让后面的元素上来进行覆盖
举个例子:
当你想删除3的时候,用erase操作,这是一个O(N)的操作其实是4和5上来补位,这个时候你再调用vector.size(),返回的是4,可是表格的内存空间占的地方还是5
1.暴力解法:
用for循环遍历列表,当出现相等的数值时,用后边的数据覆盖前面的数据,然后需要i-1,因为下一位数据已经被放在了上一个被删除数据的位置上,size-1,因为我们删除了这个相等的数据
我的错误代码分析:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for(int i = 0; i < size-1; i++){
if (nums[i] == val){
for ( int j = i ; j < size-1; j++){
nums[j] = nums[j+1];
}
}
i--;
size--;
}
return size;
}
};
错误分析:
1.如果想要遍历整个表格,也就是下标从0到size-1,那么应该是i<size
2.第二个for循环的遍历应该是 j=i+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;
}
};
2.双指针法
数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili
首先需要有两个指针,一个slow,一个fast,fast是用来遍历整体的数组元素,slow是新的数组的下标位置
slow = 0
for (fast = 0; fast < size; fast ++)
if(nums[fast] != val)
nums[slow] = nums[fast];
slow++;
//如果指向的这个新数组元素等于我们需要的值,那么就是删除操作,这里就是新数组的下标不变,会把下一个不等于val的数组元素放到这里
//快指针会一直+1,做到遍历数组元素,slow只有在满足相应条件的时候才+1
//最后slow会加1,所以就是size了
代码展示:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
int slow = 0;
for(int fast = 0; fast < size; fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};
注意:也可以把slow++放到num[]里面,是一样的效果
3.相向双指针法(只在文章里面有)
我的代码报错:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
int left = 0;
int right = size - 1;
while(left <= right){
//用左指针找到从左面起不等于val的值
while(nums[left] != val){
left++;
}
//用右指针找到等于val的值
while(nums[right] == val){
right++;
}
if(left < right){
nums[left++] = nums[right++];
}
}
//在找到最后一个val的值的时候,左指针会跳到下一个
return left;
}
};
报错原因:
1.AddressSanitizer 被用来检查内存的非法访问,在 leetcode 中出现 AddressSanitizer: heap-buffer-overflow on address
类似报错,主要原因可能是存在数组越界。
---> 应该是right--,写成++了
2.
因为左右两个指针的while都没有left<=right,这样会反复加
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
int left = 0;
int right = size - 1;
while(left <= right){
//用左指针找到从左面起不等于val的值
while(left <= right && nums[left] != val){
left++;
}
//用右指针找到等于val的值
while(left <= right && nums[right] == val){
right--;
}
if(left < right){
nums[left++] = nums[right--];
}
}
//在找到最后一个val的值的时候,左指针会跳到下一个
return left;
}
};
今日收获:
今天终于完成了代码随想录day1的内容,虽然说看上去好像很简单,但是由于我并没有算法的基础,还对c++的语言掌握得不太熟练,又学习算法又学习c++的语法,所以付出了比别人更多的时间和心血,但是!我至少搞完了!我觉得自己很棒!
学习时长:6h