LeetCode 2: 两数相加(Add Two Numbers)解法汇总

文章目录

  • My Solution
    • 注意点
    • 代码臃肿的原因
    • 第一步简化
    • 第二步简化
    • 使用二级指针
  • python递归解法
    • 转换为字符串,偷懒的方法

更多LeetCode题解

My Solution

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
	ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
		ListNode* result = new ListNode(0);
		ListNode* result_bak = result;
		int carry = 0;
		int value = 0;
		//add the first two nodes
		result->val = (l1->val + l2->val + carry) % 10;
		carry = (l1->val + l2->val + carry) / 10;
		result->next = NULL;
		//add subsequent nodes one by one until one of the list ends
		while (l1->next != NULL && l2->next != NULL) {
			value = (l1->next->val + l2->next->val + carry) % 10;
			carry = (l1->next->val + l2->next->val + carry) / 10;
			ListNode* l = new ListNode(value);
			result->next = l;
			result = result->next;
			l1 = l1->next;
			l2 = l2->next;
		}
		//the following three if are all three conditions while one of or both the two lists end.
		if (l1->next == NULL && l2->next == NULL) {
			if (carry) {
				ListNode* l = new ListNode(1);
				result->next = l;
			}
		}
		if (l1->next != NULL) {
			while (l1->next != NULL) {
				value = (l1->next->val + carry) % 10;
				carry = (l1->next->val + carry) / 10;
				ListNode* l = new ListNode(value);
				result->next = l;
				result = result->next;
				l1 = l1->next;
			}
			if (carry) {
				ListNode* l = new ListNode(1);
				result->next = l;
			}
		}
		if (l2->next != NULL) {
			while (l2->next != NULL) {
				value = (l2->next->val + carry) % 10;
				carry = (l2->next->val + carry) / 10;
				ListNode* l = new ListNode(value);
				result->next = l;
				result = result->next;
				l2 = l2->next;
			}
			if (carry) {
				ListNode* l = new ListNode(1);
				result->next = l;
			}
		}
		return result_bak;
	}
};

注意点

由于返回的是局部变量指针,因此每一个ListNode都必须使用new建立在堆上。

代码臃肿的原因

  1. l1l2同时到达尾部,有一个到达尾部的情况分开讨论了。
  2. 由于result的初始节点为0,我的想法是必须用l1 l2的初始节点的和覆盖,由此多了while开头的操作。实际上只要在返回的时候返回头结点后一个节点就可以了

第一步简化

去掉了分情况讨论

class Solution {
public:
	ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
		ListNode *dummyHead = new ListNode(0);
		ListNode *p = l1, *q = l2, *curr = dummyHead;
		int carry = 0;
		int x = p->val;
		int y = q->val;
		carry = (x + y) / 10;
		curr->val = (x + y) % 10;
		curr->next = NULL;
		while (p->next != NULL || q->next != NULL)
		{
			//assure that value of the nodes have been added before the pointer points to it
			//if not, it will be troublesome to add value of the last node
			x = (p->next != NULL) ? (p->next->val) : 0;
			y = (q->next != NULL) ? (q->next->val) : 0;
			ListNode* l = new ListNode((x + y + carry) % 10);
			carry = (x + y + carry) / 10;
			curr->next = l;
			curr = curr->next;
			if (p->next != NULL) p = p->next;
			if (q->next != NULL) q = q->next;
		}
		if (carry)
		{
			ListNode* l = new ListNode(1);
			curr->next = l;
		}
		return dummyHead;
	}
};

第二步简化

去掉了while之前的头结点处理

class Solution {
public:
	ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
		ListNode *dummyHead = new ListNode(0);
		ListNode *p = l1, *q = l2, *curr = dummyHead;
		int carry = 0;
		while (p != NULL || q != NULL)
		{
			int x = (p != NULL) ? (p->val) : 0;
			int y = (q != NULL) ? (q->val) : 0;
			ListNode* l = new ListNode((x + y + carry) % 10);
			carry = (x + y + carry) / 10;
			curr->next = l;
			curr = curr->next;
			if (p != NULL) p = p->next;
			if (q != NULL) q = q->next;
		}
		if (carry)
		{
			curr->next = new ListNode(1);
		}
		return dummyHead->next;
	}
};

伪代码如下:

  • 将当前结点初始化为返回列表的哑结点。
  • 将进位 carry 初始化为 0
  • pq 分别初始化为列表 l1l2 的头部。
    • 遍历列表 l1l2 直至到达它们的尾端。
    • x 设为结点 p 的值。如果 p 已经到达 l1 的末尾,则将其值设置为 0
    • y 设为结点 q 的值。如果 q 已经到达 l2 的末尾,则将其值设置为 0
    • 设定 sum = x + y + carry
    • 更新进位的值,carry = sum / 10
    • 创建一个数值为 (sum mod 10) 的新结点,并将其设置为当前结点的下一个结点,然后将当前结点前进到下一个结点。
    • 同时,将 pq 前进到下一个结点。
  • 检查 carry = 1 是否成立,如果成立,则向返回列表追加一个含有数字 1 的新结点。
  • 返回哑结点的下一个结点。

使用二级指针

class Solution {
public:
	ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
		int sum = 0;
		ListNode *l3 = NULL;
		ListNode **node = &l3;
		while (l1 != NULL || l2 != NULL || sum>0)
		{
			if (l1 != NULL)
			{
				sum += l1->val;
				l1 = l1->next;
			}
			if (l2 != NULL)
			{
				sum += l2->val;
				l2 = l2->next;
			}
			(*node) = new ListNode(sum % 10);
			sum /= 10;
			node = &((*node)->next);
		}
		return l3;
	}
};

python递归解法

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode, c = 0) -> ListNode:
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        val = l1.val + l2.val + c
        c = val // 10
        ret = ListNode(val % 10 ) 
        
        if (l1.next != None or l2.next != None or c != 0):
            if l1.next == None:
                l1.next = ListNode(0)
            if l2.next == None:
                l2.next = ListNode(0)
            ret.next = self.addTwoNumbers(l1.next,l2.next,c)
        return ret

转换为字符串,偷懒的方法

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        str_l1, str_l2 = '', ''
        while l1:            
            str_l1 += str(l1.val)
            l1 = l1.next
        while l2:            
            str_l2 += str(l2.val)
            l2 = l2.next
        int_l1 = int(str_l1[::-1])
        int_l2 = int(str_l2[::-1])       
        return list(map(int, str(int_l1 + int_l2)[::-1]))

你可能感兴趣的:(LeetCode,LeetCode刷题题解记录)