Given a non-negative integer represented as non-empty a singly linked list of digits, plus one to the integer.
You may assume the integer do not contain any leading zero, except the number 0 itself.
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; } };
類似題目:
參考資料:
https://leetcode.com/problems/plus-one-linked-list/
https://leetcode.com/discuss/111165/2-accepted-java-solution
https://leetcode.com/discuss/111205/simple-solution-use-recursion
https://leetcode.com/discuss/111157/9-lines-recursive-without-helper
https://leetcode.com/discuss/111155/java-stack-solution-with-inline-explanation