代码随想录的第一天

358 阅读2分钟

代码随想录的第一天

704:二分查找

暴力算法
var search = function(nums, target) {
    let tem = -1
    for (let i = 0; i< nums.length; i++) {
        if (target === nums[i]) {
            tem = i
        }
    }
    return tem
};
二分算法
左闭右闭:
var search = function(nums, target) {
    let left = 0, right = nums.length - 1
    while (left <= right) {
        const temp = Math.floor((left + right) / 2)
        if (nums[temp] === target) {
            return temp
        } else if (nums[temp] < target) {
            left = temp + 1
        } else if (nums[temp] > target) {
            right = temp - 1
        }
    }
    return -1
};
左闭右开:
var search = function(nums, target) {
    let left = 0, right = nums.length
    while (left < right) {
        const temp = Math.floor((left + right) / 2)
        if (nums[temp] === target) {
            return temp
        } else if (nums[temp] < target) {
            left = temp + 1
        } else if (nums[temp] > target) {
            right = temp
        }
    }
    return -1
};

思路:根据区间的边界的是否闭合来判断

1、判断右边是否闭合:闭合即包括,长度自然需要减去一(长度溢出);非闭合等于长度就行,相当于一个用边界进行处理,一个用边界里面的内容进行处理

2、左右是否相等:闭合1=1成立,不闭合1=1不成立

3、当目标值小于中间值:闭合时,需要减一,因为边界不包含,要去下一个边界;非闭合时,用的是边界中的内容,不需要减一

27:移除元素

暴力算法:
不符合题意
var removeElement = function(nums, val) {
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] === val) {
            nums.splice(i, 1)
            i--
        }
    }
    return nums.length
};

var removeElement = function(nums, val) {
    for (let i = 0; i< nums.length; i++) {
        if (nums[i] === val) {
            for (let j = i + 1;j < nums.length;j++) {
                nums[j - 1] = nums[j]
            }
            i--
            nums.length--
        }
    }
    return nums.length
};
覆盖法:(取巧)
var removeElement = function(nums, val) {
    let ans = 0
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] !== val) {
            nums[ans] = nums[i]
            ans++
        }
    }
    return ans
};
数组的元素位置改变了下,记录了下长度
双指针:
var removeElement = function(nums, val) {
    let slow = 0,fast = 0
    while (fast < nums.length) {
        if (nums[fast] !== val) {
            nums[slow] = nums[fast]
            slow++
        }
        fast++
    }
    nums.length = slow		// 也可以直接拿数组
    return slow
};

思路:(双指针)

1、顾名思义需要定义两个指针,一快一慢

2、全部从0开始走,快指针走的快,走到nums.length的时候就走完了

3、快指针遇到目标值就跳过去,没有遇到就将值给慢指针,慢指针走下一个,快指针一直走,最后会把目标值都放在数组最后,慢指针走过的长度就是新数组的长度

附加:

35.搜索插入位置

暴力算法
var searchInsert = function(nums, target) {
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] >= target) {
            return i
        }
    }
    return nums.length
};

二分算法

左闭右闭:
var searchInsert = function(nums, target) {
    let left = 0,right = nums.length - 1;
    while (left <= right) {
        const mid = Math.floor((left + right) / 2)
        if (nums[mid] === target) {
            return mid
        } else if (nums[mid] < target) {
            left = mid + 1
        } else if (nums[mid] > target) {
            right = mid - 1
        }
    }
    return left
};
左闭右开:
var searchInsert = function(nums, target) {
    let left = 0,right = nums.length;
    while (left < right) {
        const mid = Math.floor((left + right) / 2)
        if (nums[mid] === target) {
            return mid
        } else if (nums[mid] < target) {
            left = mid + 1
        } else if (nums[mid] > target) {
            right = mid
        }
    }
    return left
};

思路:

1、和二分查找基本一样

2、为什么最后返回left?需要注意当left < 或者 <= right的时机,是左边高于右边,那么上一步的操作必然是left = mid + 1,那么就是刚好没找到目标值跳了过去,所以返回上一步的left

34.在排序数组中查找元素的第一个和最后一个位置

暴力解法:
var searchRange = function(nums, target) {
    let arr = []
    for (let i = 0; i<nums.length;i++) {
        if (nums[i] === target) {
            arr.push(i)
        }
    }
    return arr.length > 0 ? [arr[0], arr[arr.length - 1]] : [-1,-1]
};
二分算法:
var searchRange = function(nums, target) {
    let ans = [-1,-1]
    const leftIndex = getIndex(nums, target, true)
    const rightIndex = getIndex(nums, target, false) - 1
    if (leftIndex <= rightIndex && rightIndex < nums.length && nums[leftIndex] === target && nums[rightIndex] === target) {
        ans = [leftIndex, rightIndex]
    }
    return ans
}

const getIndex = (nums, target, type) => {
    let left = 0, right = nums.length - 1, ans = nums.length;
    while (left <= right) {
        const mid = Math.floor((left + right) / 2)
        if (nums[mid] > target || (type && nums[mid] === target)) {
            right = mid - 1
            ans = mid
        } else {
            left = mid + 1
        }
    }
    return ans
}

思路:

1、首先需要找到左右的各自边界值,所以定义一个函数去进行寻找

2、左边:当目标值大于或者等于的时候,都需要往左边移动,因为需要找的是左边界,当右边刚好移动到左边非目标值的时候,左边界会大于右边界,得出之前存的右边界最后一次值

3、右边:寻找的是目标值过一的位置,所以最后需要去减去一得到正确下标