🛸蓝蓝计算机考研算法-day14删除排序链表中的重复元素

207 阅读1分钟

Day14 2023/03/14

难度:简单

题目

给定一个已排序的链表的头heād,删除所有重复的元素使每个元素只出现一次。返回已排序 的链表。

提示: 链表中节点数目在范围(0,300)内
-100<=Node.va<=100
题目数据保证链表已经按升序排列

示例

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

运行实例

image.png

思路


本题是对链表进行去重操作,核心步骤就是判断某节点是不是重复元素,可以类比为-快速判断某个元素在该集合中是否存在,像这样的题目最常规的,最好用的做法就是哈希法,即使用一个哈希表作为辅助数组,用来记录每个元素出现的次数,对出现次数大于1的节点,进行删除去重即可。
具体步骤:

  • 遍历链表,从虚拟头节点开始,每次判断下一个节点,是否为首次出现,(其中recorde[val] == 0表示首次出现,否则不是),如果是首次出现就将该节点记录在辅助数中record中,否则删除该节点。

关键点


  • 每次判断下一个节点,是否为首次出现,而不是判断当前节点,是为了方便删除操作,这样每次删除一个节点的时候,我们都可以快速的拿到该节点的前驱节点。
  • 辅助数组中record[key] = val,其中key为节点的数据,val为该节点出现的次数。

算法实现


c++代码实现-删除排序链表中的重复元素

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

//定义链表节点
typedef struct LNode {
  int val;                                    //数据域
  LNode *next;                                //指针域
  LNode(int val) : val(val), next(nullptr){}; //构造函数
} * LinkList, LNode;

//创建链表(带虚拟头节点的尾插法)
LinkList ListTailInsert(int n) { // num为链表节点个数
  LNode *dummyHead = new LNode(-1), *r = dummyHead,
        *s; //虚拟头节点 尾指针,待插入节点指针
  int val;  //带插入节点的数据
  while (n-- && cin >> val) {
    s = new LNode(val);
    r->next = s;
    r = s;
  }
  cout << "链表创建完毕!!!" << endl;
  return dummyHead; // 返回虚拟头节点,方便操作
}

//对链表数据域相同的节点进行去重操作
void DelDupNode(LinkList &L) {
  LNode *cur = L, *tmp;           // 遍历指针,临时指针
  unordered_map<int, int> record; // 辅助数组,记录各个节点出现的次数
  while (cur->next) {
    int val = cur->next->val; // 数据域
    if (record[val] == 0) { // 对于第一次出现的节点,把它记录到辅助数组中
      record[val] = 1;
      cur = cur->next;
    } else {
      tmp = cur->next;             // 重复节点
      cur->next = cur->next->next; // 防止断链
      delete tmp;                  // 删除重复节点
    }
  }
}

int main() {
  //创建链表 ,测试数据[1,1,2]
  LinkList L = ListTailInsert(3); //创建链表
  DelDupNode(L);                  //去重
  LNode *cur = L->next;
  cout << "去重后的链表:";
  while (cur) {
    cout << cur->val << ' ';
    cur = cur->next;
  }
  return 0;
}
  • 时间复杂度 O(n)O(n)--- 不考虑创建链表所占用的时间,仅遍历整个链表,其中n为链表节点个数
  • 空间复杂度 O(n)O(n)---最坏情况下,该链表无重复节点,record辅助数组所占用的空间就等于链表节点个数n

总结

  • 小Tip: 当遇到快速判断某个集合中是否含有该元素的时候,一般可以尝试一下哈希法!!!(😏)