leetcode之路-两数相加

 

题目

给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例1

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

题干解析

  1. 数据是采用链表逆向存储的非负整数
  2. 链表的节点只存一位数据,且是10进制数据。数据的存储方式是类似以个十百千万的方式存储的。
  3. 输入异常处理,两个数都不会以0开头
  4. 题目未规定数据范围

边界情况分析

  • 一个数据比一个短。例如 30 + 123 前面的数据是没有百位的
  • 一个数据为空。例如 134+0 = 140 题干只是提及不可能两个数为空,并未数单个不为0
  • 如果两个数相加刚好进一位。例如50+50 = 100

解题思路

数据转换

一般这种题目最先想到的就是此种先转换为10进制的数,然后进行求和。最后进行转换。转换的过程是链表的基础操作过程。没什么好解释的。但是此处需要注意的是数据范围(我在此处犯了两次错误)。直接采用BigDecimal的类型进行操作。由于leetcode好像不支持import。故只作为参考

示例代码

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1.val == 0 && l1.next == null && l2.val == 0 && l2.next == null){
            return new ListNode(0);
	}
	BigDecimal sum = getValue(l1).add(getValue(l2));
	return setValue(sum);
    }
    
    public BigDecimal getValue(ListNode node){
	int i = 0;
	BigDecimal v1 = new BigDecimal(0);
	while(node.next != null){
	    v1 = v1.add(new BigDecimal(node.val).multiply(new BigDecimal(10).pow(i)));
	    node = node.next;
	    i++;
	}
	v1 = v1.add(new BigDecimal(node.val).multiply(new BigDecimal(10).pow(i)));
	return v1;
    }

    public ListNode setValue(BigDecimal sum){
        //取模运算
        ListNode node = new ListNode(sum.divideAndRemainder(new BigDecimal(10))[1].intValue());
	ListNode temp = node;
        sum = sum.divide(new BigDecimal(10)).setScale(0,BigDecimal.ROUND_DOWN);
        while (!sum.toString().equals("0")){
	    temp.next=new ListNode(new Long(sum.divideAndRemainder(new BigDecimal(10))[1].intValue()).intValue());
	    //类似int的/操作,因为BigDecimal除法会有小数
	    sum = sum.divide(new BigDecimal(10)).setScale(0,BigDecimal.ROUND_DOWN);
	    temp = temp.next;
	}
        return node;
    }
}

普通加法计算

这个其实就是类似在纸上运算两个数之和的方式。先加个位然后再加十位的方式。

实例代码

class Solution2 {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
	if(l1.val == 0 && l1.next == null && l2.val == 0 && l2.next == null){
	    return new ListNode(0);
	}
	ListNode sum = new ListNode(0);
	ListNode temp =sum;
	int carry = 0;
	while(l1 != null || l2 != null){
	    int val1 = l1 == null? 0: l1.val;
	    int val2 = l2 == null? 0: l2.val;
	    int s = val1 + val2 + carry;
	    //如果需要进位,则记录进位的值的大小
	    if(s >= 10){
		temp.val = s % 10 ;
		carry = s / 10;
	    }else{
		temp.val = s;
		carry = 0;
	    }
	    //只有有数据未遍历完,或者遍历完有进位产生时才会新建下一位
	    if((l1 != null && l1.next != null) || (l2 != null && l2.next != null)){
		temp.next = new ListNode(0);
		temp = temp.next;
	    } else {
	        if(carry > 0){
		    temp.next = new ListNode(carry); 
		}
	    }
	    if(l1 != null){
		l1 = l1.next;
	    }
	    if(l2 != null){
		l2 = l2.next;
	    }
	    
	}
	return sum;
    }
}

自己看法

我看过官方给的实例代码,基本上和我的代码差不多,但是官方给的代码实际的运行时间需要比我的代码多出30ms左右。所以就贴上了我自己的代码。此题只考了基本的链表的遍历操作+两数相加问题。没必要多做展开。

你可能感兴趣的:(java,算法)