LeetCode--2.Add Two Numbers & 445. Add Two Numbers II & 989. Add to Array-Form of Integer

 问题链接:

https://leetcode.com/problems/add-two-numbers/

https://leetcode.com/problems/add-two-numbers-ii/

https://leetcode.com/problems/add-to-array-form-of-integer/

这三个问题都是基于特殊数据结构的加法运算。需要注意整数int的范围和加法进位操作的表达。

问题一:基于链表存储的整数加法,数字从低位到高位依次存储在链表中,这是我的代码,有点丑陋,效率较低。

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode p1=l1;
		ListNode p2=l2;
		int sign=0;
		int temp=0;
		ListNode r=new ListNode(1);
		ListNode p3=r;
        while(p1!=null || p2!=null)
        {
            if(p1==null)
                p1=new ListNode(0);
            if(p2==null)
                p2=new ListNode(0);
        	temp=p1.val+p2.val+sign;
        	if(temp>=10)
        		{
        		sign=1;
        		temp-=10;
        		}
        	else
        		sign=0;
        	p3.next=new ListNode(temp);
            if(p2.next==null && sign==1)
            {
                p3.next.next=new ListNode(1);
            }
        	p3=p3.next;
        	p1=p1.next;
        	p2=p2.next;
        }
        return r.next;
      }
}

Solutions里面的解法思路基本一致,但是处理的非常优雅:

有些tricks十分值得学习:虚拟头节点的加入,空节点统一处理为加上0。

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;
        int y = (q != null) ? q.val : 0;
        int sum = carry + x + y;
        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;
}

问题二:这个问题与第一问的区别是:数字从高位到低位依次存储在链表中,而链表的遍历只能从头到尾遍历,跟问题一一个解法,先上我捉急的代码:

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1==null)
			return l2;
		if(l2==null)
			return l1;
		int len1=1,len2=1,temp=0;
		ListNode p1=l1,p2=l2;
		while(p1.next!=null)
		{
			p1=p1.next;
			len1++;
		}
		while(p2.next!=null)
		{
			p2=p2.next;
			len2++;
		}
		
		if(len1<len2)
		{
			p1=l2;
			p2=l1;
			temp=len1;
			len1=len2;
			len2=temp;
		}
		else
		{
			p1=l1;
			p2=l2;
		}
		
		ListNode[] arr=new ListNode[len1+1];
		arr[0]=new ListNode(0);
		int i=1;
		while(len1!=len2)
		{
			arr[i]=new ListNode(p1.val);
			p1=p1.next;
			len1--;
			i++;
		}
		while(len1>0)
		{
			arr[i]=new ListNode(p1.val+p2.val);
			i++;
			p1=p1.next;
			p2=p2.next;
			len1--;
		}
			
		for(int j=arr.length-1;j>0;j--)
		{
			if(arr[j].val>=10)
			{
				arr[j-1].val+=1;
				arr[j].val-=10;
			}
				
		}
		
		if(arr[0].val!=0)
		{
			for(i=0;i<arr.length-1;i++)
			{
				arr[i].next=arr[i+1];
			}
			return arr[0];
		}
		else
		{
			for(i=1;i<arr.length-1;i++)
			{
				arr[i].next=arr[i+1];
			}
			return arr[1];
		}
    }
}

我的解法十分粗暴,因为是一年前刚开始刷LeetCode时写的,那时候有思路能AC就很不错了。更高效的处理方式是借助栈来从个位开始计算:

public class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<Integer> s1 = new Stack<Integer>();
        Stack<Integer> s2 = new Stack<Integer>();
        
        while(l1 != null) {
            s1.push(l1.val);
            l1 = l1.next;
        };
        while(l2 != null) {
            s2.push(l2.val);
            l2 = l2.next;
        }
        
        int sum = 0;
        ListNode list = new ListNode(0);
        while (!s1.empty() || !s2.empty()) {
            if (!s1.empty()) sum += s1.pop();
            if (!s2.empty()) sum += s2.pop();
            list.val = sum % 10;
            ListNode head = new ListNode(sum / 10);
            head.next = list;
            list = head;
            sum /= 10;
        }
        
        return list.val == 0 ? list.next : list;
    }
}

问题三:

思路一:在参加LeetCode contest遇到一道很脏的easy题目,边界条件处理起来比较痛苦(可能我没想到更好的方法,所以处理起来很暴力),代码如下:

class Solution {
    public List<Integer> addToArrayForm(int[] A, int K) {
        LinkedList<Integer> ret=new LinkedList<>();
        boolean flag=false;

        ArrayList<Integer> arr=new ArrayList<>();
        while(K!=0)
        {
            arr.add(0,K%10);
            K/=10;
        }
        int[] B=new int[arr.size()];
        for(int i=0;i<arr.size();i++)
            B[i]=arr.get(i);

        if(A.length<B.length)
        {
            int[] tmp=B;
            B=A;
            A=tmp;
        }

        int j=A.length-1;
        int k=B.length-1;
        while(j>=0 && k>=0)
        {
            if(flag)
            {
                A[j] += B[k]+1;
                flag=false;
            }
            else
                A[j] += B[k];
            if(A[j]>=10)
            {
                A[j]-=10;
                flag=true;
            }
            k--;
            j--;
        }

        while(j>=0)
        {
            if(flag)
            {
                A[j]+=1;
                flag=false;
            }
            else
                break;
            if(A[j]>=10)
            {
                A[j]-=10;
                flag=true;
            }
            j--;
        }
        
        if(flag)
            ret.add(1);
        for(int i:A)
            ret.add(i);
        return ret;
    }
}

后来这个问题我看了Solutions觉得十分佩服,观察和思路都十分细腻,借鉴问题一的代码风格,该算法如下:

class Solution {
    public List<Integer> addToArrayForm(int[] A, int K) {
        
        LinkedList<Integer> ret=new LinkedList<>();
        int i=A.length-1;
        while(K!=0 || i>=0)
        {
            int p=i>=0?A[i]:0;
            ret.add(0,(K+p)%10);
            K=(K+p)/10;
            i--;
        }
        return ret;
    }
}

写出这样简洁的代码才让我感觉这是一道easy的问题,思路一的代码提交了5次才过也是没谁了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值