01两数之和
用哈希表(python字典)优化运行时间
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
n=len(nums)
dic={}
for i in range(n):
res=target-nums[i]
if dic.get(res) is not None:
return [dic[res],i]
dic[nums[i]]=i
02两数相加
基本链表操作
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
re=ListNode(0)#开头位置
r=re# 操作指针
carry=0
while(l1 or l2):
x=l1.val if l1 else 0
y=l2.val if l2 else 0
s=carry+x+y
carry=s//10
r.next=ListNode(s%10)
r=r.next
if(l1!=None): l1=l1.next
if(l2!=None): l2=l2.next
if carry>0:
r.next=ListNode(1)
return re.next
03无重复字符
滑动搜索窗口,加哈希表优化
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
n=len(s)
ans=0
dic={}
i=0
for j in range(n):
if dic.get(s[j]) is not None:
i=max(dic[s[j]]+1,i)# 如果需要将窗口起点移动
ans=max(ans,j-i+1)# 评估窗口大小
dic[s[j]]=j#更新字符记录
return ans
04寻找两个有序数组的中位数
时间没要求的话直接进行归并排序,复杂度O(n)
时间复杂度要求高的话,需要进行二分查找,复杂度O(log n)
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
m=len(nums1)
n=len(nums2)
if m>n:
nums1,nums2,m,n=nums2,nums1,n,m
imin,imax,half_len=0,m,(m+n+1)//2
while imin<=imax:
i=(imin+imax)//2
j=half_len-i
if i<m and nums2[j-1]>nums1[i]:
imin=i+1
elif i>0 and nums1[i-1]>nums2[j]:
imax=i-1
else:
if i==0: left=nums2[j-1]
elif j==0: left=nums1[i-1]
else: left = max(nums1[i-1],nums2[j-1])
if (m+n)%2==1:
return left
if i == m: right = nums2[j]
elif j == n: right = nums1[i]
else: right = min(nums1[i], nums2[j])
return (left+right)/2.0
05 最长回文子串
马拉车算法,复杂度O(n),先将将如ABAC字符串处理成~#A#B#A#C#的形式,最长子串的长度是回最长文半径减1,起始位置是中间位置减去半径再除以2,所以问题转化为找到中间位置和半径
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
ns="~#"
for l in s:
ns=ns+l+"#"
maxl=-1
p=[0]*len(ns)
mx=0
mid=0
kid=0
for i in range(1,len(ns)):
if i <mx:
p[i]=min(p[2*mid-i],mx-i)
else:
p[i]=1
while i+p[i]<len(ns) and ns[i-p[i]]==ns[i+p[i]]:
p[i]+=1
if mx<i+p[i]:
mid=i
mx=i+p[i]
if maxl<p[i]:
maxl=p[i]
kid=i
sat=(kid-p[kid])//2
slen=p[kid]-1
return s[sat:sat+slen]
06 Z字形变换
找规律按行输出,周期2*numRows-2
class Solution:
def convert(self, s: 'str', numRows: 'int') -> 'str':
if numRows==1:
return s
l=len(s)
cycl=2*numRows-2
res=""
for i in range(numRows):
for j in range(0,l-i,cycl):
res=res+s[j+i]
if i>0 and i<numRows-1 and j+cycl-i<l:
res=res+s[j+cycl-i]
return res
07 整数反转
用字符串处理
class Solution:
def reverse(self, x: 'int') -> 'int':
str_x=str(x)
flag=1
if x<0:
flag=-1
str_x=str_x[1:]
res=str_x[::-1]
res=int(res)*flag
if res>-2**31 and res<2**31-1:
return res
else:
return 0
08 字符转整数
主要是考虑各种测试用例
class Solution:
def myAtoi(self, str: 'str') -> 'int':
set0={" ","-","+","1","2","3","4","5","6","7","8","9","0"}
set1={"1","2","3","4","5","6","7","8","9","0"}
if not str:
return 0
flag=1
num=""
index=0
for i,s in enumerate(str):
index=i
if s not in set0:
break
if s=="-":
flag=-1
break
if s=="+":
break
if s in set1:
num=num+s
break
if str[index] not in set0:
return 0
if index+1<len(str):
for s in str[index+1:]:
if s in set1:
num=num+s
else:
break
if not num:
return 0
num=flag*int(num)
if flag==-1:
return max(-2**31,num)
else:
return min(2**31-1,num)
09 回文数
简单的字符串处理
class Solution:
def isPalindrome(self, x: 'int') -> 'bool':
if x<0:
return False
strx=str(x)
rx=strx[::-1]
rx=int(rx)
return rx==x
11 盛水最多的容器
class Solution:
def maxArea(self, height: 'List[int]') -> 'int':
i=0
j=len(height)-1
maxv=0
while i!=j:
maxv=max(min(height[i],height[j])*(j-i),maxv)
if height[i]>height[j]:
j=j-1
else:
i=i+1
return maxv
13 罗马数字转数字
利用字典储存字符对应值,根据左边字符小于右边处理特殊情况
class Solution:
def romanToInt(self, s: 'str') -> 'int':
dic={"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
res=0
l=len(s)
i=0
while i<l:
if i+1<l and 2*dic[s[i]]<dic[s[i+1]]:
res=res+dic[s[i+1]]-dic[s[i]]
i=i+2
else:
res=res+dic[s[i]]
i=i+1
return res
15 三数之和
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res=[]
if len(nums)<3:
return res
maps={i:0 for i in nums}
for i in nums:
if i in maps:
maps[i]+=1
ls=list(maps.keys())
ls.sort()
for i in range(len(ls)-1):
if ls[i]!=0 and maps[ls[i]]>=2 and maps.get(-2*ls[i]):
res.append([ls[i],ls[i],-2*ls[i]])
for j in range(i+1,len(ls)):
t=-ls[i]-ls[j]
if maps.get(t) and t<ls[j] and t>ls[i]:
res.append([ls[i],t,ls[j]])
if ls[-1]!=0 and maps[ls[-1]]>=2 and maps.get(-2*ls[-1]):
res.append([ls[-1],ls[-1],-2*ls[-1]])
if maps.get(0) and maps[0]>=3:
res.append([0,0,0])
return res
最长公共前缀
主要是特殊情况处理
class Solution:
def longestCommonPrefix(self, strs: 'List[str]') -> 'str':
l=len(strs)
if l==0:
return ""
maxl=len(strs[0])
for i in range(l-1):
k=0
maxl=min(maxl,len(strs[i+1]))
while k<maxl and strs[i][k]==strs[i+1][k]:
k=k+1
maxl=min(k,maxl)
if maxl==0:
return ""
return strs[0][:maxl]
18 四数之和
和三数类似,注意去重
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums.sort()
ll=len(nums)
maps=set()
res=[]
if ll<4:
return res
for i in range(ll-3):
for j in range(i+1,ll-2):
l=j+1
r=ll-1
while l<r:
s=nums[i]+nums[j]+nums[l]+nums[r]
if s==target:
ans=str(nums[i])+str(nums[j])+str(nums[l])+str(nums[r])
if ans not in maps:
maps.add(ans)
res.append([nums[i],nums[j],nums[l],nums[r]])
l=l+1
r=r-1
elif s<target:
l=l+1
else:
r=r-1
return res
19 删除倒数第n个结点
注意处理删头的特殊情况
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
first=head
second=head
for i in range(n):
second=second.next
if second is None:
return head.next
while second.next:
first=first.next
second=second.next
first.next=first.next.next
return head
20 有效的括号
使用栈
class Solution:
def isValid(self, s: 'str') -> 'bool':
stack=[]
set={")":"(","}":"{","]":"["}
p=""
for c in s:
if c in set:
tp=stack.pop() if stack else "#"
if set[c]!=tp:
return False
else:
stack.append(c)
return not stack
33 搜索旋转排序数组
二分一半有序一半无,或者先整理成有序(找旋转点)
class Solution:
def bisearch(self,nums: List[int], target: int,l:int,r:int)->int:
while l<=r:
mid =(l+r)//2
if nums[mid]==target:
return mid
if nums[mid]<target:
l=mid+1
if nums[mid]>target:
r=mid-1
return -1
def ubisearch(self,nums: List[int], target: int,l:int,r:int)->int:
if l>r:
return -1
mid=(l+r)//2
# print(l,r,mid)
if mid<0 or mid>=len(nums):
return -1
if nums[mid]==target:
return mid
if nums[l]<=nums[mid]:
if target>=nums[l] and target<=nums[mid]:
r=mid-1
return self.bisearch(nums,target,l,r)
else:
l=mid+1
return self.ubisearch(nums,target,l,r)
else:
if target>=nums[mid] and target <=nums[r]:
l=mid+1
return self.bisearch(nums,target,l,r)
else:
r=mid-1
return self.ubisearch(nums,target,l,r)
def search(self, nums: List[int], target: int) -> int:
return self.ubisearch(nums,target,0,len(nums)-1)
43 字符串相乘
完全模拟
class Solution:
def add(self, num1: str, num2: str) -> str:
if len(num1)<len(num2):
num1,num2=num2,num1
num1=num1[::-1]+"0"
num2=num2[::-1]+"0"*(len(num1)-len(num2)+1)
l=0
carry=0
res=""
while l<len(num1):
sums=int(num1[l])+int(num2[l])+carry
res+=str(sums%10)
carry=sums//10
l=l+1
if res[-1]=="0":
res=res[:-1]
return res[::-1]
def singlemultiply(self, num1: str, num2: str) -> str:
n2=int(num2)
if n2==0:
return "0"
if n2==1:
return num1
num1=num1[::-1]+"0"
res=""
carry=0
for n1 in num1:
prod=int(n1)*n2+carry
res+=str(prod%10)
carry=prod//10
if res[-1]=="0":
res=res[:-1]
return res[::-1]
def multiply(self, num1: str, num2: str) -> str:
if len(num1)<len(num2):
num1,num2=num2,num1
res=""
for n2 in num2:
res=self.add(res+"0",self.singlemultiply(num1,n2))
return res
50 快速幂
位运算版
class Solution:
def myPow(self, x: float, n: int) -> float:
if n<0:
x=1/x
n=-n
ans=1
while n!=0:
if n&1 !=0:
ans*=x
x*=x
n>>=1
return ans
51 n 皇后
经典回溯法
class Solution(object):
def check(self,s):
if len(s)>len(set(s)):
return False
pl=[int(v)-i for i,v in enumerate(s)]
pl2=[int(v)+i for i,v in enumerate(s)]
if len(pl)>len(set(pl)) or len(pl2)>len(set(pl2)):
return False
return True
def back(self,s,n,ans):
if len(s)==n:
ans.append(s)
for i in range(n):
if self.check(s+str(i)):
self.back(s+str(i),n,ans)
def printans(self,ans,n):
anss=[]
for a in ans:
midans=[]
for i in a:
t=int(i)
s="."*t+"Q"+"."*(n-1-t)
midans.append(s)
anss.append(midans)
return anss
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
ans=[]
self.back("",n,ans)
print(self.printans(ans,n))
52 n皇后2
只要求输出解法种数
class Solution(object):
def totalNQueens(self, n):
"""
:type n: int
:rtype: int
"""
def DFS(s,n,xy_diff,xy_sum):
if len(s)==n:
return 1
ans=0
for i in range(n):
if (i not in s )and (len(s)-i) not in xy_diff and (i+len(s)) not in xy_sum:
ans+=DFS(s+[i],n,xy_diff+[len(s)-i],xy_sum+[i+len(s)])
return ans
return(DFS([],n,[],[]))
88 合并有序数组(原地)
从后向前,处理特殊情况 m=0,n=0
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
if m==0 and n>0:
for i in range(n):
nums1[i]=nums2[i]
if n==0:
pass
while m>0 and n>0:
if nums2[n-1]>nums1[m-1]:
nums1[m+n-1]=nums2[n-1]
n-=1
else:
nums1[m+n-1]=nums1[m-1]
m-=1
if n>0:
for i in range(n):
nums1[i]=nums2[i]
208 前缀树
用defaultdict字典实现
from collections import defaultdict
class TrieNode:
def __init__(self):
self.children = defaultdict(TrieNode)
self.is_word = False
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.root=TrieNode()
def insert(self, word: str) -> None:
"""
Inserts a word into the trie.
"""
cur=self.root
for w in word:
cur=cur.children[w]
cur.is_word=True
def search(self, word: str) -> bool:
"""
Returns if the word is in the trie.
"""
cur=self.root
for w in word:
cur=cur.children.get(w)
if cur is None:
return False
return cur.is_word
def startsWith(self, prefix: str) -> bool:
"""
Returns if there is any word in the trie that starts with the given prefix.
"""
cur = self.root
for w in prefix:
cur = cur.children.get(w)
if cur is None:
return False
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
235 二叉搜索树的最近公共祖先
t 满足t.val>=p.val and t.val<=q.val,其中p.val<q.val
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if p.val>q.val:
p,q=q,p
t=root
while not (t.val>=p.val and t.val<=q.val):
if t.val>q.val:
t=t.left
if t.val<p.val:
t=t.right
return t
294 二叉树序列化
先序遍历
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
s=""
q=[root]
while q:
root=q.pop(0)
if root:
s+=str(root.val)
q.append(root.left)
q.append(root.right)
else:
s+="~"
s+=","
return s
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
ss=data.split(",")
if ss[0]=="~":
return None
root=TreeNode(int(ss[0]))
q=[root]
i=1
while q:
c=q.pop(0)
if ss[i]!="~": c.left=TreeNode(int(ss[i]))
if ss[i+1]!="~": c.right=TreeNode(int(ss[i+1]))
i=i+2
if c.left: q.append(c.left)
if c.right: q.append(c.right)
return root
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))
342 4的幂
4的幂可以表示0100 奇数位上为1,且只有一个1
class Solution:
def isPowerOfFour(self, num: int) -> bool:
if num<=0:
return False
else:
return (num&(num-1))==0 and (num & 0x5555555555)!=0
326 3的幂
素数幂都同余,所以这道题等价于找最大的int型3的幂
class Solution(object):
def isPowerOfThree(self, n):
"""
:type n: int
:rtype: bool
"""
if n<=0:
return False
big3=3**19
return big3%n==0
363 矩形区域不超过 K 的最大数值和
bisect排序插入
class Solution:
def maxSumSubmatrix(self, matrix: List[List[int]], k: int) -> int:
M = len(matrix)
N = len(matrix[0]) if M else 0
ans = -10000086
for x in range(N):
sums = [0] * M
for y in range(x, N):
slist, num = [], 0
for z in range(M):
sums[z] += matrix[z][y]
num += sums[z]
if num <= k:
ans = max(ans, num)
i = bisect.bisect_left(slist, num - k)
if i != len(slist):
ans = max(ans, num - slist[i])
bisect.insort(slist, num)
return ans
1001 网格照明
类似于n皇后,但是要利用set和hashmap优化查询
from collections import defaultdict
class Solution:
def gridIllumination(self, N, lamps, queries):
r,c,dxy,sxy=defaultdict(int),defaultdict(int),defaultdict(int),defaultdict(int)
ans=[]
lamps_set=set(map(tuple,lamps))
pxy=[(1,1),(1,0),(1,-1),(0,1),(0,-1),(-1,1),(-1,0),(-1,-1),(0,0)]
for x,y in lamps_set:
r[x]+=1
c[y]+=1
dxy[x-y]+=1
sxy[x+y]+=1
for x,y in queries:
if r[x] or c[y] or dxy[x-y] or sxy[x+y]:
ans.append(1)
for dx,dy in pxy:
nx=dx+x
ny=dy+y
if (nx,ny) in lamps_set:
r[nx]-=1
c[ny]-=1
dxy[nx-ny]-=1
sxy[nx+ny]-=1
lamps_set.remove((nx,ny))
else:
ans.append(0)
return ans
单调队列
# -*- coding:utf-8 -*-
class Solution:
def maxInWindows(self, nums, size):
# write code here
ans=[]
if len(nums)<1 or size>len(nums) or size<1:
return ans
if size==1 or len(nums)==1:
return nums
dds=[(nums[0],0)]
ans=[nums[0]]
i=1
for i in range(1,len(nums)):
if dds[0][1]<i-size+1:
dds.pop(0)
# print(nums[i],dds)
v,t=dds[0]
v2,t2=dds[-1]
if nums[i]>=v:
dds=[[nums[i],i]]
elif nums[i]<v2:
dds.append([nums[i],i])
else:
while dds[-1][0]<=nums[i]:
dds.pop()
dds.append([nums[i],i])
ans.append(dds[0][0])
return ans[size-1:]