【LeetCode】每日一题 2023_11_28 设计前中后队列(数组/链表/双端队列)

2023-11-29 16:44

本文主要是介绍【LeetCode】每日一题 2023_11_28 设计前中后队列(数组/链表/双端队列),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 刷题前唠嗑
  • 题目:设计前中后队列
    • 题目描述
    • 代码与解题思路
    • 偷看大佬题解
  • 结语

刷题前唠嗑


LeetCode?启动!!!

这道题的难度,才是我想象中的中等题的难度好吧,昨天那玩意对我来说还是太难了。。。

题目:设计前中后队列

题目链接:1670. 设计前中后队列

题目描述

代码与解题思路

type FrontMiddleBackQueue struct {queue []intsize int
}func Constructor() FrontMiddleBackQueue {return FrontMiddleBackQueue {queue: make([]int, 1001), size: 0,}
}func (this *FrontMiddleBackQueue) PushFront(val int)  {tmp := make([]int, 1001)tmp[0] = valfor i := 1; i < this.size+1; i++ {tmp[i] = this.queue[i-1]}this.queue = tmpthis.size++
}func (this *FrontMiddleBackQueue) PushMiddle(val int)  {tmp := make([]int, 1001)for i := 0; i < this.size/2; i++ {tmp[i] = this.queue[i]}tmp[this.size/2] = valfor i := this.size/2+1; i < this.size+1; i++ {tmp[i] = this.queue[i-1]}this.queue = tmpthis.size++
}func (this *FrontMiddleBackQueue) PushBack(val int)  {tmp := make([]int, 1001)for i := 0; i < this.size; i++ {tmp[i] = this.queue[i]}tmp[this.size] = valthis.queue = tmpthis.size++
}func (this *FrontMiddleBackQueue) PopFront() int {if this.size == 0 {return -1}ans := this.queue[0]this.queue = this.queue[1:]this.size--return ans
}func (this *FrontMiddleBackQueue) PopMiddle() int {if this.size == 0 {return -1}ans := this.queue[(this.size-1)/2]this.queue = append(this.queue[:(this.size-1)/2], this.queue[(this.size-1)/2+1:]...)this.size--return ans
}func (this *FrontMiddleBackQueue) PopBack() int {if this.size == 0 {return -1}ans := this.queue[this.size-1]this.queue = this.queue[:this.size-1]this.size--return ans
}

快来欣赏一下我的数组屎山,当时一开始做的时候我在想是用链表做还是数组做,链表做肯定是更优的,但是我感觉链表可能比较麻烦(事实证明数组更麻烦。。。早知道用链表写了,后悔)

题目的思路就是:跟着题目要求写就行了,主要考察的是代码能力

偷看大佬题解

Go 链表实现:

