!!!学习自labuladong
递归条件
大问题拆成两个子问题——头结点和除头结点之外所有结点
子问题求解方式和大问题一样
存在最小子问题
遍历方式
void traverse(ListNode head) {
// 前序遍历代码
traverse(head.next);
// 后序遍历代码
}
双指针技巧——快慢指针
fast = slow = head; while(fast!=null&&fast.next!=null){ fast = fast.next.next; slow = slow.next; }
206. 反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
public ListNode reverseList(ListNode head) {
if(head==null) return null;
if(head.next==null) return head;
ListNode last = reverseList(head.next);
head.next.next = head;
head.next = null;
return last;
}
92. 反转链表 II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
public ListNode reverseBetween(ListNode head, int left, int right) {
if(left==1){
return reverseN(head,right);
}
head.next = reverseBetween(head.next,left-1,right-1);
return head;
}
ListNode successor;
ListNode reverseN(ListNode head,int n){
if(n==1){
successor = head.next;
return head;
}
ListNode last = reverseN(head.next,n-1);//把head.next看作索引1
head.next.next = head;
head.next=successor;
return last;
}
234. 回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
//注意这种方法效率较低
ListNode left;
public boolean isPalindrome(ListNode head) {
left = head;
return build(head);
}
boolean build(ListNode right){
if(right==null) return true;
boolean ans = build(right.next);
//后序遍历
ans = ans&&(left.val==right.val);
left = left.next;
return ans;
}
- 快慢指针
141. 环形链表
如果有环,两个指针会相遇
public boolean hasCycle(ListNode head) {
ListNode slow,fast;
slow = fast = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast==slow) return true;
}
return false;
}
142. 环形链表 II
-
脑筋急转弯,fast走了2k,slow走了k步。环为k长。
-
public ListNode detectCycle(ListNode head) { ListNode slow,fast; slow = fast = head; boolean flag=true; while(fast!=null&&fast.next!=null){ slow=slow.next; fast=fast.next.next; if(slow==fast){ flag=false; break; } } if(flag) return null; slow = head; while(slow!=fast){ slow=slow.next; fast=fast.next; } return slow; }
876. 链表的中间结点
剑指 Offer 22. 链表中倒数第k个节点
21. 合并两个有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null||l2==null){
return l1==null?l2:l1;
}
if(l1.val<l2.val){
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
23. 合并K个升序链表
public ListNode mergeKLists(ListNode[] lists) {
return merge(lists,0,lists.length-1);
}
ListNode merge(ListNode[] lists,int lo,int hi){
if(lo>hi) return null;
if(lo==hi) return lists[lo];
int mid= (lo+hi)>>1;
return merge2Lists(merge(lists,lo,mid),merge(lists,mid+1,hi));
}
ListNode merge2Lists(ListNode a,ListNode b){
if(a==null||b==null) return a==null?b:a;
if(a.val<b.val){
a.next = merge2Lists(a.next,b);
return a;
}else{
b.next = merge2Lists(a,b.next);
return b;
}
}