二分查找和移除元素

文章讲述了如何使用二分查找算法在有序数组中寻找目标值,分别讨论了暴力方法和二分法的实现,并指出二分查找时左闭右闭和左闭右开形式的区别。此外,还介绍了如何通过双指针法在数组中删除指定元素,避免了额外的空间复杂度。
摘要由CSDN通过智能技术生成
  1. 二分查找(704)

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/binary-search

1.1暴力

class solution{
public:
     int search(vector<int>& nums,int target){
          for(int i=0;i<nums.size();i++)
          {
              if(nums[i]==targrt)
                  return i;
          }
          return -1;//为什么
     }
};

1.2 二分法做题

什么是二分法,无非就是一半一半分,即middle=(left+right)/2,到底割去那一半,留下那一半,就要看我们找的目标值target和nums[middle]进行比较:

num[middle]>target :考虑左区间[left,middle]

num[middle]<target : 考虑右区间[midlle,right]

num[middle]=target : 找到了,返回middle

采用二分法需要注意的问题

第一点:设置left和right时要么采用左闭右闭的形式:[left,right]

要么采用左闭右开的形式:[left,right)

第二点:什么条件下进入循环,即:while(left<=right) 还是 while(left<rigth)

如果是采用左闭右闭的形式:[left,right],即定义的时候:int left=0;int right=nums.size()-1;

while(left<=right) 取等号是有意义的

num[middle]>target :考虑左区间[left,middle-1]

num[middle]<target : 考虑右区间[midlle+1,right]

num[middle]=target : 找到了,返回middle

class Solution {
public:
    int search(vector<int>& nums, int target) {
       int left=0;
       int right=nums.size()-1;
       while(left<=right)
       {
           int middle=(left+right)/2;
           if(nums[middle]<target)
           {
               left=middle+1;
           }
           else if(nums[middle]>target)
           {
               right=middle-1;
           }
           else
           {
               return middle;
           }
       }
        return -1;
    }
};

如果是采用左闭右开的形式:[left,right), 即定义的时候:int left=0;int right=nums.size();

while(left<rigth) 取等号没有意义

num[middle]>target :考虑左区间[left,middle)

num[middle]<target : 考虑右区间[midlle+1,right)

num[middle]=target : 找到了,返回middle

class Solution {
public:
    int search(vector<int>& nums, int target) {
       int left=0;
       int right=nums.size();
       while(left<right)
       {
           int middle=(left+right)/2;
           if(nums[middle]<target)
           {
               left=middle+1;
           }
           else if(nums[middle]>target)
           {
               right=middle;
           }
           else
           {
               return middle;
           }
       }
        return -1;
    }
};
  1. 移除元素(27)

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝

int len = removeElement(nums, val);

在函数里修改输入数组对于调用者是可见的。

根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。

for (int i = 0; i < len; i++) {

print(nums[i]);

}

链接:https://leetcode.cn/problems/remove-element

2.1暴力

数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖

一个for循环遍历数组元素 ,第二个for循环更新数组

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len=0;
        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];
                }
                i--;
                size--;
            }
        }
        return size;
    }
};

2.2双指针法

通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组

慢指针:指向更新新数组下标的位置

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowly=0;
        for(int fast=0;fast<nums.size();fast++)
        {
            if(nums[fast]!=val)
            {
                nums[slowly]=nums[fast];
                slowly++;
            }
        }
        return slowly;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值