142. 环形链表 II + 21.合并两个有序链表 + 2. 两数相加

69 阅读2分钟

142. 环形链表 II

题目

找出环形链表的入口

分析

典型快慢指针追及问题(每次快指针走两步,慢指针走一步),难点在于如何找到环的入口,快慢指针第一次相遇时的节点并不一定是环的入口

将链表从入口处截断,前半段距离为a,后半段为环距离为b,快指针走的距离为f,慢指针走的距离为s,

快慢指针相遇时,快指针走的距离一定比慢指针多n圈,即f -s = nb,同时f速度为s的2倍,即 f = 2s,则 s = nb

要找到环的入口点,在于如何让两个指针相遇在入口,此时慢指针走了nb,若再走a,则到达环的入口(s = a + nb),那么a是取得呢,

显然让一个指针从头开始走a,也是到达入口点,因此在快慢指针第一次相遇之后,一个新的指针同时开始走,当新指针与慢指针相遇时,即为入口

总结:

  1. 快慢指针,不相遇为无环,相遇有环
  2. 此时新的指针每次和慢指针走同样速度,相遇时即为环的入口
fun detectCycle(head: ListNode?): ListNode? {
    if (head == null) return null
    var fast = head
    var slow = head
    while (fast!!.next != null && fast.next!!.next != null) {
        fast = fast.next!!.next
        slow = slow!!.next
        if (fast == slow) {
            fast = head
            while (fast != slow) {
                fast = fast!!.next
                slow = slow!!.next
            }
            return fast
        }
    }
    return null
}

21.合并两个有序链表

模拟合并简单题,不做陈述

fun mergeTwoLists(list1: ListNode?, list2: ListNode?): ListNode? {
    var curr1 = list1
    var curr2 = list2
    var result = ListNode(0)
    var curr = result
    while (curr1 != null && curr2 != null) {
        when {
            curr1.`val` > curr2.`val` -> {
                curr.next = curr2
                curr = curr2
                curr2 = curr2.next

            }

            else -> {
                curr.next = curr1
                curr = curr1
                curr1 = curr1.next
            }

        }
    }
    var temp = curr1 ?: curr2
    while (temp != null) {
        curr.next = temp
        curr = temp
        temp = temp.next
    }
    return result.next

}

2. 两数相加

模拟相加简单题,不做陈述

fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? {
    val result = ListNode(0)
    deep(l1, l2, result)
    return result.next
}

fun deep(l1: ListNode?, l2: ListNode?, curr: ListNode, add: Int = 0) {
    when {
        l1 == null && l2 == null -> {
            add.takeIf { it != 0 }?.let { curr.next = ListNode(add) }
        }

        l1 == null -> {
            curr.next = ListNode((l2!!.`val` + add) % 10)
            deep(null, l2.next, curr.next!!, (l2.`val` + add) / 10)
        }

        l2 == null -> {
            curr.next = ListNode((l1.`val` + add) % 10)
            deep(l1!!.next, null, curr.next!!, (l1.`val` + add) / 10)
        }

        else -> {
            curr.next = ListNode((l1.`val` + l2.`val` + add) % 10)
            deep(l1.next, l2.next, curr.next!!, (l1.`val` + l2.`val` + add) / 10)
        }
    }
}

关于我

一个希望友友们能提出建议的代码下毒糕手