题目
1.138. 复制带随机指针的链表
2.21. 合并两个有序链表
3.23. 合并K个升序链表
思路与算法
- 返回深拷贝这个题目的意思读清楚就好了,要去找确定那个random指针到底指向了哪个节点。这是关键。用map来映射比较清晰,附上cpp和java两种语言的代码题解
- 合并链表的题目思路大致相同,对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];
}
};
写在最后
复杂度基本都是排序函数的复杂度,因此不再深究,冲!