算法-链表1

127 阅读3分钟

基础知识学习

题目1: 203.移除链表元素

203.移除链表元素
文章讲解

思路: 还记得点虚拟节点的用法,算是写出来了。
按我的理解说一下,单链表删除节点的时候,只能是查当前节点和下一个节点(也可以说是 上一个节点和当前节点)。
在链表中间的时候,这操作没问题。
但是如果头结点就是要被删除的值,那他没有头结点,就导致需要额外处理这个case。 也就是提前while循环把头结点检查到不是目标值,再写循环。
那么优化的方式二就 显而易见了:给头结点加个前置的节点(这样头结点也就有上一个节点了),就可以用一个循环解决。

// @lc code=start
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init() { self.val = 0; self.next = nil; }
 *     public init(_ val: Int) { self.val = val; self.next = nil; }
 *     public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
 * }
 */
class Solution {
    func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? {
        let dummyNode = ListNode(-1, head) 
        var node: ListNode? = dummyNode
        while let next = node?.next {
            if next.val == val {
                node?.next = next.next
            } else {
                node = node?.next
            }
        }
        return dummyNode.next
    }
}
// @lc code=end

看一下题解swift的写法,node的 optional解包操作处理的不好
node = node?.next 改成 node = next
这样就不用到处都是问号了。

题目2:707.设计链表

题目链接
文章讲解

优化一下写法 再提个pull request 替换一下swift的题解。

// @lc code=start

class MyLinkedList {
    var dummyNode = ListNode()
    var size = 0

    init() {}
    
    func get(_ index: Int) -> Int {
        if index < 0 || index >= size {
            return -1
        }
        var node = dummyNode.next
        var curIndex = index
        while curIndex > 0 {
            curIndex -= 1
            node = node?.next
        }
        return node?.val ?? -1
    }
    
    func addAtHead(_ val: Int) {
        let newNode = ListNode(val)
        newNode.next = dummyNode.next
        dummyNode.next = newNode
        size += 1
        printNodeList()
    }
    
    func addAtTail(_ val: Int) {
        var curNode = dummyNode
        while let nextNode = curNode.next {
            curNode = nextNode
        }
        curNode.next = ListNode(val)
        size += 1
        printNodeList()
    }
    
    func addAtIndex(_ index: Int, _ val: Int) {
        if index > size {
            return
        }
        var preNode = findPreNode(index)
        let newNode = ListNode(val)
        // 添加节点
        newNode.next = preNode?.next
        preNode?.next = newNode
        size += 1
        printNodeList()
    }
    
    func deleteAtIndex(_ index: Int) {
        print("deleteAtIndex index:\(index)")
        if index < 0 || index >= size {
            return
        }
        var preNode = findPreNode(index)
        // 删除节点
        preNode?.next = preNode?.next?.next
        size -= 1          
        printNodeList()
    }

    // 找到index之前的元素,如果index小于0,则返回dummyNode
    func findPreNode(_ index: Int) -> ListNode? {
        if index > size {
            return nil
        }
        var curNode = dummyNode
        // 要找到index位置的前一个节点,因为dummyNode的存在,从index开始遍历,正好找到的是index位置的前一个节点
        var curIndex = index
        while curIndex > 0 {
            curIndex -= 1
            curNode = curNode.next!
        }
        return curNode
    }
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * let obj = MyLinkedList()
 * let ret_1: Int = obj.get(index)
 * obj.addAtHead(val)
 * obj.addAtTail(val)
 * obj.addAtIndex(index, val)
 * obj.deleteAtIndex(index)
 */
// @lc code=end

题目3: 206.反转链表

题目、题解

// 没有理解为什么这种写法会超时。 未AC
// 第一个节点 少反转了。  导致 5 4 3 2 1 2 1 2 1 ... 死循环了。😭
func reverseList(_ head: ListNode?) -> ListNode? {
    if head == nil || head?.next == nil {
        return head
    }
    var pre: ListNode?
    var cur = head
    var next = head?.next
    while next != nil {
        print("新一轮")
        pre = cur
        cur = next
        next = next?.next
        cur?.next = pre
        print("pre:\(pre?.val) cur:\(cur?.val) next:\(next?.val)")
    }
    print("结束")
    return cur
}

// 抛弃上述想法,直接按照题解 清晰不容易出错。
func reverseList(_ head: ListNode?) -> ListNode? {
    if head == nil || head?.next == nil {
        return head
    }
    var pre: ListNode? = nil
    var cur: ListNode? = head
    var temp: ListNode? = nil
    while cur != nil {
        temp = cur?.next
        cur?.next = pre
        pre = cur
        cur = temp
    }
    return pre
}