2023-04-23:给定你一个整数数组 nums
我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中
使得 A 集合和 B 集合不为空,并且 average(A) == average(B)
如果可以完成则返回true,否则返回false。
注意:对于数组 arr, average(arr) 是 arr 的所有元素的和除以 arr 长度。
输入: nums = [1,2,3,4,5,6,7,8]。
输出: true。

答案2022-04-23:

  1. 定义全局变量 nslr,分别表示数组长度、数组元素之和、左侧集合的元素个数和右侧集合的元素个数。
  2. 定义两个数组 lvaluesrvalues,用于存储左侧集合和右侧集合的指标值。
  3. 编写函数 splitArraySameAverage(nums []int) bool,其中 nums 是输入的整数数组。首先检查数组长度是否为 1,如果是则返回 false。
  4. 计算数组元素之和 s
  5. 创建一个长度为 n/2 的切片 larr 和一个长度为 n-len(larr) 的切片 rarr,将前半部分元素存储在 larr 中,将后半部分元素存储在 rarr 中。
  6. 调用函数 collect(larr, true) 收集左侧集合的指标值,并调用函数 collect(rarr, false) 收集右侧集合的指标值。
  7. 对右侧集合的指标值进行排序,以便进行二分查找。
  8. 遍历左侧集合的指标值,在右侧集合中查找是否存在相反数,如果存在则说明可以分割成两个具有相同平均数的子集,返回 true;否则返回 false。
  9. 编写函数 collect(arr []int, isLeft bool),其中 arr 是需要遍历的整数数组,isLeft 指示是否为左侧集合。在函数中调用递归函数 process(arr, 0, 0, 0, isLeft)
  10. 编写函数 process(arr []int, index int, sum int, num int, isLeft bool),其中 index 表示当前处理的元素下标,sum 表示当前元素之和,num 表示当前元素个数。如果 index 等于数组长度,则计算指标值并将其存储在 lvaluesrvalues 中。
  11. 对于每个元素,都有两种选择:不加入集合(包括左侧集合和右侧集合),或者加入集合并递归到下一个元素。因此,递归函数应该调用 process(arr, index+1, sum, num, isLeft)process(arr, index+1, sum+arr[index], num+1, isLeft) 这两个函数。
  12. 编写函数 contains(num int) bool,其中 num 是需要查找的元素。使用二分查找算法在 rvalues 数组中查找相应的元素。

时间复杂度:

该算法的时间复杂度主要受到递归函数 process 对数组的遍历方式和左侧集合大小的约束,以及二分查找函数 contains 的时间复杂度的影响。

process 函数中,对于每个元素都有两种选择,因此共有

2

n

2^n

2n 种可能的组合。对于每种组合,最坏情况下需要进行一个二分查找操作,因此 process 函数的时间复杂度为

O

(

n

×

2

n

log

n

)

O(n\times 2^n \log n)

O(n×2nlogn)。

contains 函数中,二分查找的时间复杂度为

O

(

log

n

)

O(\log n)

O(logn)。

因此,该算法的总时间复杂度为

O

(

n

×

2

n

log

n

)

O(n\times 2^n \log n)

O(n×2nlogn)。

空间复杂度:

该算法的空间复杂度主要受到存储左侧集合指标值的数组 lvalues 和存储右侧集合指标值的数组 rvalues 的影响。这两个数组的长度分别为

2

n

/

2

2^{n/2}

2n/2 和

2

n

n

/

2

2^{n-n/2}

2n−n/2,因此总空间复杂度为

O

(

2

n

)

O(2^n)

O(2n)。

此外,还需要定义一些全局变量和局部变量,它们的空间占用不会随着输入规模的增加而增加,因此可以忽略。

总的来说,该算法的空间复杂度为

O

(

2

n

)

O(2^n)

O(2n)。由于

n

n

n 的取值范围较小,因此该算法的空间复杂度是可以接受的。

golang完整代码如下:

package main

