zoukankan      html  css  js  c++  java
  • LeetCode 2——两数相加(JAVA)

    给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

    您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

    示例:

    输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    输出:7 -> 0 -> 8
    原因:342 + 465 = 807

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/add-two-numbers
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    先来看一下我错误的代码:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    
    class Solution 
    {
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) 
        {
            if(l1==null)
                return l2;
            if(l2==null)
                return l1;
            if(l1==null&&l2==null)
                return null;
            ListNode head1=l1;
            ListNode head2=l2;
            ListNode l3=new ListNode(-1);
            ListNode head3=l3;
            Stack stack1=new Stack();
            Stack stack2=new Stack();
            int length1=0;
            int length2=0;
            long sum=0;
            while(head1!=null)//将第一个链表的节点值入栈1
            {
                stack1.push(head1.val);
                head1=head1.next;
                length1++;
            }
            while(head2!=null)//将第二个链表的值入栈
            {
                stack2.push(head2.val);
                head2=head2.next;
                length2++;
            }
            
            while(!stack1.empty())//将栈1中的数直接转换为数值
            {
               int temp=Integer.parseInt(String.valueOf(stack1.peek()));
               temp*=Math.pow(10,length1-1);
               sum+=temp;
               stack1.pop();
               length1--;
            }
            while(!stack2.empty())//链表一和链表二的值相加
            {
               int temp=Integer.parseInt(String.valueOf(stack2.peek()));
               temp*=Math.pow(10,length2-1);
               sum+=temp;
               stack2.pop();
               length2--;
            }
            //System.out.print(sum);
            //同时sum也出了很多问题,那就是范围超限,超出了int 的可表示范围
            /*下面的问题就是如何把这个结果正确的放入链表当中,这个卡了很长时间,结果还是不对*/
            if(sum==0)
            {
                ListNode head=new ListNode(0);
                head3.next=head;
            }
            while(sum!=0)
            {
                ListNode head=new ListNode(sum%10);
                head3.next=head;
                System.out.print(head.val);
                sum/=10;
                head3=head3.next;
            }
            return l3.next;
        }
    }

    说一下思路:将两个链表节点的值分别入栈,最终求和得到sum,接着把数值sum正确的放进一个新的链表中去,当然结果失败了,遇到的问题有int超限等,不打算继续优化了,失败

    我们接着看一下AK的正确代码:

    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;//x为当前链表节点P的值,如果链表已经到底了,就取0
            int y = (q != null) ? q.val : 0;//y为当前链表节点Q的值,如果链表已经到底了,就取0
            int sum = carry + x + y;//sum为当前两位以及上两个节点的进位的和
            carry = sum / 10;
            curr.next = new ListNode(sum % 10);//得到正确的值放入新链表
            curr = curr.next;
            if (p != null) p = p.next;
            if (q != null) q = q.next;
        }
        if (carry > 0) //如果最后还有一个进位,把进位再加上
       {
            curr.next = new ListNode(carry);
        }
        return dummyHead.next;//dummyHead是一个空的头节点
    }

    看一下正确的算法分析:

    方法:初等数学
    思路

    我们使用变量来跟踪进位,并从包含最低有效位的表头开始模拟逐位相加的过程。

     

    对两数相加方法的可视化: 342 + 465 = 8077,每个结点都包含一个数字,并且数字按位逆序存储。

    复杂度分析

    时间复杂度:O(max(m, n))O(max(m,n)),假设 mm 和 nn 分别表示 l1l1 和 l2l2 的长度,上面的算法最多重复 max(m, n)max(m,n) 次。

    空间复杂度:O(max(m, n))O(max(m,n)), 新列表的长度最多为 max(m,n) + 1max(m,n)+1。

    对比分析:

    自己写的程序问题以及不足的地方体现在哪:

    最大的优化:就是一位一位的处理,得到一位的正确结果,直接放进新链表,而不是得到最终的结果再按位放进新链表,避免了int超限。

    进一步思考:如果不是按照逆序存储哪?

    需要栈,先将链表中的值逆序一下,这样方便。

  • 相关阅读:
    数据库隔离级别
    前端传递的参数名称和后端接收的参数名称不一致
    事务管理
    AOP
    spring 集成 shiro安全框架
    SpringMVC----@RequestMapping__请求方式
    SpringMVC----@RequestMapping__修饰类
    SpringMVC入门概述+案例
    SpringMVC-web.xml头代码
    Spring注解驱动开发----->容器day02
  • 原文地址:https://www.cnblogs.com/jiameng991010/p/11294983.html
Copyright © 2011-2022 走看看