代码随想录算法训练营第一天|704.二分查找,24.移除元素
题目链接 -704.二分查找
解答状态:已通过
自己的解答:
class Solution {
public:
int search(vector<int>& nums, int target)
{
int length = nums.size();
if(length==0)
{
return -1;
}
if(length==1)
{
if(nums[0]==target)
{
return 0;
}
else
{
return -1;
}
}
int mid = length / 2;
if(nums[mid]==target)
{
return mid;
}
else if(nums[mid]>target)
{
return divide(0,mid-1,nums,target);
}
else if(nums[mid]<target)
{
return divide(mid+1,length-1,nums,target);
}
else
{
return -1;
}
}
int divide(int front,int after,vector<int>& nums,int target)
{
if(front==after)
{
if(nums[after]==target)
{
return after;
}
else
{
return -1;
}
}
int mid = (front+after)/2;
int length = after-front+1;
if(nums[mid]==target)
{
return mid;
}
else if(nums[mid]>target)
{
return divide(0,mid-1,nums,target);
}
else if(nums[mid]<target)
{
return divide(mid+1,after,nums,target);
}
else
{
return -1;
}
}
};
解题思路:不知道为什么,自己一开始就想到用递归,首先求出中间元素【mid】,用于与target进行比较,如果正确则直接返回,如果小于target,则在右区间进行求解,相反,在左区间进行求解,当然我的这个方法都是基于题目中提到的两个关键条件:【所有元素是不重复的】和【元素有序】
代码随想录题解:直接用while循环进行搜索,比我的代码要简单一些
左闭右闭
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;
}
};
[704-代码解析](代码随想录 (programmercarl.com))
[704-视频讲解](手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili)
题目链接-24.移除元素
解答状态:已通过
自己的解答:
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int length = nums.size();
int pos = 0;
for(int i=0;i<length;i++)
{
if(nums[i]!=val)
{
nums[pos] = nums[i];
pos++;
}
}
return pos;
}
};
解题思路:因为题目要求移除值为val的元素,那就可以把val值的元素都移到数组尾,非val的元素向前移动,最后返回的pos就是非val元素构成的数组的长度,题目已经说明,超出非val值的部分不用在意
代码随想录题解:
快慢双指针法
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;
}
};
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
相向双指针法
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一定指向了最终数组末尾的下一个元素
}
};