• Remove Nth Node From End of List 和链表题目总结


    Given a linked list, remove the nth node from the end of list and return its head.

    For example,

       Given linked list: 1->2->3->4->5, and n = 2.
    
       After removing the second node from the end, the linked list becomes 1->2->3->5.
    

    Note:
    Given n will always be valid.
    Try to do this in one pass.

    链表的一道简单题目,题目要求只扫one pass只扫一遍链表,但是通常情况下不知道链表总长度,则无法知道倒数第N个结点(实际考虑的是倒数第N+1个结点)在哪里。使用是链表中常用的技巧,维护一前一后两个指针fast和slow。fast指针比slow指针先走N步。这样当fast指针指向链表最后一个元素时,slow指针指向的是倒数(N+1)个结点,然后进行删除元素的处理。

    值得注意的是:如果删除的是头结点,则在fast先走N步(等于链表长度)之后,fast为None,之后再同时移动fast和slow时,判断fast.next来决定是否已到达尾结点会直接造成访问错误。解决方法有两种:第一种是在fast先走N步时判断fast是否已经为None,为None,则说明删除的是头结点,返回head.next。第二种是增加一个dummy哑元素,fast先走N步之后,即使是删除头元素,也会指向尾结点。防止后序的判断错误,但是这种做法有一个坏处,即是多了辅助元素,并且实际fast和slow都各多走了1步。

    方法一代码:
    class Solution(object):
        def removeNthFromEnd(self, head, n):
            """
            :type head: ListNode
            :type n: int
            :rtype: ListNode
            """
            fast = slow = head
            for _ in range(n):
                fast = fast.next
            if not fast:
                return head.next
            while fast.next:
                fast = fast.next
                slow = slow.next
            slow.next = slow.next.next
            return head

    方法二代码:

    class Solution(object):
        def removeNthFromEnd(self, head, n):
            """
            :type head: ListNode
            :type n: int
            :rtype: ListNode
            """
            if not head:
                return None
            dummy = ListNode(-1)
            dummy.next = head
            fast = slow = dummy
            for i in range(n):
                fast = fast.next
            while fast.next:
                slow = slow.next
                fast = fast.next
            slow.next = slow.next.next
            return dummy.next

    注意题目本身说到n是合法的,但是在实际面试中这种合理的假设通常不存在,所以需要加入一些合理性判断,判断是否合法,这里事先假设越界时直接返回head。基于第一种解法更改如下:

    class Solution(object):
        def removeNthFromEnd(self, head, n):
            """
            :type head: ListNode
            :type n: int
            :rtype: ListNode
            """
            fast = slow = head
            i = 0
            while i < n and fast:
                fast = fast.next
                i += 1
            if i < n-1:
                return head 
            if not fast:
                return head.next
            while fast.next:
                fast = fast.next
                slow = slow.next
            slow.next = slow.next.next
            return head
    总结来说:链表需要注意的点为:
    1. 越界:容易造成内存访问错误,比如调用了None.next。尤其对于空链表的特殊情况。
    2. 更新head的特殊处理
    3. 删除节点时没有保留下一个移动位置的指针(多用于reverse linked list)。
    4. 移动位置存在+-1的偏差。 

    常用技巧:
    1. Dummy head:简化改变、删除头指针的处理。
    2. 前后双指针:多用于链表反转。

     递归解法,值得注意:

    class Solution:
        def removeNthFromEnd(self, head, n):
            def remove(head):
                if not head:
                    return 0, head
                i, head.next = remove(head.next)
                return i+1, (head, head.next)[i+1 == n]
            return remove(head)[1]
  • 相关阅读:
    vlc-ts
    es 模板
    zookeeper 启动脚本
    received shard failed for shard id
    gitlab runner 配置
    kafka 配置文件注释
    logstash 统计告警
    BigBao 的python开发到DevOps 之路
    logstash 自动重新加载配置
    rsyslog 传输日志
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5425083.html
Copyright © 2020-2023  润新知