Day01算法| 704. 二分查找、27. 移除元素

本文详细介绍了二分查找在有序数组中的应用,包括左闭右闭和左闭右开两种情况,并探讨了如何使用快慢指针法移除数组中的元素,提供了两种移除元素的方法及其时间复杂度分析。
摘要由CSDN通过智能技术生成

二分查找

二分查找

1.使用条件:有序数组且互不重复

2.前闭后闭:

  •   left=0;right=nums.length-1;//右端需要保证闭区间必须减一
  • 因为右端点有定义,所以判断条件while (left <= right) 要使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1
 class Solution {
    public int search(int[] nums, int target) {
    	//二分查找左闭右闭
    	int left=0,right=nums.length-1;
    	while(left<=right) {
    		int middle=left+(right-left)>>1;
    		if(target<nums[middle]) 
    			right=middle-1;
    		else if(target>nums[middle])
				left=middle+1;
    		else if (target==nums[middle])
				return middle;
    	}
    	return -1;
    }
}

3.前闭后开

  •   left=0;right=nums.length;
  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle
    class Solution {
    public int search2(int[] nums, int target) {
        	//二分查找左闭右开
        	int left = 0, right = nums.length;
            while (left < right) {
    //     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;
        }
    }

    移除元素(双指针法)

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

整个过程保持不变的性质是:区间 [0,left)[0,left})[0,left) 中的元素都不等于 val。当左右指针遍历完输入数组以后,left 的值就是输出数组的长度。

这样的算法在最坏情况下(输入数组中没有元素等于 val\textit{val}val),左右指针各遍历了数组一次。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
    // 时间复杂度:O(n)
    // 空间复杂度:O(1)
    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;
        }
    };
  • 相向双指针方法

基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素

如果左指针 left 指向的元素等于 val,此时将右指针 right 指向的元素复制到左指针 left 的位置,然后右指针 right 左移一位。如果赋值过来的元素恰好也等于 val,可以继续把右指针 right指向的元素的值赋值过来(左指针 left指向的等于 val 的元素的位置继续被覆盖),直到左指针指向的元素的值不等于 val 为止。

当左指针 left和右指针 right重合的时候,左右指针遍历完数组中所有的元素。

这样的方法两个指针在最坏的情况下合起来只遍历了数组一次。与方法一不同的是,方法二避免了需要保留的元素的重复赋值操作。

public int removeElement4(int[] nums, int val) {
        int left = 0;
        int right = nums.length;
        while (left < right) {
            if (nums[left] == val) {
                nums[left] = nums[right - 1];
                right--;
            } else {
                left++;
            }
        }
        return left;
    }

小技巧:

1.left + ((right -left) >> 1) == (left + right) /2

left + right 在某种情况下可能会超过基本类型所能容纳的最大值,而且 >> (位运算) 比 / 运算要快一点

2.数组的输出的方式

调用Array.toString(a),返回一个包含数组元素的字符串,这些元素被放置在括号内,并用逗号分开

System.out.println(Arrays.toString(array)); 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值