Leetcode-数据结构

Leetcode-数据结构



q146 LRU缓存


题目传送门


题解

该题需要使用hash表+双向链表来解决。
我们把最常使用的节点放在链表头,而把最不常使用的节点放在链表尾,这样每次缓存容量满的时候就去掉表尾,每次访问或者添加节点的时候就将这个节点放在表头。
另外为了方便操作,我们为双向链表的两端加入了head和tail哨兵节点。
缓存中还有一个hash表,我们把key作为hash表的key,而把链表的整个节点作为hash表的value。

package main

// DLinkNode 双向链表节点
type DLinkNode struct {
	key, value int
	prev, next *DLinkNode
}

type LRUCache struct {
	size int
	cap int
	cache map[int] *DLinkNode
	head, tail *DLinkNode
}

// InitDLinkNode 初始化双向链表节点
func InitDLinkNode(key, value int) *DLinkNode {
	return &DLinkNode{
		key:   key,
		value: value,
	}
}

func Constructor(capacity int) LRUCache {
	l := LRUCache{
		size:  0,
		cap:   capacity,
		cache: make(map[int]*DLinkNode),
		// 头尾两个哨兵节点置为0
		head:  InitDLinkNode(0, 0),
		tail:  InitDLinkNode(0, 0),
	}
	// 一开始只有这两个节点
	l.head.next = l.tail
	l.tail.prev = l.head
	return l
}


func (this *LRUCache) Get(key int) int {
	// 先判断hash表中有没有这个元素
	if _, ok := this.cache[key]; !ok {
		return -1
	} else {
		// 如果有就将它移动到链表头
		node := this.cache[key]
		this.moveToHead(node)
		// 并返回它的key
		return node.value
	}
}


func (this *LRUCache) Put(key int, value int)  {
	// 如果hash表中没有该元素
	if _, ok := this.cache[key]; !ok {
		// 用传进来的key和value初始化一个节点
		node := InitDLinkNode(key, value)
		// 添加到hash表
		this.cache[key] = node
		// 添加到链表头
		this.addToHead(node)
		this.size++
		// 查看缓存是否到达上限
		if this.size > this.cap {
			// 缓存到达上限就删掉尾结点
			removed := this.removeTail()
			delete(this.cache, removed.key)
			this.size--
		}
	} else {
		// 如果元素已经存在就更新值
		node := this.cache[key]
		node.value = value
		// 移动到头结点的位置
		this.moveToHead(node)
	}
}

// 双向链表的相关操作
func (this *LRUCache) addToHead(node *DLinkNode) {
	node.prev = this.head
	node.next = this.head.next
	this.head.next.prev = node
	this.head.next = node
}
func (this *LRUCache) removeNode(node *DLinkNode) {
	node.prev.next = node.next
	node.next.prev = node.prev
}
func (this *LRUCache) moveToHead(node *DLinkNode) {
	this.removeNode(node)
	this.addToHead(node)
}
func (this *LRUCache) removeTail() *DLinkNode {
	node := this.tail.prev
	this.removeNode(node)
	return node
}

q208 实现Trie(前缀树)


题目传送门


题解

字典树是一种用于快速检索的多叉树结构。字典树把字符串看成字符序列,根据字符串中字符序列的先后顺序构造从上到下的树结构,树结构中的每一条边都对应着一个字符。字典树上存储的字符串被视为从根节点到某个节点之间的一条路径,并在终点节点上做个标记"该节点对应词语的结尾",正因为有终点节点的存在,字典树不仅可以实现简单的存储字符串,还可以实现字符串的映射,只需要将相对应的值悬挂在终点节点上即可,比如"自然"=“nature"的映射,只需要将"自然"路径上终点节点的值设置为"natrue”。

在这里插入图片描述参考:https://zhuanlan.zhihu.com/p/143975546

这道题目要求构建的字典树中只包含小写字母,不是很复杂,我们首先来构建一个可以表示字典树节点的结构体:

type Trie struct {
	children [26]*Trie
	isTail   bool
}

children字段表示一个节点后面的字符,isTail表示当前节点是否是一个单词的最后一个字符。

构造函数就是构造一个空节点:

func Constructor() Trie {
	return Trie{}
}

然后是对应的插入和搜索方法:

func (t *Trie) Insert(word string) {
	node := t
	for _, v := range word {
		v = v - 'a'
		if node.children[v] == nil {
			node.children[v] = &Trie{}
		}
		node = node.children[v]
	}
	node.isTail = true
}

func (t *Trie) SearchPrefix(prefix string) *Trie {
	node := t
	for _, v := range prefix {
		v = v - 'a'
		if node.children[v] == nil {
			return nil
		}
		node = node.children[v]
	}
	return node
}

func (t *Trie) Search(word string) bool {
	node := t.SearchPrefix(word)
	return node != nil && node.isTail
}

func (t *Trie) StartsWith(prefix string) bool {
	return t.SearchPrefix(prefix) != nil
}

剑指 Offer 30. 包含min函数的栈


题目传送门


题解

这道题其实就是最小栈,要求实现一个栈数据表结构,而且可以向外提供返回栈内最小值的API,且每个操作的时间复杂度必须为O(1)。

我们可以使用辅助栈的方法来求解,额外定义一个栈,主栈push或者pop,辅助栈也进行相应的push和pop。辅助栈在push的时候进行判断,如果当前push的值比栈内的所有元素都小,就push这个新值到栈顶,否则就push栈内的最小值到栈顶,所以我们可以时刻保证辅助栈的栈顶元素永远是栈内元素的最小值。

type MinStack struct {
	stack    []int
	minStack []int
}

func Constructor() MinStack {
	return MinStack{
		stack:    make([]int, 0),
		minStack: []int{math.MaxInt32},
	}
}

func (this *MinStack) Push(x int) {
	this.stack = append(this.stack, x)
	// 原来辅助栈中的最小元素
	top := this.minStack[len(this.minStack)-1]
	// push的时候更新辅助栈顶的最小值
	this.minStack = append(this.minStack, min(top, x))
}

func (this *MinStack) Pop() {
	this.stack = this.stack[:len(this.stack)-1]
	this.minStack = this.minStack[:len(this.minStack)-1]
}

func (this *MinStack) Top() int {
	return this.stack[len(this.stack)-1]
}

func (this *MinStack) Min() int {
	// 辅助栈的栈顶就是栈内的最小值
	return this.minStack[len(this.minStack)-1]
}

func min(a, b int) int {
	if a < b {
		return a
	} else {
		return b
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值