lpc0828 发表于 2021-2-22 11:52

LeetCode_Subject2

基础很差这道题折腾了这么久 我相信后面的题目会做的越来越好!!!!!!!!
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
下面这个是给的链表类
public static class ListNode {
      int val;
      ListNode next;

      ListNode() {
      }

      ListNode(int val) {
            this.val = val;
      }

      ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
      }
    }
输入:l1 = , l2 =
输出:
解释:342 + 465 = 807.


题目的大概意思就是两个倒序链表相加,结果也得是倒序的


基础较差 啪!上来就是一个循环!很快啊!下面是车祸现场!
public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
      boolean a = true;
      boolean b = true;
      boolean c = true;
      ListNode listNode1 = l1;
      ListNode listNode2 = l2;
      ListNode listNode3 = new ListNode();
      StringBuffer buffer1 = new StringBuffer();
      StringBuffer buffer2 = new StringBuffer();
      while (a) {
            buffer1.append(listNode1.val);
            listNode1 = listNode1.next;
            if (listNode1 == null || listNode1.next == null) {
                buffer1.append(listNode1 == null ? "" : listNode1.val);
                a = false;
            }
      }

      while (b) {
            buffer2.append(listNode2.val);
            listNode2 = listNode2.next;
            if (listNode2 == null || listNode2.next == null) {
                buffer2.append(listNode2 == null ? "" : listNode2.val);
                b = false;
            }
      }
      Long result = Long.parseLong(buffer1.reverse().toString()) + Long.parseLong(buffer2.reverse().toString());
      String s = new StringBuffer(result.toString()).reverse().toString();
      List<String> list = Stream.iterate(0, n -> ++n).limit(s.length())
                .map(n -> "" + s.charAt(n))
                .collect(Collectors.toList());
      List<Integer> collect = list.stream().map(o -> {
            return Integer.parseInt(o);
      }).collect(Collectors.toList());

      return test(collect, listNode3);
    }

    public static ListNode test(List<Integer> collect, ListNode listNode) {
      Integer integer = collect.get(0);
      if (integer != null) {
            ListNode listNode1 = new ListNode();
            collect.remove(0);
            if (collect.size() == 0) {
                listNode.val = integer;
                return listNode;
            }
            listNode.val = integer;
            listNode.next = test(collect, listNode1);
            return listNode;
      }
      return null;
    }
先把它俩循环出来 挨个把数字取出来 然后计算总和 再把它们包装到链表类里面 完美!但是!
提示:
每个链表中的节点数在范围 内0 <= Node.val <= 9题目数据保证列表表示的数字不含前导零
题目没有这么笨尽管我用了long double 也没法装的下这么大的数字

咨询了一位好大哥,用递归试试
什么是递归呢


public static ListNode l11 = new ListNode(666);

    public static ListNode test1(ListNode l1, ListNode l2, int 进位) {
      if (l1.next != null || l2.next != null) {
            // 每两位和进位的和
            int sum = l1.val + l2.val + 进位;
            // 十 分离个位十位 是要进位的值
            int 进 = sum / 10 % 10;
            // 个 是当前对象的值
            int a = sum % 10;
            test2(l11, a);
            test1(l1.next, l2.next, 进);
      } else {
            // 最后一位的和
            int sum = l1.val + l2.val + 进位;
            // 十 分离个位十位
            int ten = sum / 10 % 10;
            //个
            int a = sum % 10;
            // 最后一个对象
            if (ten == 0) {
                test2(l11, a);
            } else {
                test2(l11, a);
                test2(l11, ten);
            }

      }
      return l11;
    }

    public static void test2(ListNode l1, int a) {
      if (l1.next != null) {
            test2(l1.next, a);
      } else {
            // 找到它的最后一位 放进去
            if (l11.val == 666) {
                l11 = new ListNode(a);
            } else {
                l1.next = new ListNode(a);
            }

      }
    }
用的办法也是很笨 但是没法通过官方LeetCode的提交校验,我现在都不知道为什么

