146. LRU缓存机制
我们用一个哈希表和一个双向链表维护所有在缓存中的键值对
我们首先使用哈希表进行定位,找出缓存项在双向链表中的位置,随后将其移动到双向链表的头部,即可在 O(1) 的时间内完成 get 或者 put 操作。
在双向链表的实现中,使用一个伪头部(dummy head)和伪尾部(dummy tail)标记界限,这样在添加节点和删除节点的时候就不需要检查相邻的节点是否存在。
每次添加新节点都将节点添加到头部,每次删除节点都删除尾部节点
#定义双向链表
class listnode:
def __init__(self,key=0,value=0):
self.key=key
self.value=value
self.prev=None
self.next=None
class LRUCache:
#移走该节点,将该节点前后节点的两个指针链接起来
def removenode(self,node):
node.prev.next=node.next
node.next.prev=node.prev
#将节点添加到头部
def addtohead(self,node):
node.prev=self.head
node.next=self.head.next
self.head.next.prev=node
self.head.next=node
#将节点移动到头部
def removehead(self,node):
self.removenode(node)
self.addtohead(node)
#移除尾部节点
def removetail(self):
node=self.tail.prev
self.removenode(node)
return node
def __init__(self, capacity: int):
self.stack=dict()
self.size=0
self.mac=capacity
#伪 头尾节点
self.head=listnode()
self.tail=listnode
self.head.next=self.tail
self.tail.prev=self.head
def get(self, key: int) -> int:
if key not in self.stack:
return -1
# 如果 key 存在,先通过哈希表定位,再移到头部
node=self.stack[key]
self.removehead(node)
return node.value
def put(self, key: int, value: int) -> None:
#如果节点不存在,则在头部添加节点
if key not in self.stack:
node=listnode(key,value)
self.addtohead(node)
self.stack[key]=node
self.size+=1
#容量超限,则删除尾部节点
if self.size>self.mac:
removed=self.removetail()
self.stack.pop(removed.key)
self.size-=1
else:
#如果节点存在,则更新节点值,并把该节点挪到头部
node=self.stack[key]
node.value=value
self.removehead(node)
常用双指针
注意处理边界
6. Z 字形变换
按顺序遍历s时,每个字符的行索引先从s1增大到sn,在从sn递减到s1,遍历s,把每个字符填充到正确的行res[i]上,i从0-numrows-1
注意i=0和i=numrows-1是转折点,要将s反向
https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows<2:
return s
#存储每一行字符串
res=['' for _ in range(numRows)]
i,flag=0,-1
for c in s:
res[i]+=c
if i==0 or i==numRows-1:
flag=-flag
i+=flag
return ''.join(res)
273. 整数转换英文表示
从低三位开始,每三个分成一组,接下来,我们可以继续将三位整数分解,例如数字 234 可以分别成百位 2 和十位个位 34,它的英文表示为 2 Hundred 34。这样我们继续将原问题分解成一位整数和两位整数的英文表示。其中一位整数的表示是很容易的,而两位整数中除了 10 到 19 以外,其余整数的的表示可以分解成两个一位整数的表示,这样问题就被圆满地解决了。
class Solution:
def numberToWords(self, num):
"""
:type num: int
:rtype: str
"""
def one(num):
switcher = {
1: 'One',
2: 'Two',
3: 'Three',
4: 'Four',
5: 'Five',
6: 'Six',
7: 'Seven',
8: 'Eight',
9: 'Nine'
}
return switcher.get(num)
def two_less_20(num):
switcher = {
10: 'Ten',
11: 'Eleven',
12: 'Twelve',
13: 'Thirteen',
14: 'Fourteen',
15: 'Fifteen',
16: 'Sixteen',
17: 'Seventeen',
18: 'Eighteen',
19: 'Nineteen'
}
return switcher.get(num)
def ten(num):
switcher = {
2: 'Twenty',
3: 'Thirty',
4: 'Forty',
5: 'Fifty',
6: 'Sixty',
7: 'Seventy',
8: 'Eighty',
9: 'Ninety'
}
return switcher.get(num)
def two(num):
if not num:
return ''
elif num < 10:
return one(num)
elif num < 20:
return two_less_20(num)
else:
tenner = num // 10
rest = num - tenner * 10
return ten(tenner) + ' ' + one(rest) if rest else ten(tenner)
def three(num):
hundred = num // 100
rest = num - hundred * 100
if hundred and rest:
return one(hundred) + ' Hundred ' + two(rest)
elif not hundred and rest:
return two(rest)
elif hundred and not rest:
return one(hundred) + ' Hundred'
billion = num // 1000000000
million = (num - billion * 1000000000) // 1000000
thousand = (num - billion * 1000000000 - million * 1000000) // 1000
rest = num - billion * 1000000000 - million * 1000000 - thousand * 1000
if not num:
return 'Zero'
result = ''
if billion:
result = three(billion) + ' Billion'
if million:
result += ' ' if result else ''
result += three(million) + ' Million'
if thousand:
result += ' ' if result else ''
result += three(thousand) + ' Thousand'
if rest:
result += ' ' if result else ''
result += three(rest)
return result
12. 整数转罗马数字
python divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)
class Solution:
def intToRoman(self, num: int) -> str:
roman_dict = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M'}
roman_num=''
a=1000
#从大到小
while num>0:
s=num//a
num=num%a
if s in [4,9]:
roman_num+=roman_dict[a]+roman_dict[(s+1)*a]
elif s<4:
roman_num+=s*roman_dict[a]
elif s==5:
roman_num+=roman_dict[s*a]
else:
roman_num+=roman_dict[5*a]+(s-5)*roman_dict[a]
a=a//10
return roman_num
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
for i in range(len(s)-1):
if dic[s[i]]<dic[s[i+1]]:
res-=dic[s[i]]
else:
res+=dic[s[i]]
return res+dic[s[-1]]
class Solution:
def compareVersion(self, version1: str, version2: str) -> int:
v1=version1.split('.')
v2=version2.split('.')
n=max(len(v1),len(v2))
for i in range(len(v1),n):
v1.append('0')
for i in range(len(v2),n):
v2.append('0')
for i in range(n):
if int(v1[i])<int(v2[i]):
return -1
elif int(v1[i])>int(v2[i]):
return 1
else:
continue
return 0
class Solution:
def numUniqueEmails(self, emails: List[str]) -> int:
res=set()
for email in emails:
name,domain=email.split('@')
name=name.replace('.','')
name=name.split('+')[0]
res.add(name+'@'+domain)
return len(res)
使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的
常见问题:
对于一个序列,用两个指针维护一段区间
对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作
32. 最长有效括号
对于遇到的每个 ‘(’ ,我们将它的下标放入栈中。
对于遇到的每个 ‘)’ ,我们弹出栈顶的元素并将当前元素的下标与弹出元素下标作差,得出当前有效括号字符串的长度。通过这种方法,我们继续计算有效子字符串的长度,并最终返回最长有效子字符串的长度
class Solution:
def longestValidParentheses(self, s: str) -> int:
stack=[-1]
maxl=0
for i in range(len(s)):
if s[i]=='(':
stack.append(i)
else:
stack.pop()
if stack:
maxl=max(maxl,i-stack[-1])
else:
stack.append(i)
return maxl
class Solution:
def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float:
dp = [[0 for _ in range(query_row + 2)] for _ in range(query_row + 2)]
dp[0][0] = poured
for i in range(query_row + 1):
for j in range(i + 1):
if dp[i][j] > 1:
dp[i + 1][j] += (dp[i][j] - 1) / 2
dp[i + 1][j + 1] += (dp[i][j] - 1) / 2
return min(1, dp[query_row][query_glass])
287. 寻找重复数(快慢指针) (判断链表是否有环)
将数组看成链表,val是结点值也是下个节点的地址。因此这个问题就可以转换成判断链表有环
如果可以修改原数组,那么可以用遇到一个数变复数,或者哈希表
二分法太难想到了,不如判断有环
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
slow,fast=0,0
slow=nums[slow]
fast=nums[nums[fast]]
#说明入环了
while slow !=fast:
slow=nums[slow]
fast=nums[nums[fast]]
f1,f2=0,slow
#为了找到环的入口
while nums[f1]!=nums[f2]:
f1=nums[f1]
f2=nums[f2]
return nums[f1]