从零学算法

2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

  • 我的原始人解法:首先按照现在从前往后的顺序遍历两个链表就是从个位开始相加,正好省的我反转链表,定义一个变量记录是否满十进一,然后根据相加的结果不断创建新结点,并且不断更新头结点,如果最后满十进一变量仍为 true 则再加一位 1(否则 99 + 1 得到 00 了),最后的链表反转即可。
  •   public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
          ListNode l = null;
          boolean addOne = false;
          while(l1!=null || l2!=null){
              int val;
              // l1 的加完了那直接加 l2 的即可,l2 的加完了同理,否则两数相加
              if(l1 == null){
                  val = l2.val;
                  l2=l2.next;
              }else if (l2 == null){
                  val = l1.val;
                  l1=l1.next;
              }else{
                  val = l1.val + l2.val;
                  l1=l1.next;
                  l2=l2.next;
              }
              // 如果满十进一,我加上进的 1
              if(addOne) val++;
             	// 如果新结果小于十,之后就暂时不进一了
              if(val < 10){
                  addOne=false;
              }else{
              // 新结果还大于等于 10 那就继续进一
                  val%=10;  
                  addOne=true;
              } 
              ListNode t = new ListNode(val,l);
              l = t;
          }
          if(addOne){
              ListNode t = new ListNode(1,l);
              l = t;
          }
          return reverse(l);
      }
      // 从前往后遍历链表,不断把结果加到新链表尾部就实现了链表反转
      public ListNode reverse(ListNode l) {
          ListNode r = null;
          while(l != null){
          	// 暂时保存头结点下一个结点
              ListNode t = l.next;
              // 把摘出来的头结点的下一位连上要返回的结果链表 r
              // 上面要是不暂存下一个结点,l 都没法继续遍历了
              l.next = r;
              // 更新头结点
              r=l;
              // 继续下一位
              l=t;
          }
          return r;
      }
    
  • 他人解法:既然位数不一定相等,那就补 0 使其相等。(关于返回的结果链表,我是不断 new ListNode 最后反转链表。他人题解是创建两个链表第一个为记录头结点的链表 pre,让第二个链表等于 pre,然后让第二个链表不断往后加结点并遍历到下一结点,最后返回 pre.next 即可。)
  •   public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
          ListNode pre = new ListNode(0);
          ListNode cur = pre;
          int carry = 0;
          while(l1 != null || l2 != null) {
          	// 补 0
              int x = l1 == null ? 0 : l1.val;
              int y = l2 == null ? 0 : l2.val;
              int sum = x + y + carry;
              
              // 这么写就省的每次判断是否要加上进的 1 了
              carry = sum / 10;
              sum = sum % 10;
              // 这就是我说的第二个链表不断往后加结点并遍历到下一结点
              cur.next = new ListNode(sum);
              cur = cur.next;
              
              if(l1 != null)
                  l1 = l1.next;
              if(l2 != null)
                  l2 = l2.next;
          }
          if(carry == 1) {
              cur.next = new ListNode(carry);
          }
          return pre.next;
      }
    

你可能感兴趣的:(算法学习,算法,链表,数据结构)