2.兩數(shù)相加-java實(shí)現(xiàn)

第二題:兩數(shù)相加

給出兩個(gè) 非空 的鏈表用來表示兩個(gè)非負(fù)的整數(shù)。其中,它們各自的位數(shù)是按照 逆序 的方式存儲的,并且它們的每個(gè)節(jié)點(diǎn)只能存儲 一位 數(shù)字。
如果,我們將這兩個(gè)數(shù)相加起來,則會返回一個(gè)新的鏈表來表示它們的和。
您可以假設(shè)除了數(shù)字 0 之外,這兩個(gè)數(shù)都不會以 0 開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/check-permutation-lcci
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請聯(lián)系官方授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

V1版本

剛看到這個(gè)題目,就被誤導(dǎo)了,老套路,先暴力破解
解題思路
先提供兩個(gè)工具方法
1.鏈表轉(zhuǎn)整數(shù)
2.整數(shù)轉(zhuǎn)鏈表
執(zhí)行流程
1.將兩個(gè)鏈表轉(zhuǎn)成整數(shù)并相加
2.結(jié)得到的結(jié)果轉(zhuǎn)成鏈表
于是乎有了

鏈表轉(zhuǎn)int方法

例:鏈表 2 -> 4 -> 3 ==> 342
這個(gè)方法開始想復(fù)雜了,還想著先反轉(zhuǎn)鏈表后在計(jì)算整數(shù)值,寫完之后發(fā)現(xiàn)根本沒有畢要,
只需要循環(huán)鏈表,即 (2 * 10^0) + (4 * 10^1) + (3 * 10^2),代碼如下

private static int convertToInt(ListNode list) {
        // 結(jié)果整數(shù)
        int result = 0;
        // 索引位置
        int index = 0;
        while (list != null) {
            // 整數(shù)累加
            result += list.val * Math.pow(10, index++);
            // 將下一個(gè)節(jié)點(diǎn)賦值給list,之前的節(jié)點(diǎn)由于沒有引用,后續(xù)會被垃圾回收器回收
            list = list.next;
        }
        return result;
    }
整數(shù)轉(zhuǎn)鏈表

例:整數(shù) 807 ==> 7 -> 0 -> 8
整數(shù)轉(zhuǎn)鏈表也很簡單,對整數(shù)依次 %10 和 /10,遍歷取出7、0、8,將數(shù)值放入鏈表返回即可,代碼如下

private ListNode convertToListNode(int num) {
        // 第一個(gè)節(jié)點(diǎn)
        ListNode result = new ListNode(num % 10);
        // 將num
        num /= 10;
        // 定義臨時(shí)節(jié)點(diǎn)
        ListNode node = result;
        while (num > 0) {
            node.next = new ListNode(num % 10);
            num /= 10;
            node = node.next;
        }
        return result;
    }

只是讓我沒有想到的是,測試用例中的超長的鏈表,int根本不夠用,后改成long也不行,還有更長的鏈表


image.png

沒辦法,只能Plan B了

V2版本

一開始就說了被誤導(dǎo)了,其實(shí)認(rèn)真觀察可以發(fā)現(xiàn),根本不需要轉(zhuǎn)來轉(zhuǎn)去
(2 -> 4 -> 3) + (5 -> 6 -> 4)
可以想成是
2 + 5 -> 4 + 6 -> 3 + 4
只是要注意兩條鏈表不對等及需要進(jìn)位的情況,代碼如下

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1.val == 0) {
            return l2;
        }
        if (l2.val == 0) {
            return l1;
        }
        // 當(dāng)前節(jié)點(diǎn)的值
        int num;
        // 溢出值(進(jìn)位值),用于下一步累加,如6 + 6 = 12,那么 num = 2, overflowNum = 1
        int overflowNum = 0;
        // 兩個(gè)列表第一位進(jìn)行想加
        num = l1.val + l2.val;
        if (num >= 10) {
            overflowNum = 1;
            num %= 10;
        }
        // 返回的節(jié)點(diǎn)
        ListNode resultNode = new ListNode(num);
        // 兩個(gè)鏈表分別指向下一個(gè)鏈表
        l1 = l1.next;
        l2 = l2.next;

        int val1, val2;
        // 臨時(shí)節(jié)點(diǎn)
        ListNode node = resultNode;
        while (true) {
            if (l1 == null && l2 == null) {
                // 有進(jìn)位值則有一個(gè)節(jié)點(diǎn)
                if (overflowNum == 1) {
                    node.next = new ListNode(1);
                }
                return resultNode;
            }
            val1 = l1 == null? 0 : l1.val;
            val2 = l2 == null? 0 : l2.val;
            // 這里需要將進(jìn)位值一起加上
            num = val1 + val2 + overflowNum;
            if (num >= 10) {
                overflowNum = 1;
                num %= 10;
            } else {
                overflowNum = 0;
            }
            node.next = new ListNode(num);
            node = node.next;
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
    }

提交結(jié)果


image.png

為什么還會有0開頭的情況,是我誤解的

您可以假設(shè)除了數(shù)字 0 之外,這兩個(gè)數(shù)都不會以 0 開頭。

好吧,問題也不大,這里改一下就行了

        if (l1.val == 0 && l1.next == null) {
            return l2;
        }
        if (l2.val == 0 && l2.next == null) {
            return l1;
        }
image.png

V3版本

V3版本想解決的是
例:[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
[1]
這種情況下,算完第一個(gè)數(shù)字之后,根本不需要在向下執(zhí)行下去,直接將后續(xù)長的鏈表接到結(jié)果鏈表返回就可以了,同步參考了評論區(qū)一個(gè)大佬的精簡代碼實(shí)現(xiàn),代碼如下

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1.val == 0 && l1.next == null) {
            return l2;
        }
        if (l2.val == 0 && l2.next == null) {
            return l1;
        }
        ListNode resultNode = new ListNode(-1);
        ListNode node = resultNode;
        int num = 0;
        while (l1 != null || l2 != null || num != 0) {
            // 當(dāng)l1不為空,l2已經(jīng)沒有了,且num也為0的情況下根本不需要繼續(xù)走下去了,下面同理
            if (l1 != null && l2 == null && num == 0) {
                node.next = l1;
                return resultNode.next;
            }
            if (l1 == null && l2 != null && num == 0) {
                node.next = l2;
                return resultNode.next;
            }
            if (l1 != null) {
                num += l1.val;
                l1 = l1.next;
            }
            if (l2 != null) {
                num += l2.val;
                l2 = l2.next;
            }
            node.next = new ListNode(num % 10);
            node = node.next;
            num /= 10;
        }
        // 將一個(gè)-1節(jié)點(diǎn)剔除
        return resultNode.next;
    }

后面還參考官版本寫了個(gè)V4,不過都大同小異,現(xiàn)在還是還是太慢了,一個(gè)這題目寫了5~6個(gè)小時(shí),后續(xù)熟練后希望能提升點(diǎn)速度

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容