// 第一种写法:链表
type FrontMiddleBackQueue struct {left  *list.Listright *list.List
}func Constructor() FrontMiddleBackQueue {return FrontMiddleBackQueue{left:  list.New(),right: list.New(),}
}// 调整长度,保证 0 <= right.Len() - left.Len() <= 1
// 从而保证可以在正中间插入删除元素
func (q *FrontMiddleBackQueue) balance() {if q.left.Len() > q.right.Len() {q.right.PushFront(q.left.Remove(q.left.Back()))} else if q.right.Len() > q.left.Len()+1 {q.left.PushBack(q.right.Remove(q.right.Front()))}
}func (q *FrontMiddleBackQueue) PushFront(val int) {q.left.PushFront(val)q.balance()
}func (q *FrontMiddleBackQueue) PushMiddle(val int) {if q.left.Len() < q.right.Len() {q.left.PushBack(val)} else {q.right.PushFront(val)}
}func (q *FrontMiddleBackQueue) PushBack(val int) {q.right.PushBack(val)q.balance()
}func (q *FrontMiddleBackQueue) PopFront() (val int) {if q.right.Len() == 0 { // 整个队列为空return -1}if q.left.Len() > 0 {val = q.left.Remove(q.left.Front()).(int)} else {val = q.right.Remove(q.right.Front()).(int)}q.balance()return
}func (q *FrontMiddleBackQueue) PopMiddle() int {if q.right.Len() == 0 { // 整个队列为空return -1}if q.left.Len() == q.right.Len() {return q.left.Remove(q.left.Back()).(int)}return q.right.Remove(q.right.Front()).(int)
}func (q *FrontMiddleBackQueue) PopBack() int {if q.right.Len() == 0 { // 整个队列为空return -1}val := q.right.Remove(q.right.Back()).(int)q.balance()return val
}

Go 双端队列实现

// 第二种写法:四个 slice
type FrontMiddleBackQueue struct {left  *Dequeright *Deque
}func Constructor() FrontMiddleBackQueue {return FrontMiddleBackQueue{left:  &Deque{},right: &Deque{},}
}// 调整长度,保证 0 <= right.Len() - left.Len() <= 1
// 从而保证可以在正中间插入删除元素
func (q *FrontMiddleBackQueue) balance() {if q.left.Len() > q.right.Len() {q.right.PushFront(q.left.PopBack())} else if q.right.Len() > q.left.Len()+1 {q.left.PushBack(q.right.PopFront())}
}func (q *FrontMiddleBackQueue) PushFront(val int) {q.left.PushFront(val)q.balance()
}func (q *FrontMiddleBackQueue) PushMiddle(val int) {if q.left.Len() < q.right.Len() {q.left.PushBack(val)} else {q.right.PushFront(val)}
}func (q *FrontMiddleBackQueue) PushBack(val int) {q.right.PushBack(val)q.balance()
}func (q *FrontMiddleBackQueue) PopFront() (val int) {if q.right.Len() == 0 { // 整个队列为空return -1}if q.left.Len() > 0 {val = q.left.PopFront()} else {val = q.right.PopFront()}q.balance()return
}func (q *FrontMiddleBackQueue) PopMiddle() int {if q.right.Len() == 0 { // 整个队列为空return -1}if q.left.Len() == q.right.Len() {return q.left.PopBack()}return q.right.PopFront()
}func (q *FrontMiddleBackQueue) PopBack() int {if q.right.Len() == 0 { // 整个队列为空return -1}val := q.right.PopBack()q.balance()return val
}// 两个 slice 头对头,即可实现双端队列
// 但这并不是一个「工业级」的实现,因为 slice 没有「缩容」的概念
// 这意味着在大量的 pop 操作后,会产生大量无法被自动 GC 的空间
type Deque struct {left  []intright []int
}func (q Deque) Empty() bool {return len(q.left) == 0 && len(q.right) == 0
}func (q Deque) Len() int {return len(q.left) + len(q.right)
}func (q *Deque) PushFront(v int) {q.left = append(q.left, v)
}func (q *Deque) PushBack(v int) {q.right = append(q.right, v)
}func (q *Deque) PopFront() (v int) {if len(q.left) > 0 {q.left, v = q.left[:len(q.left)-1], q.left[len(q.left)-1]} else {v, q.right = q.right[0], q.right[1:]}return
}func (q *Deque) PopBack() (v int) {if len(q.right) > 0 {q.right, v = q.right[:len(q.right)-1], q.right[len(q.right)-1]} else {v, q.left = q.left[0], q.left[1:]}return
}

用官方题解评论区大佬的话来说就是,双端队列考思路,链表解法考代码能力。这就是这道题考察的点。

结语

终于,又做出了一道每日一题,晕倒了

这篇关于【LeetCode】每日一题 2023_11_28 设计前中后队列(数组/链表/双端队列)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/433550

相关文章

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

SpringKafka错误处理(重试机制与死信队列)

《SpringKafka错误处理(重试机制与死信队列)》SpringKafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、Spring Kafka错误处理基础二、配置重试机制三、死信队列实现四、特定异常的处理策略五

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

Spring Boot整合消息队列RabbitMQ的实现示例

《SpringBoot整合消息队列RabbitMQ的实现示例》本文主要介绍了SpringBoot整合消息队列RabbitMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录RabbitMQ 简介与安装1. RabbitMQ 简介2. RabbitMQ 安装Spring

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::