您的位置:首页 > 编程语言 > Python开发

剑指offer系列-面试题22-链表中倒数第k个节点(python)

2019-07-07 18:14 246 查看
版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

文章目录

  • 4.总结
  • 5.参考文献
  • 1.题目

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

    struct ListNode
    {
    int m_nValue;
    ListNode* m_pNext;
    };

    当然对于python而言,链表的定义如下:

    class ListNode(object):
    def __init__(self, value, next_node):
    self.value = value
    self.next = next_node

    2. 解题思路

    我看过这个题之后的思路就是,因为这个单链表,不是双向链表,因此要获得某一个节点,那么只能遍历,而且,一开始我们并不知道倒数第k个节点是哪一个,只有在遍历过一边链表之后,才能知道倒数第k个节点在哪儿。过程就是,第一次遍历链表得到链表的长度,计算出倒数第k个节点是顺数第几个节点(因为我们无法按照倒数来获得这个节点), 然后在再一次遍历这个链表,知道到达这个节点。时间复杂度O(n^2),空间复杂度S(1)。

    上面的方法很简单,但是时间复杂度是O(n^2),面试官不会满意的,那么能不能降低时间复杂度呢?定义两个指针:第一个指针从链表头部开始遍历向前走k-1步,第二个指针保持不动;从第k步开始,第二个指针也开始从链表的头部开始遍历。两个指针的距离是k-1,当第一个指针到达链表的尾节点时,由于这两个节点的距离始终是k-1,这时第二个指针正好指向倒数第k个节点

    3. 代码实现

    3.1 常规思路

    def find_kth_to_tail(head, k):
    count = 0 # 链表的长度
    if k <= 0:
    return
    if head:
    cur = head # 当前节点
    while cur:
    count += 1
    cur = cur.next
    
    # 倒数第k个节点是顺数的第n-k+1这个节点
    index = count - k + 1
    if index < 1:
    return
    cur = head
    while index > 1:
    cur = cur.next
    index -= 1
    return cur

    3.2 更优思路

    def find_kth_to_tail(head, k):
    count = 1
    3ff7
    # 第几个节点
    cur = head # 指针1
    k_node = head # 指针2
    if k <= 0: # 负值条件,返回None
    return
    while cur:
    cur = cur.next
    if count > k: # 从顺数第k+1个节点开始,同时移动cur和k_node
    k_node = k_node.next
    count += 1
    if count < k: # 若k>链表长度,应该返回None
    return
    return k_node
    
    def find_kth_to_tail(head, k):
    count = 1 # 第几个节点
    cur = head
    k_node = head
    if k <= 0:
    return
    while count < k: # count最后的值为k
    if cur:
    cur = cur.next
    count += 1
    else:
    return
    # 此时cur指向顺数第k个节点,而k_node指向第一个节点(头节点),当cur指向尾节点时终止。
    while cur.next:
    cur = cur.next
    k_node = k_node.next
    return k_node

    4.总结

    当我们用一个指针遍历链表不能解决问题的时候,可以考虑使用两个指针来遍历链表,然后控制两个指针的速度或者某个指针先出发。
    而对于列表而言,指针一般是从两端往中间移动。

    5.参考文献

    [1]剑指offer丛书

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: