remove duplicates from sorted list(移除有序链表中的重复元素)

题目描述

Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given1->1->2, return1->2.
Given1->1->2->3->3, return1->2->3.

题目大意

给定一个有序链表,删除其中重复元素,仅剩下一个。
如例子所见。

第一种方法

思路

维护两个指针,前指针负责向后遍历,后指针负责连接不重复的元素。
注意delete操作,以防止内存泄漏。

代码

#include<iostream>
using namespace std;
// Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
typedef ListNode* list_node; // 别名
ListNode *deleteDuplicates(ListNode *head)
{
    if(head == NULL)return NULL;
    list_node p1 = head;
    list_node p2 = head->next;
    while(p2)
    {
        if(p1->val == p2->val)
        {
            p1->next = NULL;
            list_node tmp = p2;
            p2 = p2->next;
            delete tmp;
        }
        else
        {
            p1->next = p2;
            p1 = p1->next;
            p2 = p2->next;
        }
    }

    return head;
}

int main()
{
    list_node p1, p2, p3, p4, p5;

    p1 = new ListNode(1);
    p2 = new ListNode(1);
    p3 = new ListNode(2);
    p4 = new ListNode(3);
    p5 = new ListNode(3);

    p1->next = p2;
    p2->next = p3;
    p3->next = p4;
    p4->next = p5;

    p1 = deleteDuplicates(p1);

    while(p1)
    {
        cout << p1->val << ' ';
        p1 = p1->next;
    }

    return 0;
}

运行结果

第二种方法

思路

思路跟第一种并无大的区别。

代码

typedef ListNode* list_node; // 别名
ListNode *deleteDuplicates(ListNode *head)
{
    if(head == NULL)return head;
    list_node cur = head;
    while(cur != NULL)
    {
        while(cur->next != NULL && cur->val == cur->next->val)
        {
            list_node tmp = cur->next;
            cur->next = cur->next->next;
            delete tmp;
        }
        cur = cur->next;
    }
    return head;
}

运行结果

以上。

<think>好的,我现在需要帮助用户解决如何在Python中移除列表里的重复元素的问题。首先,我得仔细理解用户的需求。用户提到了几个引用,看起来是关于LeetCode上删除有序链表或数组中重复元素的题目。这可能意味着用户正在准备面试或者练习算法题,所以需要高效且正确的方法。 用户的问题具体是询问如何移除Python列表中的重复元素。根据提供的引用,例如引用[4]中的代码,这是一个处理有序数组的例子。这可能说明用户知道有序和无序的情况可能需要不同的处理方法。因此,我应该分情况讨论:有序列表和无需列表的不同处理方式。 首先,对于有序列表,重复元素是相邻的,所以可以遍历列表,比较当前元素和前一个元素,跳过重复的。这种方法的时间复杂度是O(n),效率较高。例如引用[4]中的解决方案就是针对有序数组的,用户可能希望类似的方法应用到列表中。 其次,如果列表是无序的,常见的方法是使用集合(set)来去重,因为集合不允许重复元素。但要注意集合会打乱原有顺序,所以如果用户需要保持顺序,可以使用字典(在Python 3.7+中字典保留插入顺序)或者遍历列表并记录已出现的元素。比如,遍历列表,将元素添加到一个新列表,同时维护一个集合来检查是否已经存在。这种方法的时间复杂度也是O(n),但空间复杂度较高,因为需要额外的存储。 另外,用户可能还希望了解原地修改列表的方法,类似引用[4]中的数组处理,但列表在Python中是可变的,可以通过双指针的方法来实现。不过,对于列表来说,可能需要更多的元素移动操作,这可能效率不如新建一个列表。 还需要考虑用户是否需要保留一个重复元素(如去重后每个元素只出现一次)还是删除所有重复元素(只保留出现一次的元素)。根据引用[1]、[2]、[5],用户提供的例子中有两种情况:删除所有重复的节点,只保留不重复的。这可能意味着用户需要知道这两种不同的处理方式。 因此,我应该分情况给出不同的解决方案,并解释每种方法的适用场景、时间复杂度和空间复杂度。同时,提供示例代码,并指出哪些方法保持原有顺序,哪些不保持。 此外,用户可能对代码的效率有要求,所以需要比较不同方法的优劣。例如,使用集合的方法简单但可能不保持顺序,而遍历的方法保持顺序但需要更多空间。 最后,根据用户提供的引用,尤其是引用[4]中的数组处理,可能用户对处理数组(列表)更感兴趣,所以重点应放在列表操作上,而不是链表。但需要确认用户的问题是否仅限于列表。 总结步骤: 1. 确定用户需求:移除列表重复元素,保持顺序与否,是否允许使用额外空间。 2. 分情况讨论:有序列表和无需列表。 3. 针对每种情况给出不同的方法,如集合、遍历、双指针等。 4. 提供示例代码,并解释优缺点。 5. 引用相关的LeetCode题目作为参考,帮助用户进一步练习。</think>在Python中移除列表重复元素主要有以下几种方法,根据是否保留顺序和列表是否有序可选择不同方案: ### 一、无需保留原始顺序(无序列表) $$O(n) \text{时间复杂度,} O(n) \text{空间复杂度}$$ ```python def remove_duplicates(lst): return list(set(lst)) ``` 该方法利用集合特性自动去重,但会丢失元素顺序[^4]。 ### 二、需要保留原始顺序 1. **通用方法(适合任意列表)** $$O(n^2) \text{最差时间复杂度}$$ ```python def remove_duplicates_ordered(lst): seen = [] for item in lst: if item not in seen: seen.append(item) return seen ``` 2. **优化方法(适合大型列表)** $$O(n) \text{时间复杂度,} O(n) \text{空间复杂度}$$ ```python def remove_duplicates_fast(lst): seen = set() result = [] for item in lst: if item not in seen: seen.add(item) result.append(item) return result ``` ### 三、有序列表特化方法 $$O(n) \text{时间复杂度,} O(1) \text{空间复杂度(原地修改)}$$ ```python def remove_duplicates_sorted(nums): if not nums: return 0 write_idx = 1 for i in range(1, len(nums)): if nums[i] != nums[i-1]: nums[write_idx] = nums[i] write_idx += 1 return nums[:write_idx] # 返回新列表 ``` 该方法适用于已排序列表,采用双指针技术实现原地修改,与LeetCode第26题解法一致[^4]。 ### 四、删除所有重复元素(仅保留唯一值) 当需要删除所有出现过重复的元素(如LeetCode第82题要求[^2][^5])时: ```python def remove_all_duplicates(lst): from collections import defaultdict count = defaultdict(int) for num in lst: count[num] += 1 return [k for k, v in count.items() if v == 1] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值