445.2つの数値を追加するII2つのソリューション(配列とスタック)

トピック

2つの非負の整数を表す、2つの空でないリンクリストを提供します。番号の最上位ビットは、リンクリストの先頭にあります。それぞれのノードは1桁しか格納しません。これらの2つの数値を追加すると、新しいリンクリストが返されます。

数値0を除いて、これら2つの数値はどちらもゼロで始まらないと想定できます。

 

上級:

入力リンクリストを変更できない場合はどうすればよいですか?つまり、リスト内のノードを反転することはできません。

例:

输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 8 -> 0 -> 7

 構文解析

この質問の混乱の1つのポイントは、入力リストを結果として再利用する必要があるかどうかです。再利用する場合は、キャリーの問題に対処するための結果リストがあります。再利用しない場合は、ノードを直接作成すると大幅に削減されます。不利な点は、より多くのスペースを占めることです。

考える最も簡単な方法は、フリップして追加してからフリップすることです。反転が許可されていない場合は、スペースを利用し、補助配列、長いリンクリストの長さを使用して、リンクリストのキャリーを処理し、結果を出力できます。3番目のタイプは、トピック設定を使用した逆処理です。つまり、スタック、最初の入力と出力です。

解決策1:配列を助長し、入力リンクリストを再利用すると、時間とスペースが非常に効果的です

class Solution {
    int cntNodes(ListNode* list) {
        if (NULL == list)
            return 0;
        
        int len = 0;
        while (list) {
            ++len;
            list = list->next;
        }

        return len;
    }
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        if (NULL == l1)
            return l2;
        if (NULL == l2)
            return l1;
        
        //l1指向长链表
        int len1 = cntNodes(l1);
        int len2 = cntNodes(l2);
        if (len1 < len2) {
            swap(l1, l2);
            swap(len1, len2);
        }

        //tmp存两个数的和
        vector<int> tmp(len1);
        ListNode *p = l1;
        for (int i = 0; i < len1; ++i) {
            tmp[i] = p->val;
            p = p->next;
        }
        p = l2;
        for (int i = len1-len2; i < len1; ++i) {
            tmp[i] += p->val;
            p = p->next;
        }

        //处理进位
        int chg = 0;
        for (int i = len1-1; i >= 0; --i) {
            tmp[i] = tmp[i]+chg;
            chg = tmp[i]/10;
            tmp[i] = tmp[i]%10;
        }

        //将数存入长链表
        p = l1;
        for (int i = 0; i < len1; ++i) {
            p->val = tmp[i];
            p = p->next;
        }
        if (chg) {
            ListNode* node = new ListNode(chg);
            node->next = l1;
            return node;
        }

        return l1;
    }
};

空間はO(max(m、n))、時間はO(m + n)

解決策2:入力リンクリストを再利用する代わりにスタックを使用する

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        if (NULL == l1)
            return l2;
        if (NULL == l2)
            return l1;

        //链表入栈
        stack<int> sta1;
        stack<int> sta2;
        ListNode *p = l1;
        while (p) {
            sta1.push(p->val);
            p = p->next;
        }
        p = l2;
        while (p) {
            sta2.push(p->val);
            p = p->next;
        }

        //节点出栈
        ListNode dummy(0);
        ListNode *node = &dummy;
        int chg = 0;
        while (!sta1.empty() || !sta2.empty()) {
            int num = 0;
            if (!sta1.empty()) {
                num = sta1.top();
                sta1.pop();
            }
            if (!sta2.empty()) {
                num += sta2.top();
                sta2.pop();
            }

            num += chg;
            chg = num/10;
            num %= 10;

            p = new ListNode(num);
            p->next = node->next;
            node->next = p;
        }
        if (chg) {
            p = new ListNode(chg);
            p->next = node->next;
            node->next = p;
        }

        return dummy.next;
    }
};

    スタック時間の複雑さで言われる解釈はO(max(m、n) )(なぜ私はそれがO(m + n)だと思うのか、それなら2つのスタックの圧力ではなく、ああを横断するためのプッシュと見なすことができます.. 。)、スペースはO(m + n)です。入力リンクリストを再利用すると、多くの作業が発生します。それはあなたがそれをどのように実現するかに依存します。

おすすめ

転載: blog.csdn.net/sy_123a/article/details/109320279