代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
1.代码随想录算法训练营第二天| 977.有序数组的平方,209.长度最小的子数列,59.螺旋矩阵Ⅱ
2.代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
3.代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表4.代码随想录算法训练营第四天| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个结点,面试题02.07.链表相交,142.环形链表Ⅱ5.代码随想录算法训练营第六天| 242.有效的字母异位词,349.两个数组的交集,202.快乐数,1.两数之和6.代码随想录算法训练营第7天| ● 454.四数相加II ● 383. 赎金信 ● 15. 三数之和 ● 18. 四数之和7.代码随想录算法训练营第8天| ● 344.反转字符串 ● 541. 反转字符串II ● 剑指Offer 05.替换空格 ● 151.翻转字符串里的单词 ● 剑指Offer58-II.左旋转字符串8.代码随想录算法训练营第9天| ●28. 实现 strStr() ●459.重复的子字符串 ●字符串总结 ●双指针回顾 9.代码随想录算法训练营第10天| 232.用栈实现队列 ● 225. 用队列实现栈10.代码随想录算法训练营day13| ● 239. 滑动窗口最大值 ● 347.前 K 个高频元素 ● 总结11.代码随想录算法训练营day11| ● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值12.代码随想录算法训练营day14| ● 二叉树理论基础 ● 递归遍历 ● 迭代遍历 ● 统一迭代13.代码随想录算法训练营day15 | ● 层序遍历 10 ● 226.翻转二叉树 ● 101.对称二叉树 2 14.代码随想录算法训练营day16 | ● 104.二叉树的最大深度 559.n叉树的最大深度 ● 111.二叉树的最小深度 ● 222.完全二叉树的节点个数15.代码随想录算法训练营day17 | ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和 16.代码随想录day21 | ● 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● 236. 二叉树的最近公共祖先 数组
704.二分查找
mydemo
class Solution {
public:
int search(vector<int>& nums, int target) {
int len = nums.size();
//cout << len;
int left = 0;
int right = len-1;
int mid = (left + right) / 2;
while(left <= right)
{
if(nums[mid] < target)
{
left = mid + 1;
mid = (left + right) / 2;
}
if(nums[mid] == target)
return mid;
if(nums[mid] > target)
{
right = mid - 1;
mid = (left + right) / 2;
}
}
return -1;
}
};
为什么是
left = mid + 1; right = mid - 1
而不是
left = mid; right= mid;
解答
其实在发生大小判断进入更新left或right的分支后,mid就已经被排除在外了,所以不用考虑mid所在位置,+1或者-1进行移动即可。
而且移动有一个好处,就是可以让left何right重叠甚至是反向(right在left前面),这是跳出循环的重要条件
而且不进行移动的话,考虑一种极限情况:
[7,8], target = 8
left = 0, right = 1,mid = 0;
你会发现无论怎么样mid都无法到达target。
要是target过大或过小不在数组里,这个算法怎么输出-1呢?
解
关键:
while(left <= right)
target过大,left会不断朝着right移动,到达临界点(left = right),然后继续变大,跳出循环
target过小则反之
为什么是
while(left <= right)
而不是
while(left < right)
解
考虑一种极限情况,即数组一开始就只有一个元素 {5},
令 target = 5
那么:
mid = 0 ,left = 0, right = 0
left 等于 right,无法进入循环进行二分查找,从而输出-1,这是显然是错误的
27.移除元素
1 暴力解法
my demo:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
for(int i = 0; i < len; i++)
{
if(nums[i] == val)
{
//cout << "i=" << i << endl;
if(nums[i] == val)
{
if(i==len)
len--; //不加的话,当i=len-1时,nums[j] = nums[j+1];有可能会越界
else
{
for(int j = i; j < len-1; j++)
{
nums[j] = nums[j+1];
}
len--;
i--; //不加这一行,在 0,1,2,2,3,val=2这种要删除的元素重复出现的时候会出错
}
}
}
}
return len;
}
};
2 快慢指针法
my demo
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
int slow = 0;
for(int fast = 0; fast < len; fast++)
{
if(nums[fast] != val)
{
nums[slow] = nums[fast];
slow++;
}
}
return slow;
};
};
优化版:
nums[slow] = nums[fast];
slow++;
改为
nums[slow++] = nums[fast];
合集:
代码随想录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!