“集合划分问题”如何解决?这里教你个妙招,轻松掌握这类问题~

news2024/9/29 21:30:41

目录

“集合划分”这类问题的解题思路

一、划分为k个相等的子集

二、火柴拼正方形


“集合划分”这类问题的解题思路

        这类题一般都会描述成这个样子:“给你一个数组,是否能将他划分成n个数值相等的子集?”,再或者有些可能题目描述稍微优点隐晦(下面会给出栗子),这类问题实际上是有通法的,通过 “桶 + 回溯 + 剪枝” 的思路便可以迎刃而解;

什么是 “桶 + 回溯 + 剪枝” 呢?

        根据题目描述,是让你把数组划分成n个数值相等的子集,即每一个子集的和都是一样的,那么我们就可以求出每一个子集的和是多少(就是把数组每一个值加起来,然后除以要划分的子集个数),那桶是干什么的呢?我们可以用n个桶来装这些子集,每个桶的容量便是子集的和;以下将用一个栗子让你更加清楚~

假设数组nums为[1, 1, 2, 2, 2] ,是否能划分成4个相等子集?

解决过程如下:

        先给数组求和,即sum = 8,要将他划分成4个相等的子集,也就是说每个子集的大小因该为sum / 4 = 2,那么便可以创建4个桶,每一个桶的大小为2;

        nums[0] = 1,用第一个桶来装,能装下,并且还剩一个位置;nums[1] = 1,继续用第一个桶来装,能正好能把第一个桶装满;nums[2] = 2,用第一个桶来装,发现装不下了,就往第二个桶里装,正好能装满;nums[3] = 2,用第一个桶来装,装不下,在试试用第二个桶来装,装不下,就往第三个桶里装,发现正好能装满;nums[4] = 2,用第一个桶,装不下、用第二个桶,装不下、用第三个桶,装不下、用第四个桶正好能装下;这时候可以发现,四个桶都装满了,那么回原问题上,就相当于可以划分为四个相等的子集

        以上便是一个dfs的全过程,若放错桶,不能将每个桶装满,并且还有剩余数字没有放入桶中,这时便可以回溯回去,再试试其他可能;

如何剪枝呢?

剪枝一:降序排序

        不排序也能做对,但是时间上开销就相对较大了,为什么降序排序就可以优化时间呢?我们从num中最大的数开始找,若最大的数都要比子集还要大,或者装下它后,没有装满桶,但是装不下nums中的最小值了,那么这个题的答案一定是false,因为这样一个数的存在,放在哪一个桶里都不合适,通过降序排序,就可以提早发现这个问题,并直接返回false解决;

剪枝二:回溯时若桶的大小等于0,直接返回false

        这就表示,如果前面做出选择之后,递归完没有找到任何一个合适的值装满桶,那么回溯撤掉这个值以后,一定为零;比如桶的大小为4,桶中加入了3,但是递归完,发现不存在长度为1的,那么回溯撤掉这个值后桶的大小就是0了;

以上便是这类问题的通解,接下来的两道题,便是“集合划分”的经典问题,思路不能说相似,简直是完全一样;


一、划分为k个相等的子集

题目描述

        给定一个整数数组  nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。

示例:

输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
输出: True
说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。

题目来源:698. 划分为k个相等的子集 - 力扣(LeetCode)

代码如下:

class Solution {

    public boolean canPartitionKSubsets(int[] nums, int k) {
        if(nums.length < k) {//比均分的数目还小就肯定不能均分
            return false;
        }
        int sum = 0;
        for(int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if(sum % k != 0) {//想要均分成k个区间,那么每个区间的值一定相等,因此sum一定能被k整除
            return false;
        }
        int len = sum / k;//每个区间要满足的大小
        //桶
        int[] bucket = new int[k];
        //剪枝:倒序效率更高
        Arrays.sort(nums);
        for(int i = 0, j = nums.length - 1; i < j; i++, j--) {
            int tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
        }
        return dfs(nums, bucket, len, k, 0);
    }

    private boolean dfs(int[] nums, int[] bucket, int len, int k, int index) {
        if(nums.length == index) {
            return true;
        }
        for(int i = 0; i < k; i++) {
            if(bucket[i] + nums[index] > len) {//装不下,就放到下一个桶中去
                continue;
            }
            bucket[i] += nums[index];
            if(dfs(nums, bucket, len, k, index + 1)) {
                return true;
            }
            bucket[i] -= nums[index];
            if(bucket[i] == 0) return false;//到了这儿,若为0,说明没有合适的值等于len
        }
        return false;
    }
}

二、火柴拼正方形

题目描述:

你将得到一个整数数组 matchsticks ,其中 matchsticks[i] 是第 i 个火柴棒的长度。你要用 所有的火柴棍 拼成一个正方形。你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次 。

如果你能使这个正方形,则返回 true ,否则返回 false 。

示例:

输入: matchsticks = [1,1,2,2,2]

输出: true

解释: 能拼成一个边长为2的正方形,每边两根火柴。

代码如下:

class Solution {
    //火柴拼正方形
    public boolean makesquare(int[] matchsticks) {
        int len = matchsticks.length;
        if(len < 4) { //特判:正方形有四条边
            return false;
        }
        //给所有火柴求和
        int sum = 0;
        for(int i = 0; i < matchsticks.length; i++) {
            sum += matchsticks[i];
        }
        if(sum % 4 != 0) { //特判:正方形有四条边
            return false;
        }
        //求出每一条边的长度
        int lenSide = sum / 4;
        //剪枝:降序排序更早触发回溯中的第一个continue
        Arrays.sort(matchsticks);
        //降序
        for(int i = 0, j = matchsticks.length - 1; i < j; i++, j--) {
            int tmp = matchsticks[i];
            matchsticks[i] = matchsticks[j];
            matchsticks[j] = tmp;
        }
        //四个桶
        int[] bucket = new int[4];
        return dfs(matchsticks, lenSide, bucket, 0);
    }

