ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

练习题

2019-11-03 21:52:40  阅读:254  来源: 互联网

标签:练习题 count cur2 val cur1 链表 进位


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

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

解题思路:在任一个链表只剩一个数或者两个链表都只剩一个数的时候,就单独来计算,判断是否产生进位。如果两个链表不等长,还需要再把较长的链表的后几位计算,判断是否产生进位。同样是计算到最后一位,再判断是否产生进位,是否需要链表扩容。

/**
* 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) {
ListNode cur1 = l1;
ListNode cur2 = l2;
int count = 0;//每位之和
int s = 0;//进位

while(cur1.next != null && cur2.next != null){//加到其中有一个链表剩一位,或者两个链表都只剩一位
count = cur1.val + cur2.val + s;
if(count > 9){
cur1.val = count % 10 ;
cur2.val = count % 10 ;
s = 1;
}else{
cur1.val = count;
cur2.val = count;
s = 0;
}
cur1 = cur1.next;
cur2 = cur2.next;

}

if(cur1.next == null && cur2.next == null){ //当两个链表都只剩一位时
count = cur1.val + cur2.val +s;
if(count > 9)
{
cur1.val = count % 10;
cur2.val = count % 10;
s = 1;
}else{
cur1.val = count ;
cur2.val = count ;
s = 0;
}
if(s == 1){ //说明最后两个数产生了进位,需要扩充链表。
ListNode tmp = new ListNode(1);
cur1.next = tmp;
return l1;
}
return l1;
}

if(cur1.next == null){ //cur1链表剩一位
count = cur1.val + cur2.val + s ;
cur2.val = cur1.val + cur2.val;
if(count < 10){ //cur1的最后一位加cur2的一位 没产生进位,直接返回
cur2.val = count;
return l2;
}
while(cur2.next != null){ //因为有进位,需要再把cur2的剩余数计算 直到最后一位
count = cur2.val + s;
if(count > 9){
cur2.val = count % 10 ;
s = 1;
} else{
cur2.val = count;
s = 0;
}
cur2 = cur2.next;
}
if(cur2.val + s > 9){ //判断cur2 最后一位是否产生进位
cur2.val = (cur2.val + s) % 10;
s = 1;
}else{
cur2.val = cur2.val +s;
s = 0;
}
if(s == 1){ //产生进位,扩充链表
ListNode tmp = new ListNode(1);
cur2.next = tmp;
return l2;
}
return l2;
}else{ //cur2链表剩一位
count = cur1.val + cur2.val + s;
cur1.val = cur2.val + cur1.val;
if(count < 10){ //cur2的最后一位加cur1的一位 没产生进位,直接返回
cur1.val = count;
return l1;
}
while(cur1.next != null){ //因为有进位,需要再把cur1的剩余数计算 直到最后一位
count = cur1.val + s;
if(count > 9){
cur1.val = count % 10 ;
s = 1;
} else{
cur1.val = count;
s = 0;
}
cur1 = cur1.next;
}
if(cur1.val + s > 9){ //判断cur1 最后一位是否产生进位
cur1.val = (cur1.val + s) % 10;
s = 1;
}else{
cur1.val = cur1.val +s;
s = 0;
}
if(s == 1){ //产生进位,扩充链表
ListNode tmp = new ListNode(1);
cur1.next = tmp;
return l1;
}
}
return l1;
}
}
————————————————

思路 在一个循环里 两个链表同时往下走
数据每位相加 可能有进位
加完新的链表也往下走

假设两个链表分别是:
[4,7,6] [9,1,8]

 

     674 + 819

     假如l1 = (4,7,6) l2 = (9,1,8)

         l1      =      4      7      6
         l2      =      9      1      8
        sum      =     13      8     14            和
       curr      =      3      8      4            当前位
  curr.next      =      1      0      1            进位 进位数值只可能为0或1
       sumX      =      3      9      4      1     进位加在后面 新数



和一般计算略有不同的是,需要把进位往右移。仅此而已

func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
    //把当前节点初始化为哑节点
    let dummyHead = ListNode(0)
    //把p初始化为l1的头节点
    var p: ListNode? = l1
    //把q初始化为l2的头节点
    var q: ListNode? = l2
    //把起始节点(最后一个节点)初始化为哑节点
    //思路 每次curr要去获取下一个节点,但是上一个节点的值需要被保存起来
    //dummyHead是用来存储curr的 因为要操作curr去获取下一位 所以上一位必须被保存下来
    var curr: ListNode = dummyHead
    //进位默认为0
    var carry: Int = 0
    //只要有一个链表不为nil就进入循环
    while p != nil || q != nil {
        //如果l1的当前节点不为nil 取当前节点 如果为nil取0
        let x = (p != nil) ? p!.val : 0
        //如果l2的当前节点不为nil 取当前节点 如果为nil取0
        let y = (q != nil) ? q!.val : 0
        //求和
        //当前节点的数值相加并加上进位
        //(第一组数相加完才会有进位,所以第一组数的进位一定为0)
        let sum = carry + x + y
        //数字为一位还是两位 如果是一位 没有进位 如果是两位 有进位
        //一共10个数0->9
        carry = sum / 10
        //新链表当前节点的值为两个原链表当前节点的和除以10(进位)取余
        //(取后一位,因为可能有进位)
        curr.next = ListNode(sum % 10)
        //把下一个节点设置为当前节点
        curr = curr.next!
        //如果l1不为空 往下走查看下一个节点
        if p != nil { p = p!.next }
        //如果l2不为空 往下走查看下一个节点
        if q != nil { q = q!.next }
    }
    //如果carry不为0 则有进位(carry == 1) 把carry带入 直接把最右侧一个节点数值设置为1
    if carry > 0 {
        //curr是当前位 在循环结束后也是最后一位(不含进位)
        curr.next = ListNode(carry)
    }
    //返回链表
    return dummyHead.next;
}





1)方法实现1:
原理如下:原理:第一次给node挂上nextnode的时候,原理是当node开辟出一块内存的时候 temp也指向了node对应的这块内存,给temp的nextcode挂上节点以后,同时也就给node挂上了nextnode,第二次第三次给node挂节点的时候,再把temp指向temp的nextcode
————————————————

public static void main(String[] args) {
ChainNode node1 = new ChainNode(2);
ChainNode node1_1 = new ChainNode(4);
ChainNode node1_2 = new ChainNode(3);
node1.setNextNode(node1_1);
node1_1.setNextNode(node1_2);
ChainNode node2 = new ChainNode(5);
ChainNode node2_1 = new ChainNode(6);
ChainNode node2_2 = new ChainNode(4);
node2.setNextNode(node2_1);
node2_1.setNextNode(node2_2);
ChainNode node = TestAddTwoNumber.getNode(node1,node2);
while(null != node){
System.out.println(node.getVal());
node = node.getNextNode();
}

}

/***
* 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

原理:第一次给node挂上nextnode的时候,原理是当node开辟出一块内存的时候 temp也指向了node对应的这块内存,给temp的nextcode挂上节点以后,同时也就给node挂上了nextnode,
第二次第三次给node挂节点的时候,再把temp指向temp的nextcode
为了方便大家理解,我画了个原理图如下:
![在这里插入图片描述](https://www.icode9.com/i/ll/?i=20190408175525581.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTM2NDI4OQ==,size_16,color_FFFFFF,t_70)
* @param args
*/
public static ChainNode getNode(ChainNode node1,ChainNode node2){
ChainNode node = new ChainNode(0);
ChainNode temp = node;
// ChainNode nodetemp = new ChainNode(0);
int carry = 0;//0 不进位 1 进位
while(node1 != null || node2 != null){
int x = node1.getVal();
int y = node2.getVal();
int sum = x + y + carry;
carry = sum / 10;
temp.setNextNode(new ChainNode(sum % 10));
temp = temp.getNextNode();
node1 = node1.getNextNode();
node2 = node2.getNextNode();
}
// node.setNextNode(nodetemp);
return node.getNextNode();
}
————————————————

标签:练习题,count,cur2,val,cur1,链表,进位
来源: https://www.cnblogs.com/hanling/p/11789349.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有