LeetCode2-链表两数和

题目描述

 

 

示例提示

 

 

经验教训

链表题的判空条件不是万能的,有时候示例会极其复杂,根本难以通过判空来区分不同情况。

/**

 \* Definition for singly-linked list.

 \* struct ListNode {

 \*   int val;

 \*   ListNode *next;

 \*   ListNode() : val(0), next(nullptr) {}

 \*   ListNode(int x) : val(x), next(nullptr) {}

 \*   ListNode(int x, ListNode *next) : val(x), next(next) {}

 \* };

 */

class Solution {
public:
  ListNode* AttachNode(ListNode* La, int temp){
    if(1==temp){
      ListNode* x = new ListNode;
      x->val = 1;
      La->next = x;
      x->next = NULL;
   }
    return La; 
  }
  ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {//新链表与l1共用
    int temp=0;
    ListNode *La=l1,*Lb=l2,*Lc=l1;
    while(La&&Lb){//设置两个指针分别对l1和l2操作
      La->val = La -> val + Lb -> val + temp;
      if(La->val>=10){
        temp = 1;
        La->val-=10;
      }
      else{
        temp = 0;
      }
      if(La->next&&Lb->next){
        La = La -> next;
        Lb = Lb -> next;
      }
      else{
        break;
      }
    }
    if(La->next==NULL&&Lb->next==NULL&&temp==1){
      AttachNode(La,temp);
      return l1;
    }
    if(1==temp){
      if(Lb->next)La->next=Lb->next;
      if(La->next){
        La=La->next;
      }
      while(La){  
        //if(La->next==NULL&&Lb->next==NULL)break;      
        La->val += temp;
        if(La->val>=10){
          temp = 1;
          La->val-=10;
        }
        else{
          temp = 0;
        }
        if(La->next){
          La = La->next;
        }
        else{
          break;
        }
      }
    }
    // if(1==temp){

    //   ListNode* x = new ListNode;

    //   x->val = 1;

    //   La->next = x;

    //   x->next = NULL;

    // } 
    AttachNode(La,temp);
    return l1;
  }
};

  

比如说

[5]
[5]

的情况与

[9,9,9,9]
[9,9,9]

的情况就无法区分(是指la->next为空且lb->next为空时,者要进行的操作是不一样的。)上述代码已经是想要两者兼顾了,但还是不行。

这里犯了一个致命的错误。觉得统计链表节点个数会很麻烦,所以直接针对各个情况判空来做,实际上示例给的会麻烦的多。仅凭结点判空的组合很难精确区分各个情况,所以不如节点个数来的块。

参考正解

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        int size_1 = 0, size_2 = 0;
        ListNode* temp = l1;
        //统计l1长度
        while(temp){
            size_1++;
            temp = temp->next;
        }
        //统计l2长度
        temp = l2;
        while(temp){
            size_2++;
            temp = temp->next;
        }
        
        //大于10的部分由remainder保留
        int remainder = 0;
        //longer指向最长的数组,shorter指向最短的;
        ListNode* longer = (size_1 >= size_2) ? l1 : l2;
        ListNode* shorter = (size_1 < size_2) ? l1 : l2;
        //res指向最长的
        //我们基于较长链进行操作
        ListNode* res = longer;
        //进行循环赋值
        while(longer||shorter){
            //长链先加上余数
            longer->val += remainder;
            //再加上短链
            if(shorter){
                longer->val += shorter->val;
            }
            //保留大于10的部分
            if(longer->val > 9){
                longer->val -= 10;
                remainder = 1;
            }
            else{
                remainder = 0;
            }
            //如果longer遍历到最后一位且大于10,末尾加上一个1的节点
            //这里我是考虑到了,但是在我前面最终决定放弃的那个版本里产生了麻烦
            if(longer->next == nullptr && remainder){
                ListNode* ll = new ListNode(1);
                longer->next = ll;
                return res;
            }
            //继续走
            longer = longer->next;
            if(shorter){
                shorter = shorter->next;
            }
        }
        return res;
    }
};

  

最大的问题就在于我在操作时没能就谁长谁短进行简化思考,觉得无端的遍历一遍链表很亏。所以只是随便挑选l1作为基准链表,然后将长的链表的后半部分链接过来,这样就增加了很多种处理情况给自己为难。

 

posted @ 2021-09-25 17:11  climerecho  阅读(77)  评论(0编辑  收藏  举报