數據結構與算法:前綴和的問題

例題:
給你一個鏈表的頭節點 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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章