文章目录
146. LRU 缓存
利用python的dic存入key是有顺序的
加入一个数: 如果该数存在,则删除原本的,重新加入该数 并更新value
如果该数不存在,且满了,则删除第一个key。没满则直接存
访问一个数:如果该数存在,则保留value,然后删除,重新再存
不存在,返回-1
class LRUCache:
def __init__(self, capacity: int):
self.dic={}
self.cap=capacity
def get(self, key: int) -> int:
if key in self.dic.keys():
value=self.dic[key]
del self.dic[key]
self.dic[key]=value
return self.dic[key]
return -1
def put(self, key: int, value: int) -> None:
if key in self.dic.keys():
del self.dic[key]
elif len(self.dic.keys())>=self.cap:
del self.dic[list(self.dic.keys())[0]]
self.dic[key]=value
130. 被围绕的区域
首先对边界上每一个’O’做深度优先搜索,将与其相连的所有’O’改为’-‘。然后遍历矩阵,将矩阵中所有’O’改为’X’,将矩阵中所有’-‘变为’O’
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
"""
Do not return anything, modify board in-place instead.
"""
for i in range(len(board)):
if board[i][0]=='O':
vis=[[ 0 for j in range(len(board[0]))] for i in range(len(board))]
dfs(board,i,0,vis)
if board[i][len(board[0])-1] == 'O':
vis = [[0 for j in range(len(board[0]))] for i in range(len(board))]
dfs(board,i,len(board[0])-1,vis)
for j in range(len(board[0])):
if board[0][j]=='O':
vis=[[ 0 for j in range(len(board[0]))] for i in range(len(board))]
dfs(board,0,j,vis)
if board[len(board)-1][j] == 'O':
vis = [[0 for j in range(len(board[0]))] for i in range(len(board))]
dfs(board,len(board)-1,j,vis)
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j]=='O':
board[i][j]='X'
if board[i][j]=='-':
board[i][j]='O'
def dfs(board,i,j,visited):
# 边界越界
if i<0 or i>=len(board) or j<0 or j>=len(board[0]):
return
# 前进不了
print(i,j)
if board[i][j]=='X':
return
# 已经访问过
if visited[i][j]==1:
return
# 可以访问到的O,先用其他的代替
if board[i][j]=='O':
board[i][j]='-'
visited[i][j]=1
# 继续前进
dfs(board, i - 1, j, visited)
dfs(board, i + 1, j, visited)
dfs(board, i, j-1, visited)
dfs(board, i, j+1, visited)
visited[i][j]=0
return
133. 克隆图
关键是建立旧节点到新节点的映射
然后用深度遍历即可
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
dic={}
ls=set()
class Solution:
def cloneGraph(self, node: 'Node') -> 'Node':
if node ==None:
return None
global dic,ls
dic={}
ls=set()
dfs(node)
for old_node in list(ls):
dic[old_node].neighbors=[dic[old_neighbor] for old_neighbor in old_node.neighbors]
return dic[node]
def dfs(node):
global dic,ls
if node==None:
return
if node in ls:
return
# 复制 并建立旧节点-新节点的映射
new_node=Node(val=node.val)
dic[node] = new_node
# 存原来的node
ls.add(node)
for inode in node.neighbors:
dfs(inode)
return
134. 加油站
有一个环形路上有n个站点; 每个站点都有一个好人或一个坏人; 好人会给你钱,坏人会收你一定的过路费,如果你带的钱不够付过路费,坏人会跳起来把你砍死; 问:从哪个站点出发,能绕一圈活着回到出发点?
首先考虑一种情况:如果全部好人给你 的钱加起来 小于 坏人收的过路费之和,那么总有一次你的钱不够付过路费,你的结局注定会被砍死。
假如你随机选一点 start 出发,那么你肯定会选一个有好人的站点开始,因为开始的时候你没有钱,遇到坏人只能被砍死;
现在你在start出发,走到了某个站点end,被end站点的坏人砍死了,说明你在 [start, end) 存的钱不够付 end点坏人的过路费,因为start站点是个好人,所以在 (start, end) 里任何一点出发,你存的钱会比现在还少,还是会被end站点的坏人砍死;
于是你重新读档,聪明的选择从 end+1点出发,继续你悲壮的征程; 终于有一天,你发现自己走到了尽头(下标是n-1)的站点而没有被砍死; 此时你犹豫了一下,那我继续往前走,身上的钱够不够你继续走到出发点Start?
当然可以,因为开始已经判断过,好人给你的钱数是大于等于坏人要的过路费的,你现在攒的钱完全可以应付 [0, start) 这一段坏人向你收的过路费。 这时候你的嘴角微微上扬,眼眶微微湿润,因为你已经知道这个世界的终极奥秘:Start就是这个问题的答案。
为什么如果k+1->end
全部可以正常通行,且rest>=0
就可以说明车子从k+1
站点出发可以开完全程?
-
因为,起始点将当前路径分为
A
、B
两部分。其中,必然有(1)A部分剩余油量<0。(2)B部分剩余油量>0。 -
所以,无论多少个站,都可以抽象为两个站点(A、B)。(1)从B站加满油出发,(2)开往A站,车加油,(3)再开回B站的过程。
重点:B剩余的油>=A缺少的总油。必然可以推出,B剩余的油>=A站点的每个子站点缺少的油。
问题可以抽象成两个站
B站 可以获得多余的油量 A站 要消耗更多油
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
# 0 1 2 3 4
# -2 -2 -2 3 3
start=0
havgas=0
co=[ga-cos for ga,cos in zip(gas,cost)]
if sum(co)<0:
return -1
for index,c in enumerate(co):
havgas+=c
if havgas<0:
start=index+1
havgas=0
return start