📅  最后修改于: 2023-12-03 15:07:27.312000             🧑  作者: Mango
在链表问题中,如何处理满足特定条件的子链表是一个常见问题。可被给定数 k 整除的链表的最大和最小元素,是一道利用前缀和来解决的经典问题。
给定一个长度为 n 的整数链表和一个整数 k,请找出链表中满足以下条件的最大和和最小元素:
链表上的前缀和及取模运算是解决此类问题的通用方法。使用前缀和可以将求和问题转化为相减问题,使用取模运算可以将求余问题转化为相减问题。
为了找到满足条件的最小元素,我们可以对链表进行一次前缀和处理,得到每个节点的前缀和 p[i],则节点 i 到节点 j 的元素和为 p[j] - p[i-1]。接着,我们可以枚举起点 i 和终点 j,找出满足条件的最小元素。
为了找到满足条件的最大和,我们也可以先对链表进行一次前缀和处理,得到每个节点的前缀和 p[i],则节点 i 到节点 j 的元素和为 p[j] - p[i-1]。接着,我们可以从前往后遍历链表,维护一个最大前缀和 max_prefix_sum 和一个最小前缀和 min_prefix_sum,每次计算当前节点到之前某个节点的前缀和的差值(即可被 k 整除的元素之和),并更新最大值和最小值。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def max_min_sum(self, head: ListNode, k: int) -> List[int]:
# 前缀和取模
p = {0: -1}
cur_sum = 0
node = head
while node:
cur_sum += node.val
mod = cur_sum % k
if mod not in p:
p[mod] = node.val
else:
p[mod] = max(p[mod], cur_sum - p[mod])
node = node.next
# 最小元素
min_sum = float('inf')
for i in range(k):
if i not in p:
continue
if p[i] < min_sum:
min_sum = p[i]
# 最大和
max_sum, min_prefix_sum, max_prefix_sum = 0, 0, 0
cur_sum = 0
node = head
while node:
cur_sum += node.val
mod = cur_sum % k
if mod in p:
max_sum = max(max_sum, cur_sum - p[mod])
if cur_sum < min_prefix_sum:
min_prefix_sum = cur_sum
if cur_sum > max_prefix_sum:
max_prefix_sum = cur_sum
node = node.next
if max_prefix_sum % k == 0:
max_sum = max(max_sum, max_prefix_sum - min_prefix_sum)
return [max_sum, min_sum]
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
vector<int> maxMinSum(ListNode* head, int k) {
// 前缀和取模
map<int, int> p{{0, -1}};
int cur_sum = 0;
ListNode *node = head;
while (node) {
cur_sum += node->val;
int mod = cur_sum % k;
if (!p.count(mod)) p[mod] = node->val;
else p[mod] = max(p[mod], cur_sum - p[mod]);
node = node->next;
}
// 最小元素
int min_sum = INT_MAX;
for (auto &[mod, sum] : p) {
if (mod == 0) min_sum = min(min_sum, sum);
else if (p.count(mod)) min_sum = min(min_sum, cur_sum - p[mod]);
}
// 最大和
int max_sum = 0, min_prefix_sum = 0, max_prefix_sum = 0;
cur_sum = 0;
node = head;
while (node) {
cur_sum += node->val;
int mod = cur_sum % k;
if (p.count(mod)) max_sum = max(max_sum, cur_sum - p[mod]);
if (cur_sum < min_prefix_sum) min_prefix_sum = cur_sum;
if (cur_sum > max_prefix_sum) max_prefix_sum = cur_sum;
node = node->next;
}
if (max_prefix_sum % k == 0)
max_sum = max(max_sum, max_prefix_sum - min_prefix_sum);
return {max_sum, min_sum};
}
};