代码随想录算法训练营第一天 数组 | 704. 二分查找 | 27. 移除元素
数组
使用连续的内存空间,间隔为储存数据类型的大小,C++中多维数组的内存空间也是连续的。
二分查找
二分查找多用于有序数组,通过不断缩小查找范围来实现。
具体实现一般有 左闭右闭 和 左闭右开 两种 (其他实现有可能不符合直觉,提高代码阅读的难度)
一般时间复杂度是
两种写法的差别
以下为leetcode第704题
左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
//左闭右闭
int left = 0, right = nums.size()-1;//右闭
while(left <= right){//范围内只有一个元素时,左右相等
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] < target){
left = middle + 1;
}
else if (nums[middle] > target){
right = middle - 1;
}
else {
return middle;
}
}
return -1;
}
};
左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
//左闭右开
int left = 0, right = nums.size();//右开
while(left < right){//任何情况,左也不能大于等于右
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] < target){
left = middle + 1;
}
else if (nums[middle] > target){
right = middle;
}
else {
return middle;
}
}
return -1;
}
};
移除元素
数组中并不存在现实意义上的的 “移除” ,我们需要在连续的内存空间内将目标删除元素之后的所有元素向前移动。
以下为leetcode第27题, 要求空间复杂度为
自己写的暴力算法
时间复杂度为
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int count = 0;
for (int i = 0; i < nums.size()-count; i++){
if (nums[i] == val){ //执行删除,后面的元素向前移动,当前元素放到最后
count++;
for (int j = i; j < nums.size()-1; j++){
nums[j] = nums[j+1];
}
nums[nums.size()-1] = val;
--i;
}
/*
//log
for (auto &n : nums){
cout << n << ' ';
}
cout<<count<<'\n';
*/
}
return nums.size() - count;
}
};
双指针
使用双指针使时间复杂度为
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for (int fast = 0; fast < nums.size(); fast++){
if (nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};
/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while (leftIndex <= rightIndex) {
// 找左边等于val的元素
while (leftIndex <= rightIndex && nums[leftIndex] != val){
++leftIndex;
}
// 找右边不等于val的元素
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
-- rightIndex;
}
// 将右边不等于val的元素覆盖左边等于val的元素
if (leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; // leftIndex一定指向了最终数组末尾的下一个元素
}
};
虽然暂时理解了双指针在删除数组元素的应用,但是具体从复杂问题到想到使用双指针,以及快慢指针或两个指针指向什么的过程缺乏锻炼,希望以后遇到得以巩固。
Reference
二分法 # 手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找
本文作者:冰镇杨梅 | phi
本文链接:https://www.cnblogs.com/frozenwaxberry/p/17044680.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步