先计算苹果总数是多少,然后将箱子按容量从大到小排序,然后直到把所有苹果装满为止的箱子数就是最少的。
class Solution {
public:
int minimumBoxes(vector<int>& a, vector<int>& b) {
//箱子容量从大到小排序
sort(b.begin(), b.end());
reverse(b.begin(), b.end());
//苹果总数
int sum = accumulate(a.begin(), a.end(), 0);
for (int i = 0; i < b.size(); i++) {
sum -= b[i];
if (sum <= 0) return i + 1;
}
return 0;
}
};
每轮都选当前幸福值最大的孩子。因为你每轮选最大的那么你的损失是最小的。因为正常来说k轮损失的值是(k - 1) + (k - 2) + ... + 2 + 1 = (k - 1) * k / 2(每轮没选的每个孩子幸福值都减1了)。但是幸福值最小值为0,如果你后选幸福值小的孩子,有可能在k轮前他的幸福值就已经为0了,不会再减少了,这肯定是比后选幸福值大的方案是更优的。
class Solution {
public:
long long maximumHappinessSum(vector<int>& a, int k) {
//幸福值从大到小排序
sort(a.begin(), a.end());
reverse(a.begin(), a.end());
long long ans = 0;
//幸福值最小是0
for (int i = 0; i < k; i++) ans += max(a[i] - i, 0);
return ans;
}
};
n的范围很小,直接枚举每一个字串,然后用map记录。时间复杂度O(n^3)
class Solution {
public:
vector<string> shortestSubstrings(vector<string>& arr) {
int n = arr.size();
//记录子串在不同字符串出现过的次数
map<string, int> mp;
//枚举每个字符串
for (int i = 0; i < n; i++) {
int m = arr[i].size();
//nice数组是只将字符串相同的子串记录一次
map<string, bool> nice;
//记录每个不同的子串
for(int j = 0; j < m; j++) {
for (int len = 1; len + j - 1 < m; len++) {
string substr = arr[i].substr(j, len);
if (nice[substr] == 1) continue;
mp[substr]++, nice[substr] = 1;
}
}
}
//记录答案
vector<string> ans(n, "");
for (int i = 0; i < n; i++) {
int m = arr[i].size();
for(int j = 0; j < m; j++) {
for (int len = 1; len + j - 1 < m; len++) {
string substr = arr[i].substr(j, len);
if (mp[substr] == 1) {
if (ans[i] == "") ans[i] = substr;
else {
if (ans[i].length() > substr.length()) ans[i] = substr;
else if (ans[i].length() == substr.length()) ans[i] = min(ans[i], substr);
}
}
}
}
}
return ans;
}
};
动态规划。
首先前缀和数组s[],用于方便求一段连续数组的和。
状态设置:
设f[i][j]为前j个数中选i个不相交数组的最大能量值。
状态转移:
第i个数组第j个值(最后)不选:f[i][j] = f[i][j - 1];
第i个数组第j个值选,此时我们就要枚举第i个数组的起点l。状态方程为:f[i][j] = max(f[i][j], (s[j] - s[l - 1]) * w + f[i - 1][l - 1]);
时间复杂度为O(n^3),超时。
for (int i = 1; i <= k; i++) {
f[i][i - 1] = LLONG_MIN;
//w为题目要求的某一轮相乘的值
int w = (k - i + 1) * (i % 2 ? 1 : -1);
long long mx = LLONG_MIN;
for (int j = i; j <= n; j++) {
f[i][j] = f[i][j - 1];
//第i组数组的起点至少是i,因为每个数组至少要1个数
for (int l = i; l<= j; l++)
f[i][j] = max(f[i][j], (s[j] - s[l - 1]) * w + f[i - 1][l - 1]);
}
}
优化方程:
进行拆解:。
我们只需要维护,就可以省去枚举k的循环。因为k的每轮循环只比他上一轮循环只增加了一个数
,我们在枚举j的过程中就可以维护好这个最大值,我们只需要用一个mx维护
就可以达到O(n^2)的时间复杂度了。
class Solution {
public:
long long maximumStrength(vector<int> &nums, int k) {
int n = nums.size();
vector<long long> s(n + 1);
for (int i = 0; i < n; i++) {
s[i + 1] = s[i] + nums[i];
}
vector<vector<long long>> f(k + 1, vector<long long> (n + 1));
for (int i = 1; i <= k; i++) {
f[i][i - 1] = LLONG_MIN;
int w = (k - i + 1) * (i % 2 ? 1 : -1);
long long mx = LLONG_MIN;//最小值
for (int j = i; j <= n; j++) {
mx = max(mx, f[i - 1][j - 1] - s[j - 1] * w);
f[i][j] = max(f[i][j - 1], mx + s[j] * w);
}
}
return f[k][n];
}
};