### 祝我顺利,申请季太难受了 ###
Leetcode 34
# 这道题,一开始使用二分没写出来,我又纯粹按照自己的思路解答看能否跑通所有的用例,最后得到了复杂度为N的解法, 不符合题目要求,但技术面手撕代码的时候,可以用。
解题思路一
读懂题目很重要:数组里没有目标,返回[-1,-1];数组里有一个符合的目标且是数组首元素,返回[0,0];数组里有一个符合的目标且不是数组首元素,返回[符合索引,符合索引];数组里有多个符合目标,返回[首符合索引,末符合索引]。看完下面的代码,再返回看这个分析,你会恍然大悟。
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
if len(nums) >= 2: #nums长度大于等于2情况
li = []
for i in range(0,len(nums)): #python列表中如果有重复的元素,列表的index()函数只返回第一个元素的索引
if nums[i] == target: #故而使用range函数
li.append(i) #记录所有符合的索引
else:
continue
# li有元素
if len(li) > 1:
return [li[0],li[-1]] #输出首末索引
elif len(li) == 1:
if li[0] == 0: #nums只有一个符合target,且nums里首元素0
return [0,0]
else:
return [nums.index(target),nums.index(target)] #nums只有一个符合target,但非nums里首元素
# li无元素
else:
return[-1,-1]
elif len(nums) == 1: #nums长度为1,要输出[左,右]格式,调整代码,通过所有用例;
if nums[0] == target:
return[0,0]
else:
return [-1,-1]
else: #nums长度为0情况
return [-1,-1]
解题思路二——二分法
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# 复杂度为logn,想到二分法。
# 找到数组中首末索引并返回,不存在返回[-1,-1]
def left_index(nums, target):
left = 0
right = len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target: #mid是目标元素
if mid == 0 or nums[mid - 1] < target: #mid是首元素位置或mid左边小于target,左下标确认
return mid
else:
right = mid - 1
elif nums[mid] > target: #递增数组mid大于目标元素,改变right
right = mid - 1
else:
left = mid + 1 #递增数组mid小于目标元素,改变left
# 找不到目标元素
return -1
def right_index(nums, target):
left = 0
right = len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target: #mid是目标元素
if mid == len(nums)-1 or nums[mid + 1] > target: #末元素是mid或者mid右边大于target,右下标确认
return mid
else: #mid右边小于等于target
left = mid + 1
elif nums[mid] > target: #递增数组mid大于目标元素,改变right
right = mid - 1
else:
left = mid + 1 #递增数组mid小于目标元素,改变left
# 找不到目标元素
return -1
#返回左右下标
return [left_index(nums, target), right_index(nums, target)]
Leetcode 35
易错点:if判断,我第一次写的是<=,无法跑过所有用例,比如当数组是[1],target也是1,应该返回0
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left, right = 0, len(nums)-1
if nums[right] < target: #nums无重复升序,先比较最后一个元素与target关系
return len(nums)
else:
while left <= right:
mid = left + (right-left)//2
if nums[mid] > target:
right = mid - 1
elif nums[mid] < target:
left = mid + 1
else:
return mid
return left
Leetcode 69
方法一:库函数
import math
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
return int(math.sqrt(x))
方法二:二分法
第一次写的时候,mid被赋值 left + (right - left) // 2 ,超时警告,碰到这种问题,可以写一个较小的数字判断几圈(会发现无法逼近正确答案)。修改为取平均数, 即(left + right)//2。
Note: 这几道题,你会发现,最后的return, 有left, 有right, 感觉return哪一个,最简单的方法,用一个小数尝试,看满足条件结束时,左指针还是右指针该被输出
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
left = 0
right = x
while left <= right:
mid = (right + left)//2
if mid * mid == x:
return mid
elif mid * mid < x:
left = mid + 1
else:
right = mid - 1
return right
Leetcode 367
方法1:循环,不仔细考虑有超时的风险
超时代码
class Solution(object):
def isPerfectSquare(self, num):
"""
:type num: int
:rtype: bool
"""
for i in range(num+1):
if i * i == num:
return True
else:
continue
return False
优化代码
简单分析,一个数的完全平方数肯定不会大过该数的一半的平方,画个函数图像辅助理解,一元线性函数的增幅会在临界点后远小于指数增长
class Solution(object):
def isPerfectSquare(self, num):
"""
:type num: int
:rtype: bool
"""
j = int(math.sqrt(num)) + 1
for i in range(j):
if i * i == num:
return True
else:
continue
return False
方法2:二分
class Solution(object):
def isPerfectSquare(self, num):
"""
:type num: int
:rtype: bool
"""
left = 0
right = num
while left <= right:
mid = left + (right-left)//2
if mid * mid == num:
return True
if mid * mid > num:
right = mid - 1
else:
left = mid + 1
return False