mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-12-26 20:36:18 +00:00
Merge branch 'chefyuan:main' into main
This commit is contained in:
commit
bf547801e9
@ -102,3 +102,34 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func inorderTraversal(_ root: TreeNode?) -> [Int] {
|
||||
var list:[Int] = []
|
||||
guard root != nil else {
|
||||
return list
|
||||
}
|
||||
var p1 = root, p2: TreeNode?
|
||||
while p1 != nil {
|
||||
p2 = p1!.left
|
||||
if p2 != nil {
|
||||
while p2!.right != nil && p2!.right !== p1 {
|
||||
p2 = p2!.right
|
||||
}
|
||||
if p2!.right == nil {
|
||||
p2!.right = p1
|
||||
p1 = p1!.left
|
||||
continue
|
||||
} else {
|
||||
p2!.right = nil
|
||||
}
|
||||
}
|
||||
list.append(p1!.val)
|
||||
p1 = p1!.right
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -51,5 +51,32 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func inorderTraversal(_ root: TreeNode?) -> [Int] {
|
||||
var arr:[Int] = []
|
||||
var cur = root
|
||||
var stack:[TreeNode] = []
|
||||
|
||||
while !stack.isEmpty || cur != nil {
|
||||
//找到当前应该遍历的那个节点
|
||||
while cur != nil {
|
||||
stack.append(cur!)
|
||||
cur = cur!.left
|
||||
}
|
||||
//此时指针指向空,也就是没有左子节点,则开始执行出栈操作
|
||||
if let temp = stack.popLast() {
|
||||
arr.append(temp.val)
|
||||
//指向右子节点
|
||||
cur = temp.right
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
###
|
||||
|
||||
|
@ -406,6 +406,42 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func levelOrder(_ root: TreeNode?) -> [[Int]] {
|
||||
var res:[[Int]] = []
|
||||
guard root != nil else {
|
||||
return res
|
||||
}
|
||||
var queue:[TreeNode?] = []
|
||||
queue.append(root!)
|
||||
|
||||
while !queue.isEmpty {
|
||||
let size = queue.count
|
||||
var list:[Int] = []
|
||||
|
||||
for i in 0..<size {
|
||||
guard let node = queue.removeFirst() else {
|
||||
continue
|
||||
}
|
||||
if node.left != nil {
|
||||
queue.append(node.left)
|
||||
}
|
||||
if node.right != nil {
|
||||
queue.append(node.right);
|
||||
}
|
||||
list.append(node.val)
|
||||
}
|
||||
res.append(list)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
时间复杂度:O(n) 空间复杂度:O(n)
|
||||
|
||||
大家如果吃透了二叉树的层序遍历的话,可以顺手把下面几道题目解决掉,思路一致,甚至都不用拐弯
|
||||
|
@ -103,4 +103,41 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func preorderTraversal(_ root: TreeNode?) -> [Int] {
|
||||
var list:[Int] = []
|
||||
guard root != nil else {
|
||||
return list
|
||||
}
|
||||
var p1 = root, p2: TreeNode?
|
||||
while p1 != nil {
|
||||
p2 = p1!.left
|
||||
if p2 != nil {
|
||||
//找到左子树的最右叶子节点
|
||||
while p2!.right != nil && p2!.right !== p1 {
|
||||
p2 = p2!.right
|
||||
}
|
||||
//添加 right 指针,对应 right 指针为 null 的情况
|
||||
if p2!.right == nil {
|
||||
list.append(p1!.val)
|
||||
p2!.right = p1
|
||||
p1 = p1!.left
|
||||
continue
|
||||
}
|
||||
//对应 right 指针存在的情况,则去掉 right 指针
|
||||
p2!.right = nil
|
||||
} else {
|
||||
list.append(p1!.val)
|
||||
}
|
||||
//移动 p1
|
||||
p1 = p1!.right
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
好啦,今天就看到这里吧,咱们下期见!
|
@ -67,3 +67,32 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
|
||||
func preorderTraversal(_ root: TreeNode?) -> [Int] {
|
||||
var list:[Int] = []
|
||||
var stack:[TreeNode] = []
|
||||
|
||||
guard root != nil else {
|
||||
return list
|
||||
}
|
||||
stack.append(root!)
|
||||
while !stack.isEmpty {
|
||||
let temp = stack.popLast()
|
||||
if let right = temp?.right {
|
||||
stack.append(right)
|
||||
}
|
||||
if let left = temp?.left {
|
||||
stack.append(left)
|
||||
}
|
||||
//这里也可以放到前面
|
||||
list.append((temp?.val)!)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -71,6 +71,39 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func postorderTraversal(_ root: TreeNode?) -> [Int] {
|
||||
var list:[Int] = []
|
||||
var stack:[TreeNode] = []
|
||||
var cur = root, preNode: TreeNode?
|
||||
while !stack.isEmpty || cur != nil {
|
||||
//和之前写的中序一致
|
||||
while cur != nil {
|
||||
stack.append(cur!)
|
||||
cur = cur!.left
|
||||
}
|
||||
//1.出栈,可以想一下,这一步的原因。
|
||||
cur = stack.popLast()
|
||||
//2.if 里的判断语句有什么含义?
|
||||
if cur!.right === nil || cur!.right === preNode {
|
||||
list.append(cur!.val)
|
||||
//更新下 preNode,也就是定位住上一个访问节点。
|
||||
preNode = cur
|
||||
cur = nil
|
||||
} else {
|
||||
//3.再次压入栈,和上面那条 1 的关系?
|
||||
stack.append(cur!)
|
||||
cur = cur!.right
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当然也可以修改下代码逻辑将 `cur = stack.pop()` 改成 `cur = stack.peek()`,下面再修改一两行代码也可以实现,这里这样写是方便动画模拟,大家可以随意发挥。
|
||||
|
||||
时间复杂度 O(n), 空间复杂度O(n)
|
||||
|
@ -116,6 +116,62 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
var list:[Int] = []
|
||||
func postorderTraversal(_ root: TreeNode?) -> [Int] {
|
||||
guard root != nil else {
|
||||
return list
|
||||
}
|
||||
var p1 = root, p2: TreeNode?
|
||||
while p1 != nil {
|
||||
p2 = p1!.left
|
||||
if p2 != nil {
|
||||
while p2!.right != nil && p2!.right !== p1 {
|
||||
p2 = p2!.right
|
||||
}
|
||||
if p2!.right == nil {
|
||||
p2!.right = p1
|
||||
p1 = p1!.left
|
||||
continue
|
||||
} else {
|
||||
p2!.right = nil
|
||||
postMorris(p1!.left)
|
||||
}
|
||||
}
|
||||
p1 = p1!.right
|
||||
}
|
||||
//以根节点为起点的链表
|
||||
postMorris(root!)
|
||||
return list
|
||||
}
|
||||
|
||||
func postMorris(_ root: TreeNode?) {
|
||||
let reverseNode = reverseList(root)
|
||||
//从后往前遍历
|
||||
var cur = reverseNode
|
||||
while cur != nil {
|
||||
list.append(cur!.val)
|
||||
cur = cur!.right
|
||||
}
|
||||
reverseList(reverseNode)
|
||||
}
|
||||
|
||||
func reverseList(_ head: TreeNode?) -> TreeNode? {
|
||||
var cur = head, pre: TreeNode?
|
||||
while cur != nil {
|
||||
let next = cur?.right
|
||||
cur?.right = pre
|
||||
pre = cur
|
||||
cur = next
|
||||
}
|
||||
return pre
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
时间复杂度 O(n)空间复杂度 O(1)
|
||||
|
||||
总结:后序遍历比起前序和中序稍微复杂了一些,所以我们解题的时候,需要好好注意一下,迭代法的核心是利用一个指针来定位我们上一个遍历的节点,Morris 的核心是,将某节点的右子节点,看成是一条链表,进行反向遍历。
|
||||
|
@ -200,6 +200,31 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func countDigitOne(_ n: Int) -> Int {
|
||||
var high = n, low = 0, cur = 0, count = 0, num = 1
|
||||
while high != 0 || cur != 0 {
|
||||
cur = high % 10
|
||||
high /= 10
|
||||
//这里我们可以提出 high * num 因为我们发现无论为几,都含有它
|
||||
if cur == 0 {
|
||||
count += high * num
|
||||
} else if cur == 1 {
|
||||
count += high * num + 1 + low
|
||||
} else {
|
||||
count += (high + 1) * num
|
||||
}
|
||||
low = cur * num + low
|
||||
num *= 10
|
||||
}
|
||||
return count
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
时间复杂度 : O(logn) 空间复杂度 O(1)
|
||||
|
||||
|
||||
|
@ -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..<len {
|
||||
if grumpy[i] == 0 {
|
||||
rightSum += customers[i]
|
||||
}
|
||||
}
|
||||
// 窗口的值
|
||||
for i in 0..<minutes {
|
||||
winSum += customers[i]
|
||||
}
|
||||
var maxCustomer = winSum + leftSum + rightSum
|
||||
// 窗口左边缘
|
||||
var left = 1, right = minutes
|
||||
while right < len {
|
||||
// 重新计算左区间的值,也可以用 customer 值和 grumpy 值相乘获得
|
||||
if grumpy[left - 1] == 0 {
|
||||
leftSum += customers[left - 1]
|
||||
}
|
||||
// 重新计算右区间值
|
||||
if grumpy[right] == 0 {
|
||||
rightSum -= customers[right]
|
||||
}
|
||||
// 窗口值
|
||||
winSum = winSum - customers[left - 1] + customers[right]
|
||||
maxCustomer = max(maxCustomer, winSum + leftSum + rightSum) // 保留最大值
|
||||
// 移动窗口
|
||||
left += 1
|
||||
right += 1
|
||||
}
|
||||
|
||||
return maxCustomer
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -111,3 +111,152 @@ class Solution:
|
||||
return maxwin
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
Swift:数组模拟,超时(58 / 61 个通过测试用例)
|
||||
```swift
|
||||
class Solution {
|
||||
func longestSubarray(_ nums: [Int], _ limit: Int) -> 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<Int>.init()
|
||||
var minQueue = Deque<Int>.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<T> {
|
||||
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!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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..<count {
|
||||
for j in i+1..<count {
|
||||
// 发现符合条件情况
|
||||
if nums[i] + nums[j] == target {
|
||||
rearr.append(i)
|
||||
rearr.append(j)
|
||||
}
|
||||
}
|
||||
}
|
||||
return rearr
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**哈希表**
|
||||
|
||||
**解析**
|
||||
@ -159,3 +185,20 @@ class Solution:
|
||||
return [0]
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
|
||||
var m:[Int:Int] = [:]
|
||||
for i in 0..<nums.count {
|
||||
let n = nums[i]
|
||||
if let k = m[target - n] { // 如果存在则返回
|
||||
return [k, i]
|
||||
}
|
||||
m[n] = i // 不存在则存入
|
||||
}
|
||||
return [0]
|
||||
}
|
||||
}
|
||||
```
|
@ -94,6 +94,32 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func containsNearbyDuplicate(_ nums: [Int], _ k: Int) -> Bool {
|
||||
if nums.count == 0 {
|
||||
return false
|
||||
}
|
||||
var dict:[Int:Int] = [:]
|
||||
for i in 0..<nums.count {
|
||||
// 如果含有
|
||||
if let v = dict[nums[i]] {
|
||||
// 判断是否小于K,如果小于等于则直接返回
|
||||
let abs = abs(i - v)
|
||||
if abs <= k {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// 更新索引,此时有两种情况,不存在,或者存在时,将后出现的索引保存
|
||||
dict[nums[i]] = i
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**HashSet**
|
||||
|
||||
**解析**
|
||||
@ -174,3 +200,27 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func containsNearbyDuplicate(_ nums: [Int], _ k: Int) -> Bool {
|
||||
if nums.count == 0 {
|
||||
return false
|
||||
}
|
||||
var set:Set<Int> = []
|
||||
for i in 0..<nums.count {
|
||||
// 含有该元素,返回true
|
||||
if set.contains(nums[i]) {
|
||||
return true
|
||||
}
|
||||
// 添加新元素
|
||||
set.insert(nums[i])
|
||||
if set.count > k {
|
||||
set.remove(nums[i - k])
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
```
|
@ -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..<nums.count {
|
||||
if nums[j] != val {
|
||||
nums[i] = nums[j]
|
||||
i += 1
|
||||
}
|
||||
|
||||
}
|
||||
return i
|
||||
}
|
||||
}
|
||||
```
|
@ -89,6 +89,33 @@ class Solution:
|
||||
return len(res)
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func firstMissingPositive(_ nums: [Int]) -> 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..<res.count {
|
||||
if res[i] != i {
|
||||
return i
|
||||
}
|
||||
}
|
||||
// 缺少最后一个,例如 1,2,3此时缺少 4 ,细节2
|
||||
return res.count
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
我们通过上面的例子了解这个解题思想,我们有没有办法不使用辅助数组完成呢?我们可以使用原地置换,直接在 nums 数组内,将值换到对应的索引处,与上个方法思路一致,只不过没有使用辅助数组,理解起来也稍微难理解一些。
|
||||
|
||||
@ -166,3 +193,42 @@ class Solution:
|
||||
return n + 1
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func firstMissingPositive(_ nums: [Int]) -> Int {
|
||||
var nums = nums
|
||||
let len = nums.count
|
||||
if len == 0 {
|
||||
return 1
|
||||
}
|
||||
// 遍历数组
|
||||
for i in 0..<len {
|
||||
// 需要考虑指针移动情况,大于0,小于len+1,不等与i+1,
|
||||
// 两个交换的数相等时,防止死循环
|
||||
while nums[i] > 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..<len {
|
||||
if nums[i] != i + 1 {
|
||||
return i + 1
|
||||
}
|
||||
}
|
||||
|
||||
return len + 1
|
||||
}
|
||||
func swap(_ nums: inout [Int], _ i: Int, _ j: Int) {
|
||||
let temp = nums[i]
|
||||
nums[i] = nums[j]
|
||||
nums[j] = temp
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -84,6 +84,32 @@ class Solution:
|
||||
return max(maxcount, right - left)
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func findMaxConsecutiveOnes(_ nums: [Int]) -> 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..<len {
|
||||
if nums[i] == 1 {
|
||||
count += 1
|
||||
} else { // 这里可以改成 while
|
||||
maxCount = max(maxCount, count)
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
return max(maxCount, count)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -156,5 +156,40 @@ 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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -176,6 +176,43 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
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:
|
||||
@ -298,3 +335,44 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -103,3 +103,23 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -117,6 +117,38 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
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]
|
||||
@ -220,3 +252,37 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
```
|
@ -61,6 +61,24 @@ class Solution:
|
||||
return -1
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func findRepeatNumber(_ nums: [Int]) -> Int {
|
||||
var set: Set<Int> = []
|
||||
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..<nums.count {
|
||||
while nums[i] != i {
|
||||
if nums[i] == nums[nums[i]] {
|
||||
return nums[i]
|
||||
}
|
||||
nums.swapAt(i, nums[i])
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
}
|
||||
```
|
@ -106,3 +106,22 @@ class Solution:
|
||||
return windowlen
|
||||
```
|
||||
|
||||
Swift Code
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
|
||||
|
||||
var sum = 0, windowlen = Int.max, i = 0
|
||||
for j in 0..<nums.count {
|
||||
sum += nums[j]
|
||||
while sum >= target {
|
||||
windowlen = min(windowlen, j - i + 1)
|
||||
sum -= nums[i]
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
return windowlen == Int.max ? 0 : windowlen
|
||||
}
|
||||
}
|
||||
```
|
@ -145,6 +145,35 @@ class Solution:
|
||||
return True
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func isPalindrome(_ head: ListNode?) -> Bool {
|
||||
// 这里需要用动态数组,因为我们不知道链表的长度
|
||||
var arr:[Int?] = []
|
||||
var copynode = head
|
||||
// 将链表的值复制到数组中
|
||||
while copynode != nil {
|
||||
arr.append(copynode?.val)
|
||||
copynode = copynode?.next
|
||||
}
|
||||
// 双指针遍历数组
|
||||
var back = 0, pro = arr.count - 1
|
||||
while back < pro {
|
||||
// 判断两个指针的值是否相等
|
||||
if arr[pro] != arr[back] {
|
||||
return false
|
||||
}
|
||||
// 移动指针
|
||||
back += 1
|
||||
pro -= 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这个方法可以直接通过,但是这个方法需要辅助数组,那我们还有其他更好的方法吗?
|
||||
|
||||
**双指针翻转链表法**
|
||||
@ -375,3 +404,57 @@ class Solution:
|
||||
return low
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func isPalindrome(_ head: ListNode?) -> Bool {
|
||||
if head == nil || head?.next == nil {
|
||||
return true
|
||||
}
|
||||
//找到中间节点,也就是翻转的头节点,这个在昨天的题目中讲到
|
||||
//但是今天和昨天有一些不一样的地方就是,如果有两个中间节点返回第一个,昨天的题目是第二个
|
||||
var midnode = searchmidnode(head)
|
||||
//原地翻转链表,需要两个辅助指针。这个也是面试题目,大家可以做一下
|
||||
//这里我们用的是midnode.next需要注意,因为我们找到的是中点,但是我们翻转的是后半部分
|
||||
var backhalf = reverse(midnode?.next);
|
||||
//遍历两部分链表,判断值是否相等
|
||||
var p1 = head
|
||||
var p2 = backhalf
|
||||
while p2 != nil {
|
||||
if p1?.val != p2?.val {
|
||||
midnode?.next = reverse(backhalf)
|
||||
return false
|
||||
}
|
||||
p1 = p1?.next
|
||||
p2 = p2?.next
|
||||
}
|
||||
//还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文,
|
||||
//当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。
|
||||
midnode?.next = reverse(backhalf)
|
||||
return true
|
||||
}
|
||||
//找到中点
|
||||
func searchmidnode(_ head: ListNode?) -> ListNode? {
|
||||
var fast = head, slow = head
|
||||
while fast?.next != nil && fast?.next?.next != nil {
|
||||
fast = fast?.next?.next
|
||||
slow = slow?.next
|
||||
}
|
||||
return slow
|
||||
}
|
||||
//翻转链表
|
||||
func reverse(_ slow: ListNode?) -> ListNode? {
|
||||
var slow = slow
|
||||
var low: ListNode?
|
||||
var temp: ListNode?
|
||||
while slow != nil {
|
||||
temp = slow?.next
|
||||
slow?.next = low
|
||||
low = slow
|
||||
slow = temp
|
||||
}
|
||||
return low
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -108,3 +108,20 @@ class Solution:
|
||||
return False
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func hasCycle(_ head: ListNode?) -> Bool {
|
||||
var fast = head, slow = head
|
||||
while fast != nil && fast?.next != nil {
|
||||
fast = fast?.next?.next
|
||||
slow = slow?.next
|
||||
if fast === slow {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -132,8 +132,6 @@ class Solution:
|
||||
return head
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 快慢指针
|
||||
|
||||
这个方法是比较巧妙的方法,但是不容易想到,也不太容易理解,利用快慢指针判断是否有环很容易,但是判断环的入口就没有那么容易,之前说过快慢指针肯定会在环内相遇,见下图。
|
||||
@ -275,3 +273,29 @@ class Solution:
|
||||
return slow
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func detectCycle(_ head: ListNode?) -> ListNode? {
|
||||
// 快慢指针
|
||||
var fast = head, slow = head
|
||||
while fast != nil && fast?.next != nil {
|
||||
fast = fast?.next?.next
|
||||
slow = slow?.next
|
||||
// 相遇
|
||||
if fast === slow {
|
||||
// 设置一个新的指针,从头节点出发,慢指针速度为1,所以可以使用慢指针从相遇点出发
|
||||
// 此处也可以不创新结点,直接将 fast = head
|
||||
var newNode = head
|
||||
while newNode !== slow {
|
||||
slow = slow?.next
|
||||
newNode = newNode?.next
|
||||
}
|
||||
return slow
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
```
|
@ -225,5 +225,41 @@ class Solution:
|
||||
return dummyNode.next
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func insertionSortList(_ head: ListNode?) -> ListNode? {
|
||||
if head == nil && head?.next == nil {
|
||||
return head
|
||||
}
|
||||
//哑节点
|
||||
var dummyNode = ListNode(-1)
|
||||
dummyNode.next = head
|
||||
//pre负责指向新元素,last 负责指向新元素的前一元素
|
||||
//判断是否需要执行插入操作
|
||||
var pre = head?.next
|
||||
var last = head
|
||||
while pre != nil {
|
||||
//不需要插入到合适位置,则继续往下移动
|
||||
if last!.val <= pre!.val {
|
||||
pre = pre?.next
|
||||
last = last?.next
|
||||
continue
|
||||
}
|
||||
//开始出发,查找新元素的合适位置
|
||||
var temphead = dummyNode
|
||||
while temphead.next!.val <= pre!.val {
|
||||
temphead = temphead.next!
|
||||
}
|
||||
//此时我们已经找到了合适位置,我们需要进行插入,大家可以画一画
|
||||
last?.next = pre?.next
|
||||
pre?.next = temphead.next
|
||||
temphead.next = pre
|
||||
//继续往下移动
|
||||
pre = last?.next
|
||||
}
|
||||
return dummyNode.next
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -138,6 +138,32 @@ class Solution:
|
||||
return low
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func reverseList(_ head: ListNode?) -> ListNode? {
|
||||
// 边界条件
|
||||
if head == nil || head?.next == nil {
|
||||
return head
|
||||
}
|
||||
var pro = head
|
||||
var low: ListNode?
|
||||
while pro != nil {
|
||||
// 代表橙色指针
|
||||
var temp = pro
|
||||
// 移动绿色指针
|
||||
pro = pro?.next
|
||||
// 反转节点
|
||||
temp?.next = low
|
||||
// 移动黄色指针
|
||||
low = temp
|
||||
}
|
||||
return low
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面的迭代写法是不是搞懂啦,现在还有一种递归写法,不是特别容易理解,刚开始刷题的同学,可以只看迭代解法。
|
||||
|
||||
|
||||
@ -227,6 +253,25 @@ class Solution:
|
||||
return pro
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func reverseList(_ head: ListNode?) -> ListNode? {
|
||||
// 结束条件
|
||||
if head == nil || head?.next == nil {
|
||||
return head
|
||||
}
|
||||
var pro = reverseList(head?.next)
|
||||
// 将节点进行反转
|
||||
head?.next?.next = head
|
||||
// 防止循环
|
||||
head?.next = nil
|
||||
return pro
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
> 贡献者[@jaredliw](https://github.com/jaredliw)注:
|
||||
|
@ -128,3 +128,27 @@ class Solution:
|
||||
return head
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func oddEvenList(_ head: ListNode?) -> ListNode? {
|
||||
if head == nil || head?.next == nil {
|
||||
return head
|
||||
}
|
||||
var odd = head
|
||||
var even = head?.next
|
||||
var evenHead = even
|
||||
while odd?.next != nil && even?.next != nil {
|
||||
//将偶数位合在一起,奇数位合在一起
|
||||
odd?.next = even?.next
|
||||
odd = odd?.next
|
||||
even?.next = odd?.next
|
||||
even = even?.next
|
||||
}
|
||||
//链接
|
||||
odd?.next = evenHead
|
||||
return head
|
||||
}
|
||||
}
|
||||
```
|
@ -165,3 +165,34 @@ class Solution:
|
||||
return dummy.next # 注意,这里传回的不是head,而是虚拟节点的下一个节点,head有可能已经换了
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func deleteDuplicates(_ head: ListNode?) -> ListNode? {
|
||||
// 侦察兵指针
|
||||
var pre = head
|
||||
// 创建哑节点,接上head
|
||||
var dummy = ListNode(-1)
|
||||
dummy.next = head
|
||||
// 跟随的指针
|
||||
var low:ListNode? = dummy
|
||||
while pre != nil && pre?.next != nil {
|
||||
if pre?.val == pre?.next?.val {
|
||||
// 移动侦察兵指针直到找到与上一个不相同的元素
|
||||
while pre != nil && pre?.next != nil && pre?.val == pre?.next?.val {
|
||||
pre = pre?.next
|
||||
}
|
||||
// while循环后,pre停留在最后一个重复的节点上
|
||||
pre = pre?.next
|
||||
// 连上新节点
|
||||
low?.next = pre
|
||||
} else {
|
||||
pre = pre?.next
|
||||
low = low?.next
|
||||
}
|
||||
}
|
||||
return dummy.next // 注意,这里传回的不是head,而是虚拟节点的下一个节点,head有可能已经换了
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -157,3 +157,34 @@ class Solution:
|
||||
return headsmall.next
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func partition(_ head: ListNode?, _ x: Int) -> ListNode? {
|
||||
var pro = head
|
||||
var big = ListNode(-1)
|
||||
var small = ListNode(-1)
|
||||
var headbig = big
|
||||
var headsmall = small
|
||||
//分
|
||||
while pro != nil {
|
||||
//大于时,放到 big 链表上
|
||||
if pro!.val >= x {
|
||||
big.next = pro
|
||||
big = big.next!
|
||||
//小于时,放到 small 链表上
|
||||
} else {
|
||||
small.next = pro
|
||||
small = small.next!
|
||||
}
|
||||
pro = pro?.next
|
||||
}
|
||||
//细节
|
||||
big.next = nil
|
||||
//合
|
||||
small.next = headbig.next
|
||||
return headsmall.next
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -218,3 +218,50 @@ class Solution:
|
||||
return low
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func reverseBetween(_ head: ListNode?, _ left: Int, _ right: Int) -> ListNode? {
|
||||
// 虚拟头结点
|
||||
var temp = ListNode(-1)
|
||||
temp.next = head
|
||||
var pro:ListNode? = temp
|
||||
// 来到 left 节点前的一个节点
|
||||
var i = 0
|
||||
for n in i..<left - 1 {
|
||||
pro = pro?.next
|
||||
i += 1
|
||||
}
|
||||
// 保存 left 节点前的一个节点
|
||||
var leftNode = pro
|
||||
// 来到 right 节点
|
||||
for n in i..<right {
|
||||
pro = pro?.next
|
||||
}
|
||||
// 保存 right 节点后的一个节点
|
||||
var rightNode:ListNode? = pro?.next
|
||||
// 切断链表
|
||||
pro?.next = nil // 切断 right 后的部分
|
||||
var newHead:ListNode? = leftNode?.next // 保存 left 节点
|
||||
leftNode?.next = nil // 切断 left 前的部分
|
||||
// 反转
|
||||
leftNode?.next = reverse(newHead)
|
||||
// 重新接头
|
||||
newHead?.next = rightNode
|
||||
return temp.next
|
||||
}
|
||||
// 和反转链表1代码一致
|
||||
func reverse(_ head: ListNode?) -> ListNode? {
|
||||
var low:ListNode?
|
||||
var pro = head
|
||||
while pro != nil {
|
||||
var temp = pro
|
||||
pro = pro?.next
|
||||
temp?.next = low
|
||||
low = temp
|
||||
}
|
||||
return low
|
||||
}
|
||||
}
|
||||
```
|
@ -123,3 +123,27 @@ class Solution:
|
||||
return headtemp.next
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func mergeTwoLists(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
|
||||
var l1 = l1, l2 = l2
|
||||
var headpro: ListNode? = ListNode(-1)
|
||||
var headtemp = headpro
|
||||
while l1 != nil && l2 != nil {
|
||||
//接上大的那个
|
||||
if l1!.val >= l2!.val {
|
||||
headpro?.next = l2
|
||||
l2 = l2!.next
|
||||
} else {
|
||||
headpro?.next = l1
|
||||
l1 = l1!.next
|
||||
}
|
||||
headpro = headpro?.next
|
||||
}
|
||||
headpro?.next = l1 != nil ? l1 : l2
|
||||
return headtemp?.next
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -135,6 +135,40 @@ class Solution:
|
||||
return tempb
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func getIntersectionNode(_ headA: ListNode?, _ headB: ListNode?) -> ListNode? {
|
||||
var tempa = headA
|
||||
var tempb = headB
|
||||
var arr:Set<ListNode> = []
|
||||
//遍历链表A,将所有值都存到arr中
|
||||
while tempa != nil {
|
||||
arr.insert(tempa!)
|
||||
tempa = tempa?.next
|
||||
}
|
||||
//遍历列表B,如果发现某个结点已在arr中则直接返回该节点
|
||||
while tempb != nil {
|
||||
if arr.contains(tempb!) {
|
||||
return tempb
|
||||
}
|
||||
tempb = tempb?.next
|
||||
}
|
||||
//若上方没有返回,此刻tempb为null
|
||||
return tempb
|
||||
}
|
||||
}
|
||||
extension ListNode: Hashable, Equatable {
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(val)
|
||||
hasher.combine(ObjectIdentifier(self))
|
||||
}
|
||||
public static func ==(lhs: ListNode, rhs: ListNode) -> Bool {
|
||||
return lhs === rhs
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
下面这个方法比较巧妙,不是特别容易想到,大家可以自己实现一下,这个方法也是利用我们的双指针思想。
|
||||
@ -221,6 +255,25 @@ class Solution:
|
||||
return tempa # 返回tempb也行
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func getIntersectionNode(_ headA: ListNode?, _ headB: ListNode?) -> ListNode? {
|
||||
//定义两个节点
|
||||
var tempa = headA
|
||||
var tempb = headB
|
||||
//循环
|
||||
while tempa != tempb {
|
||||
// 如果不为空就指针下移,为空就跳到另一链表的头部
|
||||
tempa = tempa != nil ? tempa?.next : headB
|
||||
tempb = tempb != nil ? tempb?.next : headA
|
||||
}
|
||||
return tempa //返回tempb也行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。
|
||||
|
||||
<br/>
|
||||
|
@ -136,3 +136,28 @@ class Solution:
|
||||
return after
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func getKthFromEnd(_ head: ListNode?, _ k: Int) -> ListNode? {
|
||||
//特殊情况
|
||||
if head == nil {
|
||||
return head
|
||||
}
|
||||
//初始化两个指针
|
||||
var pro = head, after = head
|
||||
//先移动绿指针到指定位置
|
||||
for i in 0..<k-1 {
|
||||
pro = pro?.next
|
||||
}
|
||||
//两个指针同时移动
|
||||
while pro?.next != nil {
|
||||
pro = pro?.next
|
||||
after = after?.next
|
||||
}
|
||||
//返回倒数第k个节点
|
||||
return after
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -118,3 +118,20 @@ class Solution:
|
||||
return slow
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func middleNode(_ head: ListNode?) -> ListNode? {
|
||||
var fast = head //快指针
|
||||
var slow = head //慢指针
|
||||
//循环条件,思考一下跳出循环的情况
|
||||
while fast != nil && fast?.next != nil {
|
||||
fast = fast?.next?.next
|
||||
slow = slow?.next
|
||||
}
|
||||
//返回slow指针指向的节点
|
||||
return slow
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -230,3 +230,42 @@ class Solution:
|
||||
return nList.next # 去除哑节点
|
||||
```
|
||||
|
||||
Swift Code:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
|
||||
var l1 = l1, l2 = l2
|
||||
var nList = ListNode(-1) // 哑节点
|
||||
var tempnode = nList
|
||||
// 用来保存进位值,初始化为0
|
||||
var summod = 0
|
||||
while l1 != nil || l2 != nil {
|
||||
// 链表的节点值
|
||||
let l1num = l1?.val ?? 0
|
||||
let l2num = l2?.val ?? 0
|
||||
// 将链表的值和进位值相加,得到为返回链表的值
|
||||
var sum = l1num + l2num + summod
|
||||
// 更新进位值,例18/10=1,9/10=0
|
||||
summod = sum / 10
|
||||
// 新节点保存的值,18%8=2,则添加2
|
||||
sum = sum % 10
|
||||
// 添加节点
|
||||
tempnode.next = ListNode(sum)
|
||||
// 移动指针
|
||||
tempnode = tempnode.next!
|
||||
if l1 != nil {
|
||||
l1 = l1?.next
|
||||
}
|
||||
if l2 != nil {
|
||||
l2 = l2?.next
|
||||
}
|
||||
}
|
||||
// 最后根据进位值判断需不需要继续添加节点
|
||||
if (summod != 0) {
|
||||
tempnode.next = ListNode(summod)
|
||||
}
|
||||
return nList.next //去除哑节点
|
||||
}
|
||||
}
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user