// 链表节点
class ListNode {
var val: Int
var next: ListNode?
init(_ val: Int) {
self.val = val
self.next = nil
}
}
// 链表
class List {
var head: ListNode?
var tail: ListNode?
// 尾插法
func appendToTail(_ val:Int) {
if tail == nil {
tail = ListNode(val)
head = tail
} else {
tail!.next = ListNode(val)
tail = tail!.next
}
}
// 头插法
func appendToHead(_ val:Int) {
if head == nil {
head = ListNode(val)
tail = head
} else {
let tmp = ListNode(val)
tmp.next = head
head = tmp
}
}
}
算法题一:
给出一个链表和一个值X,要求将链表中所有小于X的值放到左边,所有大于等于X的值放到右边,并且原链表的节点顺序不能变
思路:
先处理左边(比x小的节点),然后再处理右边(比x大的节点),最后再把左右两边连起来。
func partition(_ head: ListNode?, _ x:Int) -> ListNode? {
let prevDummy = ListNode(0), postDummy = ListNode(0)
var prev = prevDummy, post = postDummy
var node = head
while node != nil {
if node!.val < x {
prev.next = node
prev = node!
} else {
post.next = node
post = node!
}
node = node?.next
}
// 防止构成环
post.next = nil
// 左右两部分相连
prev.next = postDummy.next
return prevDummy.next
}
前面提到了环,怎么检测链表中是否有环存在?
算法题二:快慢指针
如何检测一个链表中是否有环
思路:
用两个指针同时访问链表,其中一个的速度是另一个的两倍,如果它们变成相等了,那么这个链表就有环了,
func hasCycle(_ head:ListNode?) -> Bool {
var slow = head
var fast = head
while fast != nil && fast!.next != nil {
slow = slow!.next
fast = fast!.next!.next
// 引用类型判断相等用 === ,值类型用 ==
if slow === fast {
return true
}
}
return false
}
算法题三:
删除链表中倒数第n个节点,例:1->2->3->4->5, n=2,返回 1->2->3->5
注意:给定n的长度小于等于链表的长度
思路:
依然是快行指针,这次两个指针移动速度相同。但是一开始,第一个指针(在指向头结点之前)就落后第二个指针n个节点。接着两者同时移动,当第二个指针移动到尾节点时,第一个节点的下一个节点就是我们要删除的节点。
func removeNthFromEnd(_ head:ListNode?,_ n:Int) ->ListNode? {
guard let head = head else {
return nil
}
let dummy = ListNode(0)
dummy.next = head
var prev:ListNode? = dummy
var post:ListNode? = dummy
for _ in 0 ..< n {
if post == nil {
break
}
post = post!.next
}
while post != nil && post!.next != nil {
prev = prev!.next
post = post!.next
}
// 删除节点
prev!.next = prev!.next!.next
return dummy.next
}
网友评论