Leetcode1 两数之和
Leetcode1 两数之和,这道题逻辑应该很简单,我认为是最简单的简单题了,没什么好说的
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
result = []
n = len(nums)
for i in range(n):
for j in range(i+1,n):
if nums[i]+ nums[j] == target:
result.append(i)
result.append(j)
return result
Leetcode15 三数之和
Leetcode15 三数之和,其实也是利用双指针,不多说,上代码
算法流程:
1、特判,对于数组长度n,如果数组为null或者数组长度小于3,返回[ ] 2、对重复数组:跳过,避免出现重复解 3、令左指针L= i+1, 右指针R=n-1,当L<R时,执行循环: 当nums[i] +nums[L]+nums[R] == 0,执行循环,判断左界和右界是否和下一位置重复,去除重复解,并同时将L,R移到下一位置,寻找新的解 若和大于0,说明nums[R]太大,R左移 若和小于0,说明nums[L]太小,L右移
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 1、特判,对于数组长度n,如果数组为null或者数组长度小于3,返回[]
# 2、对重复数组:跳过,避免出现重复解
# 令左指针L= i+1, 右指针R=n-1,当L<R时,执行循环:
# 当nums[i] +nums[L]+nums[R] == 0,执行循环,判断左界和右界是否和下一位置重复,去除重复解,并同时将L,R移到下一位置,寻找新的解
# 若和大于0,说明nums[R]太大,R左移
# 若和小于0,说明nums[L]太小,L右移
# 复杂度分析:时间复杂的 O(n^2),数组排序O(NlogN),遍历数组O(n),双指针遍历O(n),总体O(NlogN)+O(n^2)
n = len(nums)
res = []
if not nums or n<3:
return []
nums.sort() # 升序
for i in range(n):
if nums[i]>0:
return res
if i>0 and nums[i] == nums[i-1]: # 当i>0,即从i=1开始就需要判断,如果相邻的两个数相同,则会出现重复解
continue
L = i+1
R = n-1
while L<R:
if nums[i]+nums[L]+nums[R] == 0:
res.append([nums[i],nums[L],nums[R]])
while L<R and nums[L] == nums[L+1]: # 避免第二位出现重复解
L = L+1
while L<R and nums[R] == nums[R-1]: # 避免第三位出现重复解
R = R-1
L = L+1
R = R-1
elif nums[i]+nums[L]+nums[R] >0:
R = R-1
else:
L = L+1
return res
Leetcode 31. 下一个排列
必须原地修改,只允许使用额外常数空间,即不能是由栈和队列或者构建列表之类的
这里我举一个例子:例如, nums=[1,3,3,9,6,5,4],那么它的下一排序是什么呢?
读懂题的小伙伴一定知道下一个排列是[1,3,4,3,5,6,9] 其实这个就是字典序的排列,不太懂的可以查一下
这里讲一个方法,就是从后向前找一个对相邻元素对,这个元素对应该满足什么呢?应该满足升序,即设两个指针 i, j (i+1=j), 且如果满足nums[i]<nums[j],那么一定满足从j元素到nums的最后一个元素是降序的,如nums= [1,3,3,9,6,5,4]中第一个符合条件的元素对索引是(2,3)对应元素是3,9。之后我们在[j.end)中找到第一个比nums[i]大的元素这里是4,将nums[i]与4互换,此时nums=[1,3,4,9,6,5,3],[j,end)天然满足降序排列,我们此时将nums[j]到nums[end]升序即可。最后得到结果nums=[1,3,4,3,5,6,9]
算法流程:
标准的“下一个排列”算法可以描述为:
1、从后向前 查找第一个相邻升序的元素对(i,j),满足A[i]<A[j]。此时,[j,end)天然降序
2、在[j,end)从后向前查找第一个满足A[i]<A[k]的k。A[i]、A[k]分别是局部最小数与相较于局部最小数的较大数
3、将A[i]与A[k]交换
4、可以断定此时[j,end)必然是降序, 逆置[j,end),使其升序
5、如果在步骤1中找不到符合的相邻元素对,说明当前[begin,end)为一个降序顺序,则直接跳到步骤
可视化
以求 12385764 的下一个排列为例:
首先从后向前查找第一个相邻升序的元素对 (i,j)。这里 i=4,j=5,对应的值为 5,7:
然后在 [j,end) 从后向前查找第一个大于 A[i] 的值 A[k]。这里 A[i] 是 5,故 A[k] 是 6:
将 A[i] 与 A[k] 交换。这里交换 5、6:
这时 [j,end) 必然是降序,逆置 [j,end),使其升序。这里逆置 [7,5,4]:
因此,12385764 的下一个排列就是 12386457。
最后再可视化地对比一下这两个相邻的排列(橙色是蓝色的下一个排列):
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i,j,k = len(nums)-2,len(nums)-1,len(nums)-1
# find A[i] A[j]
while i>=0 and nums[i]>nums[j]:
i-=1
j-=1
if i>=0: # 不是最后一个排列
# find:A[i]<A[j]
while nums[i]>= nums[k]:
k-=1
# swap A[i],A[k]:
nums[i], nums[k] = nums[k], nums[i]
# reberse A[j:end]
end = len(nums)-1
while j<end:
nums[j], nums[end] = nums[end], nums[j]
j+=1
end-=1