首页 > 其他分享 >书籍叠放

书籍叠放

时间:2023-09-09 12:32:08浏览次数:26  
标签:arr int 元素 -- 分组 数组 叠放 书籍

题目描述

给定一个数组nums,可以将元素分为若干个组,使得每组和相等,求出满足条件的所有分组中,最大的平分组个数。

输入描述

  • 第一行输入 书籍叠放_System
  • 接下来输入 书籍叠放_System 个数,表示此数组
  • 数据范围:书籍叠放_数组_03

输出描述

最大的平分组个数

用例

用例1

--输入
7
4 3 2 3 5 2 1

--输出
4

--说明
可以等分的情况有
4个子集: (5)  (1,4)  (2,3)  (2,3)
2个子集: (5, 1, 4)  (2, 3, 2, 3)
最大的平分组数个数为 4 个

用例2

--输入
9
5 2 1 5 2 1 5 2 1

--输出
4

--说明
可以等分的情况有
4 个子集  (5, 1) (5, 1) (5, 1) (2, 2, 2)
2 个子集  (5, 1, 5, 1) (2, 2, 2, 5, 1)
最大的平分组数个数为4个

题目解析

直观理解,需要尽可能把数组进行分成若干组,并且保证 每组 元素和相等. 那么以数组 arr = [1, 1, 1, 1, 1] 为例,最多分成 5 组 ---> (1),(1),(1),(1),(1) 如何考虑解决该问题呢?


  • 需要保证分组之后,每一组的元素之和都相同。那么很显然
  • 每一组的元素和,最小 -- 不能小于数组中最小元素的值。
  • 每一组的元素和,最大 -- 不能大于数组中所有元素的和。
  • 最少也能分成一组,即所有元素分成一组。
  • 假设数组长度为 n,那么最多分成 n 组(数组中所有元素都相同的情况下)

代码实现思路

  • 令数组长度等于 n 那么最多分为 n 组,最少分为 1 组(所有的元素分在一起)
  • 那么可以倒叙验证,目标数组是否可以等分为 i 组,i = n,n-1,n-2,n-3......1依次递减
  • 找到结果直接返回
  • 那么现在问题变成了,验证一个数组是否能够等分为 i
  • 如何验证呢?

  1. 首先可以求得数组和sum,已知需要分成k组,那么可以得到平均值average 和 余数
  1. 如果余数不等于0,证明不能等分,直接跳过
  1. 然后对数组进行排序,如果average < arr[n - 1],证明同样不能等分
  2. 接下来如何解决呢?——————“动态规划”
  3. 数组中有 n 个元素,那么就一共有 1 << n个状态
  1. ex:如果选择了数组中的所有元素,那么对应的下标索引就是 (1 << n) - 1

show code

import java.util.Arrays;
import java.util.Scanner;

/**
 * desc : <a href="https://fcqian.blog.csdn.net/article/details/128199836">最大平分数组</a>
 * <p>
 * create time : 2023/4/11 15:32
 */
public class MaxAverageArr {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNextInt()) {
            int m = in.nextInt();
            int[] arr = new int[m];
            for(int i = 0;i < m;i++) {
                arr[i] = in.nextInt();
            }

            //System.out.println("最大平分数组的个数是:" + maxCutArr(arr));
            System.out.println("最大平分数组的个数是:" + maxCutArr1(arr));
        }
    }

    private static int maxCutArr(int[] arr) {
        // 假设数组和为 sum  最大分组方案肯定小于等于  sum 数组中每一个元素都需要用到
        int sumArr = Arrays.stream(arr).sum();
        int n = arr.length;
        Arrays.sort(arr);
        // 因为每一个子数组的和需要保证相等,并且元素越多越好,所以划分子数组的和越小,就意味着分组个数越多.
        // 最多划分为  n  个子集,(数组内所有元素都相同的情况) 最少划分为1个子集,即没有办法划分的情况.
        // 那么划分的子数组的和 应当是 从 1 -> sumArr
        for (int i = n; i >= 1; i--) {
            if(sumArr % i != 0) {
                // 无法划分
                continue;
            }
            // 判断能不能划分为 i 个子集
            if(check(arr, i, sumArr)) {
                return i;
            }
        }
        return 1;
    }

    private static boolean check(int[] arr, int k, int all) {
        int n = arr.length;
        int average = all/k;
        if(arr[n-1] > average) {
            return false;
        }
        //  1 << n :表示 1 << n 个状态,对应了元素被选择的情况
        //  ex:如果选择了所有的元素,那么 dp[n] == all
        int[] dp = new int[1 << n];
        // 初始化所有的元素的值都是 -1 表示尚未计算.
        Arrays.fill(dp, -1);
        // 初始化 dp[0] = 0 表示一个元素都没有选择.
        dp[0] = 0;
        for(int i = 0;i < (1 << n);i++) {
            if(dp[i] == -1) {
                continue;
            }
            for(int j = 0;j < n;j++) {
                // dp[i] % average 表示当前选择的方案
                // arr[j] 表示接下来要选择 arr[j] 进行添加
                // 判断其是否大于  average ,如果大于,表示超过了平均值,跳过该方案.
                if(dp[i] % average + arr[j] > average) {
                    break;
                }
                //  这里判断  arr[j] 是否已经被选择,如果没有选择,则考虑加入到当前状态 i 中.
                if(((i >> j) & 1) == 0) {
                    // next:表示 当前状态 i 添加了 arr[j] 之后的状态.
                    int next = i + (1 << j);
                    // 如果 dp[next] 已经大于 0 了,表示当前状态已经计算过了,跳过这个状态的计算.
                    if(dp[next] > 0) {
                        continue;
                    }
                    // 计算 dp[next] 的值.
                    dp[next] = dp[i] + arr[j];
                }
                if(dp[(1 << n) - 1] == all) {
                    return true;
                }
            }
        }
        return dp[(1 << n) - 1] == all;
    }
}

