格式:
题号+题名+简单思路+code
T146: LRU缓存机制
- Least Recently Used
- O(1)→哈希双链表
- 自己构造双链表
type Node struct {
key int
value int
prev *Node
next *Node
}
type BiList struct {
head *Node
tail *Node
}
func BuildBiList() BiList {
return BiList{nil, nil}
}
func (b *BiList) Delete(node *Node) {
if node==nil {
return
}
if node==b.head {
b.head=node.next
} else {
node.prev.next=node.next
}
if node==b.tail {
b.tail=node.prev
} else {
node.next.prev=node.prev
}
}
func (b *BiList) DeleteLast() int {
tmp:=b.tail.key
b.Delete(b.tail)
return tmp
}
func (b *BiList) AddFirst(node *Node) {
if b.head==nil {
b.head=node
b.tail=node
return
}
node.next=b.head
b.head.prev=node
b.head=node
}
func (b *BiList) MoveToFirst(node *Node) {
if node==b.head {
return
}
if node==b.tail {
node.next=b.head
b.head.prev=node
b.tail=node.prev
b.tail.next=nil
b.head=node
node.prev=nil
return
}
node.prev.next=node.next
node.next.prev=node.prev
node.next=b.head
b.head.prev=node
b.head=node
node.prev=nil
}
func (b BiList) PrintAll() []Node {
ans:=[]Node{}
for node:=b.head;node!=nil;node=node.next {
ans=append(ans,*node)
}
return ans
}
type LRUCache struct {
hashMap map[int]*Node
biList BiList
length int
capacity int
}
func Constructor(capacity int) LRUCache {
return LRUCache{map[int]*Node{}, BuildBiList(), 0, capacity}
}
func (this *LRUCache) Get(key int) int {
if node,ok:=this.hashMap[key];ok {
this.biList.MoveToFirst(node)
// fmt.Println(this.biList.PrintAll())
return node.value
} else {
return -1
}
}
func (this *LRUCache) Put(key int, value int) {
if node,ok:=this.hashMap[key];ok {
this.biList.Delete(node)
delete(this.hashMap, key)
this.length--
} else {
if this.length==this.capacity {
t_v:=this.biList.DeleteLast()
delete(this.hashMap, t_v)
this.length--
}
}
tmp:=&Node{key, value, nil, nil}
this.biList.AddFirst(tmp)
this.hashMap[key]=tmp
this.length++
// fmt.Println(this.biList.PrintAll())
// fmt.Println(this.hashMap)
}
/**
* Your LRUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/
- 利用
container/list
import "container/list"
type Node struct {
key int
value int
}
type LRUCache struct {
hashMap map[int]*list.Element
biList *list.List
length int
capacity int
}
func Constructor(capacity int) LRUCache {
return LRUCache{map[int]*list.Element{}, list.New(), 0, capacity}
}
func (this *LRUCache) Get(key int) int {
if node,ok:=this.hashMap[key];ok {
this.biList.MoveToFront(node)
return node.Value.(Node).value
} else {
return -1
}
}
func (this *LRUCache) Put(key int, value int) {
if node,ok:=this.hashMap[key];ok {
this.biList.Remove(node)
delete(this.hashMap, key)
this.length--
} else {
if this.length==this.capacity {
t_v:=this.biList.Remove(this.biList.Back())
delete(this.hashMap, t_v.(Node).key)
this.length--
}
}
tmp:=Node{key, value}
ele:=this.biList.PushFront(tmp)
this.hashMap[key]=ele
this.length++
}
/**
* Your LRUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/
T460: LFU缓存机制
- Least Frequently Used
- 利用最小堆结构(索引优先队列,即可以更新堆中的节点),使用调用频率和时间戳来比较大小
- Get操作为O(logN);Put操作为O(logN)
- 使用平衡二叉树同理,复杂度相同
import "container/heap"
type Node struct {
key int
value int
index int
freq int
time int
}
type PQ []*Node
func (pq PQ) Len() int {
return len(pq)
}
func (pq PQ) Less(i int, j int) bool {
if pq[i].freq<pq[j].freq {
return true
} else if pq[i].freq>pq[j].freq {
return false
} else {
if pq[i].time<pq[j].time {
return true
} else {
return false
}
}
}
func (pq PQ) Swap(i int, j int) {
pq[i], pq[j]=pq[j], pq[i]
pq[i].index, pq[j].index=pq[j].index, pq[i].index
}
func (pq *PQ) Push(i interface{}) {
x:=i.(*Node)
x.index=pq.Len()
*pq=append(*pq, x)
}
func (pq *PQ) Pop() interface{} {
x:=(*pq)[len(*pq)-1]
*pq=(*pq)[:len(*pq)-1]
return x
}
func (pq *PQ) Update(node *Node, value int, time int) {
node.value=value
node.time=time
node.freq++
heap.Fix(pq, node.index)
}
type LFUCache struct {
hashMap map[int]*Node
pq *PQ // 使用最小堆,删除最小频率最早调用节点
length int
capacity int
time int
}
func Constructor(capacity int) LFUCache {
return LFUCache{map[int]*Node{}, &PQ{}, 0, capacity, 0}
}
func (this *LFUCache) Get(key int) int {
if point, ok:=this.hashMap[key];ok {
item:=point.value
this.pq.Update(point, item, this.time)
this.time++
return item
} else {
return -1
}
}
func (this *LFUCache) Put(key int, value int) {
if this.capacity==0 {
return
}
if point, ok:=this.hashMap[key];ok {
point.value=value
this.pq.Update(point, value, this.time)
this.time++
} else {
if this.length==this.capacity {
item:=heap.Pop(this.pq).(*Node)
delete(this.hashMap, item.key)
this.length--
}
tmp:=&Node{key, value, 0, 1, this.time}
heap.Push(this.pq, tmp)
this.hashMap[key]=tmp
this.length++
this.time++
}
}
/**
* Your LFUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/
- 哈希表+二级双向链表;哈希表决定O(1)的是否存在;双向链表决定freq的增减和找freq最小和最旧的节点
import "container/list"
type Node struct {
key int
value int
freq int
location *list.Element // 在一级链表中的指针
}
type LFUCache struct {
priList *list.List // 一级链表,元素为不同freq的Node链表
secList *list.List // 二级链表,元素为相同freq的Node
hashMap map[int]*list.Element // key -> Node
length int
capacity int
}
func Constructor(capacity int) LFUCache {
return LFUCache{list.New(), list.New(), map[int]*list.Element{}, 0, capacity}
}
func (this *LFUCache) Get(key int) int {
if point, ok:=this.hashMap[key];ok {
value:=point.Value.(*Node).value
this.AddOne(key, value)
return value
} else {
return -1
}
}
func (this *LFUCache) Put(key int, value int) {
if _, ok:=this.hashMap[key];ok {
this.AddOne(key, value)
} else {
if this.length==this.capacity {
if this.capacity==0 {
return
}
lastList:=this.priList.Back().Value.(*list.List)
delete(this.hashMap, lastList.Back().Value.(*Node).key)
lastList.Remove(lastList.Back()) // 删除freq最小且最旧的节点
if lastList.Front()==nil { // 若最后的链表为空,则删除该链表
this.priList.Remove(this.priList.Back())
}
this.AddFreqOne(key, value)
} else {
this.AddFreqOne(key, value)
this.length++
}
}
}
func (this *LFUCache) AddOne(key int, value int) {
point:=this.hashMap[key]
node:=point.Value.(*Node)
currList:=node.location.Value.(*list.List)
currList.Remove(point) // 删除当前freq的节点
delete(this.hashMap, key)
if node.location.Prev()==nil { // 不存在freq+1的链表则创建一个
this.priList.InsertBefore(list.New(), node.location)
} else {
next_list:=node.location.Prev().Value.(*list.List)
if next_list.Front().Value.(*Node).freq>node.freq+1 {
this.priList.InsertBefore(list.New(), node.location)
}
}
next_list:=node.location.Prev().Value.(*list.List)
node.freq++
node.value=value
node.location=node.location.Prev()
this.hashMap[key]=next_list.PushFront(node)
if currList.Front()==nil { // 若当前二级链表为空,则删除该链表
this.priList.Remove(node.location.Next())
}
}
func (this *LFUCache) AddFreqOne(key int, value int) {
if this.priList.Back()==nil { // 增加freq为1的链表
this.priList.PushBack(list.New())
} else {
lastList:=this.priList.Back().Value.(*list.List)
if lastList.Front().Value.(*Node).freq>1 {
this.priList.PushBack(list.New())
}
}
lastList:=this.priList.Back().Value.(*list.List)
this.hashMap[key]=lastList.PushFront(&Node{key, value, 1, this.priList.Back()})
}
/**
* Your LFUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/
T432: 全O(1)的数据结构
- 增加了减少freq的操作
import "container/list"
type Node struct {
key string
freq int
location *list.Element // 在一级链表中的指针
}
type AllOne struct {
priList *list.List // 一级链表,元素为不同freq的Node链表
secList *list.List // 二级链表,元素为相同freq的Node
hashMap map[string]*list.Element // key -> Node
}
func Constructor() AllOne {
return AllOne{list.New(), list.New(), map[string]*list.Element{}}
}
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
func (this *AllOne) Inc(key string) {
if _, ok:=this.hashMap[key];ok {
this.AddOne(key)
} else {
this.AddFreqOne(key)
}
}
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
func (this *AllOne) Dec(key string) {
if point, ok:=this.hashMap[key];ok {
node:=point.Value.(*Node)
if node.freq==1 {
lastList:=node.location.Value.(*list.List)
lastList.Remove(point) // 在freq1中删除该节点
delete(this.hashMap, key)
if lastList.Front()==nil { // 若当前二级链表为空,则删除该链表
this.priList.Remove(node.location)
}
} else {
this.MinusOne(key)
}
} else {
return
}
}
/** Returns one of the keys with maximal value. */
func (this *AllOne) GetMaxKey() string {
if this.priList.Front()!=nil {
return this.priList.Front().Value.(*list.List).Front().Value.(*Node).key
} else {
return ""
}
}
/** Returns one of the keys with Minimal value. */
func (this *AllOne) GetMinKey() string {
if this.priList.Back()!=nil {
return this.priList.Back().Value.(*list.List).Back().Value.(*Node).key
} else {
return ""
}
}
func (this *AllOne) AddOne(key string) {
point:=this.hashMap[key]
node:=point.Value.(*Node)
currList:=node.location.Value.(*list.List)
currList.Remove(point) // 删除当前freq的节点
delete(this.hashMap, key)
if node.location.Prev()==nil { // 不存在freq+1的链表则创建一个
this.priList.InsertBefore(list.New(), node.location)
} else {
next_list:=node.location.Prev().Value.(*list.List)
if next_list.Front().Value.(*Node).freq>node.freq+1 {
this.priList.InsertBefore(list.New(), node.location)
}
}
next_list:=node.location.Prev().Value.(*list.List)
node.freq++
node.location=node.location.Prev()
this.hashMap[key]=next_list.PushFront(node)
if currList.Front()==nil { // 若当前二级链表为空,则删除该链表
this.priList.Remove(node.location.Next())
}
}
func (this *AllOne) MinusOne(key string) {
point:=this.hashMap[key]
node:=point.Value.(*Node)
currList:=node.location.Value.(*list.List)
currList.Remove(point) // 删除当前freq的节点
delete(this.hashMap, key)
if node.location.Next()==nil { // 不存在freq-1的链表则创建一个
this.priList.InsertAfter(list.New(), node.location)
} else {
next_list:=node.location.Next().Value.(*list.List)
if next_list.Front().Value.(*Node).freq<node.freq-1 {
this.priList.InsertAfter(list.New(), node.location)
}
}
next_list:=node.location.Next().Value.(*list.List)
node.freq--
node.location=node.location.Next()
this.hashMap[key]=next_list.PushFront(node)
if currList.Front()==nil { // 若当前二级链表为空,则删除该链表
this.priList.Remove(node.location.Prev())
}
}
func (this *AllOne) AddFreqOne(key string) {
if this.priList.Back()==nil { // 增加freq为1的链表
this.priList.PushBack(list.New())
} else {
lastList:=this.priList.Back().Value.(*list.List)
if lastList.Front().Value.(*Node).freq>1 {
this.priList.PushBack(list.New())
}
}
lastList:=this.priList.Back().Value.(*list.List)
this.hashMap[key]=lastList.PushFront(&Node{key, 1, this.priList.Back()})
}
/**
* Your AllOne object will be instantiated and called as such:
* obj := Constructor();
* obj.Inc(key);
* obj.Dec(key);
* param_3 := obj.GetMaxKey();
* param_4 := obj.GetMinKey();
*/
T155: 最小栈
- 使用辅助栈,记录当前最小元素,出栈时判断是否需要在辅助栈中出栈
type MinStack struct {
inner []int
innerS []int
}
/** initialize your data structure here. */
func Constructor() MinStack {
minStack:=MinStack{}
return minStack
}
func (this *MinStack) Push(x int) {
if len(this.innerS)==0 {
this.innerS=append(this.innerS,x)
} else if this.innerS[len(this.innerS)-1]>=x{ // 相等也要加入辅助栈,解决重复
this.innerS=append(this.innerS,x)
}
this.inner=append(this.inner,x)
}
func (this *MinStack) Pop() {
if len(this.inner)>0 {
if this.Top()==this.GetMin() {
this.innerS=this.innerS[:len(this.innerS)-1]
}
this.inner=this.inner[:len(this.inner)-1]
}
}
func (this *MinStack) Top() int {
if len(this.inner)>0 {
return this.inner[len(this.inner)-1]
}
return 999
}
func (this *MinStack) GetMin() int {
if len(this.innerS)>0 {
return this.innerS[len(this.innerS)-1]
}
return 999
}
/**
* Your MinStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.GetMin();
*/
剑指59: 最大队列
- 维护一个单调递减队列
class MaxQueue:
def __init__(self):
self.nums=[]
self.assist=[]
def max_value(self) -> int:
if len(self.assist)>0:
return self.assist[0]
return -1
def push_back(self, value: int) -> None:
self.nums.append(value)
while len(self.assist)>0 and self.assist[-1]<value:
self.assist.pop()
self.assist.append(value)
def pop_front(self) -> int:
if len(self.nums)>0:
if len(self.assist)>0 and self.assist[0]==self.nums[0]:
self.assist=self.assist[1:]
item=self.nums[0]
self.nums=self.nums[1:]
return item
return -1
# Your MaxQueue object will be instantiated and called as such:
# obj = MaxQueue()
# param_1 = obj.max_value()
# obj.push_back(value)
# param_3 = obj.pop_front()
T208: 实现Trie
- 相当于N叉树,构建节点
- 搜索时间复杂度只与单词长度有关
type Node struct {
IsEnd bool
Next map[byte]*Node
}
type Trie struct {
root *Node
}
/** Initialize your data structure here. */
func Constructor() Trie {
return Trie{&Node{false, nil}}
}
/** Inserts a word into the trie. */
func (this *Trie) Insert(word string) {
node:=this.root
for idx := range word {
if node.Next==nil {
node.Next=map[byte]*Node{}
}
if next, ok := node.Next[word[idx]];ok {
node=next
} else {
node.Next[word[idx]]=&Node{false, nil}
node=node.Next[word[idx]]
}
}
node.IsEnd=true
}
/** Returns if the word is in the trie. */
func (this *Trie) Search(word string) bool {
node:=this.root
for idx := range word {
if node.Next==nil {
return false
}
if next, ok := node.Next[word[idx]];!ok {
return false
} else {
node=next
}
}
return node.IsEnd
}
/** Returns if there is any word in the trie that starts with the given prefix. */
func (this *Trie) StartsWith(prefix string) bool {
node:=this.root
for idx := range prefix {
if node.Next==nil {
return false
}
if next, ok := node.Next[prefix[idx]];!ok {
return false
} else {
node=next
}
}
return true
}
/**
* Your Trie object will be instantiated and called as such:
* obj := Constructor();
* obj.Insert(word);
* param_2 := obj.Search(word);
* param_3 := obj.StartsWith(prefix);
*/
T211: 添加与搜索单词
type Node struct {
IsEnd bool
Next map[byte]*Node
}
type WordDictionary struct {
root *Node
}
/** Initialize your data structure here. */
func Constructor() WordDictionary {
return WordDictionary{&Node{false, nil}}
}
/** Inserts a word into the trie. */
func (this *WordDictionary) AddWord(word string) {
node:=this.root
for idx := range word {
if node.Next==nil {
node.Next=map[byte]*Node{}
}
if next, ok := node.Next[word[idx]];ok {
node=next
} else {
node.Next[word[idx]]=&Node{false, nil}
node=node.Next[word[idx]]
}
}
node.IsEnd=true
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
func (this *WordDictionary) Search(word string) bool {
return this.SearchAssist(word, 0, this.root)
}
func (this *WordDictionary) SearchAssist(word string, idx int, node *Node) bool {
if idx==len(word) {
return node.IsEnd
}
b:=word[idx]
if node.Next==nil {
return false
}
if b=='.' {
for _, next := range node.Next {
if this.SearchAssist(word, idx+1, next) {
return true
}
}
return false
} else {
if next,ok:=node.Next[b];ok {
return this.SearchAssist(word, idx+1, next)
} else {
return false
}
}
}
/**
* Your WordDictionary object will be instantiated and called as such:
* obj := Constructor();
* obj.AddWord(word);
* param_2 := obj.Search(word);
*/
T173: 二叉搜索树迭代器
- ①扁平化BST,空间复杂度为O(N)
- ②拆分,只在需要时调用
Next()
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
type BSTIterator struct {
stack []*TreeNode
root *TreeNode
}
func Constructor(root *TreeNode) BSTIterator {
stack:=[]*TreeNode{}
return BSTIterator{stack, root}
}
/** @return the next smallest number */
/*
stack中最深为树的高度,O(h)空间复杂度
每个节点只会被入栈和出栈一次,所以平均时间复杂度为O(1)
*/
func (this *BSTIterator) Next() int {
if len(this.stack)>0 || this.root!=nil {
for this.root!=nil {
this.stack=append(this.stack, this.root)
this.root=this.root.Left
}
if len(this.stack)>0 {
item:=this.stack[len(this.stack)-1]
this.stack=this.stack[:len(this.stack)-1]
this.root=item.Right
return item.Val
}
}
return -1
}
/** @return whether we have a next smallest number */
// O(1)时间复杂度
func (this *BSTIterator) HasNext() bool {
if len(this.stack)>0 || this.root!=nil {
return true
}
return false
}
/**
* Your BSTIterator object will be instantiated and called as such:
* obj := Constructor(root);
* param_1 := obj.Next();
* param_2 := obj.HasNext();
*/
T284: 顶端迭代器
- 给只有
next()
和hasNext()
方法的迭代器添加peek()
方法 - 辅助队列
/* Below is the interface for Iterator, which is already defined for you.
*
* type Iterator struct {
*
* }
*
* func (this *Iterator) hasNext() bool {
* // Returns true if the iteration has more elements.
* }
*
* func (this *Iterator) next() int {
* // Returns the next element in the iteration.
* }
*/
type PeekingIterator struct {
inner []int
iter *Iterator
}
func Constructor(iter *Iterator) *PeekingIterator {
return &PeekingIterator{[]int{}, iter}
}
func (this *PeekingIterator) hasNext() bool {
if len(this.inner)==0 && !this.iter.hasNext(){
return false
}
return true
}
func (this *PeekingIterator) next() int {
if len(this.inner)==0 {
return this.iter.next()
}
item:=this.inner[0]
this.inner=this.inner[1:]
return item
}
func (this *PeekingIterator) peek() int {
if len(this.inner)==0 {
this.inner=append(this.inner, this.iter.next())
}
return this.inner[0]
}
T341: 扁平化嵌套列表迭代器
- 逻辑写在
hasNext()
中 [[]], [[[6]]]
是难点- 提交了6遍才AC
import "container/list"
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* type NestedInteger struct {
* }
*
* // Return true if this NestedInteger holds a single integer, rather than a nested list.
* func (this NestedInteger) IsInteger() bool {}
*
* // Return the single integer that this NestedInteger holds, if it holds a single integer
* // The result is undefined if this NestedInteger holds a nested list
* // So before calling this method, you should have a check
* func (this NestedInteger) GetInteger() int {}
*
* // Set this NestedInteger to hold a single integer.
* func (n *NestedInteger) SetInteger(value int) {}
*
* // Set this NestedInteger to hold a nested list and adds a nested integer to it.
* func (this *NestedInteger) Add(elem NestedInteger) {}
*
* // Return the nested list that this NestedInteger holds, if it holds a nested list
* // The list length is zero if this NestedInteger holds a single integer
* // You can access NestedInteger's List element directly if you want to modify it
* func (this NestedInteger) GetList() []*NestedInteger {}
*/
type NestedIterator struct {
queue *list.List
nestedList []*NestedInteger
}
func Constructor(nestedList []*NestedInteger) *NestedIterator {
return &NestedIterator{list.New(), nestedList}
}
func (this *NestedIterator) Next() int {
item:=this.queue.Front().Value.(*NestedInteger)
this.queue.Remove(this.queue.Front())
return item.GetInteger()
}
func (this *NestedIterator) HasNext() bool {
// 当队列为空或者队列起始不为单个数时进行循环处理
for this.queue.Front()==nil || !(this.queue.Front().Value.(*NestedInteger).IsInteger()) {
// 队列为空时,需要从list添加一个节点入队
if this.queue.Front()==nil {
if len(this.nestedList)==0 {
return false
}
item:=this.nestedList[0]
this.nestedList=this.nestedList[1:]
if !(item.IsInteger()) && len(item.GetList())==0 {
continue
}
this.queue.PushFront(item)
}
// 处理直至队列开头节点为单个数
for item:=this.queue.Front().Value.(*NestedInteger);!item.IsInteger();item=this.queue.Front().Value.(*NestedInteger) {
this.queue.Remove(this.queue.Front())
t_list:=item.GetList()
for i:=len(t_list)-1;i>=0;i-- {
if !(t_list[i].IsInteger()) && len(t_list[i].GetList())==0 {
continue
}
this.queue.PushFront(t_list[i])
}
if this.queue.Front()==nil {
break
}
}
}
return true
}