Home

LinkWorld Algorithm Blog

20 Feb 2018

输出单链表倒数第K个结点

一、题目

输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。

二、解题思路

Notzuonotdied的解题思路

  1. 题目说的是输出倒数的第K个结点,所以我们可以通过维护两个索引[指针]head和last。
  2. 假设链表的头结点为root,head和last都指向root。
  3. 注意:head和last相差$K - 1$个结点。
  4. head先走K个结点,如果链表总的结点数小于K个结点,就直接返回null;如果链表总的结点数大于K个结点,就遍历K个结点:
    • 之后,head和last索引一起遍历结点,直到head为null。
  5. 返回last所在的结点的值。

kotlin实现

fun main(args: Array<String>) {
    val length = 16
    val root = initLinkList(length)
    print(root)
    // index比链表长度小
    var postIndex = 5
    println("倒数第${postIndex}个的值为:${printLastKthNode(root, postIndex)?.value}")
    // index比链表长度大
    postIndex = length + 1
    println("倒数第${postIndex}个的值为:${printLastKthNode(root, postIndex)?.value}")

    // 测试边界
    println("××××××测试一个结点的情况××××××")
    val root1 = LinkNode(0, null)
    // 一个元素
    println("倒数第${1}个的值为:${printLastKthNode(root1, 1)?.value}")
    println("倒数第${2}个的值为:${printLastKthNode(root1, 2)?.value}")
    // 零个元素
    println("××××××测试零个结点的情况××××××")
    println("倒数第${1}个的值为:${printLastKthNode(null, 1)?.value}")
    println("倒数第${2}个的值为:${printLastKthNode(null, 2)?.value}")

}

/**
 * 初始化单链表
 *
 * @return 返回单链表
 * */
fun initLinkList(length: Int): LinkNode? {
    val root = LinkNode(0, null)
    var temp: LinkNode = root
    for (i in 1..(length - 1)) {
        temp.next = LinkNode(i, null)
        temp = temp.next!!
    }
    return root
}

/**
 * 输出倒数第K个结点
 *
 * @param root 头结点
 * @param k 倒数第几个结点的索引值
 * @return 返回倒数第K个结点
 * */
fun printLastKthNode(root: LinkNode?, k: Int): LinkNode? {
    // 如果k的值等于0,就直接抛出异常
    if (k == 0) throw Exception("请输入大于0的数字k")
    // 如果头结点为空,就直接返回root
    if (root == null) return root

    // 初始化遍历的head索引
    var head = root
    // head先遍历k个结点,保持head和
    for (i in 0..(k - 1)) {
        // 不为空就往下走,为空就直接返回null
        if (head != null) {
            head = head.next
        } else return null
    }
    // 遍历直到head为null,找到倒数第k个结点
    var last = root
    while (head != null) {
        head = head.next
        last = last?.next
    }

    return last
}

输出结果

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
倒数第5个的值为:11
倒数第17个的值为:null
××××××测试一个结点的情况××××××
倒数第1个的值为:0
倒数第2个的值为:null
××××××测试零个结点的情况××××××
倒数第1个的值为:null
倒数第2个的值为:null

Til next time,
LinkWorld at 09:07

scribble