一、参考资料
数组理论基础
文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
二分查找
题目链接:https://leetcode.cn/problems/binary-search/
文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
移除元素
题目链接:https://leetcode.cn/problems/remove-element/
文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP
二、LeetCode704-二分查找
我的代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
cout << left << ' ' << right<<endl;
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] == target){
return mid;
}
else if(nums[mid] > target){
right = mid - 1;
}
else{
left = mid + 1;
}
}
return -1;
}
};
遇到的问题:
- 好久没刷题,基本语法还要再熟悉的,size和length需要区分一下
- left注意初始化的问题,不然会编译报错
- mid如果为了防止溢出,可采用left + (right - left) / 2
- 今天写之前花了点时间看代码规范的问题!还是很有必要的,学习到很多细节问题,以后也要慢慢注重培养呢
- 对于二分查找的方法,理解起来觉得并不难,但是看完视频讲解和文章,才认识到有“左闭右闭”及“左闭右开”两种思路,这直接影响到代码的逻辑实现
接下来学习一下规范的代码实现:
左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1; // target 在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左区间,在[left, middle)中
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,在[middle + 1, right)中
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
三、LeetCode27-移除元素
这题有两种解法,分别是暴力求解和双指针
思路一:暴力求解-第一层for循环枚举所有数组的元素,第二层for循环做元素的覆盖,当找到与目标值相同的元素时,在第二层循环中依次将后续元素向前移动。
暴力求解-代码实现
// 时间复杂度: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--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位 size--; // 此时数组的大小-1 } } return size;
}
};
思路二:双指针-也称快慢指针操作,视频讲解的很好,值得看一下动画效果,这里的移除也相当于是库函数的实现
双指针-代码实现
// 时间复杂度:O(n)
// 空间复杂度:O(1)
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;
}
};
标签:27,target,nums,int,随想录,middle,right,移除,left From: https://www.cnblogs.com/ucaszym/p/17045096.html