题目:167. 两数之和 II - 输入有序数组 解法一:两层for循环,暴力求解。Fail,超时! 时间复杂度:O(n^2) 空间复杂度:O(1)
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
n = len(numbers)
for i in range(n - 1):
for j in range(i + 1, n):
if numbers[i] + numbers[j] == target:
return [i + 1, j + 1]
解法二:双指针。前提:数组是有序数组 时间复杂度:O(n) 空间复杂度:O(1)
# 解法二:
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
# 数组 已经排好序,两数之和 == target,两个索引不同
n = len(numbers)
# 双指针
left = 0
right = n - 1
while left < right: # 因为有唯一解,条件可替换成True
s = numbers[left] + numbers[right]
if s < target:
left += 1
elif s > target:
right -= 1
else:
return [left + 1, right + 1]
return []
题目:15. 三数之和 解法:数组排序后,for循环嵌套双指针→将三数之和转化为两数之和。注意三个数都要去重、以及小优化 时间复杂度:O(n^2) 空间复杂度:O(1)
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 数组,未排序→排序
# i != j != k, 有序
# 三数之和为0,且不重复→去重
nums.sort()
n = len(nums)
ans = []
for i in range(n - 2):
x = nums[i]
# 剪枝
if i > 0 and nums[i] == nums[i - 1]:
continue
# 优化一
if x + nums[-2] + nums[-1] < 0:
continue
# 优化二
if x + nums[i + 1] + nums[i + 2] > 0:
break
# 双指针
left = i + 1
right = n - 1
while left < right:
s = x + nums[left] + nums[right]
if s < 0:
left += 1
elif s > 0:
right -= 1
else:
ans.append([x, nums[left], nums[right]])
left += 1
right -= 1
while left < right and nums[left] == nums[left - 1]: # 去重
left += 1
while right > left and nums[right] == nums[right + 1]: # 去重
right -= 1
return ans
题目:2824. 统计和小于目标的下标对数目 解法:排序后同两数之和,双指针 时间复杂度:O(n) 空间复杂度:O(1)
class Solution:
def countPairs(self, nums: List[int], target: int) -> int:
# 排序、计数器
nums.sort()
n = len(nums)
cnt = 0
# 双指针
left = 0
right = n - 1
while left < right:
s = nums[left] + nums[right]
# 优化一
if nums[0] + nums[1] > target:
break
if s >= target:
right -= 1
else:
cnt += right - left
left += 1
return cnt
题目:16. 最接近的三数之和 解法:三数之和的变形, 时间复杂度:O(n^2) 空间复杂度:O(1)
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
n = len(nums)
ans = inf
for i in range(n - 2):
x = nums[i]
if i > 0 and x == nums[i - 1]:
continue
# 优化一
s = x + nums[i + 1] + nums[i + 2]
if s > target:
if s - target < abs(ans - target):
ans = s
return ans
# 双指针
left, right = i + 1, n - 1
while left < right:
s = x + nums[left] + nums[right]
if s == target:
return target
if abs(s - target) < abs(ans - target):
ans = s
if s > target:
right -= 1
else:
left += 1
return ans
题目:18. 四数之和 解法:两层循环+双指针,去重、两层循环内均可适当优化
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
ans = []
n = len(nums)
for a in range(n - 3):
x = nums[a]
if a > 0 and x == nums[a - 1]:
continue
# 优化一
if x + nums[a + 1] + nums[a + 2] + nums[a + 3] > target:
break
# 优化二
if x + nums[-3] + nums[-2] + nums[-1] < target:
continue
for b in range(a + 1, n - 2):
y = nums[b]
# 优化三
if b > a + 1 and y == nums[b - 1]:
continue
# 优化四
if x + y + nums[-2] + nums[-1] < target:
continue
if x + y + nums[b + 1] + nums[b + 2] > target:
break
# 双指针
c, d = b + 1, n - 1
while c < d:
s = x + y + nums[c] + nums[d]
if s == target:
ans.append([x, y, nums[c], nums[d]])
c += 1
d -= 1
while c < d and nums[c] == nums[c - 1]:
c += 1
while d > c and nums[d] == nums[d + 1]:
d -= 1
elif s > target:
d -= 1
else: # s < target
c += 1
return ans
时间复杂度:O(n^3) 空间复杂度:O(1)
题目:611. 有效三角形的个数 解法-代码实现:两边之和大于第三边,控制第3边,一点点扩大范围、第1/2条边依次移动
class Solution:
def triangleNumber(self, nums: List[int]) -> int:
nums.sort()
# 三角形定理:两边之和大于第三边,控制第3边,一点点扩大范围
# 计数器
cnt = 0
n = len(nums)
# i,j,k分别代表三边索引,a,b,c分别对应三边的值
for k in range(2, n):
c = nums[k]
i = 0 # a = nums[i]
j = k - 1 # b = nums[j]
while i < j:
if nums[i] + nums[j] > c:
cnt += j - i
j -= 1
else:
i += 1
return cnt
时间复杂度:O(n^2) 空间复杂度:O(1)