算法面试通关札记 02-线性表 - 极客时间 【系列】

372 阅读2分钟

算法与数据结构是程序员基本功,但是入门着实不易,在极客时间找了一门非常适合新手人们入门的课程,一遍学习一遍记录,方便日后查看。编程语言选用Swift,并针对技术点丰富了一些感想和随笔。

Github的算法Repo包括了所有的系列札记,同时还有本人刷leetcode、《剑指offer》的历程。如果你感兴趣,可以去看看。Go to Github

数组和链表

数据结构 时间复杂度
数组(顺序表) O(1)的查找,O(n)的插入和删除
单链表 O(n)的查找,O(1)的插入和删除
双链表 O(n)的查找,O(1)的插入和删除,既有前驱节点又有后继节点 ,同上

Leetcode真题

206-翻转链表

//提供两种办法,分析题意需要一个哨兵节点记录链表的头部位置。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */
class Solution {
    func reverseList(_ head: ListNode?) -> ListNode? {

        guard let safeHead = head else {
            return nil
        }
        var cur: ListNode = safeHead
        var pre: ListNode? = nil

        while(cur.next != nil) {
            let curNext = cur.next!
            cur.next = pre
            pre = cur
            cur = curNext
        }

        cur.next = pre
        return cur
    }
}

class Solution {
    func reverseList(_ head: ListNode?) -> ListNode? {
        guard let safeHead = head else {
            return nil
        }
        var cur: ListNode? = safeHead
        var pre: ListNode? = nil
        while cur != nil {
            let curNext: ListNode? = cur!.next
            cur!.next = pre
            pre = cur
            cur =  curNext
        }
        return pre
    }
}

24-两两交换链表中的节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */
class Solution {
    func swapPairs(_ head: ListNode?) -> ListNode? {
        guard let safeHead = head, safeHead.next != nil else {
            return head
        }

        var secondNode = safeHead.next
        var thirdNode = secondNode?.next

        secondNode?.next = safeHead
        safeHead.next = swapPairs(thirdNode)

        return secondNode
    }
}

class Solution {
    func swapPairs(_ head: ListNode?) -> ListNode? {
        guard let safeHead = head else {
                return nil
        }
        let firstNode: ListNode = ListNode(0) //哨兵
        var pre: ListNode = firstNode
        pre.next = safeHead
        while (pre.next != nil) && (pre.next?.next != nil) {
            let a = pre.next!
            let b = pre.next?.next!
            let bnext = b?.next

            pre.next = b
            b?.next = a
            a.next = bnext
            pre = a //这个是重点
        }
        return firstNode.next
    }
}

141-环形链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */
 //方法一,快慢指针。
 func hasCycle(head: ListNode?) -> Bool {
    guard let safeHead = head else {
        return false
    }

    var slow = safeHead
    var fast = safeHead

    while slow.next != nil && fast.next?.next != nil {
        slow = slow.next!
        fast = (fast.next?.next)!

        if slow === fast {
            return true
        }
    }
    return false
}

方法二,使用数据结构set。
func hasCycle(head: ListNode?) -> Bool {
   guard let safeHead = head else {
       return false
   }
   var set: Set<ListNode> = []
   var cur: ListNode? = safeHead
   while cur != nil {
       if set.contains(cur!) {
           return true
       }
       set.insert(cur!)
       cur = cur!.next
   }
   return false
}

142- 环形链表 II

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */
 //检测到有环后,一个指针从头开始动,另外的指针接着之前判断环的地方动,那么两个指针相遇的位置就是第一次入环的位置啦。
 func detectCycle(head: ListNode?) -> ListNode? {
    guard let safeHead = head, safeHead.next != nil else {
        return nil;
    }

    var slow = safeHead
    var fast = safeHead
    var hasCycle = false
    while slow.next != nil && fast.next?.next != nil {
        slow = slow.next!
        fast = (fast.next?.next)!

        if slow === fast {
            hasCycle = true
            break
        }
    }

    if hasCycle {
        var follower = safeHead
        while follower !== slow {
            follower = follower.next!
            slow = slow.next!
        }
        return follower
    }

本系列仅是个人学习笔记,并未包括所有教程内容,如有侵权请联系删除。 极客时间链接

下一篇:栈和队列