1. 程式人生 > >[LeetCode] Plus One Linked List 連結串列加一運算

[LeetCode] Plus One Linked List 連結串列加一運算

Given a non-negative number represented as a singly linked list of digits, plus one to the number.

The digits are stored such that the most significant digit is at the head of the list.

Example:

Input:
1->2->3

Output:
1->2->4

這道題給了我們一個連結串列,用來模擬一個三位數,表頭是高位,現在讓我們進行加1運算,這道題的難點在於連結串列無法通過座標來訪問元素,只能通過遍歷的方式進行,而這題剛好讓我們從鏈尾開始操作,從後往前,遇到進位也要正確的處理,最後還有可能要在開頭補上一位。那麼我們反過來想,如果鏈尾是高位,那麼進行加1運算就方便多了,直接就可以邊遍歷邊進行運算處理,那麼我們可以做的就是先把連結串列翻轉一下,然後現在就是鏈尾是高位了,我們進行加1處理運算結束後,再把連結串列翻轉回來即可,參見程式碼如下:

解法一:

class Solution {
public:
    ListNode* plusOne(ListNode* head) {
        if (!head) return head;
        ListNode *rev_head = reverse(head), *cur = rev_head, *pre = cur;
        int carry = 1;
        while (cur) {
            pre = cur;
            int t = cur->val + carry;
            cur
->val = t % 10; carry = t / 10; if (carry == 0) break; cur = cur->next; } if (carry) pre->next = new ListNode(1); return reverse(rev_head); } ListNode* reverse(ListNode *head) { if (!head) return head; ListNode
*dummy = new ListNode(-1), *cur = head; dummy->next = head; while (cur->next) { ListNode *t = cur->next; cur->next = t->next; t->next = dummy->next; dummy->next = t; } return dummy->next; } };

我們也可以通過遞迴來實現,這樣我們就不用翻轉連結串列了,通過遞迴一層一層的呼叫,最先處理的是鏈尾元素,我們將其加1,然後看是否有進位,返回進位,然後回溯到表頭,加完進位,如果發現又產生了新的進位,那麼我們在最開頭加上一個新節點即可,參見程式碼如下:

解法二:

class Solution {
public:
    ListNode* plusOne(ListNode* head) {
        if (!head) return head;
        int carry = helper(head);
        if (carry == 1) {
            ListNode *res = new ListNode(1);
            res->next = head;
            return res;
        }
        return head;
    }
    int helper(ListNode *node) {
        if (!node) return 1;
        int carry = helper(node->next);
        int sum = node->val + carry;
        node->val = sum % 10;
        return sum / 10;
    }
};

下面這種方法比較巧妙了,思路是遍歷連結串列,找到右起第一個不為9的數字,如果找不到這樣的數字,說明所有數字均為9,那麼在表頭新建一個值為0的新節點,進行加1處理,然後把右邊所有的數字都置為0即可。舉例來說:

比如1->2->3,那麼第一個不為9的數字為3,對3進行加1,變成4,右邊沒有節點了,所以不做處理,返回1->2->4。

再比如說8->9->9,找第一個不為9的數字為8,進行加1處理變成了9,然後把後面的數字都置0,得到結果9->0->0。

再來看9->9->9的情況,找不到不為9的數字,那麼再前面新建一個值為0的節點,進行加1處理變成了1,把後面的數字都置0,得到1->0->0->0。

解法三:

class Solution {
public:
    ListNode* plusOne(ListNode* head) {
        ListNode *cur = head, *right = NULL;
        while (cur) {
            if (cur->val != 9) right = cur;
            cur = cur->next;
        }
        if (!right) {
            right = new ListNode(0);
            right->next = head;
            head = right;
        }
        ++right->val;
        cur = right->next;
        while (cur) {
            cur->val = 0;
            cur = cur->next;
        }
        return head;
    }
};

最後這種解法是解法二的迭代寫法,我們用到棧,利用棧的先進後出機制,就可以實現從後往前的處理節點,參見程式碼如下:

解法四:

class Solution {
public:
    ListNode* plusOne(ListNode* head) {
        stack<ListNode*> s;
        ListNode *cur = head;
        while (cur) {
            s.push(cur);
            cur = cur->next;
        }
        int carry = 1;
        while (!s.empty() && carry) {
            ListNode *t = s.top(); s.pop();
            int sum = t->val + carry;
            t->val = sum % 10;
            carry = sum / 10;
        }
        if (carry) {
            ListNode *new_head = new ListNode(1);
            new_head->next = head;
            head = new_head;
        }
        return head;
    }
};

類似題目:

參考資料: