【笔试强训day13】

目录

第一题:牛牛冲钻五

输入描述:

第二题:最长无重复子数组

描述

第三题:重排字符串

题目描述

输入描述:

输出描述:

输入

输出


第一题:牛牛冲钻五

题目链接:登录—专业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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值