算法通关村第二关——单链表加1的问题解析

题目类型

链表反转

题目描述

        用一个非空单链表来表示一个非负整数,然后将这个整数加一。你可以假设这个整数除了0本身,没有任何前导的0.

        这个整数的各个数位按照 高位在链表头部,低位在链表尾部 的顺序排列

示例

输入:[1,2,3]

输出:[1,2,4]

思路分析 

1. 计算是从低位开始的,而链表是从高位开始的,所以要计算,就必须将链表反转过来,反转操作可以使用链表反转来实现,也可以使用栈来实现。

2. 基于栈的实现思路:先把题目给的链表压入栈中,然后从栈中弹出栈顶数字digit,加的时候再考虑下进位的情况,加完之后根据是否大于0决定  下一次是否要进位 

代码实现 (栈)

    /**
     * 题目:
     * 用一个非空单链表来表示一个非负整数,然后将这个整数加一。你可以假设这个整数除了0本身,没有任何前导的0.
     * 这个整数的各个位数按照  高位在链表头部、低位在链表尾部  的顺序 排列
     * @param head 链表头节点
     * @return  加一操作后的链表头节点
     */
    public Node singleListAdd1(Node head){
        Stack<Integer> stack = new Stack<>();
        while (head != null){
            stack.push(head.data);
            head = head.next;
        }
        // 定义数据
        // carry 用于存储进位标识。如果carry为0,表示没有进位;如果carry为其他数,则表示有进位
        int carry = 0;
        // addNum 表示加1 操作的变量。如果是最低位,进行加1,然后将其置为0
        int addNum = 1;
        // 虚拟节点
        Node dummyNode = new Node(0);

        while (!stack.empty() || carry >0){
            // digit 翻译为数字,表示从栈中取出来的数据(从低位(个位)  ===》 到高位(十位、百位))
            int digit = stack.empty() ? 0 : stack.pop();
            // sum 翻译为和,表示  一个位的值+ addNum(如果该位为个位,则表示第一次循环,可以加1,在结束本次循环后,被置为0)+ 进位标识(如果有进位,也只是进1))
            int sum = digit + addNum + carry;
            // 先判断sum 是否能进位,如果能进位(值大于10),将carry置为1;不能进位(值小于10),置为0
            carry = sum >= 10 ? 1 : 0;
            // 先判断sum的值是否大于10,如果大于10,说明之前有进位,此时就需要将sum的值减10;如果小于10,标识刚刚没有进位,返回原来的数
            sum = sum >= 10 ? sum - 10 : sum;
            // 将 该位最后算得的值作为当前节点
            Node cur = new Node(sum);
            cur.next = dummyNode.next;
            dummyNode.next = cur;
            // addNum只为最低位(个位)进行加1操作,当进行完加1操作后,需要将其置为0
            addNum = 0;
        }
        return dummyNode.next;
    }

基于反转链表实现:因为在开始前和结束后都需要反转链表,因此可以将反转链表提取成一个方法,并返回反转后的头节点,然后再做+1操作

代码实现(反转链表) 

    public Node singleListAdd1ByReverseList(Node head){
        head = reverseList(head);
        Node dummyNode = new Node(0,head);
        Node cur = dummyNode;
        int carry = 0;
        int addNum = 1;
        while (head != null){
            int val = carry;
            val += head.data +addNum;
            head = head.next;
            int ans = val % 10;
            carry = val / 10;
            cur.next = new Node(ans);
            addNum = 0;
            cur =cur.next;
        }
        if (carry > 0){
            cur.next = new Node(carry);
        }
        return reverseList(dummyNode.next);
    }

    private Node reverseList(Node head){
        Node pre = null;
        Node cur = head;
        Node next;
        while (cur != null){
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值