232. 用栈实现队列 (Implement Queue using Stacks)

用栈实现队列 (Implement Queue using Stacks)

题目描述

使用两个栈实现一个队列。队列的操作包括 push(x)pop()peek()empty()

示例:

plaintext 复制代码
MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);  
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

注意:

  • 你只能使用标准的栈操作,即 push to toppeek/pop from topsizeis empty 这些操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的。例如,当队列为空时,不调用 poppeek 操作。

代码实现

swift 复制代码
class MyQueue {

    private var stack1: [Int]
    private var stack2: [Int]

    /** Initialize your data structure here. */
    init() {
        stack1 = [Int]()
        stack2 = [Int]()
    }
    
    /** Push element x to the back of queue. */
    func push(_ x: Int) {
        stack1.append(x)
    }
    
    /** Removes the element from in front of queue and returns that element. */
    func pop() -> Int {
        if stack2.isEmpty {
            while !stack1.isEmpty {
                stack2.append(stack1.removeLast())
            }
        }
        return stack2.removeLast()
    }
    
    /** Get the front element. */
    func peek() -> Int {
        if stack2.isEmpty {
            while !stack1.isEmpty {
                stack2.append(stack1.removeLast())
            }
        }
        return stack2.last!
    }
    
    /** Returns whether the queue is empty. */
    func empty() -> Bool {
        return stack1.isEmpty && stack2.isEmpty
    }
}

注意点

在 Swift 中,Array 的实例(或对象)方法 removeFirst()removeLast() 除了执行本身的 remove 操作,还会 return 对应 removed 元素。

swift 复制代码
// Removes and returns the first element of the collection.
@discardableResult
@inlinable public mutating func removeFirst() -> Element
// Removes and returns the last element of the collection.
@discardableResult
@inlinable public mutating func removeLast() -> Element

swift 复制代码
// Error: Cannot use mutating member on immutable value of type '[Int]'
[1,2,3].removeFirst()

在 Swift 中,如果你试图在不可变数组上调用可变方法(例如 removeFirst()),会导致错误。为了修复这个错误,你需要确保数组是可变的。下面是一些正确处理的方式:

使用可变数组

确保你的数组是用 var 声明的,这样你就可以对它进行修改。

swift 复制代码
var array = [1, 2, 3]
array.removeFirst()  // 现在不会报错
print(array)  // 输出: [2, 3]

使用不可变数组并创建可变副本

如果你的数组必须是不可变的,你可以创建一个可变副本来进行修改。

swift 复制代码
let immutableArray = [1, 2, 3]
var mutableArray = immutableArray
mutableArray.removeFirst()
print(mutableArray)  // 输出: [2, 3]

完整示例

以下是如何在实际代码中使用可变数组的示例:

swift 复制代码
func processArray() {
    var array = [1, 2, 3]
    array.removeFirst()
    print(array)  // 输出: [2, 3]
}

processArray()

通过确保数组是可变的,你可以成功调用诸如 removeFirst() 之类的可变方法,而不会遇到错误。


拓展 - Swift 中为什么没有原生支持的 Stack 和 Queue 数据结构 ?

Swift 中没有原生支持的 Stack 和 Queue 数据结构的原因主要有以下几个方面:

1. 泛用数据结构的灵活性

Swift 标准库提供了一些强大的泛用数据结构,例如 ArrayDictionary,它们可以用来构建多种不同的数据结构。Array 本身就可以方便地用来实现 Stack 和 Queue,只需要添加一些扩展方法。例如:

swift 复制代码
// 实现 Stack
struct Stack<T> {
    private var elements: [T] = []

    mutating func push(_ element: T) {
        elements.append(element)
    }

    mutating func pop() -> T? {
        return elements.popLast()
    }

    func peek() -> T? {
        return elements.last
    }

    var isEmpty: Bool {
        return elements.isEmpty
    }
}

// 实现 Queue
struct Queue<T> {
    private var elements: [T] = []

    mutating func enqueue(_ element: T) {
        elements.append(element)
    }

    mutating func dequeue() -> T? {
        return elements.isEmpty ? nil : elements.removeFirst()
    }

    func peek() -> T? {
        return elements.first
    }

    var isEmpty: Bool {
        return elements.isEmpty
    }
}

2. 避免标准库臃肿

Swift 的设计哲学之一是保持标准库的精简和高效。如果每种数据结构都在标准库中提供实现,会导致标准库变得非常庞大和复杂。相反,Swift 鼓励开发者根据具体需求自己实现或使用第三方库。

3. 泛型与扩展

Swift 的泛型和扩展机制使得开发者可以很方便地定义自己的数据结构。通过泛型,可以实现类型安全的 Stack 和 Queue,而不需要依赖标准库中的实现。

4. 社区与第三方库支持

Swift 社区中有很多高质量的第三方库提供了各种数据结构的实现,例如 Swift Algorithm Club 就包含了丰富的数据结构和算法的实现。这种模式让标准库保持精简的同时,也能满足开发者的多样化需求。

结论

虽然 Swift 标准库没有原生支持 Stack 和 Queue 数据结构,但通过利用 Swift 强大的泛型和扩展机制,开发者可以很容易地自己实现这些数据结构。再加上丰富的第三方库支持,开发者可以根据需要选择最适合自己的解决方案。

相关推荐
童真的烂漫6 分钟前
error: Sandbox: rsync.samba in Xcode project
ios
zengy536 分钟前
代码随想录打卡第十三天
数据结构·c++·算法·leetcode
孑渡2 小时前
【LeetCode】每日一题:跳跃游戏
python·算法·leetcode·游戏·职场和发展
liulanba2 小时前
leetcode--二叉树中的最长交错路径
linux·算法·leetcode
Puppet__2 小时前
【康复学习--LeetCode每日一题】3115. 质数的最大距离
学习·算法·leetcode
每天努力进步!3 小时前
LeetCode热题100刷题6:160. 相交链表、206. 反转链表、234. 回文链表、141. 环形链表、142. 环形链表 II
c++·算法·leetcode·链表
依旧风轻4 小时前
精确计算应用的冷启动耗时
ios·swift·cold start
JokerSZ.5 小时前
【Leetcode 每日一题】268. 丢失的数字
数据结构·算法·leetcode
muyierfly6 小时前
DAY19-力扣刷题
数据结构·算法·leetcode