算法进阶——删除有序链表中重复的元素

题目


给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。

例如:

给出的链表为1→2→3→3→4→4→5, 返回1→2→5。

给出的链表为1→1→1→2→3, 返回2→3。

数据范围:链表长度0≤n≤10000,链表中的值满足∣val∣≤1000

要求:空间复杂度O(n),时间复杂度O(n)

进阶:空间复杂度O(1),时间复杂度O(n)

示例1

复制代码
输入:
{1,2,2}
返回值:
{1}

示例2

复制代码
输入:
{}
返回值:
{}

思路


因为是升序的链表,重复的元素时连在一起的,所以可以连续的跳过相同的节点。

这里有个小技巧:因为链表有可能前几个元素就是重复的,这时就需要删除头指针了,所以我们需要给链表增加一个自定义的表头,以方便后面删除了原来的头指针而找不到表头,还有需要注意的就是在返回的时候要去掉增加的表头。

这种解法的空间复杂度是O(1),另外也可以通过哈希表unordered_map来记录每个节点值出现的次数来解决这个问题。哈希表的方式空间复杂度就是O(n)了,如果链表的无序的,则哈希表的解决方法更通用。

解答代码


cpp 复制代码
/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
        // write code here
        if (head == nullptr) {
            return nullptr;
        }

        // 给链表增加一个表头,以便可以删除原链表的头结点。
        auto res = new ListNode(0);
        res->next = head;
        auto cur = res;

        while (cur->next != nullptr && cur->next->next != nullptr) {
            if (cur->next->val == cur->next->next->val) {
                int val = cur->next->val;
                // 跳过所有相同的值
                while (cur->next != nullptr && cur->next->val == val) {
                    cur->next = cur->next->next;
                }
            } else {
                cur = cur->next;
            }
        }

        // 返回值需要去掉增加的表头
        return res->next;
    }
};
相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark4 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218614 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法