LeetCode之路:237. Delete Node in a Linked List

来源:互联网 发布:华为大数据研发岗累吗 编辑:程序博客网 时间:2024/06/16 20:24

一、引言

这道题
哈哈哈

Stupid Question

这是我做完了之后看到最高票答案的标题,顿时觉得有些滑稽:)

那么接下来就让我们看看这道 Stupid Question:

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling you funtion.

题目信息不多,简单翻译一下:

请写这么一个方法:删除链表中指定节点(你只能访问到这个节点,并且此节点不为最后一个节点)
假定链表为 1 -> 2 -> 3 -> 4,并且给定节点的值为 3,那么在执行完你的方法之后,链表应该变为 1 -> 2 -> 4

看到链表,又看到了删除,那么我的下意识就是这样的:

  1. 首先,找到根结点,然后遍历整个链表;遍历的时候定义两个指针,一个标记当前节点,另一个标记当前节点的上一个节点;直到当前节点的 next 为空停止遍历

  2. 然后,找到指定值的节点,让该节点的 pre->next = cur->next,也就是让上一个节点的 next 指向该节点的下一个节点,然后 delete cur ,也就是删除该节点

按照这个思路,一切都是那么完美那么简单类似于我们大一学习数据结构第二章的时候那么轻松。

但是

这道题没有给出根节点 T_T 这就尴尬了 ~~~

二、谁说一定要根节点

没有根节点我还怎么能删除当前节点呢?

众所周知的,我们要删除链表的一个节点,必须要将前一个节点的 next 指针指向要删除节点的下一个节点,之后才能放心的 delete 掉它。

我们没有根节点只能从要删除节点处开始遍历的话,我们根本无法访问到要删除节点的前一个节点,那么我们该怎么达到删除此节点的目的呢?

哈哈,其实这就是这道题的精髓所在了,我画了一个图来帮助理解:

delete node

这里图里已经说得非常清楚了,我们想要删除第 3 个节点,于是我们将第 4 个节点的值复制到第 3 个节点,然后删除第 4 个节点即可。

于是我就写出了第一个版本的代码:

// my first solution 1 , runtime = 13 msclass Solution1 {public:    void deleteNode(ListNode* node) {        ListNode *pre = nullptr;        ListNode *cur = node;        while (cur->next != nullptr) {            cur->val = cur->next->val;            pre = cur;            cur = cur->next;        }        pre->next = nullptr;        delete cur;    }};

这里我使用了一个遍历,循环将要删除的节点之后的节点依次往前复制,最后删除掉最后一个节点即可。

其实中间的 while 循环还可以简化成 for 循环,那么代码看上去就更简化了:

// my second solution 2 , runtime = 13 msclass Solution2 {public:    void deleteNode(ListNode* node) {        ListNode *pre = nullptr;        ListNode *cur = node;        for (; cur->next; pre = cur, cur = cur->next)            cur->val = cur->next->val;        pre->next = nullptr;        delete cur;    }};

这里第二个版本的代码与第一个版本的代码思路是完全一样的。

但是 T_T
我这里有一点点思维的陷阱:为什么要循环往前复制呢?

明明我只需要将欲删除的节点的下一个节点往前复制一个,然后删除下一个节点就可以了呀(这也是我在做这道题的时候出现了的一点点思维陷阱,从一开始想到遍历就无法跳出来了),在看到了其他人的答案后,我才恍然大悟,写出了第三个版本的方法:

// perfect soluiton 3 , runtime = 13 msclass Solution3 {public:    void deleteNode(ListNode* node) {        if (node == nullptr) return;        ListNode *temp = node->next;        node->val = temp->val;        node->next = temp->next;        delete temp;    }};

这个版本的代码非常非常简单,也就是上面说的思路,找到下一个节点,然后将下一个节点的值复制到当前节点,然后删除下一个节点。

^_^ 就是这么简单 ~~~
所以你能理解引言里面我截的图里所说的了吧:

Why LeetCode accepted such stupid question?

哈哈,有时候真觉得 LeetCode 上面的人挺可爱的。

三、总结

这道题大致看了看高票答案,思路不出其右者,也就不需要再细说了。

其实我觉得这道题并非像最高票答案所说的是 Stupid Question。为什么这么说呢?

大多数人(包括我)在看到链表指定节点的删除的时候,总会想到拿到根节点然后遍历然后执行那教条般的几个步骤。但是这道题不一样了,不给你根节点,这确实对我产生了一点点迷惑。

总的来说,我觉得这是一道非常好的题目,尽管解题方法非常简单。

每天多做一道这样的又简单又能提高思维的题目,真的是非常愉悦的呢 : )

原创粉丝点击