import (
"fmt"
"sort"
) var (
n int
s int
l int
r int
lvalues [1 << 15]int
rvalues [1 << 15]int
) func splitArraySameAverage(nums []int) bool {
n = len(nums)
if n == 1 {
return false
} s = 0
for _, num := range nums {
s += num
} l = 0
r = 0 larr := make([]int, n/2)
for i := 0; i < len(larr); i++ {
larr[i] = nums[i]
} rarr := make([]int, n-len(larr))
for i := len(larr); i < len(nums); i++ {
rarr[i-len(larr)] = nums[i]
} // 左侧 : 收集指标的时候,不能一个数也没有
collect(larr, true)
// 右侧 : 收集指标的时候,不能所有数都用
collect(rarr, false) sort.Ints(rvalues[:r])
for i := 0; i < l; i++ {
// 左侧x -x
if contains(-lvalues[i]) {
return true
}
} return false
} func collect(arr []int, isLeft bool) {
process(arr, 0, 0, 0, isLeft)
} func process(arr []int, index int, sum int, num int, isLeft bool) {
if index == len(arr) {
if isLeft && num > 0 {
lvalues[l] = s*num - n*sum
l++
}
if !isLeft && num != len(arr) {
rvalues[r] = s*num - n*sum
r++
}
} else {
process(arr, index+1, sum, num, isLeft)
process(arr, index+1, sum+arr[index], num+1, isLeft)
}
} func contains(num int) bool {
left := 0
right := r - 1
for left <= right {
mid := (left + right) / 2
if rvalues[mid] == num {
return true
} else if rvalues[mid] < num {
left = mid + 1
} else {
right = mid - 1
}
}
return false
} func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8}
if splitArraySameAverage(nums) {
fmt.Println("可以分割成两个具有相同平均数的子集")
} else {
fmt.Println("无法分割成两个具有相同平均数的子集")
}
}

rust完整代码如下:

use std::cmp::Ordering;

static mut L_VALUES: [i32; 1 << 15] = [0; 1 << 15];
static mut R_VALUES: [i32; 1 << 15] = [0; 1 << 15];
static mut N: i32 = 0;
static mut S: i32 = 0;
static mut L: i32 = 0;
static mut R: i32 = 0; pub fn split_array_same_average(nums: Vec<i32>) -> bool {
unsafe {
N = nums.len() as i32;
if N == 1 {
return false;
}
S = nums.iter().sum();
L = 0;
R = 0; let mut larr = vec![0; N as usize / 2];
for i in 0..larr.len() {
larr[i] = nums[i];
} let mut rarr = vec![0; N as usize - larr.len()];
for i in larr.len()..nums.len() {
rarr[i - larr.len()] = nums[i];
} collect(&mut larr, 0, 0, 0, true);
collect(&mut rarr, 0, 0, 0, false); let mut r_values = [0; 1 << 15];
for i in 0..R {
r_values[i as usize] = R_VALUES[i as usize];
}
r_values.sort_unstable(); for i in 0..L {
if contains(-L_VALUES[i as usize], &r_values) {
return true;
}
}
false
}
} fn collect(arr: &mut [i32], index: usize, sum: i32, num: i32, is_left: bool) {
unsafe {
if index == arr.len() {
if is_left && num > 0 {
L_VALUES[L as usize] = S * num - N * sum;
L += 1;
}
if !is_left && num != arr.len() as i32 {
R_VALUES[R as usize] = S * num - N * sum;
R += 1;
}
} else {
collect(arr, index + 1, sum, num, is_left);
collect(arr, index + 1, sum + arr[index], num + 1, is_left);
}
}
} fn contains(num: i32, r_values: &[i32]) -> bool {
let mut left = 0;
let mut right = r_values.len() - 1;
while left <= right {
let mid = (left + right) / 2;
match r_values[mid].cmp(&num) {
Ordering::Equal => return true,
Ordering::Less => left = mid + 1,
Ordering::Greater => right = mid - 1,
}
}
false
} fn main() {
let nums = vec![1, 2, 3, 4, 5, 6, 7, 8];
let result = split_array_same_average(nums);
println!("{}", result);
}

