20200909:链表类题目集合下

题目

1.138. 复制带随机指针的链表
在这里插入图片描述
2.21. 合并两个有序链表
在这里插入图片描述
3.23. 合并K个升序链表
在这里插入图片描述

思路与算法

  1. 返回深拷贝这个题目的意思读清楚就好了,要去找确定那个random指针到底指向了哪个节点。这是关键。用map来映射比较清晰,附上cpp和java两种语言的代码题解
  2. 合并链表的题目思路大致相同,对21来讲,合并两个链表,两种方法,无非是使用dummy_head这类方法或者是使用递归来实现。具体见代码,对23来讲,可以使用排序的方法,排序的依据为val的大小,先将其排好序,再进行连接即可。

代码实现

1.138. 复制带随机指针的链表
C++

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
public:
    Node* copyRandomList(Node* head) {
        std::map<Node*,int> node_map;
        std::vector<Node*> node_vector;
        Node* ptr = head;
        int i = 0;
        while (ptr) {
            node_vector.push_back(new Node(ptr->val));
            node_map[ptr] = i;
            ptr = ptr->next;
            i++;
        }
        node_vector.push_back(0);
        ptr = head;
        i = 0;
        while (ptr) {
            node_vector[i]->next = node_vector[i+1];
            if (ptr->random) {
                int id = node_map[ptr->random];
                node_vector[i]->random = node_vector[id];
            }
            ptr = ptr->next;
            i++;
        }
        return node_vector[0];
    }
};

Java

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/

class Solution {
    public Node copyRandomList(Node head) {
        if(head==null) {
            return null;
        }
        
        Map<Node,Node> map = new HashMap<Node,Node>();
        Node p = head;
        
        while(p!=null) {
            Node newNode = new Node(p.val);
            map.put(p,newNode);
            p = p.next;
        }
        p = head;
        
        while(p!=null) {
            Node newNode = map.get(p);
            
            if(p.next!=null) {
                newNode.next = map.get(p.next);
            }
           
            if(p.random!=null) {
                newNode.random = map.get(p.random);
            }
            p = p.next;
        }
        
        return map.get(head);
    }
}

2.21. 合并两个有序链表
递归cpp:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *dummy_head = nullptr;
        if (l1 == nullptr) {
            return l2;
        } 
        if (l2 == nullptr) {
            return l1;
        }
        if (l1->val > l2->val) {
            dummy_head = l2;
            dummy_head->next = mergeTwoLists(l1,l2->next);
        } else {
            dummy_head = l1;
            dummy_head->next = mergeTwoLists(l1->next,l2);
        }
        return dummy_head;
    }
};

递归java:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = null;
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }

        if (l1.val <= l2.val) {
            head = l1;
            head.next = mergeTwoLists(l1.next,l2);
        }else{
            head = l2;
            head.next = mergeTwoLists(l1,l2.next);
        }
        return head;
    }
}

dummy节点法cpp:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode dummy_head(0);
        ListNode* pre = &dummy_head;
        while (l1 && l2) {
            if (l1->val > l2->val) {
                pre->next = l2;
                l2 = l2->next;
            } else {
                pre->next = l1;
                l1 = l1->next;
            }
            pre = pre->next;
        }
        if (l1) {
            pre->next = l1;
        }
        if (l2) {
            pre->next = l2;
        }
        return dummy_head.next;
    }
};

3.23. 合并K个升序链表
cpp排序重连实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

 bool cmp(const ListNode* a,const ListNode* b){
     return a->val < b->val;
 }
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        std::vector<ListNode*> node_vec;
        // 把所有链表的节点存入node_vec
        for (int i = 0;i < lists.size();i++) {
            ListNode* head = lists[i];
            while (head) {
                node_vec.push_back(head);
                head = head->next;
            }
        }

        // 进行排序并连接即可
        if (node_vec.size() == 0) {
            return NULL;
        }

        std::sort(node_vec.begin(),node_vec.end(),cmp);
        for (int i = 1;i < node_vec.size();i++) {
            node_vec[i-1]->next = node_vec[i];
        }
        node_vec[node_vec.size()-1]->next = NULL;
        return node_vec[0];
    }
};

写在最后

复杂度基本都是排序函数的复杂度,因此不再深究,冲!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMMUNIZE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值