从一个未排序的链表中移除重复项

问题

从一个未排序的链表中移除重复的项?

附,

如果不允许使用临时的缓存,你如何解决这个问题?

分析

如果可以使用额外的存储空间,我们就开一个数组来保存一个元素的出现情况。 对于这种情况,最好的解决方法当然是使用哈希表,但令人非常不爽的是C++标准里是没有 哈希表的(java里有)。网上有人用ext下的hash_map,但毕竟不是C++标准里的, 用起来怪怪的,搞不好换个环境就跑不起来了(像Linux和Windows下使用就不一样)。 所以,一般用一个数组模拟一下就好了。但,这里要注意一个问题, 就是元素的边界,比如链表里存储的是int型变量。那么,如果有负值,这个方法就不奏效
了。而如果元素里的最大值非常大,那么这个数组也要开得很大,而数组中大部分空间是用 不上的,会造成空间的大量浪费。

简言之,如果可以用哈希表,还是用哈希表靠谱。

如下代码遍历一遍链表即可,如果某个元素在数组里记录的是已经出现过, 那么将该元素删除。时间复杂度O(n):

void removedulicate(node *head){
    if(head==NULL) return;
    node *p=head, *q=head->next;
    hash[head->data] = true;
    while(q){
        if(hash[q->data]){
            node *t = q;
            p->next = q->next;
            q = p->next;
            delete t;
        }
        else{
            hash[q->data] = true;
            p = q; q = q->next;
        }
    }
}

如果不允许使用临时的缓存(即不能使用额外的存储空间),那需要两个指针, 当第一个指针指向某个元素时,第二个指针把该元素后面与它相同的元素删除, 时间复杂度O(n2 ),代码如下:

void removedulicate1(node *head){
    if(head==NULL) return;
    node *p, *q, *c=head;
    while(c){
        p=c; q=c->next;
        int d = c->data;
        while(q){
            if(q->data==d){
                node *t = q;
                p->next = q->next;
                q = p->next;
                delete t;
            }
            else{
                p = q; q = q->next;
            }
        }
        c = c->next;
    }
}

完整示例:

#include <iostream>
#include <cstring>
using namespace std;

typedef struct node{
    int data;
    node *next;
}node;
bool hash[100];

node* init(int a[], int n){
    node *head, *p;
    for(int i=0; i < n; ++i){
        node *nd = new node();
        nd->data = a[i];
        if(i==0){
            head = p = nd;
            continue;
        }
        p->next = nd;
        p = nd;
    }
    return head;
}
void removedulicate(node *head){
    if(head==NULL) return;
    node *p=head, *q=head->next;
    hash[head->data] = true;
    while(q){
        if(hash[q->data]){
            node *t = q;
            p->next = q->next;
            q = p->next;
            delete t;
        }
        else{
            hash[q->data] = true;
            p = q; q = q->next;
        }
    }
}
void removedulicate1(node *head){
    if(head==NULL) return;
    node *p, *q, *c=head;
    while(c){
        p=c; q=c->next;
        int d = c->data;
        while(q){
            if(q->data==d){
                node *t = q;
                p->next = q->next;
                q = p->next;
                delete t;
            }
            else{
                p = q; q = q->next;
            }
        }
        c = c->next;
    }
}
void print(node *head){
    while(head){
        cout << head->data << " ";
        head = head->next;
    }
}
int main(){
    int n = 10;
    int a[] = {
        3, 2, 1, 3, 5, 6, 2, 6, 3, 1
    };
    memset(hash, false, sizeof(hash));
    node *head = init(a, n);
    //removedulicate(head);
    removedulicate1(head);
    print(head);
    return 0;
}
时间: 2024-11-03 22:02:11

从一个未排序的链表中移除重复项的相关文章

【链表】有序链表中移除重复项

1 public class Main { 2 3 public Node removeDup(Node node){ 4 5 if (node == null || node.next == null || node.next.next == null){ 6 return node; 7 } 8 9 Node pre = node.next; 10 Node cur = node.next.next; 11 12 while (cur != null){ 13 if (cur.data ==

剑指offer56:删除链表中重复的结点,排序的链表中,删除重复的结点不保留,返回链表头指针。 例如,链表1-&gt;2-&gt;3-&gt;3-&gt;4-&gt;4-&gt;5 处理后为 1-&gt;2-&gt;5

1 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 2 思路和方法 (1)链表为空,不必多说,return NULL: (2)如果恰恰是头结点与头结点的后一个重复了,这种情况是可以发生的,那头结点就要被删除,另选新的结点作为头结点.如何处理这种特殊情况,多申请一个指针就可以了. 3 C++核心代码 1 /* 2 struct

【python cookbook】【数据结构与算法】10.从序列中移除重复项且保持元素间顺序不变

问题:从序列中移除重复的元素,但仍然保持剩下的元素顺序不变 解决方案: 1.如果序列中的值时可哈希(hashable)的,可以通过使用集合和生成器解决. 2.如果序列时不可哈希的,想要去除重复项,需要对上述代码稍作修改: key参数的作用是指定一个函数用来将序列中的元素转化为可哈希的类型,如此可以检测重复项.

在未排序的数组中找到第 k 个最大的元素

在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 示例 2: 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4 说明: 你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度.思路方法:这道题思路就挺简单的,考查的就是对排序算法的了解.就用排序算法把数组元素按照降序排列,最后返回排序好的数组中下标为k-1的元素即是答

一个未排序整数数组,有正负数,重新排列使负数排在正数前面,并且要求不改变原来的 相对顺序 比如: input: 1,7,-5,9,-12,15 ans: -5,-12,1,7,9,15 要求时间复杂度O(N),空间O(1) 。

#include <iostream> using namespace std; void mSort(int *arr, int iLen) { int i, j, k, tmp; for(i = 0, j = 0; i < iLen; i++) { if (arr[i] < 0) { tmp = arr[i]; for(k = i; k > j; k--) arr[k] = arr[k - 1]; arr[j++] = tmp; } } } int main() { in

18 如何从一个数组中移除重复的元素

两种方法 (1) 使用LINQ (2) 使用List static void RemoveDups(string[] myStringArray) { // LINQ string[] str = myStringArray.Distinct().ToArray(); // Array to List to Array List<String> myStringList = new List<string>(); foreach (string s in myStringArray

[Leetcode] Remove duplicate from sorted list ii 从已排序的链表中删除重复结点

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. For example,Given1->2->3->3->4->4->5, return1->2->5.Given1->1->1->2->3, return2->3. 这题和R

判断两个数组中是否有重复项

两个数组判断是否有重复项 $.each(arr1,function(i,value){ val = value; num1 = i;//用来标记当前arr1数组中的重复项 $.each(arr2,function(i,value){ if(val == value){ alert(value); } }); });

删除一个没有头节点链表中的某个节点

题目描述:给定一个链表,没有头节点,如何删除其中的某个随机节点呢? 分析:如果一个链表没有头节点的话,那么我们就不可以找到被删除节点的前面一个节点.如何按照这个思路来,就无法实现功能了. 不如我们换一个思路,删除节点的目的是什么?是要达到被删除节点中的data被删除,也就是说,我们实际上只需要删除该节点的data,而不是整个节点.如何实现呢?我们可以把需要删除节点的后面一个节点中的data,依次往前面赋值,并把此节点删除,即可.例如:ABCD三个节点,假如我们需要删除B节点,那么我们可以把C->