2023-08-02:给定一棵树,一共有n个点, 每个点上没有值,请把1~n这些数字,不重复的分配到二叉树上, 做到 : 奇数层节点的值总和 与 偶数层节点的值总和 相差不超过1。 返回奇数层节点分配
2023-08-02:给定一棵树,一共有n个点,
每个点上没有值,请把1~n这些数字,不重复的分配到二叉树上,
做到 : 奇数层节点的值总和 与 偶数层节点的值总和 相差不超过1。
返回奇数层节点分配值的一个方案。
2 <= n <= 10^5 。
来自腾讯音乐。
答案2023-08-02:
大致步骤如下:
1.计算出1到n的总和sum。
2.确定两个目标值p1和p2,它们分别是sum的整数除法结果和向上取整结果。p1和p2代表了奇数层节点总和和偶数层节点总和的一半。
3.调用generate函数来生成奇数层节点的分配方案。generate函数用于生成一个数组,其中包含k个数,这k个数的和为指定的wantSum。如果无法生成满足要求的方案,则返回nil。
4.如果generate函数返回nil并且sum是奇数,说明无法找到满足要求的奇数层节点方案。这种情况下,重新调用generate函数来生成偶数层节点的分配方案。
5.如果两次调用generate函数都没有找到满足要求的方案,则返回[-1]表示无解。
6.输出生成的方案。
时间复杂度分析:
计算sum的时间复杂度为O(1)。
generate函数的时间复杂度为O(k)。
整体时间复杂度为O(k)。
空间复杂度分析:
generate函数中创建了一个大小为k的数组来存储结果,所以空间复杂度为O(k)。
整体空间复杂度为O(k)。
go完整代码如下:
package main
import "fmt"
// generate returns an array of k numbers between 1 and n whose sum is wantSum
func generate(wantSum, n, k int) []int {
// The minimum sum of k numbers, for example: 1 2 3 ... k
sumMinK := (k + 1) * k / 2
// The range each number can increase
rangeVal := n - k
if wantSum < sumMinK || wantSum > sumMinK+k*rangeVal {
return nil
}
add := wantSum - sumMinK
rightSize := add / rangeVal
midIndex := (k - rightSize) + (add % rangeVal)
leftSize := k - rightSize
if add%rangeVal != 0 {
leftSize--
}
ans := make([]int, k)
for i := 0; i < leftSize; i++ {
ans[i] = i + 1
}
if add%rangeVal != 0 {
ans[leftSize] = midIndex
}
for i, j := k-1, 0; j < rightSize; i, j = i-1, j+1 {
ans[i] = n - j
}
return ans
}
// team returns the values of the odd nodes out of 1 to n, with a total of k nodes
func team(n, k int) []int {
sum := (n + 1) * n / 2
p1 := sum / 2
p2 := (sum + 1) / 2
ans := generate(p1, n, k)
if ans == nil && (sum&1) == 1 {
ans = generate(p2, n, k)
}
if ans == nil {
ans = []int{-1}
}
return ans
}
func main() {
// n is the maximum value, includes 1 to n
n := 100
// k is the number of nodes
k := 33
// Can we approximate half the sum of 1 to n by selecting k nodes? Return the solution.
ans := team(n, k)
fmt.Println("Sum:", (n+1)*n/2)
fmt.Println("Length:", len(ans))
sum := 0
fmt.Print("Numbers:")
for _, num := range ans {
fmt.Print(num, " ")
sum += num
}
fmt.Println()
fmt.Println("Sum:", sum)
fmt.Println("Remaining:", (n+1)*n/2-sum)
}

rust完整代码如下:
fn team(n: i32, k: i32) -> Vec<i32> {
let sum = (n + 1) * n / 2;
let p1 = sum / 2;
let p2 = (sum + 1) / 2;
let ans = generate(p1, n, k);
if ans.is_none() && sum % 2 == 1 {
generate(p2, n, k)
} else {
ans
}
.unwrap_or(vec![-1])
}
fn generate(want_sum: i32, n: i32, k: i32) -> Option<Vec<i32>> {
let sum_min_k = (k + 1) * k / 2;
let range = n - k;
if want_sum < sum_min_k || want_sum > sum_min_k + k * range {
return None;
}
let add = want_sum - sum_min_k;
let right_size = add / range;
let mid_index = (k - right_size) + (add % range);
let left_size = k - right_size - if add % range == 0 { 0 } else { 1 };
let mut ans = vec![0; k as usize];
for i in 0..left_size as usize {
ans[i] = (i + 1) as i32;
}
if add % range != 0 {
ans[left_size as usize] = mid_index;
}
let mut i = k - 1;
let mut j = 0;
while j < right_size {
ans[i as usize] = n - j;
i -= 1;
j += 1;
}
Some(ans)
}
fn main() {
let n = 100;
let k = 33;
let ans = team(n, k);
let sum: i32 = ans.iter().sum();
println!("总和: {}", (n + 1) * n / 2);
println!("长度: {}", ans.len());
print!("数字: ");
for num in ans {
print!("{} ", num);
}
println!();
println!("求和: {}", sum);
println!("剩余: {}", (n + 1) * n / 2 - sum);
}

