From c14c2297f1fa2db45fe5eda6e0661a669944c716 Mon Sep 17 00:00:00 2001 From: zhenzi Date: Sat, 17 Jul 2021 12:13:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BA=E6=95=B0=E7=BB=84=E7=AF=87=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Swift=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../数组篇/leetcode1052爱生气的书店老板.md | 42 ++++- .../leetcode1438绝对值不超过限制的最长子数组.md | 149 ++++++++++++++++++ .../数组篇/leetcode1两数之和.md | 43 +++++ .../数组篇/leetcode219数组中重复元素2.md | 51 ++++++ .../数组篇/leetcode27移除元素.md | 20 +++ .../数组篇/leetcode41缺失的第一个正数.md | 66 ++++++++ .../数组篇/leetcode485最大连续1的个数.md | 45 ++++++ .../数组篇/leetcode54螺旋矩阵.md | 35 ++++ .../数组篇/leetcode560和为K的子数组.md | 26 +++ .../数组篇/leetcode59螺旋矩阵2.md | 79 ++++++++++ animation-simulation/数组篇/leetcode66加一.md | 20 +++ .../数组篇/leetcode75颜色分类.md | 67 ++++++++ .../数组篇/剑指offer3数组中重复的数.md | 41 +++++ .../数组篇/长度最小的子数组.md | 19 +++ 14 files changed, 702 insertions(+), 1 deletion(-) diff --git a/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md b/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md index b9a94ad..79bef86 100644 --- a/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md +++ b/animation-simulation/数组篇/leetcode1052爱生气的书店老板.md @@ -114,5 +114,45 @@ class Solution: ans = max(ans, t) return ans ``` - +Swift Code + +```swift +class Solution { + func maxSatisfied(_ customers: [Int], _ grumpy: [Int], _ minutes: Int) -> Int { + let len = customers.count + var winSum = 0, rightSum = 0, leftSum = 0 + // 右区间的值 + for i in minutes.. Int { + var maxQueue:[Int] = [] + var minQueue:[Int] = [] + let len = nums.count + var right = 0, left = 0, maxWin = 0 + while right < len { + while !maxQueue.isEmpty && (maxQueue.last! < nums[right]) { + maxQueue.removeLast() + } + while !minQueue.isEmpty && (minQueue.last! > nums[right]) { + minQueue.removeLast() + } + maxQueue.append(nums[right]) + minQueue.append(nums[right]) + while (maxQueue.first! - minQueue.first!) > limit { + if maxQueue.first! == nums[left] { + maxQueue.removeFirst() + } + if minQueue.first! == nums[left] { + minQueue.removeFirst() + } + left += 1 + } + maxWin = max(maxWin, right - left + 1) + right += 1 + } + return maxWin + } +} +``` + +Swift:使用双端队列(击败了100.00%) + +```swift +class Solution { + func longestSubarray(_ nums: [Int], _ limit: Int) -> Int { + var maxQueue = Deque.init() + var minQueue = Deque.init() + let len = nums.count + var right = 0, left = 0, maxWin = 0 + while right < len { + while !maxQueue.isEmpty && (maxQueue.peekBack()! < nums[right]) { + maxQueue.dequeueBack() + } + while !minQueue.isEmpty && (minQueue.peekBack()! > nums[right]) { + minQueue.dequeueBack() + } + maxQueue.enqueue(nums[right]) + minQueue.enqueue(nums[right]) + while (maxQueue.peekFront()! - minQueue.peekFront()!) > limit { + if maxQueue.peekFront()! == nums[left] { + maxQueue.dequeue() + } + if minQueue.peekFront()! == nums[left] { + minQueue.dequeue() + } + left += 1 + } + maxWin = max(maxWin, right - left + 1) + right += 1 + } + return maxWin + } + + // 双端队列数据结构 + public struct Deque { + private var array: [T?] + private var head: Int + private var capacity: Int + private let originalCapacity: Int + + public init(_ capacity: Int = 10) { + self.capacity = max(capacity, 1) + originalCapacity = self.capacity + array = [T?](repeating: nil, count: capacity) + head = capacity + } + + public var isEmpty: Bool { + return count == 0 + } + + public var count: Int { + return array.count - head + } + + public mutating func enqueue(_ element: T) { + array.append(element) + } + + public mutating func enqueueFront(_ element: T) { + if head == 0 { + capacity *= 2 + let emptySpace = [T?](repeating: nil, count: capacity) + array.insert(contentsOf: emptySpace, at: 0) + head = capacity + } + + head -= 1 + array[head] = element + } + + public mutating func dequeue() -> T? { + guard head < array.count, let element = array[head] else { return nil } + + array[head] = nil + head += 1 + + if capacity >= originalCapacity && head >= capacity*2 { + let amountToRemove = capacity + capacity/2 + array.removeFirst(amountToRemove) + head -= amountToRemove + capacity /= 2 + } + return element + } + + public mutating func dequeueBack() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peekFront() -> T? { + if isEmpty { + return nil + } else { + return array[head] + } + } + + public func peekBack() -> T? { + if isEmpty { + return nil + } else { + return array.last! + } + } + } +} +``` + diff --git a/animation-simulation/数组篇/leetcode1两数之和.md b/animation-simulation/数组篇/leetcode1两数之和.md index 89db733..b226bc1 100644 --- a/animation-simulation/数组篇/leetcode1两数之和.md +++ b/animation-simulation/数组篇/leetcode1两数之和.md @@ -76,6 +76,32 @@ class Solution: return rearr ``` +Swift Code: + +```swift +class Solution { + func twoSum(_ nums: [Int], _ target: Int) -> [Int] { + let count = nums.count + if count < 2 { + return [0] + } + + var rearr: [Int] = [] + // 查询元素 + for i in 0.. [Int] { + var m:[Int:Int] = [:] + for i in 0.. Bool { + if nums.count == 0 { + return false + } + var dict:[Int:Int] = [:] + for i in 0.. Bool { + if nums.count == 0 { + return false + } + var set:Set = [] + for i in 0.. k { + set.remove(nums[i - k]) + } + } + return false + } +} +``` diff --git a/animation-simulation/数组篇/leetcode27移除元素.md b/animation-simulation/数组篇/leetcode27移除元素.md index db107bc..75a5f61 100644 --- a/animation-simulation/数组篇/leetcode27移除元素.md +++ b/animation-simulation/数组篇/leetcode27移除元素.md @@ -164,3 +164,23 @@ public: }; ``` +Swift Code + +```swift +class Solution { + func removeElement(_ nums: inout [Int], _ val: Int) -> Int { + if nums.count == 0 { + return 0 + } + var i = 0 + for j in 0.. Int { + if nums.count == 0 { + return 1 + } + // 因为是返回第一个正整数,不包括 0,所以需要长度加1,细节1 + var res:[Int] = Array.init(repeating: 0, count: nums.count + 1) + // 将数组元素添加到辅助数组中 + for x in nums { + if x > 0 && x < res.count { + res[x] = x + } + } + // 遍历查找,发现不一样时直接返回 + for i in 1.. Int { + var nums = nums + let len = nums.count + if len == 0 { + return 1 + } + // 遍历数组 + for i in 0.. 0 + && nums[i] < len + 1 + && nums[i] != i + 1 + && nums[i] != nums[nums[i] - 1] + { + //nums.swapAt(i, (nums[i] - 1)) // 系统方法 + self.swap(&nums, i, (nums[i] - 1)) // 自定义方法 + } + } + // 遍历寻找缺失的正整数 + for i in 0.. Int { + + var left = 0, right = 0, res = 0 + let len = nums.count + while right < len { + if nums[right] == 1 { + right += 1 + continue + } + // 保存最大值 + res = max(res, right - left) + // 跳过 0 的情况 + while right < len && nums[right] == 0 { + right += 1 + } + // 同一起点继续遍历 + left = right + } + return max(res, right - left) + } +} +``` 刚才的效率虽然相对高一些,但是代码不够优美,欢迎各位改进,下面我们说一下另外一种情况,一个特别容易理解的方法。 @@ -132,3 +158,22 @@ class Solution: return ans ``` +Swift Code + +```swift +class Solution { + func findMaxConsecutiveOnes(_ nums: [Int]) -> Int { + let len = nums.count + var maxCount = 0, count = 0 + for i in 0.. [Int] { + var arr:[Int] = [] + var left = 0, right = matrix[0].count - 1 + var top = 0, down = matrix.count - 1 + + while (true) { + for i in left...right { + arr.append(matrix[top][i]) + } + top += 1 + if top > down { break } + for i in top...down { + arr.append(matrix[i][right]) + } + right -= 1 + if left > right { break} + for i in stride(from: right, through: left, by: -1) { + arr.append(matrix[down][i]) + } + down -= 1 + if top > down { break} + for i in stride(from: down, through: top, by: -1) { + arr.append(matrix[i][left]) + } + left += 1 + if left > right { break} + } + + return arr + } +} +``` diff --git a/animation-simulation/数组篇/leetcode560和为K的子数组.md b/animation-simulation/数组篇/leetcode560和为K的子数组.md index 8e81e3e..6c4f372 100644 --- a/animation-simulation/数组篇/leetcode560和为K的子数组.md +++ b/animation-simulation/数组篇/leetcode560和为K的子数组.md @@ -45,6 +45,8 @@ class Solution { Python3版本的代码会超时 +Swift版本的代码会超时 + 下面我们我们使用前缀和的方法来解决这个题目,那么我们先来了解一下前缀和是什么东西。其实这个思想我们很早就接触过了。见下图 ![](https://cdn.jsdelivr.net/gh/tan45du/github.io.phonto2@master/myphoto/微信截图_20210113193831.4wk2b9zc8vm0.png) @@ -160,3 +162,27 @@ class Solution { } ``` +Swift Code + +```swift +class Solution { + func subarraySum(_ nums: [Int], _ k: Int) -> Int { + if nums.count == 0 { + return 0 + } + var map: [Int: Int] = [:] + map[0] = 1 // 需要添加入一个元素垫底,已支持前几位就满足的情况 + var presum = 0, count = 0 + + for x in nums { + presum += x + //当前前缀和已知,判断是否含有 presum - k的前缀和,那么我们就知道某一区间的和为 k 了。 + if let v = map[presum - k] { + count += v //获取presum-k前缀和出现次数 + } + map[presum] = (map[presum] ?? 0) + 1 + } + return count + } +} +``` diff --git a/animation-simulation/数组篇/leetcode59螺旋矩阵2.md b/animation-simulation/数组篇/leetcode59螺旋矩阵2.md index 50cf94c..42a1f0f 100644 --- a/animation-simulation/数组篇/leetcode59螺旋矩阵2.md +++ b/animation-simulation/数组篇/leetcode59螺旋矩阵2.md @@ -140,6 +140,43 @@ class Solution: return arr ``` +Swift Code: + +```swift +class Solution { + func spiralOrder(_ matrix: [[Int]]) -> [Int] { + var arr:[Int] = [] + var left = 0, right = matrix[0].count - 1 + var top = 0, down = matrix.count - 1 + + while (true) { + for i in left...right { + arr.append(matrix[top][i]) + } + top += 1 + if top > down { break } + for i in top...down { + arr.append(matrix[i][right]) + } + right -= 1 + if left > right { break} + for i in stride(from: right, through: left, by: -1) { + arr.append(matrix[down][i]) + } + down -= 1 + if top > down { break} + for i in stride(from: down, through: top, by: -1) { + arr.append(matrix[i][left]) + } + left += 1 + if left > right { break} + } + + return arr + } +} +``` + 我们仅仅是将 54 反过来了,往螺旋矩阵里面插值,下面我们直接看代码吧,大家可以也可以对其改进,大家可以思考一下,如果修改能够让代码更简洁! Java Code: @@ -226,3 +263,45 @@ class Solution: return arr.tolist() ``` +Swift Code: + +```swift +class Solution { + func generateMatrix(_ n: Int) -> [[Int]] { + var arr:[[Int]] = Array.init(repeating: Array.init(repeating: 0, count: n), count: n) + var left = 0, right = n - 1 + var top = 0, bottom = n - 1 + var num = 1, numSize = n * n + + while true { + for i in left...right { + arr[top][i] = num + num += 1 + } + top += 1 + if num > numSize { break} + for i in top...bottom { + arr[i][right] = num + num += 1 + } + right -= 1 + if num > numSize { break} + for i in stride(from: right, through: left, by: -1) { + arr[bottom][i] = num + num += 1 + } + bottom -= 1 + if num > numSize { break} + for i in stride(from: bottom, through: top, by: -1) { + arr[i][left] = num + num += 1 + } + left += 1 + if num > numSize { break} + } + + return arr + } +} +``` + diff --git a/animation-simulation/数组篇/leetcode66加一.md b/animation-simulation/数组篇/leetcode66加一.md index 3030fee..f3daa00 100644 --- a/animation-simulation/数组篇/leetcode66加一.md +++ b/animation-simulation/数组篇/leetcode66加一.md @@ -85,3 +85,23 @@ class Solution: arr[0] = 1 return arr ``` + +Swift Code: + +```swift +class Solution { + func plusOne(_ digits: [Int]) -> [Int] { + let count = digits.count + var digits = digits + for i in stride(from: count - 1, through: 0, by: -1) { + digits[i] = (digits[i] + 1) % 10 + if digits[i] != 0 { + return digits + } + } + var arr: [Int] = Array.init(repeating: 0, count: count + 1) + arr[0] = 1 + return arr + } +} +``` diff --git a/animation-simulation/数组篇/leetcode75颜色分类.md b/animation-simulation/数组篇/leetcode75颜色分类.md index 7f125f1..cc16ed0 100644 --- a/animation-simulation/数组篇/leetcode75颜色分类.md +++ b/animation-simulation/数组篇/leetcode75颜色分类.md @@ -96,6 +96,38 @@ class Solution: nums[j] = temp ``` +Swift Code: + +```swift +class Solution { + func sortColors(_ nums: inout [Int]) { + + let count = nums.count + var left = 0, i = left, right = count - 1 + while i <= right { + if nums[i] == 2 { + //nums.swapAt(i, right) 直接调用系统方法 + self.swap(&nums, i, right) // 保持风格统一走自定义交换 + right -= 1 + } else if nums[i] == 0 { + //nums.swapAt(i, left) 直接调用系统方法 + self.swap(&nums, i, left) // 保持风格统一走自定义交换 + i += 1 + left += 1 + } else { + i += 1 + } + } + } + + func swap(_ nums: inout [Int], _ i: Int, _ j: Int) { + let temp = nums[i] + nums[i] = nums[j] + nums[j] = temp + } +} +``` + 另外我们看这段代码,有什么问题呢?那就是我们即使完全符合时,仍会交换元素,这样会大大降低我们的效率。 例如:[0,0,0,1,1,1,2,2,2] @@ -174,4 +206,39 @@ class Solution: temp = nums[i] nums[i] = nums[j] nums[j] = temp +``` + +Swift Code: + +```swift +class Solution { + func sortColors(_ nums: inout [Int]) { + + let count = nums.count + var left = 0, i = left, right = count - 1 + while i <= right { + if nums[i] == 0 { + //nums.swapAt(i, left) 直接调用系统方法 + self.swap(&nums, i, left) // 保持风格统一走自定义交换 + left += 1 + } + if nums[i] == 2 { + //nums.swapAt(i, right) 直接调用系统方法 + self.swap(&nums, i, right) // 保持风格统一走自定义交换 + right -= 1 + //如果不等于 1 则需要继续判断,所以不移动 i 指针,i-- + if nums[i] != 1 { + i -= 1 + } + } + i += 1 + } + } + + func swap(_ nums: inout [Int], _ i: Int, _ j: Int) { + let temp = nums[i] + nums[i] = nums[j] + nums[j] = temp + } +} ``` \ No newline at end of file diff --git a/animation-simulation/数组篇/剑指offer3数组中重复的数.md b/animation-simulation/数组篇/剑指offer3数组中重复的数.md index 9d09871..82c541f 100644 --- a/animation-simulation/数组篇/剑指offer3数组中重复的数.md +++ b/animation-simulation/数组篇/剑指offer3数组中重复的数.md @@ -61,6 +61,24 @@ class Solution: return -1 ``` +Swift Code: + +```swift +class Solution { + func findRepeatNumber(_ nums: [Int]) -> Int { + var set: Set = [] + for n in nums { + if set.contains(n) { // 如果发现某元素存在,则返回 + return n + } + set.insert(n) // 存入集合 + } + + return -1 + } +} +``` + #### **原地置换** **解析** @@ -136,3 +154,26 @@ class Solution: nums[temp] = temp return -1 ``` + +Swift Code: + +```swift +class Solution { + func findRepeatNumber(_ nums: [Int]) -> Int { + if nums.isEmpty { + return -1 + } + var nums = nums; + for i in 0.. Int { + + var sum = 0, windowlen = Int.max, i = 0 + for j in 0..= target { + windowlen = min(windowlen, j - i + 1) + sum -= nums[i] + i += 1 + } + } + return windowlen == Int.max ? 0 : windowlen + } +} +``` \ No newline at end of file