LeetCode 刷题集 - 数组、链表、栈、队列(1)

数组:为什么很多编程语言中数组都从 0 开始编号?

链表:如何实现 LRU 缓存淘汰算法?

链表:如何轻松写出正确的链表代码?

跳表:为什么 Redis 一定要用跳表来实现有序集合?

栈:如何实现浏览器的前进和后退功能?

队列:队列在线程池等有限资源池中的应用

LeetCode题目:

Array:

1.移动零

func moveZeroes(_ nums: inout [Int]) {
        var j = 0
        for i in 0..

2.盛最多水的容器

func maxArea(_ height: [Int]) -> Int {
        // 2.双指针 移动短板方法
        var left = 0, right = height.count - 1, res = 0
        while left != right {
            let area = min(height[left], height[right]) * (right - left)
            res = max(area, res)
            if height[left] <= height[right] {
                left += 1
            } else {
                right -= 1
            }
        }
        return res
    }

3.爬楼梯

-Bottom-up DP

func climbStairs(_ n: Int) -> Int {
        if n == 1 {
            return 1
        }
        var first = 1, second = 1, res = 0
        for _ in 0..

-记忆化搜索(加缓存)

    var memDict: Dictionary = Dictionary()
    func climbStairs(_ n: Int) -> Int {
        if n == 1 {
            return 1
        }
        if n == 2 {
            return 2
        }
        //memoize
        guard (memDict[n] != nil) else {
            memDict[n] = climbStairs(n - 1) + climbStairs(n - 2)
            return memDict[n]!
        }
        return memDict[n]!
    }

4.三数之和

func threeSum(_ nums: [Int]) -> [[Int]] {
        //非暴力 内层双指针夹逼法
        if nums.count <= 2 {
            return []
        }
        let sortedArray = nums.sorted(by: <)
        var res: Array> = []
        for i in 0.. 0 && sortedArray[i] == sortedArray[i - 1] {
                continue
            }
            var j = i + 1
            var k = sortedArray.count - 1
            while j < k {
                if sortedArray[i] + sortedArray[j] + sortedArray[k] == 0 {
                    res.append([sortedArray[i], sortedArray[j], sortedArray[k]])
                    // 略过j指向的重复元素
                    while j < k && sortedArray[j] == sortedArray[j + 1] {
                        j += 1
                    }
                    j += 1
                } else if sortedArray[i] + sortedArray[j] + sortedArray[k] < 0 {
                    j += 1
                } else {
                    k -= 1
                }
            }
        }
        return res
    }

5.两数之和

func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
        var dict = Dictionary()
        for (index, value) in nums.enumerated() {
            if let value = dict[target - value] {
                // 有值 返回结果
                return [value, index]
            } else {
                // 没值 往字典里添
                dict.updateValue(index, forKey: value)
            }
        }
        return []
    }

6.删除排序数组中的重复项

func removeDuplicates(_ nums: inout [Int]) -> Int {
        var i = 0
        let originNumsCount = nums.count
        var deletedCount = 0
        while i < nums.count - 1 {
            if nums[i] == nums[i + 1] {
                nums.remove(at:i)
                deletedCount += 1
            } else {
                i += 1
            }
        }
        return originNumsCount - deletedCount
    }

7.旋转数组

-可以开一个新数组的情况下

func rotate(_ nums: inout [Int], _ k: Int) {
        var newArray = nums
        for (index, i) in nums.enumerated() {
            let newIndex = (index + k) % nums.count
            newArray[newIndex] = i
        }
        nums = newArray
    }

