演算法5: LeetCode_單連結串列_兩數相加

街頭小癟三發表於2022-11-24
  • 題目:
  • * 給你兩個 非空 的連結串列,表示兩個非負的整數。它們每位數字都是按照 逆序 的方式儲存的,並且每個節點只能儲存 一位 數字。
  • * 請你將兩個數相加,並以相同形式返回一個表示和的連結串列。
  • * 你可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。

 

本題為力扣原題,連結為 https://leetcode.cn/problems/add-two-numbers/,具體例子參照原題給的demo

  解題思路:

  • 兩個單連結串列中的整數相加,涉及到相加和超過10,需要向前進一位
  • 兩個連結串列是否等長需要判斷,如果不等長度,需要先計算等長部分,超出的部分需要根據思路1得出的結果判讀。也就是前一位相加和滿足進位,則繼續計算;反之,則停止

 

 

package code.code_02;

/**
 * 力扣原題 https://leetcode.cn/problems/add-two-numbers/
 * 題目:
 * 給你兩個 非空 的連結串列,表示兩個非負的整數。它們每位數字都是按照 逆序 的方式儲存的,並且每個節點只能儲存 一位 數字。
 * 請你將兩個數相加,並以相同形式返回一個表示和的連結串列。
 * 你可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。
 *
 * demo1
 * 輸入:l1 = [2,4,3], l2 = [5,6,4]
 * 輸出:[7,0,8]
 * 解釋:342 + 465 = 807.
 *
 * demo2
 * 輸入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
 * 輸出:[8,9,9,9,0,0,0,1]
 *
 * 提示資訊是:
 * 每個連結串列中的節點數在範圍 [1, 100] 內
 * 0 <= Node.val <= 9
 * 題目資料保證列表表示的數字不含前導零
 *
 * 解題思路
 * 1, 兩兩相加,涉及到和超過10進位數
 * 2, 涉及到兩個連結串列長度不等
 * 3, 可以補全兩個連結串列,和單獨生成一個新連結串列,但是浪費空間;
 * 4; 可以把兩數之和壓入長連結串列中,逢十進一
 *
 */
public class NodeListAddTest {

    //連結串列
    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 int length (ListNode node, int size)
      {
          while (node != null) {
              size++;
              node = node.next;
          }
          return size;
      }

    //獲取連結串列長度_遞迴方式
  /* public int length (ListNode node, int size)
    {
        if (node == null) {
            return size;
        }
        size++;
        return node.next != null ? length(node.next, size) : size;
    }*/


    public ListNode addTwoNumbers(ListNode l1, ListNode l2)
    {
        int length1 = this.length(l1, 0);
        int length2 = this.length(l2, 0);

        ListNode lNode = length1 < length2 ? l2 : l1; //長連結串列
        ListNode sNode = (lNode == l1) ? l2 : l1;   //短連結串列
        ListNode prev = null;

        int carry = 0; //進位
        ListNode node = lNode;

        //根據短連結串列進行迴圈
        while (sNode != null) {
            int total = sNode.val + lNode.val + carry;
            lNode.val = total % 10; //更新後,長連結串列當前位置的新值
            carry = total/10; //如果是1, 則需要進位
            if (lNode.next == null) {
                prev = lNode;
            }
            lNode = lNode.next;
            sNode = sNode.next;
        }

        //有可能兩個連結串列長度不一致,此時長連結串列需要繼續.
        while (lNode != null) {
            if (carry != 1) {
                break;
            }
            int total = lNode.val + carry;
            lNode.val = total % 10; //更新後,長連結串列當前位置的新值
            carry = total/10; //如果是1, 則需要進位
            if (lNode.next == null) {
                prev = lNode;
            }
            lNode = lNode.next;
        }

        //如果長連結串列最後一位數處理完還需要進位,則追加節點
        if (carry == 1) {
            ListNode tempNode = new ListNode(carry);
            prev.next = tempNode;
        }

        return node;
    }

    // 先設計列印方法,方便檢查逆轉後結果
    public void printNode (ListNode node)
    {
        if (node == null) {
            System.out.println("連結串列不存在");
        }
        System.out.println("當前節點的值為: " + node.val);
        //遞迴的方式逐層列印Node的子節點
        if(node.next != null) {
            printNode(node.next);
        }
    }

    public static void main(String[] args) {
        NodeListAddTest test = new NodeListAddTest();
        //連結串列1
        ListNode l1 = test.new ListNode(2);
        l1.next = test.new ListNode(4);
        l1.next.next = test.new ListNode(3);

        //連結串列2
        ListNode l2 = test.new ListNode(5);
        l2.next = test.new ListNode(6);
        l2.next.next = test.new ListNode(4);


        ListNode nodeList = test.addTwoNumbers(l1, l2);
        test.printNode(nodeList);

    }
}

 

 

力扣測試結果:

 

相關文章