DeepSeek LeetCode 3695. 交换元素后的最大交替和 Java实现
这个问题的核心解法是:通过并查集确定哪些下标可以自由交换,然后对每个连通块内部的元素进行贪心分配。具体的算法思路与Java实现如下。
🧠 核心思路
1. 确定连通块:swaps 中的每对 [p, q] 都代表一条边。使用并查集(Union-Find) 将所有可以互相交换的下标连接起来,形成若干独立的连通块。
2. 连通块内部分配:在一个连通块内,由于元素可以任意排列,为了最大化交替和(偶数位加、奇数位减),贪心策略是:
· 将最大的元素放在偶数下标(做加法)。
· 将最小的元素放在奇数下标(做减法)。
3. 计算贡献:对每个连通块,将元素排序后,小的 oddCount 个(奇数位数量)做减法,其余做加法,累加所有块的贡献即为答案。
💻 Java代码实现
```java
class Solution {
public long maxAlternatingSum(int[] nums, int[][] swaps) {
int n = nums.length;
UnionFind uf = new UnionFind(n);
// 1. 合并所有可交换的下标
for (int[] s : swaps) {
uf.union(s[0], s[1]);
}
// 2. 按连通块分组,并统计每个块中奇数下标的数量
Map<Integer, List<Integer>> components = new HashMap<>();
Map<Integer, Integer> oddCount = new HashMap<>();
for (int i = 0; i < n; i++) {
int root = uf.find(i);
components.computeIfAbsent(root, k -> new ArrayList<>()).add(nums[i]);
if (i % 2 == 1) {
oddCount.put(root, oddCount.getOrDefault(root, 0) + 1);
}
}
long ans = 0;
// 3. 计算每个连通块的最大交替和
for (Map.Entry<Integer, List<Integer>> entry : components.entrySet()) {
List<Integer> vals = entry.getValue();
int root = entry.getKey();
int oddCnt = oddCount.getOrDefault(root, 0);
Collections.sort(vals); // 升序排序
// 小的给奇数位(减),大的给偶数位(加)
for (int i = 0; i < vals.size(); i++) {
if (i < oddCnt) {
ans -= vals.get(i);
} else {
ans += vals.get(i);
}
}
}
return ans;
}
// --- 并查集内部类 ---
class UnionFind {
int[] parent;
int[] rank;
public UnionFind(int n) {
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) return;
// 按秩合并
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
}
```
更多推荐





所有评论(0)