    private boolean dfs(int[] arr, int lenSide, int[] bucket, int index) {
        if(index == arr.length) {
            return true;
        }
        for(int i = 0; i < 4; i++) {
            if(arr[index] + bucket[i] > lenSide) {//桶装不下了
                continue;
            }
            bucket[i] += arr[index];
            if(dfs(arr, lenSide, bucket, index + 1)) {
                return true;
            }
            bucket[i] -= arr[index];
            if(bucket[i] == 0) {
                return false;
            }
        }
        return false;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/128813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MinIO高性能对象存储

一、MinIO高性能对象存储 MinIO是一个高性能对象存储解决方案&#xff0c;它提供了与Amazon Web Services S3兼容的API&#xff0c;并支持所有核心S3功能。 MinIO旨在部署任何地方—公共或私有云、裸机基础设施、协调环境和边缘基础设施。本文档说的是Windows平台上MinIO部署的…

接口测试自动化框架选型

1、fiddler fiddler 是一个 HTTP 协议调试代理工具&#xff0c;Web 和手机测试都会用到&#xff0c;同时也支持接口测试。它能够记录并检查所有你的电脑和互联网之间的 http 通讯&#xff0c;设置断点&#xff0c;查看所有的“进出”Fiddler 的数据(指 cookie,html,js,css 等文…

ASP.NET大型药品销售ERP系统源码

ASP.NET医药ERP管理系统源码 药品销售管理系统源码 源码分享&#xff01;需要源码学习可私信我。 一、源码特点 1、渠道销售商在把药品从厂商销售到医院时&#xff0c;需要管理大量的数据&#xff0c;这些通常包括药品从厂商采购数据、药品销售到商业公司的数据&#xff0c;以…

Python文件基础操作(6)

python学习之旅(六) &#x1f44d;基础语法部分笔记(一) &#x1f44d;条件判断部分笔记(二) &#x1f44d;循环语句部分笔记(三) &#x1f44d;函数使用部分笔记(四) &#x1f44d;数据容器部分笔记(五) &#x1f44d;文件操作部分笔记(六) 一.文件编码 编码就是一种规则集合&…

数据湖---hudi核心概念

文章目录TimelineTable & Query TypesTable Types查询类型COWMOR索引Hudi索引类型索引选择策略File Layouts元数据表元数据表的动机研究中的一些数字&#xff1a;支持多模态索引写操作操作类型UPSERTINSERTBULK_INSERTDELETE写入路径schema 演进key生成并发控制Datasource …

强强联合,怿星科技艾拉比携手斩获“铃轩奖”

12月23日—24日&#xff0c;汽车行业的年度盛典2022中国汽车供应链峰会&#xff08;CASCS2022&#xff09;盛大开幕&#xff0c;全国汽车供应链大咖再次聚首中国车谷&#xff0c;怿星科技CEO潘凯在圆桌《新汽车软件到底怎么办》上分享了观点。会议同期&#xff0c;国内最具权威…

十年底层创新,2023年亚马逊云科技或再创新高

2006年&#xff0c;亚马逊云科技推出了第一代公有云产品Amazon S3和Amazon EC2&#xff0c;由此开创了企业IT的历史——云计算从此开始改变整个企业IT市场。2013年&#xff0c;亚马逊云科技再次开创了历史&#xff0c;推出了首个自研芯片Amazon Nitro&#xff0c;由此打开了全球…

屏幕录制下载安装?这3个软件,亲测好用

很多小伙伴在使用电脑进行学习、娱乐和工作的时候&#xff0c;或多或少遇到过需要使用屏幕录制功能的时候。那么有什么特别好用的屏幕录制软件吗&#xff1f;屏幕录制下载安装怎么进行&#xff1f;今天小编分享3款软件&#xff0c;特别好用。 屏幕录制下载1&#xff1a;爱拍录屏…

朗润国际期货技术分析——日内交易图表类型

一张图表胜过千言万语。你以前听说过这句话&#xff0c;对吗&#xff1f;在日内交易员的世界里&#xff0c;一张图表往往比千言万语更有价值。它不仅告诉我们过去发生了什么&#xff0c;而且告诉我们一个市场在未来可能会做什么。它将继续走高还是走低&#xff1f;它是否处于一…

第十一篇 1+X考证 Web前端测试题MySQL篇(新)

单选题 1、下列关于MySQL备份的说法中&#xff0c;错误的是&#xff08; B &#xff09; A、备份数据库的命令是mysqldump B、备份数据库的文件扩展名必须是.sql C、“mysql”命令可以还原数据库 D、可以同时备份一个或多个数据库 [ 解析&#xff1a;.txt ] 2、在MySQL…

DBSCAN聚类的python实现

文章目录介绍DBSCAN()函数介绍实例参数选择实例整理数据选择eps和min_samples建立模型作者&#xff1a;张双双介绍 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;python中的sklearn.clust…

BACnet协议详解——初识BACnet架构

文章目录BACnet协议架构BACnet简化的架构简化的四层BACnet体系结构选取BACnet 网络的拓扑结构安全BACnet协议架构 国际标准化组织在制定计算机网络通讯协议标准时定义了一个模型&#xff0c;称为开放系统互联参考模型&#xff08;OSI&#xff08;ISO 7498&#xff09;。模型的…

5 JMeter断言-Jmeter响应中出现乱码时

文章目录2 JMeter2.5 JMeter断言2.5.1 响应断言2.5.2 JSON断言2.5.3 断言持续时间3 使用问题3.1 jmeter响应中出现乱码时2 JMeter 2.5 JMeter断言 作用&#xff1a;让脚本自动化执行的过程中&#xff0c;能够自动的判断执行结果是否正确&#xff0c;需要添加断言 响应断言 J…

MobTech秒验 I 作为产品经理,你知道何时做“减法”何时做“加法”嘛?

智能手机从诞生到现在&#xff0c;无论是硬件还是软件都有很大幅度的提升&#xff0c;用户的审美和挑剔力度也不断提升。如果在一个应用中使用的不顺心或者是设计得不符合用户的使用习惯&#xff0c;或许他就会卸载这个应用&#xff0c;下载另一个同类应用。因而产品经理们在垂…

STM32 HAL I2C(IIC)通信的序列传输(restart condition)

STM32 HAL I2C&#xff08;IIC&#xff09;通信的序列(Seq)传输函数(restart condition) neozng1hnu.edu.cn 文章目录STM32 HAL I2C&#xff08;IIC&#xff09;通信的序列(Seq)传输函数(restart condition)XferOption的含义HAL源码解析实验验证阅读本文需要你对I2C协议有基本…

ceph-ansible安装指南-添加BlueStore

前言&#xff1a;ceph的资料真是很少&#xff0c;摸索一断时间&#xff0c;将整理的一资料和操作经验分享。本篇为干货&#xff0c;实操。生产环境可以借鉴使用。 知识点&#xff1a; 1、建议使用LVM卷管理作为Ceph底层的存储块设备&#xff0c;因为LVM卷可以随时扩展&#xf…

石子合并(分治+贪心+DP+前缀和)

石子合并一、题目内容二、思路分析1、状态转移方程&#xff08;1&#xff09;状态表示&#xff08;2&#xff09;状态转移2、循环设计及初始化&#xff08;1&#xff09;循环&#xff08;2&#xff09;初始化3、代码实现一、题目内容 二、思路分析 这道题也是一个很经典的DP问…

灵感来源于宇宙光束 长安汽车发布全新设计理念

12月28日&#xff0c;“重构想象 创领未来”2022首届长安汽车设计日正式启幕&#xff0c;长安汽车副总裁王孝飞发表“以创新之手、触万象之境”的主题演讲&#xff0c;分享了最新设计理念&#xff0c;正式发布长安汽车全新设计理念“纵横万象”。同时&#xff0c;基于这一理念打…

【Docker社区大会】WebAssembly:无需容器的 Docker——VMware技术总监 Daniel Lopez

本文授权翻译自 Wasm Labs VMware OCTO 的 blog&#xff1a; WebAssembly: Docker without container。这是 Wasm Labs 在 2022 年 12 月 15 日在冬季Docker Community All Hands 7 的关于 DockerWebAssembly 的演讲的文字版。 作者&#xff1a;Asen Alexandrov&#xff0c;Wa…

C#,图像二值化(08)——全局阈值优化算法及其源代码

1、全局阈值算法 基于灰度直方图的优化迭代算法之一。 Iterative Scheduler and Modified Iterative Water-Filling In the downlink, the inter-cell interference is only function of the power levels and is independent of the user scheduling decisions. This suggest…