代码随想录算法训练营第一天 | 数组-704.二分查找、27移除元素

day01:704.二分查找、27移除元素

LeetCode 704 二分查找

题目链接:

704.二分查找

文章讲解:

https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

视频讲解:

https://www.bilibili.com/video/BV1fA4y1o715

思路和解法:

暴利法:

直接遍历数组,找到需要的值后返回下标,时间复杂度O(N),但这样做就没意义了,舍弃!

二分法:

定义好查找的范围后,每次查找取范围的中点,比较nums[mid]和target的大小,然后根据情况更新查找范围。

主要有两种写法,区别是边界条件的不同, 左闭右闭 [left, right] 或 左闭右开 [left, right)

时间复杂度:O(logN)

一、左闭右闭 [left, right],循环条件:while(left <= right)
    public int Search(int[] nums, int target) {
        int left = 0;
        int right = nums.Length - 1;
        while(left <= right)
        {
            int mid = (right - left) / 2 + left;
            if(nums[mid] < target)
            {
                left = mid + 1;
            }
            else if(nums[mid] > target)
            {
                right = mid - 1;
            }
            else
            {
                return mid;
            }
        }
        return -1;
    }
二、左闭右开[left, right),while(left < right)
    public int Search(int[] nums, int target) {
        int left = 0;
        int right = nums.Length;//特殊情况:目标值在最右边,所以right的初始值要为nums.Length
        while(left < right)
        {
            int mid = (right - left) / 2 + left;
            if(nums[mid] < target)
            {
                left = mid + 1;
            }
            else if(nums[mid] > target)
            {
                //因为边界条件是左闭右开的,所以要保证右区间合法
                right = mid;
            }
            else
            {
                return mid;
            }
        }
        return -1;
    }

LeetCode 27移除元素

题目链接

LeetCode 27 移除元素

文章讲解

https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html

视频讲解

https://www.bilibili.com/video/BV12A4y1Z7LP

思路和方法

暴力法:

两层for循环,一层循环遍历数组,一层循环更新数组

public int RemoveElement(int[] nums, int val) {
        int n = nums.Length;
        for(int i = 0; i < n; i++)
        {
            //发现需要移除的元素,就将数组集体向前移动一位
            if(nums[i] == val)
            {
                for(int j = i + 1; j < n; j++)
                {
                    nums[j - 1] = nums[j];
                }
                i--;//因为下标i之后的值都向前移动了一位,所以i也要向前移一位
                n--;//此时数组的大小减一
            }
        }
        return n;
    }
双指针法

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

定义快慢两个指针。

  • 快指针:用于寻找新数组的元素,新数组指不含有目标元素的数组

  • 慢指针:指向新数组要更新的下标

    public int RemoveElement(int[] nums, int val) {
        int slow = 0,fast = 0;
        while(fast < nums.Length)
        {
            if(nums[fast] != val)
            {
                nums[slow] = nums[fast];
                slow++;//slow右移,指向下一个位置
            }
            fast++;
        }
        return slow;//因为slow当前指向的位置未被处理,所以不用slow-1
    }

总结:

上述两题涉及到的方法虽然看上去很复杂,但只要跟着思路把每一步、每次一遍历画出来,就很容易理解了,多画图!

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