美文网首页
iOS面试之道-链表

iOS面试之道-链表

作者: 认不出我来 | 来源:发表于2019-05-19 22:47 被阅读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
        }
    

    相关文章

      网友评论

          本文标题:iOS面试之道-链表

          本文链接:https://www.haomeiwen.com/subject/ypyczqtx.html