- 不熟练,思考时间太长
- 看题的时候在脑子里形成动画
5662. 满足三条件之一需改变的最少字符数
前两个条件的意思是:我们对a和b进行修改后,使得a,b中的字符在某个字符边界('a'-'z')的两侧。为了得到最小值,我们可以去枚举边界然后进行判定,取最小值。然后在与条件三的结果取最小值就ok啦
class Solution {
public:
int minCharacters(string a, string b) {
int n = a.size(), m = b.size();
vector<int> cnt_a(26,0), cnt_b(26,0);
int ans = m+n;
for (int i = 0; i <= 24; i++){//枚举边界
int left = 'a'+i, right = 'a'+i+1;
int cur1 = 0, cur2 = 0;
//边界已经确定了,我们检查一下a,b有多少个字符在边界外
//a可以在边界的左侧,也可以在右侧; b同理
for (int j = 0; j < n; j++){
if (a[j] > left) cur1++; // left
if (a[j] < right) cur2++; // right
}
for (int j = 0; j < m; j++){
if (b[j] > left) cur2++;
if (b[j] < right) cur1++;
}
ans = min(ans, min(cur1, cur2));
}
//条件三
for (int i = 0; i < n; i++) cnt_a[a[i]-'a']++;
for (int i = 0; i < m; i++) cnt_b[b[i]-'a']++;
for (int i = 0; i < 26; i++){
int cur1 = n-cnt_a[i] + m-cnt_b[i];
ans = min(ans, cur1);
}
return ans;
}
};
5664. 放置盒子
想要盒子挨地最少,那么挨地盒子数肯定有下面的规律(成阶梯状):
情形 | 按着地面盒子数 | 这种情况下能放盒子总数 |
---|---|---|
情形1 | 1 = 1(只放一个) | 1 |
情形2 | 2+1 = 3(第一行放两个,第二行放一个) | 3+1(上面可以托起一个) |
情形3 | 3+2+1 = 6 | 6+3+1(上面情形中所有的接地盒子数之和) |
..... | ..... | ..... |
情形n | n+n-1+...1 = (n+n2)/2 > n(这个可以看出,这样阶梯状放,就算全挨地,也能放下n个盒子) | ..... |
上面讨论的是极端情况,现在考虑一下变化过程:
假如接地3+2+1个盒子 向 4+3+2+1 个盒子过渡,我们在地面上添一个盒子,总共就只能放一个盒子;我们在地面上添两个盒子,那总共我们就能放2+1个盒子(上面可以顶起来一个);如果地面加三个,那总共就可以放3+2+1个盒子.....
我们考虑哪种极端条件放置的盒子总数刚好小于n,然后在地面逐个加盒子,进行判断就ok了
class Solution {
public:
int minimumBoxes(int n) {
int idx, sum = 0, base = 0;
for (idx = 1; ; idx++){
base += idx;
sum += base;
if (sum >= n) break;
}
//现在的极端条件是sum刚好大于等于n
int ans = 0;
for (int i = 1; i <= idx; i++) ans += i;
if (sum == n) return ans; //如果等于n,那就是极端条件下的接地盒子数
else ans -= idx;//否则我们要变到前面一个极端条件
for (int j = idx; j >= 1; j--) sum -= j;
//进行过渡判断
int cur_sum = 0;
for (int i = 1; i <= idx; i++){
cur_sum += i;
if (cur_sum+sum >= n){
ans += i;
break;
}
}
return ans;
}
};