LeetCode之Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

结构体定义如下:

struct RandomListNode {
    int label;
    struct RandomListNode *next;
    struct RandomListNode *random;
};

函数定义如下

struct RandomListNode *copyRandomList(struct RandomListNode *head) 


看到此题的标签是HashTable,知道应该用hash表,但是如何使用呢?

设原先的链表为list1,新的链表为list2

如果可以通过list1中的node1的random指针,找到list2中的node2的指针,

也就是说,假如random指向了list1中的第三个节点,那么random对应的node2也应该是第三个

如何建立node1和node2之间的联系呢?hash表


建立联系的过程如下:

    struct RandomListNode newhead = {0, NULL, NULL};
    struct RandomListNode* p = head;
    struct RandomListNode* q = &newhead;
    Hashtable* ht = createHashTable(1023);
    while(p){
        q->next = (struct RandomListNode*)malloc(sizeof(struct RandomListNode));
        q->next->label = p->label;
        insert(ht, (Key)p, (Value)q->next);
        q = q->next;
        p = p->next;
    }

可以看到将list1中的节点指针,和list2中的节点指针,通过一个hash表联系起来。


现在已经构建了新的链表和hash表,剩余的工作就是添加random指针。

就是使用random指针作为key,在hash表中查找对应的value,也就是list2中对应的节点指针。


但是,第一步的构建过程好像没有添加random指针,添加的是节点本身的指针,这么查找真的对吗?

仔细想一下,random指针其实是节点指针的子集。即以random为key的hash节点肯定是存在的。


添加random指针的过程如下:

    q = newhead.next;
    p = head;
    while(q){
        q->random = NULL;
        if(p->random){
            node* n1 = find(ht, (Key)p->random, comp);
            if(n1){
                q->random = (struct RandomListNode*)n1->value;
            }
        }
        p = p->next;
        q = q->next;
    }

为此,我还特意写了一个hash表,其实没有必要。

直接用STL中的unordered_map就行,为了练手,就自己写了一个。(其实是为了准备线上笔试,怕时间来不及,提前写好)

template<class Key, class Value>
class Hashtable;
template<class Key, class Value>
class node{
private:
    friend class Hashtable<Key, Value>;
    Key key;
    Value value;
    node* next;
public:
    node(const Key& k, const Value& v):key(k),value(v),next(NULL){}
    node():key(),value(),next(NULL){}
    Value& data(){ return value; }
    Key& index(){return key;}
    ~node(){ }
};

template<class Key, class Value>
class Hashtable{
private:
    node<Key,Value>* listheads;
    int size;
public:
    Hashtable(int size);
    ~Hashtable();
    void insert(const Key& key, const Value& value);
    node<Key, Value>* find(const Key& key);
};
template<class Key, class Value>
Hashtable<Key, Value>::Hashtable(int __size)
{
    listheads = new node<Key,Value>[__size];    //表头节点
    size = __size;
}
template<class Key, class Value>
Hashtable<Key, Value>::~Hashtable()
{
    node<Key, Value>* nd;
    node<Key, Value>* p;
    for(int i = 0;i<size;i++){
        nd = (listheads + i)->next;
        while(nd){
            p = nd;
            nd = nd->next;
            delete p;
        }
    }
    delete [] listheads;
}

template<class Key, class Value>
void Hashtable<Key, Value>::insert(const Key& key, const Value& value)
{
    node<Key,Value>* listhead = listheads + (key % size);
    node<Key,Value>* nd = new node<Key,Value>(key, value);
    nd->next = listhead->next;
    listhead->next = nd;       //后进先出式进链
}

template<class Key, class Value>
node<Key, Value>* Hashtable<Key, Value>::find(const Key& key){
    node<Key,Value>* nd = listheads + (key % size);
    while(nd && key != nd->key){
        nd = nd->next;
    }
    return nd;
}

功能很不完善,没有删除和修改功能,没有实现rehash,没有提供迭代器,更没有考虑线程安全性,更像是一个玩具。

想想项目中用到的hash表,确实比我这个要健全多了。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值