首页 > 编程语言 >[C++]LeetCode 1760 袋子里最少数目的球

[C++]LeetCode 1760 袋子里最少数目的球

时间:2022-12-20 00:55:06浏览次数:65  
标签:装有 nums maxOperations C++ LeetCode 袋子 1760 mx 个球

[C++]LeetCode 1760. 袋子里最少数目的球

题目描述

Difficulty: 中等

Related Topics: 数组, 二分查找

给你一个整数数组 nums ,其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数 maxOperations

你可以进行如下操作至多 maxOperations 次:

  • 选择任意一个袋子,并将袋子里的球分到 2 个新的袋子中,每个袋子里都有 正整数 个球。
    • 比方说,一个袋子里有 5 个球,你可以把它们分到两个新袋子里,分别有 1 个和 4 个球,或者分别有 2 个和 3 个球。

你的开销是单个袋子里球数目的 最大值 ,你想要 最小化 开销。

请你返回进行上述操作后的最小开销。

示例 1:

输入:nums = [9], maxOperations = 2
输出:3
解释:
- 将装有 9 个球的袋子分成装有 6 个和 3 个球的袋子。[9] -> [6,3] 。
- 将装有 6 个球的袋子分成装有 3 个和 3 个球的袋子。[6,3] -> [3,3,3] 。
装有最多球的袋子里装有 3 个球,所以开销为 3 并返回 3 。

示例 2:

输入:nums = [2,4,8,2], maxOperations = 4
输出:2
解释:
- 将装有 8 个球的袋子分成装有 4 个和 4 个球的袋子。[2,4,8,2] -> [2,4,4,4,2] 。
- 将装有 4 个球的袋子分成装有 2 个和 2 个球的袋子。[2,4,4,4,2] -> [2,2,2,4,4,2] 。
- 将装有 4 个球的袋子分成装有 2 个和 2 个球的袋子。[2,2,2,4,4,2] -> [2,2,2,2,2,4,2] 。
- 将装有 4 个球的袋子分成装有 2 个和 2 个球的袋子。[2,2,2,2,2,4,2] -> [2,2,2,2,2,2,2,2] 。
装有最多球的袋子里装有 2 个球,所以开销为 2 并返回 2 。

示例 3:

输入:nums = [7,17], maxOperations = 2
输出:7

提示:

  • 1 <= nums.length <= 105
  • 1 <= maxOperations, nums[i] <= 109

思路

二分答案+贪心

”最大值最小/最小值最大“类问题往往是二分答案+贪心。

注意可以进行如下操作至多 maxOperations 次,可以发现答案具有单调性:

以样例为例,nums = [9], maxOperations = 2,设单个袋子里球数目的最大值为\(mx\),那么\(mx\)的取值是有范围的:具体来说,\(3\leq mx \leq 9\)时,都可以在maxOperations = 2次以内找到对应的划分。

例如,(注意这里的划分方法)

\(mx=3\),可以在2次以内划分为[3, 3, 3]

\(mx=4\),可以在2次以内划分为[4, 4, 1]

\(mx=5\),可以在2次以内(实际只用1次)划分为[5, 4]

依次类推,而\(mx=2\)时,在2次以内划分无法满足要求。

于是,由答案的单调性,我们可以将原问题转化为判定问题,进而对答案二分。

二分下界\(l=1\),\(r=\max\{nums_i\}\),以样例为例,首先l = 1, r = 9,我们检查发现check( mid = 5 )成立,因此答案在[1, 5]之间,继续检查发现check( mid = 2 )不成立,因此答案在[3, 5]之间,依次类推最后确定答案。

那么,我们该如何判断一个答案\(mx\)是否成立呢?贪心即可。将nums中每个数贪心地划分至小于等于mx,最后统计需要的划分次数是否超过maxOperations

