一、内置模块及函数
# datetime
from datetime import datetime,timedelta
start_time=datetime(year=1000,month=1,day=1)
end_time=datetime(year=,month=,day=)
delta_time=timedelta(days=)
while start_time<=end_time:
if ...:
operation
start_time+=delta_time
print(...)
#全排列 itertools.permutations
#题目:给定一个不含重复数字的数组nums,返回其所有可能的全排列,你可以按任意顺序返回答案
class Solution:
def permute(self, nums: List[int]):
ans=[]
for num in itertools.permutations(nums,len(nums)):
ans.append(list(num))
return(ans)
#子集:给你一个整数数组 nums ,数组中的元素互不相同,返回该数组所有可能的子集(幂集)
#解集不能包含重复的子集。你可以按任意顺序返回解集
#方法一:库函数
class Solution:
def subsets(self, nums: List[int]):
res = []
for i in range(len(nums)+1):
for tmp in itertools.combinations(nums, i):
res.append(tmp)
return res
#方法二:迭代
class Solution:
def subsets(self, nums: List[int]):
res = [[]]
for i in nums:
res = res + [[i] + num for num in res]
return res
#方法三:递归(回溯算法)
class Solution:
def subsets(self, nums: List[int]):
res = []
n = len(nums)
def helper(i, tmp):
res.append(tmp)
for j in range(i, n):
helper(j + 1,tmp + [nums[j]] )
helper(0, [])
return res
二、两数之和
暴力枚举就不列出了,下面是哈希表
哈希表 hash 用的是 字典 dict(),哈希表查找 值为 target-nums[i] 的时间复杂度为O(1),这样的话就创建一个哈希表,对于每一个
x
,我们首先查询哈希表中是否存在target - x
,然后将x
插入到哈希表中,即可保证不会让x
和自己匹配class Solution: def twoSum(self, nums: List[int], target: int): hash=dict() k=len(nums) for i in range(k): temp=target-nums[i] if temp in hash: return [hash[temp],i] hash[nums[i]]=i
用 | 的代码同样也可以过,但是这种解法同暴力枚举都是针对无序数组的,没有利用到输入数组有序的性质
方法一:上一题代码哈希表,效率还比较高
方法二:二分查找:上一题查找 target-nums[i] ,效率高是因为哈希表,而这里数组元素有序,容易想到二分查找,一个想法是一个数固定,另一个数利用二分,总不能都二分吧,那样还不如暴力枚举
class Solution: def twoSum(self, numbers: List[int], target: int): n=len(numbers) for i in range(n): left,right=i+1,n-1 #从左边一个数 i 的右边开始二分查找 while left<=right: mid=(left+right)//2 if numbers[mid]==target-numbers[i]: #找到就返回 return [i+1,mid+1] elif numbers[mid]>target-numbers[i]: right=mid-1 else: left=mid+1
方法三:双指针
寻找两个和为 target 的数组元素的下标,从两边开始,i=0,j=len(numbers)-1
numbers[0]+numbers[len(numbers)-1] 要么大于目标值,要么小于目标值,要么等于(等于不就可以返回了吗),如果大于,由于数组有序,就让 j--,为什么,首先不能 i++,这样只会让和更大,那么只能 j--,同样的若某一时刻和小于目标值,就让 i++,让和变大一点,之后相等就返回
class Solution: def twoSum(self, numbers: List[int], target: int): left,right=0,len(numbers)-1 while left<right: temp=numbers[left]+numbers[right] if temp==target: return [left+1,right+1] elif temp>target: right-=1 else: left+=1
第二题用到双指针,这题同样,给出代码,思路同上
class Solution: def maxArea(self, height: List[int]): i,j=0,len(height)-1 ans=0 while i<j: if height[i]<height[j]: ans=max(ans,height[i]*(j-i)) i+=1 else: ans=max(ans,height[j]*(j-i)) j-=1 return(ans)
这题也用到双指针,动态规划是另一解法
不过显然动态规划解法容易理解
class Solution: def trap(self, height: List[int]): n=len(height) ans=0 if not height: return(0) left_max=[height[0]]+[0]*(n-1) right_max=[0]*(n-1)+[height[n-1]] #两次扫描寻找第i个柱子的左边最大值和右边最大值 for i in range(1,n): left_max[i]=max(height[i],left_max[i-1]) for i in range(n-2,-1,-1): right_max[i]=max(height[i],right_max[i+1]) #很显然最左边和最右边是必定接不到雨水的 ans=sum((min(left_max[j],right_max[j])-height[j]) for j in range(n)) return(ans)
class Solution: def trap(self, height: List[int]): left,right=0,len(height)-1 ans=0 left_max=right_max=0 while left<=right: if left_max<right_max: ans+=max(0,left_max-height[left]) left_max=max(left_max,height[left]) left+=1 else: ans+=max(0,right_max-height[right]) right_max=max(right_max,height[right]) right-=1 return(ans)
三、贪心算法
class Solution: def minSwapsCouples(self, row: List[int]): result=0 for i in range(0,len(row),2): 循环每次走两个,使得0、1,2、3....都是情侣坐在一起 if row[i] == row[i+1] ^ 1: #异或运算 ^ ,与 1 异或总能找到情侣的另一半,如 5^1=4,这是位运算,每一位相异为1 continue for j in range(i+2,len(row),1): #寻找情侣A的另一半B,与当前A的右边“同座”交换 if row[j] == row[i] ^ 1: row[i+1],row[j]=row[j],row[i+1] result+=1 return(result)