目录
2、给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
3、给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点
总结:
善于运用递归思想;
在头节点前设置一个哑结点很多时候会很方便;
1、将两个单向升序链表合并为一个链表
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1); //预先指针,值随便写
ListNode prev = prehead; //当前指针
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
}
2、给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode pre = new ListNode(0); //预先指针
ListNode cur = pre; //当前指针
int carry = 0; //进位值
while(l1 != null || l2 != null) {
int x = l1 == null ? 0 : l1.val;
int y = l2 == null ? 0 : l2.val;
int sum = x + y + carry;
carry = sum / 10; //表示进位值
sum = sum % 10; //实际存入链表的值
cur.next = new ListNode(sum);
cur = cur.next;
if(l1 != null)
l1 = l1.next;
if(l2 != null)
l2 = l2.next;
}
if(carry == 1) {
cur.next = new ListNode(carry);
}
return pre.next;
}
}
3、给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
int length = getLength(head);
ListNode cur = dummy;
for (int i = 1; i < length - n + 1; ++i) {
cur = cur.next;
}
cur.next = cur.next.next;
ListNode ans = dummy.next;
return ans;
}
public int getLength(ListNode head) {
int length = 0;
while (head != null) {
++length;
head = head.next;
}
return length;
}
}
4、将一个链表数组中的链表按照升序合并
思路:我们可以想到一种最朴素的方法:用一个变量 ans 来维护以及合并的链表,第 i 次循环把第 i 个链表和 ans 合并,答案保存到 ans 中。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode ans = null;
for (int i = 0; i < lists.length; ++i) {
ans = mergeTwoLists(ans, lists[i]);
}
return ans;
}
public ListNode mergeTwoLists(ListNode a, ListNode b) {
if (a == null || b == null) {
return a != null ? a : b;
}
ListNode head = new ListNode(0);
ListNode tail = head, aPtr = a, bPtr = b;
while (aPtr != null && bPtr != null) {
if (aPtr.val < bPtr.val) {
tail.next = aPtr;
aPtr = aPtr.next;
} else {
tail.next = bPtr;
bPtr = bPtr.next;
}
tail = tail.next;
}
tail.next = (aPtr != null ? aPtr : bPtr);
return head.next;
}
}
5、两两交换链表中的节点(递归)
class Solution {
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = head.next;
head.next = swapPairs(newHead.next);
newHead.next = head;
return newHead;
}
}
6、反转链表(递归)
public ListNode reverseList(ListNode head) {
//递归结束条件
if (head == null || head.next == null) {
return head;
}
// 调用递推公式反转当前结点之后的所有节点
// 返回的结果是反转后的链表的头结点
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
7、反转链表的前n个节点(递归)
ListNode topNSuccessor = null;
private ListNode reverseTopN(ListNode head, int n) {
if (n == 1) {
topNSuccessor = head.next;
return head;
}
ListNode newHead = reverseTopN(head.next, n-1);
head.next.next = head;
head.next = topNSuccessor;
return newHead;
}
8、只反转从位置m到位置n(递归)
public ListNode reverseBetween(ListNode head, int m, int n) {
if (m == 1) {
return reverseTopN(head, n);
}
ListNode between = reverseBetween(head.next, m-1,n-1);
head.next = between;
return head;
}
ListNode topNSuccessor = null;
private ListNode reverseTopN(ListNode head, int n) {
if (n == 1) {
topNSuccessor = head.next;
return head;
}
ListNode newHead = reverseTopN(head.next, n-1);
head.next.next = head;
head.next = topNSuccessor;
return newHead;
}