LeetCode链表常用技巧(一)
链表遍历
单链表中的每个结点不仅包含值,还包含链接到下一个结点的地址。通过这种方式,单链表将所有结点按顺序组织起来。所以我们对链表的遍历可以通过两种方式:迭代或者递归
我们约定链表结构如下:
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; }
}
迭代遍历代码:
public void list(ListNode head){
if(head == null){
return;
}
while(head != null){
System.out.println(head);
head = head.next;
}
}
递归遍历
public void list(ListNode head){
if(head == null){
return;
}
System.out.println(head);
list(head.next);
}
链表部分反转
LeetCode92题:
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
我们先考虑反转整个链表,然后一步一步推导出反转链表部分。
对于整个链表的反转我们有两种方式,迭代或者递归
//迭代
public ListNode reverse(ListNode head){
if(head == null || head.next == null){//当链表为空或者只有一个元素的时候
return head;
}
//pre为当前节点前一个节点,当前节点,next下一个节点
ListNode pre = null,cur = head,next = head;
while(cur != null){
next = cur.next;//获取当前节点下一个节点
cur.next = pre;//将当前节点的下一个节点设置为前一个节点
pre = cur;//将前一个节点后移
cur = next; //当前节点后移
}
return pre;
}
//递归
public ListNode reverse(ListNode head){
if(head.next == null){
return head;
}
ListNode last = reverse(head.next);//递归
head.next.next = head;
head.next = null;
return last;
}
反转链表的前k个节点
//递归反转单链表以head为头节点前k个
ListNode successor = null;
public ListNode reverseK(ListNode head,int k){
if(k == 1){
successor = head.next;
return head;
}
ListNode last = reverseK(head.next,k-1);
head.next.next = head;
head.next = successor;
return last;
}
反转链表的一部分
public ListNode reverseBetween(ListNode head, int left, int right) {
if(head == null || right - left == 0){
return head;
}
ListNode cur = head;
ListNode pre = null;
for(int i = 1; i < left;i++){
pre = cur;
cur = cur.next;
}
if(pre == null){
head = reverseK(head,right - left + 1);
}else{
pre.next = reverseK(cur,right - left + 1);
}
return head;
}
合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
//迭代遍历实现
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);//占位头指针,避免空指针
ListNode cur = prehead;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
cur.next = l1;
l1 = l1.next;
}else{
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = l1 == null ? l2 : l1;
return prehead.next;
}
//递归实现
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//递归实现
if(l1 == null){
return l2;
}else if(l2 == null){
return l1;
}else if(l1.val <= l2.val){
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}