Problem 2考察的是链表问题,两条链表,对应节点的值相加并放入新链表对应的节点中,然后利用值-10判断产生进位,然后将进位参与到下一节点的运算中,最后直到两条链表的节点为空并且不在进位。
由于是两条链表,因此必须考虑一长一短,在短的链表的节点处理完后,仅需处理长链表的剩余节点以及carry,此外还要考虑进位产生一个尾节点的情况,如[1],[9,9]相加后的链表长度为三,而最后一个节点是carry的值,因此,程序的时间复杂度为O(max(l1.length,l2.length))相当于遍历最长链表的时间复杂度。
因此代码如下
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
int carry = 0;
struct ListNode *l3, *point;
l3 = point = NULL;
while(l1 || l2 || carry) {
/*
当l1,l2或进位仍有结点未加或有值时对l3链表扩容一个结点,头结点为空时先创建头结点。
*/
if(!l3) {
l3 = point = (struct ListNode*)malloc(sizeof(struct ListNode));
l3->next = NULL;
} else {
point->next = (struct ListNode*)malloc(sizeof(struct ListNode));
point = point->next;
point->next = NULL;
}
/*
四种情况下的结点相加(1)l1l2相加的结点都存在,(2)l1结点存在,(3)l2结点存在,(4)l1l2结点都不存在
*/
if(l1 && l2) {
point->val = l1->val + l2->val + carry;
l1 = l1->next;
l2 = l2->next;
} else if(l1) {
point->val = l1->val + carry;
l1 = l1->next;
} else if(l2) {
point->val = l2->val + carry;
l2 = l2->next;
} else {
point->val = carry;
}
/*
判断新链表上的结点值是否大于10,大于10的进位并减去10,否则不进位
*/
if(point->val >= 10) {
carry = 1;
point->val = point->val - 10;
} else {
carry = 0;
}
}
return l3;
}
AC后,我看了一下他的代码,设计的思路和我的想法差不多,但代码比我的代码简洁了不少,我用C将他的方法重写了一下
struct ListNode* addTwoNumbers2(struct ListNode* l1, struct ListNode* l2) {
int x, y, sum, carry = 0;
struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* current = head;
while(l1||l2) {
if(l1) {
x = l1->val;
} else {
x = 0;
}
if(l2) {
y = l2->val;
} else {
y = 0;
}
sum = x + y + carry;
carry = sum / 10;
current->next = (struct ListNode*)malloc(sizeof(struct ListNode));
current->next->val = sum % 10;
current = current->next;
if(l1) {
l1 = l1->next;
}
if(l2) {
l2 = l2->next;
}
}
if (carry > 0) {
current->next = (struct ListNode*)malloc(sizeof(struct ListNode));
current = current->next;
current->val = carry;
}
current->next = NULL;
return head->next;
}
由于他的原来的写法是JAVA,所以新建链表结点比C方便,此外源代码中的判断都用三目运算符?:替代了,所以会更简洁,但我觉得这样会影响代码的维护性,所以仍然用了if判断。从上面代码可知,他的策略是将头结点置空来减少while里的新建头结点的代码量,同时也便于链表的读取和维护。此外他利用判断结点是否为空来决定后面表达式sum = x + y + carry中x, y的值,这样增加了程序的可读性,避免了被if,else if绕晕,这点值得我借鉴。