代码随想录 9.20 || 数组 LeetCode 704.二分查找、27. 移除元素

LeetCode 704 二分查找

题目链接:704.二分查找

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

        二分查找共有两种实现方式,即“左闭右闭”“左闭右开”,区间不同,函数实现的逻辑不同,下面给出在两种区间上基于C和C++的实现:

左闭右闭(C):

int search(int* nums, int numsSize, int target){
  int left  = 0; //左边界
  int right = numsSize - 1; //右边界
  int middle;
  while(left <= right){ //定义[left,right],左闭右闭区间
    middle = left + ((right - left) / 2); //防止right+left泄露
    if(nums[middle] > target){ //target在[left, middle-1]区间
      right = middle - 1;
    }else if(nums[middle] < target){ //target在[middle+1,right]区间
      left = middle + 1;
    }else{ // nums[middle] == target
      return middle; //找到目标值,返回下标
    }
  }
  return -1; // 未找到目标值
}

左闭右开(C):

int search(int* nums, int numsSize, int target){
  int left  = 0; //左边界
  int right = numsSize; //右边界
  int middle;
  while(left < right){ //定义[left,right),左闭右开区间
    middle = left + ((right - left) / 2);
    if(nums[middle] > target){ //target在[left, middle)区间
      right = middle;
    }else if(nums[middle] < target){ //target在[middle+1,right)区间
      left = middle + 1;
    }else{ // nums[middle] == target
      return middle; //找到目标值,返回下标
    }
  }
  return -1; // 未找到目标值
}

        在某些情况下,“左闭右开”会多跑一轮循环,在时间成本上高于“左闭右闭”,个人感觉“左闭右闭”也更符合严谨的编程思维,下面是基于C++的实现。

左闭右闭(C++):

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

左闭右开(C++):

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

        本人初学C++,如有问题,恳请指正,不胜感激。

LeetCode 27 移除元素

题目链接:27.移除元素

        给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用O(1)额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

        要求原地执行修改,不允许定义额外的数组,有两种解法,“暴力解法”和“双指针方法”:前者通过循环嵌套,将等于val元素后的所有元素前移一位,覆盖掉该元素;后者通过“慢指针”和“快指针”的组合,“慢指针”代表新数组中元素的个数,新数组中最后一个元素的下一个位置,将“快指针”指向的非val元素赋给“慢指针”,下面给出两种解法基于C和C++的实现:

暴力解法(C):

int removeElement(int* nums, int numsSize, int val){
    for(int i = 0; i < numsSize; i++){
        if(nums[i] == val){
            for(int j = i + 1; j < numsSize; j++){
                nums[j - 1] = nums[j];
            }
        numsSize--; //长度自减
        i--; //i也要自减
        }
    }
    return numsSize;
}

双指针(C):

int removeElement(int* nums, int numsSize, int val){ //双指针
    int slowIndex = 0;
    for(int fastIndex = 0; fastIndex < numsSize; fastIndex++){
        if(nums[fastIndex] != val){
            nums[slowIndex++] = nums[fastIndex]; //把所有不为val的元素都移到前面
        }
    } 
    return slowIndex;
}

        “双指针”的思想可以应用在很多算法中,请熟练掌握。

暴力解法(C++):

public:
    int removeElement(vector& nums, int val) {
        int length = nums.size();
        for(int i = 0; i < length; i++){
            if(nums[i] == val){
                for(int j = i + 1; j < length; j++){
                    nums[j - 1] = nums[j];
                }
                length--;
                i--;
            }
        }
        return length;
    }
};

双指针(C++):

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

        第一天算法训练营,打卡完毕!

你可能感兴趣的:(算法)