您现在的位置是:首页 >技术杂谈 >LC-1171. 从链表中删去总和值为零的连续节点(模拟,哈希表+前缀和)网站首页技术杂谈
LC-1171. 从链表中删去总和值为零的连续节点(模拟,哈希表+前缀和)
简介LC-1171. 从链表中删去总和值为零的连续节点(模拟,哈希表+前缀和)
1171. 从链表中删去总和值为零的连续节点
难度中等208
给你一个链表的头节点 head
,请你编写代码,反复删去链表中由 总和 值为 0
的连续节点组成的序列,直到不存在这样的序列为止。
删除完毕后,请你返回最终结果链表的头节点。
你可以返回任何满足题目要求的答案。
(注意,下面示例中的所有序列,都是对 ListNode
对象序列化的表示。)
示例 1:
输入:head = [1,2,-3,3,1]
输出:[3,1]
提示:答案 [1,2,1] 也是正确的。
示例 2:
输入:head = [1,2,3,-3,4]
输出:[1,2,4]
示例 3:
输入:head = [1,2,3,-3,-2]
输出:[1]
提示:
- 给你的链表中可能有
1
到1000
个节点。 - 对于链表中的每个节点,节点的值:
-1000 <= node.val <= 1000
.
模拟
class Solution {
public ListNode removeZeroSumSublists(ListNode head) {
ListNode dummy = new ListNode(0, head);
while(true){
ListNode pre = dummy;
boolean flag = false;
// 枚举每个点 pre 作为起点,查看从pre到cur是否存在 和为0 的连续区间
while(pre != null && pre.next != null){
ListNode cur = pre.next;
int sum = cur.val;
while(cur.next != null && sum != 0){
cur = cur.next;
sum += cur.val;
}
// 存在和为0 的连续区间,直接删除[pre+1, cur]这一段
if(sum == 0){
pre.next = cur.next;
flag = true;
}
pre = pre.next;
}
// 找不到和为0 的连续区间,停止循环
if(!flag) break;
}
return dummy.next;
}
}
时间复杂度:O(n^2)
,由于存在区间和为0的话,直接删除,所以时间复杂度和遍历节点个数有关?
空间复杂度:O(1)
哈希表
存前缀和,然后遍历找已经存在的再删除。
若链表节点的两个前缀和相等,说明两个前缀和之间的连续节点序列的和为 0,那么可以消去这部分连续节点。
class Solution {
public ListNode removeZeroSumSublists(ListNode head) {
ListNode dummy = new ListNode(0);
dummy.next = head;
Map<Integer, ListNode> map = new HashMap<>();
// 首次遍历建立 节点处链表和<->节点 哈希表
// 若同一和出现多次会覆盖,即记录该sum出现的最后一次节点
int sum = 0;
for (ListNode d = dummy; d != null; d = d.next) {
sum += d.val;
map.put(sum, d);
}
// 第二遍遍历 若当前节点处sum在下一处出现了则表明两结点之间所有节点和为0 直接删除区间所有节点
sum = 0;
for (ListNode d = dummy; d != null; d = d.next) {
sum += d.val;
d.next = map.get(sum).next;
}
return dummy.next;
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。