用它的测试用例测试代码 结果是对的 用了它的提交校验就错了
莫得办法搞不出来,我去看了官方的代码,其实没必要用这么大阵仗 还用递归 while循环就可以实现了
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
      ListNode head = null, tail = null;
      int carry = 0;
      while (l1 != null || l2 != null) {
            int n1 = l1 != null ? l1.val : 0;
            int n2 = l2 != null ? l2.val : 0;
            int sum = n1 + n2 + carry;
            if (head == null) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail.next = new ListNode(sum % 10);
                tail = tail.next;
            }
            carry = sum / 10;
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
      }
      if (carry > 0) {
            tail.next = new ListNode(carry);
      }
      return head;
    }
申明两个链表对象 第一个对象用来装整个返回值对象,第二个对象用来装返回值对象最深处的 next==null的对象 (在做题的时候我一直脑海里面有这个想法 ,但是没写出来)申明一个装进位的值 循环里面一级一级的拆 l1,l2同步进行 当第一次取得时候head还是null 需要new 到head上面
之后每次就放到tail得next里面 操作完之后 需要把l1,l2的上一级丢掉 l1=l1.next;l2=l2.next;
当它计算到最后一位的时候 如果进位大于0 那就得再给tail的next赋值

学到的东西 是对递归有了一个概念 想问题的时候应该再细一点 这道题就是小题大做了
希望未来越来越好!!!!
吃过午饭再回味回味 下午开始第三题!!!

vethenc 发表于 2021-2-22 13:14

你着火了

lpc0828 发表于 2021-2-22 13:35

vethenc 发表于 2021-2-22 13:14
你着火了

块给我下下火

aristan 发表于 2021-2-22 15:17

写的真好,可惜我是学C的,java的多多少少有点不懂

SpeII 发表于 2021-2-22 16:50

感觉用纯数学的方法更简单public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
      StringBuilder sb1 = new StringBuilder();
      StringBuilder sb2 = new StringBuilder();
      StringBuilder sb3 = new StringBuilder();
      while (l1 != null) {
            sb1.append(l1.val);
            l1 = l1.next;
      }
      while (l2 != null) {
            sb2.append(l2.val);
            l2 = l2.next;
      }
      BigInteger b1 = new BigInteger(sb1.reverse().toString());
      BigInteger b2 = new BigInteger(sb2.reverse().toString());
      BigInteger sum = b1.add(b2);
      int i1 = Integer.parseInt(sb3.append(sum).reverse().toString());
      ListNode head = new ListNode();
      ListNode cur = head;
      int firstbit;
      int tens = cardinalNum(lengthNum(sum.longValue()));
      do {
            firstbit = i1 / tens;
            cur.next = new ListNode(firstbit);
            cur = cur.next;
            i1 = i1 - firstbit * tens;
            tens = tens / 10;
      } while (i1 > 0);

      return head.next;
    }

    public static int cardinalNum(int count) {
      int tens = 1;
      for (int i = 0; i < count - 1; i++) {
            tens *= 10;
      }
      return tens;
    }

    public static int lengthNum(Long num) {
      int count = 0; //计数
      while (num >= 1) {
            num /= 10;
            count++;
      }
      return count;
    }

nj001 发表于 2021-2-22 20:54

处理数组或者链表之类用循环即可简单解决大多数问题,递归是屠龙术可以解决更复杂的问题,缺点是太耗资源,不过递归可以优化成循环

lpc0828 发表于 2021-2-23 09:59

nj001 发表于 2021-2-22 20:54
处理数组或者链表之类用循环即可简单解决大多数问题,递归是屠龙术可以解决更复杂的问题,缺点是太耗资源, ...

太对了哥{:301_978:}

lpc0828 发表于 2021-2-23 10:01

SpeII 发表于 2021-2-22 16:50
感觉用纯数学的方法更简单public static ListNode addTwoNumbers(ListNode l1, Lis ...

纯数学的方式 虽然可以 但是不符合题目了节点数的范围是
太长了 用普通的数字类型没法接收
页: [1]
查看完整版本: LeetCode_Subject2