标签:arr,int,元素,--,分组,数组,叠放,书籍
From: https://blog.51cto.com/u_16079703/7418825

相关文章

  • 整理书籍
    整理书籍书架上有若干本书排成一排。每本书要么是大型书(用 L 表示),要么是中型书(用 M 表示),要么是小型书(用 S 表示)。我们希望所有书能够从大到小有序排列,也就是说,所有大型书都在左侧,所有中型书都在中间,所有小型书都在右侧。为此,你可以进行任意次交换操作,每次可以任选两本书......
  • Java 十大必读经典书籍推荐
    今天给大家推荐十本学习Java语言必读经典书籍,它们经过了无数人的口口相传,都已成为了Java领域顶级的经典名著。 1、Java核心技术·卷I·基础知识豆瓣评分:9.4Java领域极有影响力和价值的著作之一,与《Java编程思想》齐名,10余年全球畅销不衰,广受好评。本书由拥有20多年......
  • 书籍叠放
    题目描述书籍的长、宽都是整数对应[l,w](长,宽)。如果书A的长宽度都比B长宽大时,则允许将B排列放在A上面。现在有一组规格的书籍,书籍叠放时要求书籍不能做旋转请计算最多能有多少个规格书籍能叠放在一起输入描述输入:books=[[20,16],[15,11],[10,10],[9,10]]说明:总共有4......
  • 基本经典的NLP书籍
    以下是几本经典的自然语言处理(NLP)书籍:"SpeechandLanguageProcessing:AnIntroductiontoNaturalLanguageProcessing,ComputationalLinguistics,andSpeechRecognition"byDanielJurafskyandJamesH.Martin-这是一本广泛使用的教材,介绍了自然语言处理的基本概......
  • 运动控制-CodeSys编程书籍
    网上流传的陆国君PDF书籍<<PLC综合开发利器-CodeSys基础编程及应用指南>>很不错,这本书网上有两个版本556页是新的版本,423页是老的版本,不过内容差异不大.423页是老的版本下载:url80.ctfile.com/f/25127180-539049426-f8f96c(访问密码:551685)......
  • 统计学 书籍 量化向
    董可人​金融等2个话题下的优秀答主​ 关注 编辑推荐1,615人赞同了该回答本篇偏学术。因为我自己做高频,所以首先提两本相关的学术著作。一本是2011年的论文集EconophysicsofOrder-drivenMarkets,收录了一系列关于盘口和高频数据建......
  • 亚马逊删除了人工智能生成的欺骗作者署名的书籍
    在社交媒体的强烈反对之后,亚马逊已经删除了六本以在世作者的名义出版的人工智能生成的书籍,未经她的同意。尽管误导性内容最终在周二被删除,但作者,资深出版业作家简·弗里德曼(JaneFriedman)担心,亚马逊和其他公司缺乏明确,连贯的政策为其他作者将来面临类似的争议敞开了大门。“我预......
  • 机器学习方面各层次书籍推荐
    1基础强数学型1.1FoundationsofMachineLearning豆瓣评分9.0(103人)有大量的数学公式推到和课后习题,用来提升对于机器学习原理公式的理解 1.2统计学习方法李航+b站带读  2入门型漫画机器学习入门零基础机器学习 ......
  • C/C++经典书籍
    记录四本C/C++的经典书籍。最经典的莫过于1988年出版的《TheCProgrammingLanguage》第二版1.C1.1零基础:CPrimerPlus,SixthEdition,作者:StephenPrata,2013年出版,涵盖C11标准1.2C语言作者巨著(适合有C基础的阅读):TheCProgrammingLanguage,SecondEdition,作者:Denni......
  • 2021 书单推荐 | 15 本高分 AI 书籍,统统免费读
    By超神经内容提要:目前,市面上的人工智能书籍并不少,作为一名人工智能爱好者,该如何筛选书单?新年伊始,KDnuggets整理了一份AI书单,请大家按需取用。关键词:AI书单  机器学习数据科学专注于机器学习、大数据、分析学的顶级网站KDnuggets,近期整理了一份书单,共15本书籍,涵盖机器学......