c++完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
vector<int> generate(int wantSum, int n, int k) {
int sumMinK = (k + 1) * k / 2;
int range = n - k;
if (wantSum < sumMinK || wantSum > sumMinK + k * range) {
return {};
}
int add = wantSum - sumMinK;
int rightSize = add / range;
int midIndex = (k - rightSize) + (add % range);
int leftSize = k - rightSize - ((add % range) == 0 ? 0 : 1);
vector<int> ans(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;
}
vector<int> team(int n, int k) {
int sum = (n + 1) * n / 2;
int p1 = sum / 2;
int p2 = (sum + 1) / 2;
vector<int> ans = generate(p1, n, k);
if (ans.empty() && (sum & 1) == 1) {
ans = generate(p2, n, k);
}
return ans.empty() ? vector<int>{-1} : ans;
}
int main() {
int n = 100;
int k = 33;
vector<int> ans = team(n, k);
cout << "总和 : " << (n + 1) * n / 2 << endl;
cout << "长度 : " << ans.size() << endl;
int sum = 0;
cout << "数字 : ";
for (int num : ans) {
cout << num << " ";
sum += num;
}
cout << endl;
cout << "求和 : " << sum << endl;
cout << "剩余 : " << ((n + 1) * n / 2 - sum) << endl;
return 0;
}

c完整代码如下:
#include <stdio.h>
#include <stdlib.h>
// 一共 1 ~ n 这些数字
// 其中选k个数字
// 一定要让k个数字的累加和是wantSum
// 返回,哪k个数字,只要返回一种方法就可以
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 = (int*)malloc(k * sizeof(int));
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;
}
// 1 ~ n 奇数节点的个数是k个
// 返回奇数节点的值有哪些
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 : NULL;
}
int main() {
// n是最大值,1~n这些数字都有
int n = 100;
// k是个数
int k = 33;
// 1~n这些数字,选k个,能不能求和逼近一半
// 返回方案
int* ans = team(n, k);
if (ans != NULL) {
printf("总和 : %d\n", (n + 1) * n / 2);
printf("长度 : %d\n", k);
int sum = 0;
printf("数字 : ");
for (int i = 0; i < k; i++) {
printf("%d ", ans[i]);
sum += ans[i];
}
printf("\n");
printf("求和 : %d\n", sum);
printf("剩余 : %d\n", ((n + 1) * n / 2 - sum));
}
else {
printf("无解\n");
}
free(ans); // 释放内存
return 0;
}

