Bootstrap

【链表】力扣 2816. 翻倍以链表形式表示的数字

一、题目

在这里插入图片描述

二、思路

  • 方法一
    根据题目 力扣 445. 两数相加 II 的思路。要进行链表的运算可以将链表首先进行 反转 (见 力扣 206. 反转链表),再来进行两节点之间的数值运算(见 力扣 2. 两数相加)。
  • 方法二
    本题与进行两数相加的差别在于:
    • 题目两数相加 是否产生进位的问题毫无规律可言,只取决于相加的两个链表对应的数值;
    • 而本题是将链表上的数字进行翻倍,获得的先验知识更多——可以看做两个相加的链表是一模一样的。那么,何时产生进位的规律也可以总结得到。
运算进位
1 × 20
2 × 20
3 × 20
4 × 20
5 × 21
6 × 21
7 × 21
8 × 21
9 × 21

由于链表存储数值采取的不是逆序的,与我们正常进行运算的顺序是相反的。但是根据本题中多出的先验知识,我们可以来避免进行 反转 的步骤。
根据上述表格可知,当节点的数值 大于 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;
    }
}
;