数据结构与算法:前缀和的问题

例题:
给你一个链表的头节点 head,请你编写代码,反复删去链表中由 总和 值为 0 的连续节点组成的序列,直到不存在这样的序列为止。

删除完毕后,请你返回最终结果链表的头节点。

数据案例

输入:head = [1,2,-3,3,1]
输出:[3,1]
提示:答案 [1,2,1] 也是正确的。
输入:head = [1,2,3,-3,4]
输出:[1,2,4]
输入:head = [1,2,3,-3,-2]
输出:[1]

之前有做过找最大前缀和的问题,感觉这个连续最大为0的链表题也应该类似。但是对于第一次解决链表前缀和问题,思路想了很久。
思路:
head = [1,2,-3,3,1]
1、对于这组数据来讲,我们可以依次得到他的每一位的前缀和是[1,3,0,3,4],有了这一步,思路就很清晰了,只要找到一样的前缀和,两个数之间的数字都是满足连续和为0的
2、特殊情况的处理:

  • [-1,1]这种刚好从头开始满足条件的数据案例,需要增加哑结点特殊处理
  • [1,2,-3,3,1,-1]得到的子序列和是[1,3,0,3,4,3]已经断过链再次出现断链前内和一样的情况,第二次断链必须是从第一个3开始断链,所以每次断链应该把丢掉的数据及时处理
    3、如何实现?这也是一个难题。最后我选择了用hashMap存放连续和 和 结点地址。大量空间换了时间,但是这样的效率依然不是很高
    //前缀和的问题
    public ListNode removeZeroSumSublists(ListNode head) {
    	ListNode dymmynode = new ListNode(0);
    	dymmynode.next = head;
    	ListNode cur = dymmynode;
    	HashMap<Integer,ListNode> map = new HashMap<>();
    	int count = 0;
    	while(cur != null) {
    		count += cur.val;
    		//不存在的时候
    		if(!map.containsKey(count)) {
    			map.put(count, cur);
    		}else {
    			cur = map.get(count).next;
    			int val = count + cur.val;
    			while(val != count) {
    				map.remove(val);
    				cur = cur.next;
    				val += cur.val;
    				
    			}
    			map.get(count).next = cur.next;
    		}
    		cur = cur.next;
    	}
    	return dymmynode.next;
    }

后来看了一些大佬的题解,这个题可以完全用指针实现,效率极高

class Solution {
    public ListNode removeZeroSumSublists(ListNode head) {
        //生成带头结点的链表
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode h = dummyHead;
        
        while(h.next != null){
            ListNode p = h.next;
            ListNode q = p;
            int sum = p.val;    //sum是p至q的总和
            while(q.next != null || sum == 0){   // 加个sum==0的条件,用来处理链表最后n个节点的和为0时的情形如:[1, 2, -2]
                if(sum == 0){   // 先判断sum的值再求和,可以不用对值为0的节点特殊处理
                    h.next = q.next;
                    break;
                }
                q = q.next;
                sum += q.val;
            }
            if(sum != 0) h = h.next;  
        }
        return dummyHead.next;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章