-不开新数组的情况下

    func rotate(_ nums: inout [Int], _ k: Int) {
        if k == 0 {
            return
        }
        for i in 0..

-欧几里得算法公式解法:

    // gcd(a, b) = gcd(b, a % b)
    func gcd(_ a: Int, _ b: Int) -> Int {
      let r = a % b
      if r != 0 {
        return gcd(b, r)
      } else {
        return b
      }
    }

8.合并两个有序数组

-去0拼接然后排序

    func merge(_ nums1: inout [Int], _ m: Int, _ nums2: [Int], _ n: Int) {
        if n == 0 {
            return
        }
        nums1.replaceSubrange((nums1.count - nums2.count)...(nums1.count - 1), with: nums2)
        nums1.sort(by: <)
    }

9.加一

func plusOne(_ digits: [Int]) -> [Int] {
            var mutableDigits = digits
            // 最后一位不是9
            if mutableDigits.last != 9 {
                var last = mutableDigits.removeLast()
                last += 1
                mutableDigits.append(last)
            } else {
                var j = mutableDigits.count - 1
                while mutableDigits[j] == 9 {
                    j -= 1
                    if j < 0 {
                        //全是9
                        return [1] + Array(repeating:0, count:mutableDigits.count)
                    }
                }
                // 到这说明不全是9 并且j指向的是第一个不为9的元素
                mutableDigits[j] += 1
                mutableDigits.replaceSubrange((j + 1)...mutableDigits.count - 1, with:Array(repeating: 0, count: mutableDigits.count - 1 - j))
            }
            return mutableDigits
        }

Linked List :

10.环形链表

func hasCycle(_ head: ListNode?) -> Bool {
                var preNode = head
                var nextNode = head?.next
                while nextNode?.next != nil {
                    preNode = preNode?.next
                    nextNode = nextNode?.next?.next
                    if preNode?.val == nextNode?.val {
                        return true
                    }
                }
                return false
    }

11.环形链表 II

     func detectCycle(_ head: ListNode?) -> ListNode? {
        var slowNode: ListNode? = head
        var fastNode: ListNode? = head
        while true {
            if fastNode == nil || fastNode?.next == nil {return nil}
            fastNode = fastNode?.next?.next
            slowNode = slowNode?.next
            if fastNode === slowNode {break}
        }
        fastNode = head
        while true {
            if fastNode === slowNode {return fastNode}
            fastNode = fastNode?.next
            slowNode = slowNode?.next
        }
    }

12.反转链表

func reverseList(_ head: ListNode?) -> ListNode? {
        var dummyNode: ListNode? = nil
        var currentNode = head
        while currentNode != nil {
            let nextNode = currentNode?.next
            currentNode?.next = dummyNode
            dummyNode = currentNode
            currentNode = nextNode
        }
        return dummyNode
    }

13.两两交换链表中的节点

    func swapPairs(_ head: ListNode?) -> ListNode? {
       let dummyNode = ListNode(0)
       var currentNode = dummyNode
       dummyNode.next = head
       while currentNode.next?.next != nil {
           let node1 = currentNode.next
           let node2 = currentNode.next?.next
           currentNode.next = node2
           node1?.next = node2?.next
           node2?.next = node1
           currentNode = node1!
       }
       return dummyNode.next
    }

14.K 个一组翻转链表

func reverseKGroup(_ head: ListNode?, _ k: Int) -> ListNode? {
        let dummyNode: ListNode? = ListNode(0)
        dummyNode?.next = head
        var preNode: ListNode? = dummyNode
        var endNode: ListNode? = dummyNode
        while endNode?.next != nil {
            for _ in 1...k {
                endNode = endNode?.next
            }
            if endNode == nil {break}
            let startNode = preNode?.next
            let nextNode = endNode?.next
            endNode?.next = nil
            preNode?.next = reverseList(startNode)
            startNode?.next = nextNode
            preNode = startNode
            endNode = startNode
        }
        return dummyNode?.next
    }
    func reverseList(_ head: ListNode?) -> ListNode? {
        var dummyNode: ListNode? = nil
        var currentNode = head
        while currentNode != nil {
            var nextNode = currentNode?.next
            currentNode?.next = dummyNode
            dummyNode = currentNode
            currentNode = nextNode
        }
        return dummyNode
    }

15.合并两个有序链表

     func mergeTwoLists(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
        var varL1 = l1
        var varL2 = l2
        let dummyNode: ListNode? = ListNode(0)
        var preNode = dummyNode
        while varL1 != nil && varL2 != nil {
            if varL1!.val <= varL2!.val {
                preNode?.next = varL1
                preNode = varL1
                varL1 = varL1?.next
            } else {
                preNode?.next = varL2
                preNode = varL2
                varL2 = varL2?.next
            }
        }
        if varL1 == nil {
            preNode?.next = varL2
        } else {
            preNode?.next = varL1
        }
        return dummyNode?.next
    }

-三指针,挪动大的,最后把j中剩下的按位置替换到nums1中的数据

    func merge(_ nums1: inout [Int], _ m: Int, _ nums2: [Int], _ n: Int) {
        if m == 0 {
            nums1 = nums2
            return
        } else if n == 0 {
            return
        }
        var i = m - 1, j = n - 1, k = m + n - 1
        while i >= 0 && j >= 0 {
            if nums2[j] >= nums1[i] {
                nums1[k] = nums2[j]
                k -= 1
                j -= 1
            } else {
                nums1[k] = nums1[i]
                k -= 1
                i -= 1
            }
        }
        nums1[..<(j + 1)] = nums2[..<(j + 1)]
    }
}

