日常系列LeetCode《20·数据结构设计》
Posted 常某某的好奇心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常系列LeetCode《20·数据结构设计》相关的知识,希望对你有一定的参考价值。
数据规模->时间复杂度
<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)
内容
lc 155 【剑指 30】【top100】:最小栈
https://leetcode.cn/problems/min-stack/
提示:
-2^31 <= val <= 2^31 - 1
pop、top 和 getMin 操作总是在 非空栈 上调用
push, pop, top, and getMin最多被调用 3 * 104 次
#方案一:两个栈(辅助栈)
class MinStack:
def __init__(self):
self.datastack=[]
self.minstack=[]
def push(self, val: int) -> None:
self.datastack.append(val)
#key:<=
if not self.minstack or val<=self.minstack[-1]:
self.minstack.append(val)
def pop(self) -> None:
top=self.datastack.pop()
#key
if top==self.minstack[-1]:
self.minstack.pop()
def top(self) -> int:
return self.datastack[-1]
def getMin(self) -> int:
return self.minstack[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
#方案二:一个栈-存储节点
class Node:
def __init__(self,val=0,minn=0):
self.val=val
self.min=minn
class MinStack:
def __init__(self):
self.datastack=[]
def push(self, val: int) -> None:
#key:
newnode=Node()
newnode.val=val
if not self.datastack:
newnode.min=val
else:
newnode.min=min(self.datastack[-1].min,val)
#
self.datastack.append(newnode)
def pop(self) -> None:
self.datastack.pop()
def top(self) -> int:
return self.datastack[-1].val
def getMin(self) -> int:
return self.datastack[-1].min
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
#方案三:自定义栈-链表结构
class ListNode:
def __init__(self,val=0,minn=0,next=None):
self.val=val
self.min=minn
self.next=next
class MinStack:
def __init__(self):
self.dummynode=ListNode()
def push(self, val: int) -> None:
#key:
newnode=ListNode()
newnode.val=val
if not self.dummynode.next:
newnode.min=val
else:
newnode.min=min(self.dummynode.next.min,val)
#key
newnode.next=self.dummynode.next
self.dummynode.next=newnode
def pop(self) -> None:
firstnode=self.dummynode.next
if firstnode:
self.dummynode.next=firstnode.next
firstnode.next=None
def top(self) -> int:
return self.dummynode.next.val
def getMin(self) -> int:
return self.dummynode.next.min
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
lc 225 :用队列实现栈
https://leetcode.cn/problems/implement-stack-using-queues/
注意:
你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
提示:
1 <= x <= 9
最多调用100 次 push、pop、top 和 empty
每次调用 pop 和 top 都保证栈不为空
进阶:
你能否仅用一个队列来实现栈。
#方案一:两个队列(使用push的调用次数多)
class MyStack:
def __init__(self):
self.queue1=deque()
self.queue2=deque()
def push(self, x: int) -> None:
self.queue1.append(x)
#o(n)
def pop(self) -> int:
#key-key-key:while
if self.queue1:
while(self.queue1):
x=self.queue1.popleft()
if not self.queue1:
return x
self.queue2.append(x)#key位置(最后无head元素)
#
elif self.queue2:
while(self.queue2):
x=self.queue2.popleft()
if not self.queue2:
return x
self.queue1.append(x)#key位置(最后无head元素)
#o(n)
def top(self) -> int:
if self.queue1:
while(self.queue1):
x=self.queue1.popleft()
self.queue2.append(x)#key位置(最后有head元素)
if not self.queue1:
return x
#
elif self.queue2:
while(self.queue2):
x=self.queue2.popleft()
self.queue1.append(x)#key位置(最后有head元素)
if not self.queue2:
return x
def empty(self) -> bool:
return len(self.queue1)==0 and len(self.queue2)==0
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
#方案二:两个队列(优化:适用pop与top的调用次数多)
class MyStack:
def __init__(self):
self.queue1=deque()
self.queue2=deque()
def push(self, x: int) -> None:
#key-key-key:while
self.queue2.append(x)
while(self.queue1):
self.queue2.append(self.queue1.popleft())
self.queue1,self.queue2=self.queue2,self.queue1
def pop(self) -> int:
return self.queue1.popleft()
def top(self) -> int:
return self.queue1[0]
def empty(self) -> bool:
return not self.queue1 and not self.queue2
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
#方案三:一个队列
class MyStack:
def __init__(self):
self.queue1=deque()
def push(self, x: int) -> None:
#key-key-key:123->321
size=len(self.queue1)
self.queue1.append(x)
for i in range(size):
self.queue1.append(self.queue1.popleft())
def pop(self) -> int:
return self.queue1.popleft()
def top(self) -> int:
return self.queue1[0]
def empty(self) -> bool:
return not self.queue1
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
【剑指 09】: 用两个栈实现队列
https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/
提示:
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用
#方案一:
class CQueue:
def __init__(self):
self.stack1=[]
self.stack2=[]
def appendTail(self, value: int) -> None:
while self.stack2:
self.stack1.append(self.stack2.pop())
self.stack1.append(value)
def deleteHead(self) -> int:
while self.stack1:
self.stack2.append(self.stack1.pop())
if not self.stack2:
return -1
return self.stack2.pop()
# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()
#方案二:优化
class CQueue:
def __init__(self):
self.stack1=[]
self.stack2=[]
def appendTail(self, value: int) -> None:
while self.stack2:
self.stack1.append(self.stack2.pop())
self.stack1.append(value)
def deleteHead(self) -> int:
#key-key-key:stack2已经把stack1的前入元素变成前出元素
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
#
if not self.stack2:
return -1
return self.stack2.pop()
# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()
lc 622 :设计循环队列
提示:
-2^31 <= val <= 2^31 - 1
最多调用 insert、remove 和 getRandom 函数 2 * 105 次
在调用 getRandom 方法时,数据结构中 至少存在一个 元素。
注意:你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1)
class MyCircularQueue:
def __init__(self, k: int):
self.k=k
self.data=[None]*(k+1)#k=2,5-None-1为满
self.head=0
self.tail=0#队尾元素下一位
def enQueue(self, value: int) -> bool:
#
if self.isFull():return False
#
self.data[self.tail]=value
self.tail=(self.tail+1)%(self.k+1)
return True
def deQueue(self) -> bool:
#
if self.isEmpty():return False
#
self.data[self.head]=None #可以略去这一行
self.head=(self.head+1)%(self.k+1)
return True
def Front(self) -> int:
if self.isEmpty(): return -1
return self.data[self.head]
def Rear(self) -> int:
if self.isEmpty(): return -1
return self.data[self.tail-1]
def isEmpty(self) -> bool:#key
return self.head==self.tail
def isFull(self) -> bool: #key
return (self.tail+1)%(self.k+1)==self.head
# Your MyCircularQueue object will be instantiated and called as such:
# obj = MyCircularQueue(k)
# param_1 = obj.enQueue(value)
# param_2 = obj.deQueue()
# param_3 = obj.Front()
# param_4 = obj.Rear()
# param_5 = obj.isEmpty()
# param_6 = obj.isFull()
lc 380【剑指 030】:O(1) 时间插入、删除和获取随机元素
https://leetcode.cn/problems/insert-delete-getrandom-o1/
提示:
-2^31 <= val <= 2^31 - 1
最多调用 insert、remove 和 getRandom 函数 2 * 105 次
在调用 getRandom 方法时,数据结构中 至少存在一个 元素。
注意:您必须实现类的函数,使每个函数的 平均 时间复杂度为 O(1) ;
class RandomizedSet:
def __init__(self):
self.idxmap=
self.data=[]
def insert(self, val: int) -> bool:
if val in self.idxmap:return False #self.idxmap也对
#
self.idxmap[val]=len(self.data)
self.data.append(val)
return True
def remove(self, val: int) -> bool:
#hashset/map:指定data/key->o(1)
#数组:根据随机索引->o(1)
if val not in self.idxmap:return False
#
idx=self.idxmap[val]
lastnum=self.data[-1]
self.data[idx]=lastnum
self.data.pop()
#
self.idxmap[lastnum]=idx
del self.idxmap[val]
return True
def getRandom(self) -> int:
#randint(0,9):0-9
return self.data[random.randint(0,len(self.data)-1)]#choice(self.data)
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
lc 381 :O(1) 时间插入、删除和获取随机元素 - 允许重复
https://leetcode.cn/problems/insert-delete-getrandom-o1-duplicates-allowed/
提示:
-2^31 <= val <= 2^31 - 1
insert, remove 和 getRandom 最多 总共 被调用 2 * 10^5 次
当调用 getRandom 时,数据结构中 至少有一个 元素
注意:您必须实现类的函数,使每个函数的 平均 时间复杂度为 O(1) ;
生成测试用例时,只有在 RandomizedCollection 中 至少有一项 时,才会调用 getRandom
class RandomizedCollection:
def __init__(self):
self.idsmap=defaultdict(set) #for remove o(1) #list也可以
self.data=[]
def insert(self, val: int) -> bool:
self.idsmap[val].add(len(self.data)) #允许重复插入
self.data.append(val)
return len(self.idsmap[val])==1 #但,重复插入返回False
def remove(self, val: int) -> bool:
if val not in self.idsmap:return False
#
idx=self.idsmap[val].pop()
lastnum=self.data[-1]
self.data[idx]=lastnum
self.data.pop() #注意:此时k->k-1
#key
#idx已经被pop
if len(self.idsmap[val])==0:
del self.idsmap[val]
if idx日常系列LeetCode《7·排序篇》