文章目录
leetcode 86.分隔链表
题目描述
给你一个链表和一个特定值 x ,请你对链表进行分隔,使得所有小于 x 的节点都出现在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。(传送门)
示例:
输入:head = 1->4->3->2->5->2, x = 3
输出:1->2->2->4->3->5
解题思路&代码实现
思路和题解见:【每日一题】力扣86.分隔链表
leetcode138.复制带随机指针的链表
题目描述
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。 (传送门)
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:
输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
解题思路&代码实现
使用两张map来实现
public Node copyRandomList(Node head) {
//深拷贝: 完全拷贝基本数据类型和引用数据类型,安全。
if (head == null) {
return null;
}
Node newHead = new Node(-1);
Node temp = head;
// map1 <原链表节点,编号>
HashMap<Node, Integer> map1 = new HashMap<>();
// map2 <新链表节点,编号>
HashMap<Integer, Node> map2 = new HashMap<>();
int len = 0;
Node newHead2 = newHead;
// 构造新链表,只建立next关系
while (head != null) {
map1.put(head, len);
Node tmp = new Node(head.val);
map2.put(len, tmp);
newHead.next = tmp;
newHead = newHead.next;
head = head.next;
len++;
}
newHead2 = newHead2.next;
Node ans = newHead2;
// 从新链表头节点开始建立random 关系
while (newHead2 != null) {
Integer index = map1.get(temp.random);//在原链表中查找random位置
newHead2.random = map2.get(index);//在新链表找到对应原链表index位置的新节点
newHead2 = newHead2.next;// 建立关系
temp = temp.next;
}
return ans;
}
leetcode21.合并两个有序链表
题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 (传送门)
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
解题思路&代码实现
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null ) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode newHead = new ListNode(-1);
ListNode ans = newHead;
while (l1 != null && l2 != null) {
if (l1.val > l2.val) {
newHead.next = l2;
l2 = l2.next;
newHead = newHead.next;
} else {
newHead.next = l1;
newHead = newHead.next;
l1 = l1.next;
}
}
if (l1 == null) {
// l2有剩余
newHead.next = l2;
}
if(l2 == null) {
//l1有剩余
newHead.next = l1;
}
return ans.next;
}
leetcode23.合并K个升序链表
题目描述
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。(传送门)
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
解题思路&代码实现
方法一:暴力调用上一个题的方法
比如有k个链表,先合并1和2,合并之后的结果在和第三个合并知道最后一个。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int len = lists.length;
if(len == 0) {
return null;
}
for (int i = 0; i < len - 1; i++) {
lists[i+1] = mergeTwoLists(lists[i], lists[i + 1]);
}
return lists[len - 1];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null ) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode newHead = new ListNode(-1);
ListNode ans = newHead;
while (l1 != null && l2 != null) {
if ( l1.val > l2.val) {
newHead.next = l2;
l2 = l2.next;
newHead = newHead.next;
} else {
newHead.next = l1;
newHead = newHead.next;
l1 = l1.next;
}
}
if (l1 == null) {
newHead.next = l2;
}if(l2 == null) {
newHead.next = l1;
}
return ans.next;
}
}
方法二:优化,对称合并
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int len = lists.length;
if(len == 0) {
return null;
}
// 将n个链表以中间为对称,合并,即合并
while(len>1) {
for (int i=0; i<len/2; i++) {
lists[i] = mergeTwoLists(lists[i], lists[len-1-i]);
}
len = (len+1)/2;
}
return lists[0];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null ) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode newHead = new ListNode(-1);
ListNode ans = newHead;
while (l1 != null && l2 != null) {
if ( l1.val > l2.val) {
newHead.next = l2;
l2 = l2.next;
newHead = newHead.next;
} else {
newHead.next = l1;
newHead = newHead.next;
l1 = l1.next;
}
}
if (l1 == null) {
newHead.next = l2;
}if(l2 == null) {
newHead.next = l1;
}
return ans.next;
}
}
两种方法的时间复杂度提高还是很高的。
方法三:小根堆
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null || lists.length==0) {
return null;
}
//创建一个堆,并设置元素的排序方式
PriorityQueue<ListNode> queue = new PriorityQueue(new Comparator<ListNode>() {
public int compare(ListNode o1, ListNode o2) {
return (o1.val - o2.val);
}
});
//遍历链表数组,然后将每个链表的每个节点都放入堆中
for(int i=0;i<lists.length;i++) {
while(lists[i] != null) {
queue.add(lists[i]);
lists[i] = lists[i].next;
}
}
ListNode dummy = new ListNode(-1);
ListNode head = dummy;
//从堆中不断取出元素,并将取出的元素串联起来
while( !queue.isEmpty() ) {
dummy.next = queue.poll();
dummy = dummy.next;
}
dummy.next = null;
return head.next;
}
}