2024.12.24
2134. 最少交换次数来组合所有的 1 II
class Solution {
public:
int minSwaps(vector<int>& nums) {
//先找1的长度k,再滑k,找到最大值,返回k-sum
int k=0;
for(int i=0;i<nums.size();i++)k+=nums[i];
int res=0,sum=0,n=nums.size();
for(int i=0;i<k-1;i++)sum+=nums[i];
for(int i=k-1;i<k-1+n&&i>=0;i++){
//进
sum+=nums[i%n];
//处理
res=max(res,sum);
//出
sum-=nums[i-k+1];
}
return k-res;
}
};
思考:正常套路处理,会遇到k=0的情况,导致数组越界。没有太关注这个。需要注意
67. 二进制求和
class Solution {
public:
string addBinary(string a, string b) {
//倒序遍历计算,i值a, j值b
int an=a.size(),bn=b.size();
if(an>bn){
for(int i=1;i<=an-bn;i++) b='0'+b;
}
else {
for(int i=1;i<=bn-an;i++) a='0'+a;
}
int next=0;
for(int i=max(an-1,bn-1);i>=0;i--){
int sum=0;
sum+=next+(a[i]-'0')+(b[i]-'0');
next=sum/2;
sum=sum%2;
b[i]=sum+'0';
}
if(next==1) {
b='1'+b;
}
return b;
}
};
思考:确实好坑。主要就考察对字符串的处理把。1.如何将字符'2'转换成整数2呢?'2'-'0'即可。
2.如何将整数2转换为字符'2'呢?2+'0'即可。因为'0'的ascii码是48,50对应字符'2'。3.最好先给两个字符串补齐,我没补齐刚开始,遍历的时候有点点复杂。
2024.12.26
2653. 滑动子数组的美丽值
class Solution {
public:
vector<int> getSubarrayBeauty(vector<int>& nums, int k, int x) {
//维护count数组,存对应负数的个数
//维护cnt,计数负数的值
//若cnt<x,则美丽值为0;反之,在coumt数组中找
int cnt=0;
vector<int>count(50,0);
vector<int>res;
for(int i=0;i<nums.size();i++){
//进
if(nums[i]<0){
cnt++;
count[nums[i]+50]++;
}
if(i<k-1)continue;//先建立滑动窗口
//进行处理
if(cnt<x){
res.push_back(0);
}
else{
int left=x;
for(int j=0;j<50;j++){
left-=count[j];
if(left<=0){
//结果就是j对应的值
res.push_back(j-50);
break;
}
}
}
//处理完更新滑动窗口 出
if(nums[i-k+1]<0){
cnt--;
count[nums[i-k+1]+50]--;
}
}
return res;
}
};
思考:1.对我还是挺难的,排除刚开始题目看错,“第x小的值”,而不是“第x个值”。
2.滑动窗口只维护负数值
3.根据数组顺序查找第x小。
567. 字符串的排列
class Solution {
public:
//统计s1各字符长度,
//以s1长度在s2进行滑动窗口
//滑动过程中维护
unordered_map<char,int>s1map;
unordered_map<char,int>s2map;
bool istrue(){
//如何判断为true
if(s1map.size()!=s2map.size()) return false;
for(auto [key,val]:s1map){
if(s2map[key]!=val) return false;
}
return true;
}
bool checkInclusion(string s1, string s2) {
int s1sum=0,s2sum=0;//ascii值总和
int k=s1.size();//滑动窗口长度
for(int i=0;i<k;i++){
s1sum+=s1[i]-'a'+1;
s1map[s1[i]]++;
}
//遍历s2
for(int i=0;i<s2.size();i++){
//先初始化一个窗口
s2sum+=s2[i]-'a'+1;
s2map[s2[i]]++;
if(i<k-1)continue;
//进行处理
if(s1sum==s2sum){
if(istrue()){
return true;
}
}
//出操作
s2sum-=s2[i-k+1]-'a'+1;
if(!(--s2map[s2[i-k+1]])) s2map.erase(s2[i-k+1]);
}
return false;
}
};
思考:1.思路差不多,但是处理判断结果那一部分不太行。就是对map的遍历
438. 找到字符串中所有字母异位词
class Solution {
public:
unordered_map<char,int>pmap;
unordered_map<char,int>smap;
bool istrue(){
if(pmap.size()!=smap.size()) return false;
for(auto [key,val]:pmap){
if(smap[key]!=val) return false;
}
return true;
}
vector<int> findAnagrams(string s, string p) {
//和上一题几乎一样,就是处理改成将索引压入数组
int k=p.size();
vector<int>res;
//先统计p的字符个数
for(int i=0;i<k;i++){
pmap[p[i]]++;
}
//遍历p
for(int i=0;i<s.size();i++){
//先初始化滑动窗口
smap[s[i]]++;
if(i<k-1)continue;
//处理
if(istrue()){
res.push_back(i-k+1);
}
//出
if(!(--smap[s[i-k+1]])) smap.erase(s[i-k+1]);
}
return res;
}
};
思考:1.做过上一题后,这题就很简单,几乎一样,就是处理结果不一样。
2.很抓马的事情就是这题和上题要遍历的字符串反过来了,没注意,找错了好久。
2024.12.28
3. 无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//用某结构保存字符个数,
//对s遍历,如果该字符已经被保存,就将结构清零,保存此时最大长度,重新保存该字符
int res=0;
int l=0;//左端点
int r=0;
unordered_set<char>set;
for(;r<s.size();){
if(set.find(s[r])==set.end()){
//没找到,就插入
set.insert(s[r]);
int len=r-l+1;
res=max(res,len);
r++;
}
else{
set.erase(s[l]);
l++;
}
}
return res;
}
};
思考:for循环还能这样用,手动控制指针的自增。从而实现删除之前保存维护的字符。
不是找到重复的就把前面的全部删除,从此刻字符重新统计。而是从l开始向右一直删,直到删把重复的那个字符给删掉。即,删除重复的字符及之前的。
3090. 每个字符最多出现两次的最长子字符串
class Solution {
public:
int maximumLengthSubstring(string s) {
int n=s.size();
int res=0,l=0;
unordered_map<char,int>map;
for(int i=0;i<s.size();i++){
map[s[i]]++;
while(map[s[i]]>2){//一直删除前面的,直到该字符map的val==2
//及时前面的有些字符是没超过2
map[s[l]]--;
l++;
}
res=max(res,i-l+1);
}
return res;
}
};
思考:这个是字符统计大于2时,从l往右一直删,直到此时的字符==2。即删除字符统计为3的第一次出现的位置及之前的所有字符。