代码随想录算法训练营第一天(数组篇)|Leetcode704二分查找,Leetcode27移除元素,leetcode977有序数组的平方

Leetcode 704 二分查找

题目链接 704 二分查找

思路: 二分查找的重点在于明确边界条件,初始化索引时是采用左闭右闭区间,还是左闭右开区间,直接影响到更新索引的逻辑。若取区间的方式与更新索引的方式不一致,则容易出错。建议在开始写代码之前先在纸上简单模拟一遍取元素的过程。

假设对于仅包含两个元素的数组nums = [2,3],初始化索引为leftIdx=0, rightIdx=len(nums),为左闭右开区间。
那么更新索引时,则逻辑为:

mid = (leftIdx+rightIdx)//2
if nums[mid] == target:
    return mid
elif nums[mid] < target:
    leftIdx = mid + 1  # 左侧为闭区间,mid元素不符合条件,故更新左侧索引为mid元素的右侧元素
else:
    rightIdx = mid  # 右侧为开区间,mid元素不符合条件,更新右侧索引为mid元素

初始化索引为leftIdx=0, rightIdx=len(nums)-1,为左闭右闭区间。
那么更新索引时,则逻辑为:

mid = (leftIdx+rightIdx)//2
if nums[mid] == target:
    return mid
elif nums[mid] < target:
    leftIdx = mid + 1  # 左侧为闭区间,mid元素不符合条件,故更新左侧索引为mid元素的右侧元素
else:
    rightIdx = mid + 1  # 右侧为闭区间,mid元素不符合条件,更新右侧索引为mid元素的左侧元素

完整代码实现

# 左闭右开区间
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums)
        while left < right:
            mid = (left+right)//2
            if nums[mid] == target:
                return mid
            if nums[mid] < target:
                left = mid+1
            else:
                right = mid

        return -1
# 左闭右闭区间
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums)-1
        while left < right:
            mid = (left+right)//2
            if nums[mid] == target:
                return mid
            if nums[mid] < target:
                left = mid+1
            else:
                right = mid-1

        return -1

时间复杂度: O(log(n))

Leetcode 27 移除元素

题目链接: 27 移除元素

思路: 给定一个数组,要求原地删除其中所有的特定元素,最终返回移除所有特定元素后数组的大小。我们首选双指针法,因为双指针法能够以O(n)的复杂度,完成数组元素的移除。
当使用双指针法时,应当明确快慢指针的定义。
在此题中,快指针的含义为原数组中当前正在遍历的元素的下标,慢指针的含义为移除特定元素后构成的新数组中,末尾元素的下标。

完整代码实现:
此题给出暴力解法的实现代码和双指针法的实现代码。

# 暴力解法
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i, size = 0, len(nums)
        while i<size:
            if nums[i] == val:
                for j in range(i+1, size):
                    nums[j-1] = nums[j]
                size -= 1
            else:
                i += 1
        return size
# 双指针法
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        slowIdx = 0
        for fastIdx in range(0, len(nums)):
            if nums[fastIdx] != val:
                nums[slowIdx] = nums[fastIdx]  # 当前快指针遍历的元素不等于目标值时,
                slowIdx += 1                   # 将慢指针当前指向的元素的值更新为快指针当前遍历的元素
                
        return slowIdx

时间复杂度: O(n)(双指针法), O(n^2)(暴力解法)

Leetcode 977 有序数组的平方

题目链接: 977 有序数组的平方

思路: 给定一个递增的数组,其中可能包含负数,要求给出将数组中元素的平方按照递增排序后的数组。由于平方后的元素最大值可能从数组两端的任意一段产出,此题的最佳解法为双指针法。
我们定义左指针的含义为,从左侧开始,遍历原数组时,当前正在处理的元素的下标;右指针的含义为,从右侧开始,遍历原数组时,当前正在处理的元素的下标。左右指针不断更新索引,从数组两端向中间移动,直至最终重合,完成数组的处理。

完整代码实现

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        result = [0] * len(nums)
        leftIdx, rightIdx = 0, len(nums) - 1
        Idx = len(nums) - 1
        while leftIdx <= rightIdx:
            leftNum, rightNum = nums[leftIdx] ** 2, nums[rightIdx] ** 2
            if leftNum < rightNum:
                max_num = rightNum
                rightIdx -= 1
            else:
                max_num = leftNum
                leftIdx += 1
            result[Idx] = max_num
            Idx -= 1

        return result

时间复杂度: O(n)

posted @ 2025-08-06 16:33  雪痕春风天音九重色  阅读(238)  评论(0)    收藏  举报