代码随想录算法训练营第一天(数组篇)|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)