Stack

16.最小栈

class MinStack {
    var stack = Array()
    var minStack = Array()
    init() {}
    func push(_ x: Int) {
        stack.append(x)
        guard let min = minStack.last, min < x else {
            minStack.append(x)
            return
        }
    }
    func pop() {
        if stack.last == minStack.last {
            minStack.popLast()
        }
        stack.popLast()
    }
    func top() -> Int {
        return stack.last!
    }
    func getMin() -> Int {
        return minStack.last!
    }
}

17.有效的括号

    func isValid(_ s: String) -> Bool {
            let dict = ["(" : ")", "{" : "}", "[" : "]"]
            var stack = Array()
            for c in s {
                if c == "(" || c == "{" || c == "[" {
                    stack.append(String(c))
                } else {
                    // 右括号
                    guard let cur = stack.popLast() else {
                        return false
                    }
                    if dict[String(cur)] != String(c) {
                        return false
                    }
                }
            }
            return (stack.count != 0) ? false : true
        }

18.柱状图中最大的矩形

    func largestRectangleArea(_ heights: [Int]) -> Int {
        let len = heights.count
        if len == 0 {
            return 0
        }
        if len == 1 {
            return heights[0]
        }
        var area = 0
        let newHeights = [0] + heights + [0]
        var stack = Array()
        stack.append(0)
        for i in 1...newHeights.count - 1 {
            while (newHeights[stack.last!] > newHeights[i]) {
                let height = newHeights[stack.removeLast()]
                let width = i - stack.last! - 1
                area = max(area, width * height)
            }
            stack.append(i)
        }
        return area
    }

19.接雨水

class Solution {
    func trap(_ height: [Int]) -> Int {
        var stack = Array()
        var res = 0
        var currentIndex = 0
        while currentIndex < height.count {
            while !stack.isEmpty && height[currentIndex] > height[stack.last!] {
                let cancalculateIndex = stack.removeLast()
                if stack.isEmpty {
                    break
                }
                let width = currentIndex - stack.last! - 1
                let height = min(height[stack.last!], height[currentIndex]) - height[cancalculateIndex]
                res += width * height
            }
            stack.append(currentIndex)
            currentIndex += 1
        }
        return res
    }
}

Queue

20.设计循环双端队列