2023-08-02:给定一棵树,一共有n个点, 每个点上没有值,请把1~n这些数字,不重复的分配到二叉树上, 做到 : 奇数层节点的值总和 与 偶数层节点的值总和 相差不超过1。 返回奇数层节点分配的更多相关文章
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- [LeetCode] 96. Unique Binary Search Trees(给定一个数字n,有多少个唯一二叉搜索树) ☆☆☆
[Leetcode] Unique binary search trees 唯一二叉搜索树 Unique Binary Search Trees leetcode java 描述 Given n, h ...
- 算法进阶面试题04——平衡二叉搜索树、AVL/红黑/SB树、删除和调整平衡的方法、输出大楼轮廓、累加和等于num的最长数组、滴滴Xor
接着第三课的内容和讲了第四课的部分内容 1.介绍二叉搜索树 在二叉树上,何为一个节点的后继节点? 何为搜索二叉树? 如何实现搜索二叉树的查找?插入?删除? 二叉树的概念上衍生出的. 任何一个节点,左比 ...
- 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)
树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树 ...
- [数据结构 - 第6章] 树之二叉平衡树(C语言实现)
一.什么是平衡二叉树? 平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两 ...
- HDU 3179 二叉搜索树(树的建立)
二叉搜索树 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 二叉树系列 - 二叉搜索树 - [LeetCode] 中序遍历中利用 pre节点避免额外空间。题:Recover Binary Search Tree,Validate Binary Search Tree
二叉搜索树是常用的概念,它的定义如下: The left subtree of a node contains only nodes with keys less than the node's ke ...
- 剑指offer-第四章解决面试题思路(二叉收索树和双向链表)
题目:输入一个二叉收索树,将二叉搜索树转换成排序的双向链表.要求不能创建节点,只能将链表中的指针进行改变. 将复杂的问题简单化:思路:二叉收索树,本身是一个排序结构,中序遍历二叉收索树就可以得到一组排 ...
- 【数据结构与算法Python版学习笔记】树——利用二叉堆实现优先级队列
概念 队列有一个重要的变体,叫作优先级队列. 和队列一样,优先级队列从头部移除元素,不过元素的逻辑顺序是由优先级决定的. 优先级最高的元素在最前,优先级最低的元素在最后. 实现优先级队列的经典方法是使 ...
- Trees in a Wood. UVA 10214 欧拉函数或者容斥定理 给定a,b求 |x|<=a, |y|<=b这个范围内的所有整点不包括原点都种一棵树。求出你站在原点向四周看到的树的数量/总的树的数量的值。
/** 题目:Trees in a Wood. UVA 10214 链接:https://vjudge.net/problem/UVA-10214 题意:给定a,b求 |x|<=a, |y|&l ...
随机推荐
- Golang每日一库之regex
本文地址: https://www.cnblogs.com/zichliang/p/17387436.html Golang日库合集:https://www.cnblogs.com/zichliang ...
- vue 事件中的 .native你搞清楚了吗
native是什么? .native - 监听组件根元素的原生事件. 主要是给自定义的组件添加原生事件. 官网的解释: 你可能想在某个组件的根元素上监听一个原生事件.可以使用 v-on 的修饰符 .n ...
- 2022-11-29:查找重复的电子邮箱。以下数据中a@b.com是重复的,请写出sql语句。 DROP TABLE IF EXISTS person; CREATE TABLE person (
2022-11-29:查找重复的电子邮箱.以下数据中a@b.com是重复的,请写出sql语句. DROP TABLE IF EXISTS person; CREATE TABLE person ( i ...
- 2022-04-13:给你一个下标从 0 开始包含 n 个正整数的数组 arr ,和一个正整数 k 。 如果对于每个满足 k <= i <= n-1 的下标 i ,都有 arr[i-k] <= arr
2022-04-13:给你一个下标从 0 开始包含 n 个正整数的数组 arr ,和一个正整数 k . 如果对于每个满足 k <= i <= n-1 的下标 i ,都有 arr[i-k] ...
- 2021-03-29:无序数组arr,子数组-1和1的数量一样多,请问最长子数组的长度是多少?
2021-03-29:无序数组arr,子数组-1和1的数量一样多,请问最长子数组的长度是多少? 福大大 答案2021-03-29: [1, -1, 2, 3, -4, -1, 9]变成[1, -1, ...
- 2022-01-31:迷宫 III。 由空地和墙组成的迷宫中有一个球。球可以向上(u)下(d)左(l)右(r)四个方向滚动,但在遇到墙壁前不会停止滚动。当球停下时,可以选择下一个方向。迷宫中还有一个洞
2022-01-31:迷宫 III. 由空地和墙组成的迷宫中有一个球.球可以向上(u)下(d)左(l)右(r)四个方向滚动,但在遇到墙壁前不会停止滚动.当球停下时,可以选择下一个方向.迷宫中还有一个洞 ...
- Selenium - 元素操作(2) - 页面滚动条
Selenium - 元素操作 函数滚动 一般元素定位,元素如果不在浏览器的可视位置(即可见只是不在可视位置),会自动把元素滚动到可视位置,但也有不会自己滚动的(比较少). 那我们就可以用seleni ...
- vue全家桶进阶之路42:Vue3 SCSS、SASS、CSS
SCSS和SASS都是CSS预处理器,它们的主要目的是简化CSS的编写,增加可维护性,并提供更丰富的功能.下面是它们与普通的CSS的区别: 语法:SCSS和SASS都具有比普通CSS更丰富的语法.其中 ...
- select_related一对一、多对一查询优化
select_related一对一.多对一查询优化 Course.objects.all().select_related('teacher') 查询课程时顺带查出老师的信息
- Django admin管理工具的使用、定制及源码解析
admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLE ...