代码随想录DAY1| 数组 |二分查找、移除元素

本文介绍了C++实现的二分查找和移除元素两种算法,包括问题描述、思路分析、代码实现以及调试过程中的收获。通过实例演示了如何在有序数组中寻找目标值和移除特定元素,同时强调了双指针方法在移除元素问题上的应用。
摘要由CSDN通过智能技术生成


前言

恰好在准备刷力扣的时候,看到代码随想录训练营开营,怎么不算一种顺利呢~
详细的包含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:

  1. 定义middle时,应该是right-left
  2. if(){}
    else if(){} else{} 收获:
  3. C++11的循环输出方式
  4. 如何实例化验证:定义函数实参,实例化类,定义函数返回值,进行输出

2024/4/17二刷

Debug:

  1. 判断范围之后,指针变化,变的是索引,而不是值
  2. 输出函数返回值时,判断条件是 !=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:

  1. int size = nums.size();
  2. 赋值和判断 =&==
  3. return这一步在哪一次循环或判断之后
  4. 用循环的方式输出数组或许会更好
2024/4/17二刷

Debug:

  1. 第二个循环的覆盖操作结束后,i - -
    位置 是在第二个循环结束,把所有后面的向前覆盖住之后
    原因 是为删除后的遍历做准备

双指针

2024/4/16一刷

Debug:

  1. 虽然叫双指针,但fast和slow都只是数组的index
2024/4/17二刷

Debug:

  1. 不相等的记录,相等的跳过(需要一点清晰的流程图

总结

(很麻烦的记录…谁懂…
下次纯脑里想 思路、注意点 可能会更有收获一点

还需复习:27. 移除元素 暴力解法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值