给定一个 正整数 数组 beans ,其中每个整数表示一个袋子里装的魔法豆的数目。
请你从每个袋子中 拿出 一些豆子(也可以 不拿出),使得剩下的 非空 袋子中(即 至少还有一颗 魔法豆的袋子)魔法豆的数目 相等。一旦把魔法豆从袋子中取出,你不能再将它放到任何袋子中。
请返回你需要拿出魔法豆的 最少数目。
示例 1:
输入:beans = [4,1,6,5]
输出:4
解释:
输入:beans = [2,10,3,2]
输出:7
解释:
提示:
1 <= beans.length <= 1e5
1 <= beans[i] <= 1e5
枚举即可:
class Solution {
public:
long long minimumRemoval(vector<int>& beans) {
sort(beans.begin(), beans.end());
long long s = accumulate(beans.begin(), beans.end(), 0ll);
long long ans = s;
int n = beans.size();
for (int i = 0; i < n; ++i) {
ans = min(ans, s - 1ll * beans[i] * (n - i));
}
return ans;
}
};
给你两个长度相等下标从 0 开始的整数数组 nums1 和 nums2 。每一秒,对于所有下标 0 <= i < nums1.length ,nums1[i] 的值都增加 nums2[i] 。操作 完成后 ,你可以进行如下操作:
选择任一满足 0 <= i < nums1.length 的下标 i ,并使 nums1[i] = 0 。
同时给你一个整数 x 。
请你返回使 nums1 中所有元素之和 小于等于 x 所需要的 最少 时间,如果无法实现,那么返回 -1 。
示例 1:
输入:nums1 = [1,2,3], nums2 = [1,2,3], x = 4
输出:3
解释:
第 1 秒,我们对 i = 0 进行操作,得到 nums1 = [0,2+2,3+3] = [0,4,6] 。
第 2 秒,我们对 i = 1 进行操作,得到 nums1 = [0+1,0,6+3] = [1,0,9] 。
第 3 秒,我们对 i = 2 进行操作,得到 nums1 = [1+1,0+2,0] = [2,2,0] 。
现在 nums1 的和为 4 。不存在更少次数的操作,所以我们返回 3 。
示例 2:
输入:nums1 = [1,2,3], nums2 = [3,3,3], x = 4
输出:-1
解释:不管如何操作,nums1 的和总是会超过 x 。
提示:
1 <= nums1.length <= 1e3
1 <= nums1[i] <= 1e3
0 <= nums2[i] <= 1e3
nums1.length == nums2.length
0 <= x <= 1e6
这个题目实在不会,看了题解是排序+DP:
class Solution {
public:
int minimumTime(vector<int> &nums1, vector<int> &nums2, int x) {
int n = nums1.size();
vector<int> ids(n);
iota(ids.begin(), ids.end(), 0);
sort(ids.begin(), ids.end(), [&](const int i, const int j) {
return nums2[i] < nums2[j];
});
vector<int> f(n + 1);
for (int i = 0; i < n; i++) {
int a = nums1[ids[i]], b = nums2[ids[i]];
for (int j = i + 1; j; j--) {
f[j] = max(f[j], f[j - 1] + a + b * j);
}
}
int s1 = accumulate(nums1.begin(), nums1.end(), 0);
int s2 = accumulate(nums2.begin(), nums2.end(), 0);
for (int t = 0; t <= n; t++) {
if (s1 + s2 * t - f[t] <= x) {
return t;
}
}
return -1;
}
};
这里附上 灵神的题解:教你一步步思考本题!
给你一个字符串数组 words 和一个字符 separator ,请你按 separator 拆分 words 中的每个字符串。
返回一个由拆分后的新字符串组成的字符串数组,不包括空字符串 。
注意
separator 用于决定拆分发生的位置,但它不包含在结果字符串中。
拆分可能形成两个以上的字符串。
结果字符串必须保持初始相同的先后顺序。
示例 1:
输入:words = [“one.two.three”,“four.five”,“six”], separator = “.”
输出:[“one”,“two”,“three”,“four”,“five”,“six”]
解释:在本示例中,我们进行下述拆分:
“one.two.three” 拆分为 “one”, “two”, “three”
“four.five” 拆分为 “four”, “five”
“six” 拆分为 “six”
因此,结果数组为 [“one”,“two”,“three”,“four”,“five”,“six”] 。
示例 2:
输入:words = [“
e
a
s
y
easy
easy”,“
p
r
o
b
l
e
m
problem
problem”], separator = “$”
输出:[“easy”,“problem”]
解释:在本示例中,我们进行下述拆分:
“
e
a
s
y
easy
easy” 拆分为 “easy”(不包括空字符串)
“
p
r
o
b
l
e
m
problem
problem” 拆分为 “problem”(不包括空字符串)
因此,结果数组为 [“easy”,“problem”] 。
示例 3:
输入:words = [“|||”], separator = “|”
输出:[]
解释:在本示例中,“|||” 的拆分结果将只包含一些空字符串,所以我们返回一个空数组 [] 。
提示:
1 <= words.length <= 100
1 <= words[i].length <= 20
words[i] 中的字符要么是小写英文字母,要么就是字符串 “.,|KaTeX parse error: Expected 'EOF', got '#' at position 1: #?@" 中的字符(不包括引号) …#@” 中的某个字符(不包括引号)
模拟就行:
class Solution {
public:
vector<string> splitWordsBySeparator(vector<string>& words, char separator) {
vector<string> ans;
for(string str : words){
string cur;
for(char ch : str){
if(ch == separator){
if(!cur.empty())
ans.push_back(cur);
cur.clear();
}else{
cur += ch;
}
}
if(cur.size() != 0)
ans.push_back(cur);
}
return ans;
}
};
给定一个非负整数数组 nums 和一个整数 k ,你需要将这个数组分成 k 个非空的连续子数组。
设计一个算法使得这 k 个子数组各自和的最大值最小。
示例 1:
输入:nums = [7,2,5,10,8], k = 2
输出:18
解释:
一共有四种方法将 nums 分割为 2 个子数组。
其中最好的方式是将其分为 [7,2,5] 和 [10,8] 。
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。
示例 2:
输入:nums = [1,2,3,4,5], k = 2
输出:9
示例 3:
输入:nums = [1,4,4], k = 3
输出:4
提示:
1 <= nums.length <= 1000
0 <= nums[i] <= 106
1 <= k <= min(50, nums.length)
二分(看题解DP也行):
class Solution {
public:
int splitArray(vector<int>& nums, int m) {
long l = nums[0], h = 0;
for (auto i : nums)
{
h += i;
l = l > i ? l : i;
}
while (l<h)
{
long mid = (l + h) / 2;
long temp = 0;
int cnt = 1;//初始值必须为1
for(auto i:nums)
{
temp += i;
if(temp>mid)
{
temp = i;
++cnt;
}
}
if(cnt>m)
l = mid + 1;
else
h = mid;
}
return l;
}
};