《程序员面试金典(第6版)》面试题 02.01. 移除重复节点
创始人
2024-05-28 10:09:32
0

题目描述

编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。

示例1:

  • 输入:[1, 2, 3, 3, 2, 1]
    输出:[1, 2, 3]

-示例2:

输入:[1, 1, 1, 1, 2]
输出:[1, 2]

提示:

  • 链表长度在[0, 20000]范围内。
    链表元素在[0, 20000]范围内。

进阶:

  • 如果不得使用临时缓冲区,该怎么解决?

解题思路与代码

首先,这道题于本质上是要让你删除一些重复的节点。那么删除一个节点需要做哪些操作呢?

首先本题给的是单链表。如果要删除某个节点,则要找到当前节点的前驱节点,使前驱节点的next指针指向当前节点的下一个节点,最后将当前节点的内存释放掉,至此,删除某个节点的操作才算正式完成。

哈希法

因为要删除一个节点,我们就要用该节点的前驱节点去指向该节点的下一个节点。所以,我们就先设立一个要被处理元素的前驱节点,然后依次遍历被处理元素这个节点。如果被处理元素需要被删除,那我们直接用前驱节点删除好了。

为什么要叫哈希法呢?这是因为用到了unordered_set这种无序的关联容器。当我们为在这个集合中找到这个未处理元素时,我们就将这个元素添加到这个集合中去。如果找到了呢?就直接那被处理元素的前驱节点去删除这个节点就好了。这就是这道题的完整思想,剩下的请看代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* removeDuplicateNodes(ListNode* head) {if(head == nullptr) return head;unordered_set set = {head->val};ListNode* pos = head;while(pos->next != nullptr){ListNode* cur = pos->next; //即将要删除的节点if(set.find(cur->val) == set.end()){set.insert(cur->val);pos = cur;}else{pos->next = cur->next;delete cur;}}return head;}
};

复杂度分析:

  • 时间复杂度O(N),因为只用了一个while循环,其中N是给定链表的节点数目。

  • 空间复杂度O(N),因为最坏情况下,集合中的元素都不相同,我们要存储所有的元素到集合中。

进阶:不使用临时缓冲区

说到不使用临时缓冲区,其实它的意思就是让我直接对链表进行操作。那么如果想象成删除一个string中重复出现的字符了话,这道题其实用两个for循环暴力破解了就行。但这道题是在链表上进行操作,我们就要将双层for循环,去改成双层while循环。

这解题思路还是与哈希法类似,一共需要设立3个节点。
第一个节点作为外层循环遍历节点与被处理元素的对照组,初始值:head。
第二个节点作为被处理元素的前驱节点,初始值也:第一个节点。
第三个节点作为被处理元素,初始值为:第二个节点->next。

具体实现的看代码细节:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* removeDuplicateNodes(ListNode* head) {if(head == nullptr) return head;ListNode* pos = head; //对照节点while(pos != nullptr){ListNode* pre = pos; //被处理元素的前驱节点ListNode* cur = pre->next; //被处理元素while(cur != nullptr){if(pos->val != cur->val){pre = cur;}else{pre->next = cur->next;}cur = cur->next;}pos = pos->next;}return head;}
};

复杂度分析:
时间复杂度O(N^2),其中N代表所给链表的节点数。用了两个while循环。
空间复杂度O(1),因为只用到了几个临时变量。

优化:双层遍历法

这次代码对应上次的优化是只设置了两个节点用来变量。我们将pos作为外层遍历节点与对照组节点,将cur作为前驱节点,将cur->next作为被处理节点。

减少了一个临时变量的设置,优化了一行代码,但是代码的易读性变差,并且代码易错性增强。

具体实现看代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode* removeDuplicateNodes(ListNode* head) {if(head == nullptr) return head;ListNode* pos = head; while(pos != nullptr){ListNode* cur = pos; while(cur->next != nullptr){ if(cur->next->val == pos->val)cur->next = cur->next->next; elsecur = cur->next;}pos = pos->next;}return head;}
};

复杂度分析:
时间复杂度O(N^2),其中N代表所给链表的节点数。用了两个while循环。
空间复杂度O(1),因为只用到了几个临时变量。

相关内容

热门资讯

官渡区举行春季学期期末工作会   本报讯 记者杨艳萍报道 日前,昆明市官渡区教育体育系统2024—2025学年春季学期期末工作会举...
七个成功的农村小本创业成功案例... 案例二:小王创业记某校机械专业毕业的小王。毕业后盲目创业,学着别人倒菜、倒水果、倒服装,几经波折,没...
这一新兴行业火了,成百万人选择... 目前,对于很多“懒人”来说,早已经是离不开外卖小哥了,无论想吃什么,想喝什么,外卖小哥都会准时准点为...
创业板注册制首批企业将上市 2... 创业板注册制首批企业将上市20%涨跌幅时代来临新浪财经综合原标题:创业板注册制首批企业将上市20%涨...
什么是 7大战略新兴产业 什么... 七大新兴产业,指国家战略性新兴产业规划及中央和地方的配套支持政策确定的7个领域(23个重点方向),“...
7万亩国土绿化抚育管护全面通过... 转自:黑龙江日报 日前,成都龙泉山城市森林公园管委会联合四川省林业科学研究院组成第三方验收工...
2019年有目前的新兴行业哪些... 市场上行业多,机遇多,但同样的困惑也多。很多创业者不知道该选择哪些行业哪种项目,往往面对纷繁杂乱的创...
“非法改装”得从源头刹住 转自:千龙网22处流动销售点位,均已清理处置——针对超标电动自行车销售问题,北京市有关部门主动出击,...
2012年给创业者的10点建议... 在互联网创业浪潮中,最成功的往往不是最优秀的,而是那些最能抓住机遇的。每一个时代都有它的特征,尤其是...
桂湖 并蒂莲花盛开处 文脉绵延... 桂湖并蒂莲开。□四川日报全媒体记者 张红霞 文/图  7月8日,位于成都市新都区桂湖的新都杨升庵博物...