【前端er每日算法】Leetcode 数组2题-704二分查找-27移除元素有妙招

44 阅读2分钟

题目一 704. 二分查找

思路

经典二分查找,简单但易错,需要注意边界,设定一个统一的规则,左闭右开的区间规则进行遍历。

var search = function(nums, target) {
    if (!nums) {
        return -1;
    }
    let i = 0;
    let j = nums.length;
    while (i < j) {
        let mid = Math.floor((j + i) / 2);
        let val = nums[mid];
        if (target == val) {
            return mid;
        } else if (target < val) {
            j = mid
        } else {
            i = mid + 1
        }
    }
    return -1
};

// 8.28
var search = function(nums, target) {
    let left = 0;
    let right = nums.length;
    while (left < right) {
        let mid = parseInt((right - left) / 2, 10) + left;
        if (nums[mid] === target) {
            return mid;
        }
        if (target < nums[mid]) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return -1;
};

题目2: 27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

思路

这个题一种是暴力解法

// 暴力解法
var removeElement = function(nums, val) {
    let i = 0;
    let count = 0;
    for (i = 0; i < nums.length - count; i++) {
        if (nums[i] === val) {
            for (let j = i + 1; j < nums.length; j++) {
                nums[j - 1] = nums[j]
            }
            count++
            i--
        }
    }
    return nums.length - count;
}

一种是双指针法,遍历一趟元素,如果当前元素不等于要删除的值,就赋值到i的位置,i再++,如果相等,则跳过,最后会遍历到结束,而i的位置就是不等于删除元素的位置。

var removeElement = function(nums, val) {
    let i = 0;
    let len = nums.length;
    // 找到第一个要删除的数据
    for (let j = 0; j < len; j++) {
        if (nums[j] !== val) {
            nums[i++] = nums[j];
        }
    }
    return i;
};

双指针进化版:上面的元素复制操作较多,不需要赋值的也赋值了,题解中优化解法,一个指向第一个left,一个指向最后一个right。

  • 如果元素等于要删除的元素了,则left,right交换,同时,right--
  • 如果不相等,则left++

最后i得位置就是最后不想等的元素。

写的时候边界条件容易写错,left <= right,嗯,写了几遍错了。。最后调试出来的。

// 双指针优化解法
var removeElement = function(nums, val) {
    let left = 0;
    let right = nums.length - 1;
    while (left <= right) {
        if (nums[left] === val) {
            let tmp = nums[left];
            nums[left] = nums[right];
            nums[right] = tmp;
            right--;
        } else {
            left++;
        }
    }
    return left;
}