diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index c882bf3..f01f680 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -926,3 +926,70 @@ func customSortString(order string, s string) string { ### 总结 注意题中条件, 遍历的类型有限的情况下直接使用数组保存, 遍历起来速度要快得多. + +## day15 2024-03-12 + +### 1171. Remove Zero Sum Consecutive Nodes from Linked List + +Given the head of a linked list, we repeatedly delete consecutive sequences of nodes that sum to 0 until there are no such sequences. + +After doing so, return the head of the final linked list. You may return any such answer. + +(Note that in the examples below, all sequences are serializations of ListNode objects.) + +![0312F5f5ZKGJQi7I](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0312F5f5ZKGJQi7I.png) + +### 题解 + +本题有一定难度, 寻找连续的和为0的连续序列要使用前缀和, 若某两个元素的前缀和相同, 则位于二者之间的序列和即为0. 删除这部分序列. 先遍历链表, 找到所有前缀和相同的元素, 然后将其中间的部分全部删除即可. +使用一个map来保存前缀和对应的Node的指针, 当找到一个前缀和相同的Node时, 从map保存的指针开始删除到该Node的所有节点, 同时删除以中间部分节点的前缀和为key的map中对应的项防止后面有和中间部分项相同的前缀和的节点存在. + +### 代码 + +```go +v/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + + +func removeZeroSumSublists(head *ListNode) *ListNode { + current := head + sum := 0 + summap := map[int](*ListNode){} + for current != nil{ + sum += current.Val + if sum == 0{ + for head != current.Next{ + sum += head.Val + delete(summap, sum) + head = head.Next + } + } + ptr, exist := summap[sum] + if !exist{ + summap[sum] = current + }else{ + back := ptr + ptr = ptr.Next + for ptr != current{ + sum += ptr.Val + delete(summap, sum) + ptr = ptr.Next + } + sum += ptr.Val + back.Next = current.Next + } + current = current.Next + } + return head + +} +``` + +### 总结 + +删除中间部分节点的前缀和对应的key的项时, 考虑到中间部分的和一定为0, 因此用sum去累加中间部分节点的值并依次删除, 最后得到的sum就和删除节点开始前的sum相同. 本题一是要清楚通过前缀和来寻找连续的和为0的序列, 另一方面则是时刻记住这个序列的和为0的特性. 其实本题有一种代表元的抽象思想. 可以将一组和为0的序列看为一个, 其在加和过程中与不存在的节点具有等价性. 不影响和的变化.