You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2023_03_5_week;
// 来自腾讯音乐
// 给定一棵树一共有n个点
// 每个点上没有值请把1~n这些数字不重复的分配到二叉树上
// 做到 : 奇数层节点的值总和 与 偶数层节点的值总和 相差不超过1
// 返回奇数层节点分配值的一个方案
// 2 <= n <= 10^5
// 所以课上会讲怎么转化,然后如下的代码实现
public class Code02_OddLevelEvenLevelSumClosed {
// 1 ~ n 奇数节点的个数是k个
// 返回奇数节点的值有哪些
public static int[] team(int n, int k) {
// 1 ~ n , sum = 10 k个奇数 5
// 1 ~ n , sum = 15 k个奇数 7 8
int sum = (n + 1) * n / 2;
int p1 = sum / 2;
int p2 = (sum + 1) / 2;
int[] ans = generate(p1, n, k);
if (ans == null && (sum & 1) == 1) {
ans = generate(p2, n, k);
}
return ans != null ? ans : new int[] { -1 };
}
// 一共 1 ~ n 这些数字
// 其中选k个数字
// 一定要让k个数字的累加和是wantSum
// 返回哪k个数字只要返回一种方法就可以
public static int[] generate(int wantSum, int n, int k) {
// k个数字和最小的情况1 2 3 ... k
int sumMinK = (k + 1) * k / 2;
// 每个数提升的幅度
int range = n - k;
if (wantSum < sumMinK || wantSum > sumMinK + k * range) {
return null;
}
int add = wantSum - sumMinK;
int rightSize = add / range;
int midIndex = (k - rightSize) + (add % range);
int leftSize = k - rightSize - (add % range == 0 ? 0 : 1);
int[] ans = new int[k];
for (int i = 0; i < leftSize; i++) {
ans[i] = i + 1;
}
if (add % range != 0) {
ans[leftSize] = midIndex;
}
for (int i = k - 1, j = 0; j < rightSize; i--, j++) {
ans[i] = n - j;
}
return ans;
}
public static void main(String[] args) {
// n是最大值1~n这些数字都有
int n = 100;
// k是个数
int k = 33;
// 1~n这些数字选k个能不能求和逼近一半
// 返回方案
int[] ans = team(n, k);
System.out.println("总和 : " + (n + 1) * n / 2);
System.out.println("长度 : " + ans.length);
int sum = 0;
System.out.print("数字 : ");
for (int num : ans) {
System.out.print(num + " ");
sum += num;
}
System.out.println();
System.out.println("求和 : " + sum);
System.out.println("剩余 : " + ((n + 1) * n / 2 - sum));
}
}