nums中每个数\(nums_i\),要将其划分至不超过\(mx\),需要的最少次数为nums[i] % mx == 0 ? nums[i] / mx - 1 : nums[i] / mx。举个例子,nums[i] = 9,当mx = 4时,因为9 = 2 * 4 + 1,则最少需要\(\lfloor \frac{9}{4} \rfloor = 2\)次,划分为[4, 4, 1]。而当mx = 3时,因为9 = 3 * 3,则最少需要\(\lfloor \frac{9}{3}\rfloor - 1= 2\)次,划分为[3, 3, 3]

本题中,这个写法等价于\(\lfloor \frac{nums[i] - 1}{mx} \rfloor\)。

复杂度:

二分次数\(O(\log M) , M=\max\{nums_i\}\),而每次判断是\(O(n)\)的。

故总复杂度为\(O(n\log M), M=\max\{nums_i\}\)。

Code

Language: C++

class Solution {
		inline bool check(int mx, const vector<int>& nums, int maxOperations) {
			int cnt = 0;
			for (const auto& num : nums) {
				cnt += (num - 1) / mx;
				if (cnt > maxOperations) return false;
			}
			return true;
		}
	public:
		int minimumSize(vector<int>& nums, int maxOperations) {
			int l = 1, r = 0, ans = 0;
			for (const auto &num : nums) r = max(r, num);
			while (l <= r) {
				int mid = (l + r) >> 1;
				if (check(mid, nums, maxOperations)) ans = mid, r = mid - 1;
				else l = mid + 1;
			}
			return ans;
		}
};

标签:装有,nums,maxOperations,C++,LeetCode,袋子,1760,mx,个球
From: https://www.cnblogs.com/yu-xing/p/16993441.html

相关文章

  • leetcode-最长回文子串
    给你一个字符串s,找到s中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。 示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答......
  • leetcode_D8_118杨辉三角
    1.题目  2.解一  主要思路:这个一看就看懂,没啥好说的。3.解二  主要思路:评论区看到的聪明解法,即10        011       01......
  • LeetCode HOT 100:最大子数组和
    题目:53.最大子数组和题目描述:给你一个整数数组,在该数组的所有子数组中,找到一个子数组中所有元素相加和最大,返回这个最大的和。子数组就是一个数组中,由一个或几个下标连......
  • [编程基础] C++多线程入门8-从线程返回值
    date:2020-05-2917:09:34+0800tags:-编程基础原始C++标准仅支持单线程编程。新的C++标准(称为C++11或C++0x)于2011年发布。在C++11中,引入了新的线程库。因此运行......
  • LeetCode 102_二叉树的层序遍历
    LeetCode102:二叉树的层序遍历题目给你二叉树的根节点root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。示例1:输入:root=[3,9,20,null,null,15,7]......
  • [C++]LeetCode 2502 设计内存分配器
    [C++]LeetCode2502.设计内存分配器题目描述Difficulty:中等RelatedTopics:设计,数组,哈希表,模拟给你一个整数n,表示下标从0开始的内存数组的大小。所有内存......
  • [C++]LeetCode 1971 寻找图中是否存在路径
    [C++]LeetCode1971.寻找图中是否存在路径题目描述Difficulty:简单RelatedTopics:深度优先搜索,广度优先搜索,并查集,图有一个具有n个顶点的双向图,其中每个......
  • Leetcode 169-多数元素
    Leetcode169-多数元素给定一个大小为n的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数大于 ⌊n/2⌋ 的元素。你可以假设数组是非空的,并且给定的数......
  • C++ 随机数生成器 mt19937
    一下代码来自官方示例//mersenne_twister_engineconstructor#include<iostream>#include<chrono>#include<random>intmain(){//obtainaseedfromthe......
  • [LeetCode]008-字符串转换整数(atoi)
    >>>传送门题目请你来实现一个 myAtoi(strings) 函数,使其能将字符串转换成一个32位有符号整数(类似C/C++中的atoi函数)。函数 myAtoi(strings)的算法如下:读......