iOS面试之道-链表

2019-05-19  本文已影响0人  认不出我来
// 链表节点
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
    }
上一篇下一篇

猜你喜欢

热点阅读