[每日两题系列]刷算法题咯~~

        本系列所选题目均来自力扣或者牛客网站. 所选题目主要是以其中的简单题为主, 中等题为辅, 包含少数困难题(原因是: 本人目前能力还不够~ ). 开展这个系列的目的是督促自己, 在暑假的时间里也要保持有一定的刷题量, 拒绝摆烂~
        话不多说, 直接开刷~~

从链表中删去总和值为零的连续节点

        题目描述: 给你一个链表的头节点 head,请你编写代码,反复删去链表中由 总和 值为 0 的连续节点组成的序列,直到不存在这样的序列为止。
        删除完毕后,请你返回最终结果链表的头节点。
        示例:
        输入:head = [1,2,-3,3,1]
        输出:[3,1]          (因为1+2-3总和是0, 删除这些节点, 剩下3, 1).

解题思路:
        (1) 这种类型的题也是我第一次碰到的, 刚开始我一直都在用前后指针的方法来解这道题, 结果要么是报错, 要么是部分示例没有通过… 于是看了看一些大佬的题解 — 前缀和+哈希表, 说实话, 这还是我第一次见到这样的解法, 有点被震惊到.
        (2) 记录链表中每个节点的前缀和, 将它们存到哈希表里面. 具体实现过程是 — 第一次遍历: 计算每个节点的前缀和,存到哈希表里面去(就算某个节点的前缀和是相同也没事,哈希表直接记录前缀和相同的最后一个节点位置).
        (3) 重新遍历整个链表, 看看在哈希表中是否有相同的前缀和存在, 如若有, 则找到哈希表中的这个节点, 然后直接跳过中间的所有节点(包括哈希表中存的这个节点本身), 然后从这里开始接着往下遍历; 如若没有, 那么直接往下遍历即可. 具体实现过程是 — 第二次遍历: 计算当前节点的前缀和,在哈希表中查看是否有前缀和相等的节点(这里的节点直接就是相同前缀和节点的最后一个),这样就可以直接跳过中间的元素(其实就相当于删除掉了这些节点).
        (4) 最后形成的新的链表就是目标链表.

实现代码:

class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        if(head==null){
            return null;
        }
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        Map<Integer,ListNode> map=new HashMap<>();
        // 第一次遍历
        int sum=0;
        ListNode cur=dummy;
        while(cur!=null){
            sum+=cur.val;
            map.put(sum,cur);
            cur=cur.next;
        }
        // 第二次遍历
        sum=0;
        cur=dummy;
        while(cur!=null){
            sum+=cur.val;
            cur.next=map.get(sum).next;
            cur=cur.next;
        }
        return dummy.next;
    }
}

两数相加

        题目描述: 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

解题思路:
        (1) 首先定义一个新的链表来存储最终的结果.
        (2) 同时将 l1 和 l2 进行遍历, 相加对应节点的val值, 如若相加之后的结果不大于10, 则直接将相加之后的结果存到新的链表当中去; 否则, 则将相加之后的结果减去10后, 存到新的链表中去, 同时在进行下一次遍历的时候, val值相加之后的结果加1… 如此往复, 直到 l1 和 l2 之间有一方(或两方)的链表遍历完, 跳出这个操作.
        (3) 如若 l1 没有遍历完, 则将 l1 剩下的节点全部拼接到新的链表后面; 反之 l2 没遍历完, 将 l2 剩下的节点全部拼接到新的链表后面. 这里要注意: 在拼接的时候, 还是需要判断有没有需要进位的, 判断方法也是跟之前判断进位的操作基本是类似.
        (4) 如若是最后一个节点(也就是数字最高位)需要进位, 那么就需要在链表的最后面加上一个val值为1的节点(补全最高位), 最后返回这个链表即可.

实现代码:

class Solution {
    public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head=new ListNode(0);
        ListNode cur=head;
        boolean flag=false;
        while(l1!=null&&l2!=null&&cur!=null){
            ListNode curNext=new ListNode(0);
            cur.next=curNext;
            int tmp=l1.val+l2.val;
            if(flag){
                tmp+=1;
                flag=false;
            }
            if(tmp>=10){
                tmp-=10;
                flag=true;
            }
            curNext.val=tmp;
            l1=l1.next;
            l2=l2.next;
            cur=cur.next;
        }
        while(l1!=null){
            cur.next=l1;
            if(flag){
                l1.val+=1;
                flag=false;
            }
            if(l1.val>=10){
                l1.val-=10;
                flag=true;
            }
            cur=cur.next;
            l1=l1.next;
        }
        while(l2!=null){
            cur.next=l2;
            if(flag){
                l2.val+=1;
                flag=false;
            }
            if(l2.val>=10){
                l2.val-=10;
                flag=true;
            }
            cur=cur.next;
            l2=l2.next;
        }
        if(flag){
            cur.next=new ListNode(1);
        }
        return head.next;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔡欣致

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值