zoukankan      html  css  js  c++  java
  • LeetCode题解:(19) 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.


    题目分析

    看上去还挺简单的,由于题目要求只遍历一遍链表,我的做法是采用两个指针,保证两个指针的距离为n,这样当前面的指针到达尾部的时候,另一个指针的位置就是要移除的结点。

    以下为个人实现(C++,糟糕的一坨代码):

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode *new_head = new ListNode(-1);
            new_head->next = head;
            ListNode *p1 = new_head, *p2 = new_head;
            for (int i = 0; i <= n; i++, p2 = p2->next); // p2 = p1 + n + 1
            for (; p2 != NULL; p2 = p2->next, p1 = p1->next);
            p2 = p1->next;
            p1->next = p2->next;
            delete(p2);
            p2 = new_head->next;
            delete(new_head);
            return p2;
        }
    };
    

    这里比较僵硬的一点是链表头的元素需要额外进行判断,我这种算法可以说很辣鸡了……

    于是在讨论版看到了另外一种和我思路一样,但是细节不同的代码实现:

    class Solution
    {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n)
        {
            ListNode** t1 = &head, *t2 = head;
            for(int i = 1; i < n; ++i)
            {
                t2 = t2->next;
            }
            while(t2->next != NULL)
            {
                t1 = &((*t1)->next);
                t2 = t2->next;
            }
            *t1 = (*t1)->next;
            return head;
        }
    };
    

    这份代码和我所实现的区别在于使用了二级指针,开始觉得很莫名其妙,后来看了Linus:利用二级指针删除单向链表的解释后,感觉这种做法挺巧妙的。

    在第一种方法中(不使用二级指针),我所做的操作是将entry->next赋值给prev->next,然而当entry为链表头的时候就没有prev->next可以赋值了。但是实际上,任何一个链表都会有一个和prev->next同等地位的指针,那就是head指针,对于链表头元素,执行的操作可以是将head->next赋值给head。此时第二种方法(使用二级指针)的好处是它不关心entry->next究竟赋值给了谁,只关心赋值的地址,因此也免了判断entry是不是head的步骤了。

    (微软笔试崩了……郁闷)

  • 相关阅读:
    将Ubuntu18.04安装到U盘,实现即插即用
    小技巧之 前端自适应
    web笔记之 环境搭建
    C++学习笔记之 单例模式
    推荐一款Markdown编辑器:typora
    C++学习笔记之 类和对象
    C++学习笔记之 函数
    C++学习笔记之 内联函数
    C++学习笔记之 引用
    C++学习笔记之 const
  • 原文地址:https://www.cnblogs.com/slontia/p/8698469.html
Copyright © 2011-2022 走看看