目录
第一题:牛牛冲钻五
题目链接:登录—专业IT笔试面试备考平台_牛客网
题目描述:
来源:牛客网
牛牛最近在玩炉石传说,这是一款一对一对战的卡牌游戏,牛牛打算努力冲上钻五分段,获得丰厚的天梯奖励。
炉石传说的段位可以用星数来表示,具体规则为:若牛牛本场失败,则扣除一星;若牛牛本场获胜,需要看牛牛是否触发了连胜奖励,若牛牛获得了至少三连胜(即本局对局的上一局和上上局都获胜)则获得kkk星,否则获得一星。
现在给出牛牛游玩的nnn场记录,请你判断牛牛最终的星数和初始星数的差。
输入描述:
第一行输入一个整数T(1≤T≤104)T(1\leq T\leq 10^4)T(1≤T≤104),测试组数。
每个测试的第一行输入两个整数n(3≤n≤105)n(3\leq n\leq 10^5)n(3≤n≤105)和k(2≤k≤100)k(2\leq k \leq 100)k(2≤k≤100),牛牛共打了几场比赛与连胜奖励的星数。
接下来一行输入一个长为nnn的字符串,之中WWW表示获胜,LLL表示失败,保证只含有这两种字母。
保证所有用例的Σn≤105\Sigma n\leq 10^5Σn≤105。
简单模拟题。解法:在遍历时,如果是字符L,那么直接减一星,如果是字符W,分两种情况讨论。第一种:不满足连胜奖励,只加一星;第二种:满足连胜奖励,加k星。关键是如何判断是否满足连胜奖励。其实也不难,只需判断当前位置的前两个位置是否为W即可(注意不要越界)。
#include <iostream>
#include <string>
using namespace std;
int t, n, k;
string s;
int func()
{
int ret = 0;
for(int i = 0; i < n; i++)
{
if(s[i] == 'L')
{
ret--;
}
else
{
if(i - 1 >= 0 && i - 2 >= 0
&& s[i - 1] == 'W' && s[i - 2] == 'W')
ret += k;
else ret++;
}
}
return ret;
}
int main()
{
cin >> t;
while(t--)
{
cin >> n >> k >> s;
int ret = func();
cout << ret << endl;
}
return 0;
}
第二题:最长无重复子数组
题目链接:最长无重复子数组_牛客题霸_牛客网
描述
给定一个长度为n的数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同。
子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
数据范围:0≤𝑎𝑟𝑟.𝑙𝑒𝑛𝑔𝑡ℎ≤1050≤arr.length≤105,0<𝑎𝑟𝑟[𝑖]≤1050<arr[i]≤105
输入:[2,2,3,4,3]
返回值:3
说明:[2,3,4]是最长子数组
滑动窗口——优化暴力双指针。当窗口中有重复元素时,就让left指针向右移动(出窗口),一直到窗口合法为止(窗口中无重复元素)。判断窗口中元素的个数的方法是借助一个hash数组即可。
经过上面的模拟,可以看出最长长度就为3。
class Solution {
public:
int hash[100010] = { 0 };//建立绝对映射关系,保存数字出现个数
int maxLength(vector<int>& arr)
{
int n = arr.size();
int left = 0, right = 0, ret = 0;
while(right < n)
{
hash[arr[right]]++;
while(hash[arr[right]] > 1)
{
hash[arr[left]]--;
left++;
}
ret = max(ret, right - left + 1);//每次移动完都检查是否更新
right++;
}
return ret;
}
};
第三题:重排字符串
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
小红拿到了一个只由小写字母组成的字符串。她准备把这个字符串重排(只改变字母的顺序,不改变数量)
重排后小红想让新字符串不包含任意两个相同的相邻字母。
你能帮帮她吗?
输入描述:
第一行一个正整数 nnn ,代表字符串的长度。 (1≤n≤105)(1 \leq n \leq 10^5)(1≤n≤105)
第二行为一个长度为 nnn 的、只由小写字母组成的字符串。
输出描述:
如果可以完成重排,请在第一行输出一个“yes”,第二行输出重排后的字符串。如果有多个正解,输出任意即可。
如果不能重排,则直接输出“no”
示例1
输入
5
aaaaa
输出
no
题意就是:能否将原字符串排成任意相邻的两个字符都不相同,能就输出yes和排列,不能就输出no即可。
1.找出出现次数最多的字符及其出现次数maxCount。
2.通过最大出现次数判断是否可以完成重排。
如果maxCount > (n + 1) / 2,那么不可以重排。直接输出No即可。
如果可以重排:优先排列出现次数最多的字符,然后在排剩下的字符。在排相同字符时,隔一个位置放。
#include <iostream>
#include <string>
using namespace std;
const int N = 1e5 + 10;
char ret[N];
int cnt[26] = { 0 };//统计每个字符出现的次数
int n;
string s;
char maxChar;//出现次数最多的字符
int maxCount;//出现最多字符的出现次数
int i;//下标,定位全局,避免传参
void GetMaxCharAndMaxCount()
{
for (int p = 0; p < n; p++)
{
int index = s[p] - 'a';
cnt[index]++;
if (cnt[index] > maxCount)
{
maxChar = s[p];
maxCount = cnt[index];
}
}
}
bool IsOk()
{
if (maxCount > (n + 1) / 2) return false;
else return true;
}
void ArrangeTheMost()
{
while (maxCount >= 1)
{
ret[i] = maxChar;
i += 2;//各一个位置放
maxCount--;
}
}
void ArrangeOther()
{
//遍历cnt数组,看看还有哪些字符没排
for (int j = 0; j < 26; j++)
{
if (cnt[j] != 0 && j + 'a' != maxChar)
{
while (cnt[j] >= 1)
{
//i可能越界了,需要调整回来
if (i >= n) i = 1;
ret[i] = j + 'a';
i += 2;
cnt[j]--;
}
}
}
}
void PrintRet()
{
for (int m = 0; m < n; m++)
cout << ret[m];
cout << endl;
}
int main()
{
cin >> n >> s;
GetMaxCharAndMaxCount();
if(!IsOk())
{
cout << "no" << endl;
}
else
{
cout << "yes" << endl;
ArrangeTheMost();//排列出现次数最多的字符
ArrangeOther();//排列剩下的字符
PrintRet();//输出结果
}
return 0;
}