赛题链接:https://leetcode-cn.com/contest/weekly-contest-156
赛题一:独一无二的出现次数
给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。
- 对arr排序
- 用两个迭代器统计各元素出现的次数,并记录在num中
- 对num排序
- 检查num中元素是否都是独一无二的
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Solution {
public:
bool uniqueOccurrences(vector<int>& arr) {
vector<int> num;//用于记录各个数出现的次数
vector<int>::iterator it;
vector<int>::iterator im;
sort(arr.begin(),arr.end());
int count=0;
it=arr.begin();//排序
for(im=it;im<arr.end();im++){
if(*it==*im){//如果元素相同,count累计加一
count++;
}
else if(*it!=*im){//如果元素不同,将前一元素的统计次数压入。并让it指向新的元素。count记当前元素次数为1。
num.push_back(count);
it=im;
count=1;
}
if(im==arr.end()-1){//im扫描到最后一个元素,压入当前元素统计次数count。
num.push_back(count);
}
}
//判断各个数的出现次数是否是独一无二的
sort(num.begin(),num.end());
for(it=num.begin();it+1<num.end();it++){
if(*it==*(it+1)){
return false;
}
}
return true;
}
};
int main()
{
Solution my;
vector<int> myv;
myv.push_back(1);
myv.push_back(2);
cout<<my.uniqueOccurrences(myv);
return 0;
}
赛题二:尽可能使字符串相等
给你两个长度相同的字符串,s 和 t。将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。
- 记录两个字符串对应ASCII码的差值。
- 用贪心的思想,从某一下标开始往后累加差值,直到大于maxCost。记录这个累加的子字符串长度。
- 改变上述的下标,从头至尾。
#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
class Solution {
string s,t;
int maxCost;
public:
int equalSubstring(string s, string t, int maxCost) {
int count=maxCost;
int sum=0;
int cnt[s.length()];//cnt记录两字符串对应的ASCII码差值
int l=0;//能转化的最大长度
for(int i=0;i<s.length();i++){
cnt[i]=abs(int(s[i]-t[i]));
// cout<<cnt[i]<<" ";
}
for(int i=0;i<s.length();i++){
int temp=0;//从当前字符对应差值开始加和次数的临时值,也即对应满足条件的子字符串的长度
sum=0;
for(int j=i;j<s.length();j++){
sum+=cnt[j];
if(sum>count){
break;
}
temp++;
}
// cout<<"k:"<<k<<endl;
l=max(temp,l);
}
return l;
}
};
//测试
int main()
{
Solution my;
cout<<my.equalSubstring("krpgjbjjznpzdfy","nxargkbydxmsgby",14);
return 0;
}
赛题三:
给你一个字符串 s,「k 倍重复项删除操作」将会从 s 中选择 k 个相邻且相等的字母,并删除它们,使被删去的字符串的左侧和右侧连在一起。你需要对 s 重复进行无限次这样的删除操作,直到无法继续为止。在执行完所有删除操作后,返回最终得到的字符串。(本题答案保证唯一)
- 判断当前字符串是否有重复k倍的字符(函数isok())
- 在确定有上述的情况下,找到重复字符的第一个下标
- 删去重复字符
#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
class Solution {
public:
bool isok(string str,int k)//判断字符串是否符合继续的条件
{
int i=0;//指向str的首部
for(i=0;i+2<str.length();i++){
bool is=0;
for(int j=0;j<k;j++){
if(str[i]!=str[i+j]){
is=1;
break;
}
}
if(!is){
return true;
}
}
return false;
}
string removeDuplicates(string s, int k) {
// cout<<s<<endl;
while(isok(s,k)){
// cout<<isok(s,k)<<endl;
for(int i=0;i+2<s.length();i++){
bool is=0;
for(int j=0;j<k;j++){
if(s[i]!=s[i+j]){
is=1;
break;
}
}
if(!is){
s.erase(i,k);//删去
}
}
}
return s;
}
};
int main()
{
Solution my;
cout<<my.removeDuplicates("pbbcggttciiippooaais",2);
return 0;
}
赛题四 :穿过迷宫的最少移动次数
略