我的Github地址
小码哥《恋上数据结构与算法》笔记
极客时间《iOS开发高手课》笔记
iOS大厂面试高频算法题总结
iOS面试资料汇总
- 链表(9道):
- 剑指Offer(6):从尾到头打印链表
- 剑指Offer(18):删除链表的节点
- 剑指Offer(18):删除链表中重复的节点
- 剑指Offer(22):链表中倒数第k个结点
- 剑指Offer(23):链表中环的入口节点
- 剑指Offer(24):反转链表
- 剑指Offer(25):合并两个排序的链表
- 剑指Offer(35):复杂链表的复制
- 剑指Offer(52):两个链表的第一个公共节点
面试题6:从尾到头打印链表
题目一

思路一:栈

代码
func reversePrint(_ head: ListNode?) -> [Int] {
var result = [Int]()
var node = head
while node != nil {
result.append(node!.val)
node = node!.next
}
result.reverse()
return result
}
思路二:递归

代码
func reversePrint(_ head: ListNode?) -> [Int] {
guard let head = head else {
return [Int]()
}
var list = reversePrint(head.next)
list.append(head.val)
return list
}
面试题18:删除链表的节点
题目一

思路一

代码
func deleteNode(_ head: ListNode?, _ val: Int) -> ListNode? {
var next = head?.next
var cur = head
if cur?.val == val {
cur = cur?.next
return cur
}
while next != nil {
if next?.val == val {
cur?.next = next?.next
return head
} else {
cur = next
next = next?.next
}
}
return head
}
思路二

题目二:删除链表中重复的节点

思路一

代码
func deleteDuplicates(_ head: ListNode?) -> ListNode? {
let dummy = ListNode(-1)
var newHead = head
dummy.next = newHead
while newHead != nil {
if newHead?.val == newHead?.next?.val {
newHead?.next = newHead?.next?.next
} else {
newHead = newHead?.next
}
}
return dummy.next
}
面试题22:链表中倒数第k个结点
题目一

思路一

思路二

代码
func getKthFromEnd(_ head: ListNode?, _ k: Int) -> ListNode? {
var fast : ListNode? = head
var slow : ListNode? = head
var tk = k
while tk > 0 {
fast = fast?.next
tk -= 1
}
while fast != nil {
fast = fast?.next
slow = slow?.next
}
return slow
}
相关题目

举一反三

面试题23:链表中环的入口节点
题目一

思路一

代码
func detectCycle(_ head: ListNode?) -> ListNode? {
let newHead = ListNode.init(-1)
newHead.next = head
var slow: ListNode? = newHead
var fast: ListNode? = newHead
while fast != nil {
slow = slow?.next
fast = fast?.next?.next
if slow === fast {
slow = newHead
while slow !== fast {
slow = slow?.next
fast = fast?.next
}
return slow
}
}
return nil
}
面试题24:反转链表
题目一

思路一

代码
func reverseList(_ head: ListNode?) -> ListNode? {
var newHead: ListNode? = nil
var cur = head
while cur != nil {
let tmp = cur!.next
cur!.next = newHead
newHead = cur!
cur = tmp
}
return newHead
}
思路二:递归
代码
func reverseList(_ head: ListNode?) -> ListNode? {
if head == nil || head?.next == nil {
return head
} else {
let p = reverseList(head?.next)
head?.next?.next = head
head?.next = nil
return p
}
}
面试题25:合并两个排序的链表
题目一


思路一

代码
func mergeTwoLists(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let newList = ListNode.init(-1)
var cur = newList
var l1 = l1
var l2 = l2
while l1 != nil && l2 != nil {
if l1!.val > l2!.val {
cur.next = l2
l2 = l2?.next
} else {
cur.next = l1
l1 = l1?.next
}
cur = cur.next!
}
cur.next = l1 ?? l2
return newList.next
}
思路二:递归
代码
func mergeTwoLists(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
if l1 == nil {
return l2
} else if l2 == nil {
return l1
} else if l1!.val < l2!.val {
l1?.next = mergeTwoLists(l1?.next, l2)
return l1
} else {
l2?.next = mergeTwoLists(l1, l2?.next)
return l2
}
}
面试题35:复杂链表的复制
题目一

思路一:哈希表

面试题52:两个链表的第一个公共节点
题目一

思路一

思路二

思路三

思路四
- 不管相不相交,当
currentA拼接B的时候,currentB拼接A的时候,他们能同时走到对方的尾节点,如果不相交,此时都为空,跳出循环
- 如果相交,那么我们逆推,既然能在尾节点相遇,那么尾节点的前继节点也是相遇,直到我们逆推到第一个相交点。
代码
func getIntersectionNode(_ headA: ListNode?, _ headB: ListNode?) -> ListNode? {
var A = headA
var B = headB
while A !== B {
A = A == nil ? headB : A!.next
B = B == nil ? headA : B!.next
}
return A
}