文章目录
前言
恰好在准备刷力扣的时候,看到代码随想录训练营开营,怎么不算一种顺利呢~
详细的包含main函数的代码,小白可直接在vs运行~
一、704. 二分查找
文档&视频讲解:代码随想录
1. 题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
2. 思路
通过target和middle的比较,用middle调整left和right,最终确定target的位置,返回middle(若存在target,此时middle为其索引)
提示:此处left、middle、right为索引,target为具体值
3. 代码实现
//Time:2024/4/17训练营跟练
#include<iostream>
#include<vector>
using namespace std;
//左闭右闭
//class Solution {
//public:
// int search(vector<int> &nums,int target) {
// int left = 0;
// int right = nums.size() - 1;
// while (right >= left) {
// int middle = left + (right - left) / 2;
// if (nums[middle] > target) {
// //是索引指针变,不是数值变
// //nums[right] = nums[middle]-1;
// right = middle - 1;
// }
// else if (nums[middle] < target) {
// //nums[left] = middle + 1;
// left = middle + 1;
// }
// else {
// return middle;
// }
// }
// return -1;
// }
//};
//左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (right > left) {
int middle = left + (right - left) / 2;
if (nums[middle] > target) {
//是索引指针变,不是数值变
//nums[right] = nums[middle]-1;
right = middle;
}
else if (nums[middle] < target) {
//nums[left] = middle + 1;
left = middle + 1;
}
else {
return middle;
}
}
return -1;
}
};
int main()
{
vector<int> nums = { 0,1,2,3,4,5,6,7,8 };
int target = 9;
cout << "原数组:";
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
Solution solution;
int index = solution.search(nums, target);
//index的分类不是==1或!=1
//while (index == -1) {
// cout << -1;
//}
//while (index != -1) {
// cout << index;
//}
if (index != -1) {
cout << index;
}
else {
cout << -1;
}
return 0;
}
4.Debug与收获
2024/4/15一刷
Debug:
- 定义middle时,应该是right-left
- if(){}
else if(){} else{} 收获:- C++11的循环输出方式
- 如何实例化验证:定义函数实参,实例化类,定义函数返回值,进行输出
2024/4/17二刷
Debug:
- 判断范围之后,指针变化,变的是索引,而不是值
- 输出函数返回值时,判断条件是 !=0 及 其他(不是!=0和==0
二、27. 移除元素
文档&视频讲解:代码随想录
1. 题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
2. 思路
暴力解法:两个for循环
一个遍历数组所有元素,判断条件是:nums[i]==val;
进入第二个for循环:①定义j=i+1 ②循环语句:i 后续所有 j 一步步向前覆盖;
遍历完所有元素且覆盖完成后,返回size
提示:注意i--,和return的位置
双指针:(个人感觉更简单一点)
快慢指针其实是index,
fast查找,slow记录
判断条件:nums[fast]!=val,记录到nums[slow]里 , slow++(fast的自增在循环里)
3. 代码实现
//Time:2024/4/17训练营跟练
#include<iostream>
#include<vector>
using namespace std;
//暴力解法
//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];
// }
// //遍历全部元素前的准备:指针前移、size减小
// i--;//后面的数值向前移动覆盖,但循环器里i还在++,所以i--进行抵消,保证指针位置不变
// size--;
// }
// }
// return size;
// }
//};
//双指针
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;
}
};
int main()
{
vector<int>nums = { 3,2,2,3 };
int val = 3;
Solution solution;
int len = solution.removeElement(nums, val);
cout << len << ", " << "nums = [";
for (int i = 0; i < len; i++) {
cout << nums[i]<<" ";
}
cout << "]";
return 0;
}
4. Debug与收获
暴力解法
2024/4/16一刷
Debug:
- int size = nums.size();
- 赋值和判断 =&==
- return这一步在哪一次循环或判断之后
- 用循环的方式输出数组或许会更好
2024/4/17二刷
Debug:
- 第二个循环的覆盖操作结束后,i - -
位置 是在第二个循环结束,把所有后面的向前覆盖住之后
原因 是为删除后的遍历做准备
双指针
2024/4/16一刷
Debug:
- 虽然叫双指针,但fast和slow都只是数组的index
2024/4/17二刷
Debug:
- 不相等的记录,相等的跳过(需要一点清晰的流程图
总结
(很麻烦的记录…谁懂…
下次纯脑里想 思路、注意点 可能会更有收获一点
还需复习:27. 移除元素 暴力解法