class MyCircularDeque {
    var circularQueue = Array()
    var capacity = 0
    /** Initialize your data structure here. Set the size of the deque to be k. */
    init(_ k: Int) {
        capacity = k
    }
    /** Adds an item at the front of Deque. Return true if the operation is successful. */
    func insertFront(_ value: Int) -> Bool {
        if isFull() {return false}
        circularQueue = [value] + circularQueue
        return true
    }
    /** Adds an item at the rear of Deque. Return true if the operation is successful. */
    func insertLast(_ value: Int) -> Bool {
        if isFull() {return false}
        circularQueue.append(value)
        return true
    }
    /** Deletes an item from the front of Deque. Return true if the operation is successful. */
    func deleteFront() -> Bool {
        if isEmpty() {return false}
        circularQueue.removeFirst()
        return true
    }
    /** Deletes an item from the rear of Deque. Return true if the operation is successful. */
    func deleteLast() -> Bool {
        if isEmpty() {return false}
        circularQueue.removeLast()
        return true
    }
    /** Get the front item from the deque. */
    func getFront() -> Int {
        guard let front = circularQueue.first else {
            return -1
        }
        return front
    }
    /** Get the last item from the deque. */
    func getRear() -> Int {
        guard let rear = circularQueue.last else {
            return -1
        }
        return rear
    }
    /** Checks whether the circular deque is empty or not. */
    func isEmpty() -> Bool {
        return circularQueue.count == 0 ? true : false
    }
    /** Checks whether the circular deque is full or not. */
    func isFull() -> Bool {
        return circularQueue.count == capacity ? true : false
    }
}
/**
 * Your MyCircularDeque object will be instantiated and called as such:
 * let obj = MyCircularDeque(k)
 * let ret_1: Bool = obj.insertFront(value)
 * let ret_2: Bool = obj.insertLast(value)
 * let ret_3: Bool = obj.deleteFront()
 * let ret_4: Bool = obj.deleteLast()
 * let ret_5: Int = obj.getFront()
 * let ret_6: Int = obj.getRear()
 * let ret_7: Bool = obj.isEmpty()
 * let ret_8: Bool = obj.isFull()
 */

21.滑动窗口最大值

