二分查找与双指针

文章介绍了二分查找算法的三种实现方式,包括左闭右闭、左闭右开的形式,并讨论了处理边界条件的方法。同时,文章对比了暴力解法和双指针法在移除数组元素时的效率和实现策略,双指针法通过快慢指针的配合能更高效地完成目标操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找与双指针

1. 二分查找

暴力解法

遍历数组,如果nums[i]和target值相等,则返回

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
 // 暴力解法,时间复杂度为O(n)
var search = function(nums, target) {
    let res = -1;
    for(let i = 0; i < nums.length;i++) {
        if(nums[i] == target) {
            res = i;
            break;
        } 
    }
    return res;
};

左闭右闭

[left,right]写法要注意left <=right, 和right = middle

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
 // 左闭合右闭合[left,right]
var search = function(nums, target) {
    let left = 0, right = nums.length -1;
    // 避免当target < nums[0]或者target > nums[nums.length -1]时做多余的判断
    if(target < nums[left] || target > nums[right]) {
        return -1;
    }
    while(left <= right) {
        let middle = left + Math.floor((right - left) / 2);
        if(nums[middle] == target) {
            return middle;
        } else if(nums[middle] > target) {
            right = middle - 1;
        } else {
            left = middle + 1;
        }
    }
    return -1;
};

左闭右开

[left,right]写法要注意left <right, 和right = middle - 1

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
 // 左闭合右开[left,right)
var search = function(nums, target) {
    let left = 0, right = nums.length;
    // 避免当target < nums[0]或者target > nums[nums.length -1]时做多余的判断
    if(target < nums[left] || target > nums[right - 1]) {
        return -1;
    }
    while(left < right) {
        let middle = left + Math.floor((right - left) / 2);
        if(nums[middle] == target) {
            return middle;
        } else if(nums[middle] > target) {
            right = middle; // 右开区间
        } else {
            left = middle + 1;
        }
    }
    return -1;
};

2. 移除元素

暴力解法

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    let len = nums.length;
    // 第一层循环遍历
    for(let i = 0; i < len; i++) {
        // 从i之后遍历,所有元素向前移动一位
        if(nums[i] == val) {
            for(let j = i + 1; j < len; j++) {
                nums[j-1] = nums[j];
            }
            // 此时的第i位是原来的i+1位,需要重新判断
            i--;
            len--;
        }
    }
    return len;
};

双指针

双指针的妙用在于搞清楚快指针和慢指针的作用
快慢指针一起出发,如果遇到的值不是target值,则一起前进一步,并把快指针的值放到如今的慢指针处,当遇到和target相同的值,慢指针停一步,快指针继续往前走,这样慢指针跳过几次,就有几个和target相同的值,最终返回slow,就返回了移除元素后数组的长度。

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    if(nums.length == 0) return 0;
    let slow = 0;
    let fast = 0;
    while(fast < nums.length) {
        // 当不等于val时,slow指针 ++
        if(nums[fast] !== val) {
            nums[slow] = nums[fast];
            slow++;
        }
        // 等于val时,只有fast指针++
        fast++;
    }
    return slow;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值