Leet code: 704.二分查找
题目链接:力扣
学习文章:代码随想录
初印象:拿到题目,能够比较容易理解二分法的思想,取中值选前后段。但是在实际代码实现的过程中,边界问题特别容易出现混乱,尤其是出现数组越界的情况,而且往往一头雾水。
学习提升:看完代码随想录中的讲解后,根据闭区间和半闭半开区间,始终保持target在目标区间内就可以清楚地知道边界的取值。
# 闭区间 [left, right]
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left = 0
right = len(nums) - 1
while left <= right:
middle = int((left + right) / 2)
if nums[middle] > target:
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
# 半闭半开区间 [left, right)
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left = 0
right = len(nums)
while left < right:
middle = int((left + right) / 2)
if nums[middle] > target:
right = middle
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
对比分析两种区间的解法,可以发现区别主要在于right是闭区间还是开区间,同样两种方式的代码的主要差别也在right,需要修改right的初始值,以及迭代更新的表达式。但无论那种方式,只要牢牢抓住"target要在区间内"就OK。
复杂度分析:时间复杂度 O(log(n)); 空间复杂度 O(1)
Leet code: 27. 移除元素
题目链接:力扣
学习文章:代码随想录
初印象:该题主要考察数组的删除,由于数组在内存中地址连续,如果需要在某个位置删除或者增加一个元素,除了修改插入的位置,该位置之后的元素都需要前移或者后移,非常麻烦。看到题目首先的想法是分两步:查找 + 删除。先要找到需要删除的元素的位置,然后再进行删除操作。
学习提升:有了初步的思路之后,并且参考代码随想录的想法,对暴力破解进行实现,补充了双指针法。暴力破解:每找到一个val,就对整个数组进行一次删除操作,需要两个循环。而双指针法仅仅用了两个"指针"就将算法的降为一个循环就可以解决,着实巧妙。
# 暴力破解方法
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
i,l = 0, len(nums)
while i < l:
if nums[i] == val:
for j in range(i+1,l):
nums[j - 1] = nums[j]
l = l - 1
i = i - 1
i = i + 1
return l
# 快慢指针方法
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
slowindex = 0
fastindex = 0
while fastindex < len(nums):
if nums[fastindex] == val:
fastindex += 1
else:
nums[slowindex] = nums[fastindex]
fastindex +=1
slowindex +=1
return slowindex
对比两种方法,第一种方法遇到了数组越界的问题,边界的取值还花了一些时间,反观第二种方法,只要明确了快指针用来指向新元素,慢指针用来指向结果数组的最后一个元素,在遇到val时,跳过即可,思路清晰明了。
复杂度分析: 时间复杂度 O(n^2) (暴力破解) O(n) (双指针法); 空间复杂度 O(1)