class Solution {
    // 优先队列,超出时间限制了
    // func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] {
    //     if k == nums.count {
    //         return [nums.max()!]
    //     }
    //     var heap = Heap<(Int)>(array: Array(nums[0..)
    //     var ans = Array()
    //     ans.append(heap.peek()!)
    //     for i in 1...nums.count - k {
    //         heap.remove(at: heap.index(of: nums[i - 1])!)
    //         heap.insert(nums[i + k - 1])
    //         ans.append(heap.peek()!)
    //     }
    //     return ans
    // }
        func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] {
        var circularQueue = Array()
        var ans = Array()
        for i in 0..= nums[circularQueue.last!] {
                circularQueue.removeLast()
            }
            circularQueue.append(i)
        }
        ans.append(nums[circularQueue.first!])
        for i in k..= nums[circularQueue.last!] {
                circularQueue.removeLast()
            }
            circularQueue.append(i)
            // 弹出超界下标
            while circularQueue.count != 0 && (i - k) >= circularQueue.first! {
                circularQueue.removeFirst()
            }
            ans.append(nums[circularQueue.first!])
        }
       return ans
    }
}
 public struct Heap {
  /** The array that stores the heap's nodes. */
  var nodes = [T]()
  /**
   * Determines how to compare two nodes in the heap.
   * Use '>' for a max-heap or '<' for a min-heap,
   * or provide a comparing method if the heap is made
   * of custom elements, for example tuples.
   */
  private var orderCriteria: (T, T) -> Bool
  /**
   * Creates an empty heap.
   * The sort function determines whether this is a min-heap or max-heap.
   * For comparable data types, > makes a max-heap, < makes a min-heap.
   */
  public init(sort: @escaping (T, T) -> Bool) {
    self.orderCriteria = sort
  }
  /**
   * Creates a heap from an array. The order of the array does not matter;
   * the elements are inserted into the heap in the order determined by the
   * sort function. For comparable data types, '>' makes a max-heap,
   * '<' makes a min-heap.
   */
  public init(array: [T], sort: @escaping (T, T) -> Bool) {
    self.orderCriteria = sort
    configureHeap(from: array)
  }
  /**
   * Configures the max-heap or min-heap from an array, in a bottom-up manner.
   * Performance: This runs pretty much in O(n).
   */
  private mutating func configureHeap(from array: [T]) {
    nodes = array
    for i in stride(from: (nodes.count/2-1), through: 0, by: -1) {
      shiftDown(i)
    }
  }
  public var isEmpty: Bool {
    return nodes.isEmpty
  }
  public var count: Int {
    return nodes.count
  }
  /**
   * Returns the index of the parent of the element at index i.
   * The element at index 0 is the root of the tree and has no parent.
   */
  @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int {
    return (i - 1) / 2
  }
  /**
   * Returns the index of the left child of the element at index i.
   * Note that this index can be greater than the heap size, in which case
   * there is no left child.
   */
  @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int {
    return 2*i + 1
  }
  /**
   * Returns the index of the right child of the element at index i.
   * Note that this index can be greater than the heap size, in which case
   * there is no right child.
   */
  @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int {
    return 2*i + 2
  }
  /**
   * Returns the maximum value in the heap (for a max-heap) or the minimum
   * value (for a min-heap).
   */
  public func peek() -> T? {
    return nodes.first
  }
  /**
   * Adds a new value to the heap. This reorders the heap so that the max-heap
   * or min-heap property still holds. Performance: O(log n).
   */
  public mutating func insert(_ value: T) {
    nodes.append(value)
    shiftUp(nodes.count - 1)
  }
  /**
   * Adds a sequence of values to the heap. This reorders the heap so that
   * the max-heap or min-heap property still holds. Performance: O(log n).
   */
  public mutating func insert(_ sequence: S) where S.Iterator.Element == T {
    for value in sequence {
      insert(value)
    }
  }
  /**
   * Allows you to change an element. This reorders the heap so that
   * the max-heap or min-heap property still holds.
   */
  public mutating func replace(index i: Int, value: T) {
    guard i < nodes.count else { return }
    remove(at: i)
    insert(value)
  }
  /**
   * Removes the root node from the heap. For a max-heap, this is the maximum
   * value; for a min-heap it is the minimum value. Performance: O(log n).
   */
  @discardableResult public mutating func remove() -> T? {
    guard !nodes.isEmpty else { return nil }
    if nodes.count == 1 {
      return nodes.removeLast()
    } else {
      // Use the last node to replace the first one, then fix the heap by
      // shifting this new first node into its proper position.
      let value = nodes[0]
      nodes[0] = nodes.removeLast()
      shiftDown(0)
      return value
    }
  }
  /**
   * Removes an arbitrary node from the heap. Performance: O(log n).
   * Note that you need to know the node's index.
   */
  @discardableResult public mutating func remove(at index: Int) -> T? {
    guard index < nodes.count else { return nil }
    let size = nodes.count - 1
    if index != size {
      nodes.swapAt(index, size)
      shiftDown(from: index, until: size)
      shiftUp(index)
    }
    return nodes.removeLast()
  }
  /**
   * Takes a child node and looks at its parents; if a parent is not larger
   * (max-heap) or not smaller (min-heap) than the child, we exchange them.
   */
  internal mutating func shiftUp(_ index: Int) {
    var childIndex = index
    let child = nodes[childIndex]
    var parentIndex = self.parentIndex(ofIndex: childIndex)
    while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) {
      nodes[childIndex] = nodes[parentIndex]
      childIndex = parentIndex
      parentIndex = self.parentIndex(ofIndex: childIndex)
    }
    nodes[childIndex] = child
  }
  /**
   * Looks at a parent node and makes sure it is still larger (max-heap) or
   * smaller (min-heap) than its childeren.
   */
  internal mutating func shiftDown(from index: Int, until endIndex: Int) {
    let leftChildIndex = self.leftChildIndex(ofIndex: index)
    let rightChildIndex = leftChildIndex + 1
    // Figure out which comes first if we order them by the sort function:
    // the parent, the left child, or the right child. If the parent comes
    // first, we're done. If not, that element is out-of-place and we make
    // it "float down" the tree until the heap property is restored.
    var first = index
    if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) {
      first = leftChildIndex
    }
    if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) {
      first = rightChildIndex
    }
    if first == index { return }
    nodes.swapAt(index, first)
    shiftDown(from: first, until: endIndex)
  }
  internal mutating func shiftDown(_ index: Int) {
    shiftDown(from: index, until: nodes.count)
  }
}
extension Heap where T: Equatable {
  /** Get the index of a node in the heap. Performance: O(n). */
  public func index(of node: T) -> Int? {
    return nodes.index(where: { $0 == node })
  }
  /** Removes the first occurrence of a node from the heap. Performance: O(n). */
  @discardableResult public mutating func remove(node: T) -> T? {
    if let index = index(of: node) {
      return remove(at: index)
    }
    return nil
  }
}

你可能感兴趣的:(LeetCode 刷题集 - 数组、链表、栈、队列(1))