[LeetCode19-链表-中等] 删除链表的倒数第N个节点

这道题也是关于链表的题目,题目原意是这样的,给你一个链表,删除这个链表的倒数第n个结点,并返回头结点(也就是其余的结点组成的新链表)

比如 1->3->5->7->9   n =2 也就是删除倒数第2个结点,值为7的结点。返回头结点为 1->3->5->9

 关于链表的算法题,首先我们要知道链表解题经典三板斧:  哑巴结点(dummy node), 快慢指针


针对这个题,我们首先想到的解法是什么,我们首先想到的是,我们先要找到要删除的倒数第n个结点的前一个结点,也就是倒是第n+1个结点,讲这个结点(倒数第n+1个结点)指针指向要删除结点(倒数第n个结点)的后继结点(倒数第n-1个结点). 从这个解释可以看到,它要找到要删除的这个结点的前一个结点,但是如果我们要删除的结点刚好是头结点呢(链表的第一个结点),那么它就没有前驱结点,这样我们需要对这种情况进行特殊处理。为了避免这种特殊处理的情况,我们通常会在头结点前面添加一个哑巴结点(dummy node), 等整个操作完成后,我们再把这个哑巴结点删除

有了方法论后,我们再回到这个问题本身,现在要删除链表的倒数第n个结点,我们来看个例子  1->3->5->7->9  删除倒数第2个结点(n=2)  =>  显然,我们需要找到这倒数第2个结点的位置,它处在这个链表的第4个位置,这个4是怎么得来的呢?

链表长度 5 - n (2)  + 1 = 5 - 2 +1 = 4 ,所以我们要删除的结点就是位置在  (链表长度 - n + 1)的位置的结点,也就是顺序第 (链表长度 - n + 1)个结点,我们把这个结点删除后,把它的前驱结点 ((链表长度 - n + 1 - 1) 指向它的后驱结点 (链表长度 - n + 1 + 1), 整个工作就完成了

所以,现在问题很简单, 就变成找到链表长度,显然需要从头结点开始遍历整个链表,得到链表长度L。  =》 因为我们在头部加了一个哑巴结点,所以整个链表的长度变为 (L + 1),  要删除的结点位置变为 (L + 1 - N + 1)

C#代码如下:

public class ListNode
    {
        public int val;
        public ListNode next;
        public ListNode(int x = 0, ListNode nextNode = null)
        {
            val = x;
            next = nextNode;
        }
        
    }



 public ListNode RemoveNthFromEnd(ListNode head, int n)
        {
            //获取ListNode的长度
            var L = 0;
            while (head != null)
            {
                ++L;
                head = head.next;
            }

            //在当前链表的头部添加一个哑巴结点
            var dummyNode = new ListNode(0, head);

            var currNode = dummyNode; //从哑巴结点开始遍历,把它赋给当前结点
            for (var i = 1; i < (L - n + 1); i++)  //从第一个结点(哑巴结点)开始遍历,遍历到currNode变成要删除结点的前驱结点
            {
                currNode = currNode.next;
            }

            currNode.next = currNode.next.next; // currNode此时是要删除结点的前驱结点,把它的指向变成要删除结点的后驱结点,就完成了对要删除结点的删除

            var newListNode = dummyNode.next;

            return newListNode;
            
        }

 

posted on 2023-12-10 23:09  新西兰程序员  阅读(4)  评论(0编辑  收藏  举报