第一天| 704. 二分查找、27. 移除元素、35.搜索插入位置、34. 在排序数组中查找元素的第一个和最后一个位置

博客内容:

● 今日学习的文章链接,或者视频链接
● 自己看到题目的第一想法
● 看完代码随想录之后的想法
● 自己实现过程中遇到哪些困难
● 今日收获,记录一下自己的学习时长

704. 二分查找

v1

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        n = len(nums) 
        left, right = 0, n - 1 
        while left <= right:
            mid = (left + right) // 2 
            if nums[mid] < target:
                left = mid + 1 
            elif nums[mid] > target:
                right = mid - 1 
            else:
                return mid 
        return -1

看完代码随想录之后的想法

主要就是对区间的定义没有理解清楚,在循环中没有始终坚持根据查找区间的定义来做边界处理。
区间的定义就是不变量,那么在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则。
根据两种常见的区间定义,给出了两种二分法的写法,每一个边界为什么这么处理,都根据区间的定义做了详细介绍。

两个版本写法
(版本一)左闭右闭区间

class Solution {
    public int search(int[] nums, int target) {
        // 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
        }
        return -1;
    }
}

(版本二)左闭右开区间

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

相关题目推荐

  • 35.搜索插入位置(opens new window)
  • 34.在排序数组中查找元素的第一个和最后一个位置(opens new window)
  • 69.x 的平方根
  • 367.有效的完全平方数

27. 移除元素

v1

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i, j = -1, 0 
        while j < len(nums) and i <= j:
            if nums[j] == val:
                while nums[j] == val:
                    j += 1 
                    if j >= len(nums):
                        break
                if j >= len(nums): 
                    break 
                i += 1
                nums[i] = nums[j] 
                j += 1 
            else:
                i += 1 
                nums[i] = nums[j]
                j += 1 
        return i + 1

看完代码随想录之后的想法

解法1 快慢指针(保持相对顺序不变)
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};  
解法2相向双指针(基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素)
/**
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
    int removeElement(vector& 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一定指向了最终数组末尾的下一个元素
    }
};

相关题目推荐

  • 26.删除排序数组中的重复项
  • 283.移动零
  • 844.比较含退格的字符串
  • 977.有序数组的平方

你可能感兴趣的:(第一天| 704. 二分查找、27. 移除元素、35.搜索插入位置、34. 在排序数组中查找元素的第一个和最后一个位置)