0
点赞
收藏
分享

微信扫一扫

力扣刷题笔记丨算法数据结构--链表--复制带随机指针的链表

you的日常 2022-02-16 阅读 59

1 题目分析

链接:138. 复制带随机指针的链表 - 力扣(LeetCode) (leetcode-cn.com)

该链表的结构如下:除了Next指针外,还存在一个random指针

class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};

思路一:哈希表(不太会做)

思路二:组合+拆分链表

本题关键在于如何在复制时储存random指针,由于random指针中含有之后的节点,因此必须存在一个原链表的完全复制,让新链表在构建时能够有指向。第一种使用键值储存原链表节点数据位置,第二种使用简单的结构储存节点数据,让新链表构建时指向方法较为方便

2 哈希表相关知识

参考资料:数据结构 Hash表(哈希表)_积跬步 至千里-CSDN博客_哈希表

C++ 中使用哈希表(unordered_map)的常用操作_hero_th的博客-CSDN博客_c++哈希表操作

2.1 哈希函数

数值与数值地址的映射函数

index=H(key)

2.2 哈希函数的构造

  • 直接定制
  • 数字分析
  • ……

不能太复杂,分布均匀

哈希冲突及解决方法

// 建立哈希表<a,b>从b类型到a类型的映射
unordered_map<int,int> map; //<string,string>,<char,char>

2.3 哈希表的操作

对于给定的key,计算hash地址index = H(key)

添加元素

map.insert(pair<int,int>(1, 10));
map.insert(pair<int,int>(2, 20));
map[3]=30;
map[4]=40;

查找

m.end()  //指向哈希表的最后一个容器,实则超出了哈希表的范围,为空
m.find(2)  //查找key为2的键值对是否存在 ,若没找到则返回m.end()
m.count(3)  //查找哈希表中key为3的键值对,返回其数量,为1,则找到,若没找到则返回0

遍历

unordered_map<int, int> count;
for (auto p : count) {
	int front = p.first;   //key
    int end = p.second;   //value
}

3 代码实现

3.1 哈希表方法

  • 初始化哈希列表与当前节点cur
  • 遍历链表,建立哈希表的键值对
  • 第二次遍历链表,复制next,random指针
  • 最后返回带两个指针的哈希表
class Solution {
public:
    Node* copyRandomList(Node* head) {
        // 非空判断
        if (head == nullptr) return nullptr;
        // 初始化哈希表与节点
        Node* cur = head;
        unordered_map<Node*,Node*> map;
        // 第一次遍历,建立键值对
        while (cur != nullptr){
            map[cur] = new Node(cur->val);
            cur = cur->next;
        }
        // 第二次遍历,建立next与random指针
        cur = head;
        while(cur != nullptr){
            map[cur]->next = map[cur->next];
            map[cur]->random = map[cur->random];
            cur = cur->next;
        }
    return map[head];
    }
};

3.2 组合+拆分链表

  • 第一次遍历,在原链表之后,复制新链表节点
  • 第二次遍历,指定新链表节点的random指针
  • 第三次遍历,通过拆分,指定新链表节点的next指针

这段自己写的代码超时了,下面贴的代码来自:图解算法数据结构 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台 (leetcode-cn.com)

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        Node* cur = head;
        // 1. 复制各节点,并构建拼接链表
        while(cur != nullptr) {
            Node* tmp = new Node(cur->val);
            tmp->next = cur->next;
            cur->next = tmp;
            cur = tmp->next;
        }
        // 2. 构建各新节点的 random 指向
        cur = head;
        while(cur != nullptr) {
            if(cur->random != nullptr)
                cur->next->random = cur->random->next;
            cur = cur->next->next;
        }
        // 3. 拆分两链表
        cur = head->next;
        Node* pre = head, *res = head->next;
        while(cur->next != nullptr) {
            pre->next = pre->next->next;
            cur->next = cur->next->next;
            pre = pre->next;
            cur = cur->next;
        }
        pre->next = nullptr; // 单独处理原链表尾节点
        return res;      // 返回新链表头节点
    }
};

 

举报

相关推荐

0 条评论