一、题目
二、思路
- 方法一
根据题目 力扣 445. 两数相加 II 的思路。要进行链表的运算可以将链表首先进行 反转 (见 力扣 206. 反转链表),再来进行两节点之间的数值运算(见 力扣 2. 两数相加)。 - 方法二
本题与进行两数相加的差别在于:- 题目两数相加 是否产生进位的问题毫无规律可言,只取决于相加的两个链表对应的数值;
- 而本题是将链表上的数字进行翻倍,获得的先验知识更多——可以看做两个相加的链表是一模一样的。那么,何时产生进位的规律也可以总结得到。
运算 | 进位 |
---|---|
1 × 2 | 0 |
2 × 2 | 0 |
3 × 2 | 0 |
4 × 2 | 0 |
5 × 2 | 1 |
6 × 2 | 1 |
7 × 2 | 1 |
8 × 2 | 1 |
9 × 2 | 1 |
由于链表存储数值采取的不是逆序的,与我们正常进行运算的顺序是相反的。但是根据本题中多出的先验知识,我们可以来避免进行 反转 的步骤。
根据上述表格可知,当节点的数值 大于 4 时才会有进位。因此,在不反转链表的情况下,只需要判断下一个节点的值与 4 的关系就可以确定当前节点是否要加进位 1。特别地,当头结点的数值大于 4 时,需要新创建一个节点来存储翻倍后进位产生的数值。
三、题解
- 方法一
/**
* 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 doubleIt(ListNode head) {
if (head == null) return null;
ListNode reversed = reverseList(head);
ListNode doubled = doubleList(reversed, 0);
return reverseList(doubled);
}
public ListNode reverseList(ListNode head) {
ListNode pre = null, cur = head;
while (cur != null) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
public ListNode doubleList(ListNode head, int carry) {
if (head == null) {
return carry != 0 ? new ListNode(carry) : null;
}
int value = (head.val * 2 + carry) % 10;
carry = (head.val * 2 + carry) / 10;
head.val = value;
head.next = doubleList(head.next, carry);
return head;
}
}
- 方法二
/**
* 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 doubleIt(ListNode head) {
if (head.val > 4) {
head = new ListNode(0, head);
}
ListNode cur = head;
while (cur != null) {
cur.val = cur.val * 2 % 10;
if (cur.next != null && cur.next.val > 4) {
cur.val++;
}
cur = cur.next;
}
return head;
}
}