2023-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver的更多相关文章

  1. LeetCode 周赛 342(2023/04/23)容斥原理、计数排序、滑动窗口、子数组 GCB

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 前天刚举办 2023 年力扣杯个人 SOLO 赛,昨天周赛就出了一场 Easy - Ea ...

  2. 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。

    /** * 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标. * * 你可以假设每种输入只会对应一个答案.但是,数组中 ...

  3. 整数数组的定义,然后输入一个整数X,假定X不在这个数组,返回小于X位置的最大数目i而超过X位置的最小数目j

    //整数数组的定义,然后输入一个整数x,假定X不在这个数组,返回小于X位置的最大数目i而超过X位置的最小数目j: //如果X在该阵列,返回位置的阵列中的数. 资源: #include<iostr ...

  4. 【spring set注入 注入集合】 使用set注入的方式注入List集合和Map集合/将一个bean注入另一个Bean

    Dao层代码: package com.it.dao; public interface SayHell { public void sayHello(); } Dao的Impl实现层: packag ...

  5. LeetCode竞赛题:K 次取反后最大化的数组和(给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。)

    给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次.(我们可以多次选择同一个索引 i.) 以这种方式修改数组后 ...

  6. 9.11排序与查找(三)——给定一个排序后的数组,包括n个整数,但这个数组已被旋转过多次,找出数组中的某个元素

    /**  * 功能:给定一个排序后的数组.包括n个整数.但这个数组已被旋转过多次,次数不详.找出数组中的某个元素.  * 能够假定数组元素原先是按从小到大的顺序排列的.  */ /** * 思路:数组 ...

  7. 给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。

    描述 给一个整数数组,找到两个数使得他们的和等于一个给定的数 target. 你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标.注意这里下标的范围是 0 到 n-1. ...

  8. 作业帮:给定一个整数数组,找出其中两个数相加等于目标值(去重set)

    题目描述 给定一个整数数组,找出其中两个数相加等于目标值 输入 [1,3,5,7,9,11] 10 输出 1,9 3,7 代码: import java.util.HashMap; import ja ...

  9. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

  10. 给定一个整数数组 nums 和一个目标值 target,求nums和为target的两个数的下表

    这个是来自力扣上的一道c++算法题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案 ...

随机推荐

  1. class1,2,3,4,5,6,7

    //测试你是哪一类学者 #include<stdio.h> int main() { int ans; char words[5000]; printf("网课学习让一些人喜一些 ...

  2. spring mvc加载顺序

    contextLoaderLister extends ContextLoader 实现 ServletContextListener接口 contextLoaderLister 是一个观察查模式 由 ...

  3. Python练习-3.12

    1.给文章中的手机号打上马赛克 也就是在文章中发现手机号之后,用*或者#等这一类无法将手机号直接识别出来的符号代替 # 文章中手机号的马赛克形式化 import re content="白日 ...

  4. (原创)【B4A】一步一步入门08:ListView,列表、单行、双行、双行带图片、列表项样式(控件篇04)

    一.前言 本篇教程,我们来讲一下常用的控件:ListView(列表控件). 目前官方已经不推荐使用默认的ListView控件,而是推荐另一款功能更强大的ListView:xCustomListView ...

  5. Nacos 实现 AP+CP原理[Raft 算法 NO]

    来源于网络 一.什么是 Raft算法 Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议 Raft 更易于理解和去实现它.为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导 ...

  6. 多线程基础之CAS、AQS、ABA辨析

    这三个单词算是多线程面试常见的问题了,也是很多小白不太懂的问题,这里给出我的理解来. 一.CAS J.U.C 并发包中的很多类都涉及到了 CAS,可以说没有 CAS 和 volatile 就没有 J. ...

  7. Tomcat启动报错,Server Tomcat v8.0 Server at localhost failed to start

    Eclipse 中Tomcat 启动报错Eclipse的提示窗口  Server Tomcat v8.0 Server at localhost failed to start .日志输出中报   F ...

  8. flutter util---->常用的一些工具方法

    copy text to clipboard Clipboard.setData(ClipboardData(text: string)); since Flutter1.9, you can use ...

  9. nginx中的proxy_pass配置

    Nginx 是最常用的反向代理工具之一,一个指令 proxy_pass搞定反向代理,对于接口代理.负载均衡很是实用,但 proxy_pass指令后面的参数很有讲究,通常一个/都可能引发一个血案. 通常 ...

  10. vue2双向绑定原理及源码解析

    首先我们要知道VUE实现双向绑定的步骤是什么: 实现一个监听器 Observer 对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 sett ...