首页 > 其他分享 >2023-08-02:给定一棵树,一共有n个点, 每个点上没有值,请把1~n这些数字,不重复的分配到二叉树上, 做到 : 奇数层节点的值总和 与 偶数层节点的值总和 相差不超过1。 返回奇数层节点分配

2023-08-02:给定一棵树,一共有n个点, 每个点上没有值,请把1~n这些数字,不重复的分配到二叉树上, 做到 : 奇数层节点的值总和 与 偶数层节点的值总和 相差不超过1。 返回奇数层节点分配

时间:2023-08-02 22:33:20浏览次数:40  
标签:奇数 int sum add generate range ans 节点 总和

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;
}

在这里插入图片描述

标签:奇数,int,sum,add,generate,range,ans,节点,总和
From: https://www.cnblogs.com/moonfdd/p/17601984.html

相关文章

  • 2023-08-02:给定一棵树,一共有n个点, 每个点上没有值,请把1~n这些数字,不重复的分配到二叉
    2023-08-02:给定一棵树,一共有n个点,每个点上没有值,请把1~n这些数字,不重复的分配到二叉树上,做到:奇数层节点的值总和与偶数层节点的值总和相差不超过1。返回奇数层节点分配值的一个方案。2<=n<=10^5。来自腾讯音乐。答案2023-08-02:大致步骤如下:1.计算出1到n的总和sum。2.确......
  • 动力节点第四章OpenFeign与负载均衡-最全springcloud Alibaba学习笔记
    学习笔记视频:https://www.bilibili.com/video/BV1VW4y1o7n5本课程使用的是目前最新版本2022.0.0.0-RC2。基于SpringBoot3.0与JDK20的开发环境。课程内容涵盖了SpringCloudAlibaba所有的技术点,主要讲述包括NacosDiscovery、NacosConfig、OpenFeign、SpringCloudLoadbalance......
  • 求和计算MySQL中如何对两列求和(mysql 中两列总和)
    求和计算:MySQL中如何对两列求和?在MySQL数据库中,对两列进行求和运算是一项常规操作。本文将介绍在MySQL中如何对两列进行求和运算,并给出相关的SQL代码示例。SQL语句中使用的SUM()函数是MySQL中常用的聚合函数之一,用于计算某一列的总和。而对于两列的求和,则需要将两个......
  • Tita 升级| 新增「工作总结」节点
    一、新增「工作总结」Tita-OKR和新绩效一体化管理平台支持新增「工作总结」节点;支持自由拖动「工作节点」到流程任意位置;支持自定义「工作总结」模板内容,且标题可设置必填&非必填;支持节点为空「不处理」「系统自动跳过」「指派给指定人」;二、「工作总结」录入......
  • 算法 | 就地逆置、双指针快速寻找中间节点
    2019年真题设线性表L=(a1,a2,a3,...,an-2,an-1,an)采用带头节点的单链表保存,链表中的结点定义如下:(代码1)设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各结,得到线性表L’=(a1,an,a2,an-1,a3,an-2,...)。//代码1//langCtypedefstr......
  • 112. 路径总和
    给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。示例1:输入:root=[5,4,8,11,null,13,4,7,2,null,null,null,1],targe......
  • mongodb 隐藏节点 查看
    MongoDB隐藏节点查看步骤概述在MongoDB中,隐藏节点是指那些不参与主节点选举,但可以用于读操作的节点。隐藏节点对于搭建高可用的数据库架构以及优化读取性能非常重要。本文将介绍如何在MongoDB中查看隐藏节点。步骤步骤操作步骤一连接到MongoDB实例步骤二查看复制......
  • 代码随想录第四天|力扣24.两两交换链表节点、力扣19.删除链表的倒数第N个结点、力扣面
    两两交换链表中的节点(力扣24.)dummyhead.next=head;cur=dummyhead;while(cur.next!=null&&cur.next.next!=null)temp=cur.next;temp1=cur.next.next.next;cur.next=cur.next.next;cur.next.next=temp;temp.next=temp1;cur=cur.next.next;returndummyhead.n......
  • 代码随想录算法训练营第四天| LeetCode 24. 两两交换链表中的节点 19.删除链表的倒
    24.两两交换链表中的节点     卡哥建议:用虚拟头结点,这样会方便很多。 本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。   题目链接/文章讲解/视频讲解:https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%......
  • blender 材质节点常见疑惑
    纹理坐标TextureCordinate生成与物体的区别?Generatedvsobject?棋盘格纹理:缩放5,代表有5格生成:依据最外部边界框,若{长,宽,高}={1m,2m,3m},则都设定成{1m,1m,1m},来投射纹理物体:使用全局单位(米),此处边长2m的正方体横着有10格子,刚好对应5格/m,来投射纹理颜色渐变ColorRa......