一、链表反转
剑指 Offer 24. 反转链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
25. K 个一组翻转链表
思路:反转链表的衍生,也是先分组再反转链表。
设定一个分组,保存分组的前一个结点pre,分组的后一个结点next,分组第一个结点start,分组最后一个结点end,然后让分组中的链表,进行反转,如果分组大小小于k就不需要反转了。
开始图是这样的: pre ----> [ start ----> ......----> end ] ----> next ---->......
反转后:pre ----> [ end ----> ......----> start ] ----> next ---->......
而分组中的反转,就可以直接用24题的反转链表方法
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//虚拟头结点
ListNode dummy = new ListNode();
dummy.next = head;
//保存分组的前一个结点
ListNode pre = dummy;
//分组的最后一个结点
ListNode end = dummy;
while(end.next != null){
//循环k次,找到最后一个
for(int i = 0; i < k && end != null; i++) end = end.next;
//小于k保持原有顺序
if(end == null) break;
//分组的第一个结点
ListNode start = pre.next;
//保存end的下一个
ListNode next = end.next;
//断开end和next的链接
end.next = null;
//反转start到end
pre.next = reverse(start);
//此时start和end反转了,这里的start其实在最后一个
//重新连接
start.next = next;
pre = start;
end = pre;
}
return dummy.next;
}
private ListNode reverse(ListNode head){
ListNode pre = null;
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;
//反转
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
二、合并链表
21. 合并两个有序链表
思路:递归,比较哪个小,小的那个的next指针指向,下一个指针和另外一个链表中小的那个
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1 == null) return list2;
if(list2 == null) return list1;
if(list1.val < list2.val){
list1.next = mergeTwoLists(list1.next, list2);
return list1;
}else{
list2.next = mergeTwoLists(list1, list2.next);
return list2;
}
}
}