11. <tag-链表和前缀和, 哈希表>lt.1171- 从链表中删去总和值为零的连续节点

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

[案例需求]
在这里插入图片描述

[思路分析]
在这里插入图片描述

[代码实现]

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        //前缀和的一个应用, 为什么会想到用前缀和, 因为是题目要求是一些子区间的加加减减,
        // 题目要求是去除掉和为0的结点, 所以前后的值相同的两个前缀和, 这两个前缀和之间的数之和一定是0
        //对于链表, 来回的遍历结点无非是很麻烦的, 要想实现对链表的自由遍历, 可以使用哈希表存储结点
        // 所以本题, 用哈希表存储<前缀和, 结点>, 由于哈希表中key相同的两个映射, 会自动覆盖值, 所以
        // 我们遍历完成一次链表之后, 哈希表中的结点都是各种组合不为0的结点;
        Map<Integer, ListNode> map = new HashMap<>();

        ListNode temp = head;
        // Q: 链表的前缀和如何计算?
        int preSum = 0;
        while(temp != null){
            preSum += temp.val;
            map.put(preSum, temp);

            temp = temp.next;
        } 

        //第二次遍历链表
        //再次计算前缀和, 这一次把其前缀和跟map中有重复的进行一个替换
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        temp = dummyNode;
        preSum = 0;

        while(temp != null){
            preSum += temp.val;

            if(map.containsKey(preSum)){
                temp.next = map.get(preSum).next;
            }

            temp = temp.next;
        }
        
        return dummyNode.next;
    }
}
posted @ 2022-05-26 20:29  青松城  阅读(40)  评论(0)    收藏  举报