【编程】牛客网第四次模拟笔试

序列交换
牛牛有一个长度为n的整数序列s,羊羊要在牛牛的序列中选择不同的两个位置,然后交换这两个位置上的元素。现在需要求出羊羊交换后可以得到的不同的序列个数。(注意被交换的两元素值可能相同)。
如序列{1, 47},输出1.羊羊必须交换仅有的两个元素,得到序列{47, 1}。羊羊必须交换,不能保留原有的序列。
{1, 2, 1},输出3.羊羊通过交换可以得到{2, 1, 1},{1, 1, 2},{1, 2, 1}这三个序列。
输入描述:
输入包括两行,第一行为一个整数n(2 ≤ n ≤ 50),即序列的长度。
第二行n个整数,表示序列的每个元素a_i(1 ≤ a_i ≤ 50),以空格分割。

输出描述:
输出一个整数,表示羊羊可以得到的不同的序列个数

输入例子:
3
1 2 1

输出例子:
3
思考:次题不要想复杂,我刚刚开始想着原有的序列生产A序列然后再A的基础上生成B,C然后就和题意就矛盾。
其实题意是只在原有序列基础上,交换两个不同的位置,生成多少个不同的序列,只有想办法去除重复序列,最后统计个数。
方法一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <sstream>
using namespace std;
string int2string(int x) {
    ostringstream stream;
    stream << x;
    return stream.str();
}
//添加"#"区别 [4 44] 和 [44 4]
//数组转化为字符串用于在set中去掉重复序列
string convert2string(vector<int> &v) {
    string str = "";
    for(unsigned i = 0; i < v.size(); i++) {
        str += ("#" + int2string(v[i]));
    }
    return str;
}

int main()
{
    vector<int> V;
    set<string> mySet;
    int n;
    scanf("%d", &n);
    int read;
    for(int i = 0; i < n; i++) {
        scanf("%d", &read);
        V.push_back(read);
    }
    string newStr;
    for(unsigned i = 0; i < V.size()-1; i++) {
        for(unsigned j = i+1; j < V.size(); j++) {
            swap(V[i], V[j]);
            newStr = convert2string(V);
            mySet.insert(newStr);
            swap(V[i], V[j]);
        }
    }
    cout << mySet.size() << endl;
    return 0;
}
/**
测试用例:
3
4 44 4
19
6 13 26 9 39 7 31 7 28 22 43 6 5 26 44 44 40 4 5
**/

方法二:
思考:之前不经用用容器套容器,我突然觉得是时候要看看set的源码了。

#include <bits/stdc++.h>

using namespace std;
int n;
set<vector <int> > mySet;//去重复。
vector<int> V;
int main() {
    cin >> n;
    int read;
    for(int i = 0; i < n; i++) {
        cin >> read;
        V.push_back(read);
    }
    for(int i = 0; i < n-1; i++) {
        for(int j = i+1; j < n; j++) {
            swap(V[i], V[j]);
            mySet.insert(V);
            swap(V[i], V[j]);
        }
    }
    cout << mySet.size() << endl;
    return 0;
}

丑陋的字符串
牛牛喜欢字符串,但是他讨厌丑陋的字符串。对于牛牛来说,一个字符串的丑陋值是字符串中相同连续字符对的个数。比如字符串“ABABAABBB”的丑陋值是3,因为有一对”AA”和两对重叠的”BB”。现在给出一个字符串,字符串中包含字符’A’、’B’和’?’。牛牛现在可以把字符串中的问号改为’A’或者’B’。牛牛现在想让字符串的丑陋值最小,希望你能帮帮他。
输入描述:
输入包括一个字符串s,字符串长度length(1 ≤ length ≤ 50),字符串只包含’A’,’B’,’?’三种字符。

输出描述:
输出一个整数,表示最小的丑陋值

输入例子:
A?A

输出例子:
0
思考:前缀都是’?’部分都是有方案可以抵消掉的。然后把后半部分的情况处理一下。
效率及可读性需要学习方法二。
方法一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int INF = 0x7fffffff;
void work();

string str;
//记录有多少个丑陋值
int cnt = 0;
int main()
{
    getline(cin, str);
    work();
    cout << cnt << endl;
    return 0;
}

int getCnt(string mystr) {
    if(mystr.length() == 1) return 0;
    int num = 0;
    for(unsigned i = 1; i < mystr.length(); i++) {
        if(mystr[i] == mystr[i-1]) {
            num++;
        }
    }
    return num;
}

void work()
{
    //情况1:全是?的情况
    if(str.find("A") == string::npos && str.find("B")==string::npos) {
        cnt = 0;
        return;
    //情况2:没有?的情况
    } else if(str.find("?") == string::npos) {
        cnt = getCnt(str);
        return;
    }
    //情况3 三种符合都有。
    int posA = str.find("A");
    int posB = str.find("B");
    if(posA < 0) posA = INF;
    if(posB < 0) posB = INF;
    int firstIndex = min(posA, posB);
    for(unsigned i = firstIndex; i < str.length(); i++) {
        if(i == str.length()-1) break;
        if(str[i+1] == str[i]) {
            cnt++;
            continue;
        } else if(str[i+1] != '?' && str[i+1] != str[i]) {
            continue;
        } else {
            if(str[i] == 'A') str[i+1] = 'B';
            else str[i+1] = 'A';
        }
    }
}

方法二:(来自牛客网)

#include <bits/stdc++.h>
using namespace std;
string str;
int calc(string s, int j) {
    int res = 0;
    for(int i = j + 1; i < s.size(); i++) {
        if(s[i] == s[i - 1]) res++;
    }
    return res;
}
int main() {
    cin >> str;
    int pos = 0;
    while(pos < str.size() && str[pos] == '?') pos++;
    for(int i = pos + 1; i < str.size(); i++) {
        if(str[i] == '?') {
            if(str[i - 1] == 'A') str[i] = 'B';
            else str[i] = 'A';
        }
    }
    cout << calc(str, pos) << endl;
    return 0;
}

黑白卡片
牛牛有n张卡片排成一个序列.每张卡片一面是黑色的,另一面是白色的。初始状态的时候有些卡片是黑色朝上,有些卡片是白色朝上。牛牛现在想要把一些卡片翻过来,得到一种交替排列的形式,即每对相邻卡片的颜色都是不一样的。牛牛想知道最少需要翻转多少张卡片可以变成交替排列的形式。
输入描述:
输入包括一个字符串S,字符串长度length(3 ≤ length ≤ 50),其中只包含’W’和’B’两种字符串,分别表示白色和黑色。整个字符串表示卡片序列的初始状态。

输出描述:
输出一个整数,表示牛牛最多需要翻转的次数。

输入例子:
BBBW

输出例子:
1
思路:因为最终结果只有两种,然后进行比对就可以了。

#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
int work(string str);
int main()
{
    string str;
    getline(cin, str);
    int res = work(str);
    cout << res << endl;
    return 0;
}
int work(string str) {
    int cnt1 = 0;///BWBWBW
    int cnt2 = 0;///WBWBWB
    for(unsigned i = 0; i < str.length(); i++) {
        if(i % 2 == 0) {
            if(str[i] == 'W') cnt1++;
            else cnt2++;
        } else {
            if(str[i] == 'B') cnt1++;
            else cnt2++;
        }
    }
    return min(cnt1, cnt2);
}

庆祝61
牛家庄幼儿园为庆祝61儿童节举办庆祝活动,庆祝活动中有一个节目是小朋友们围成一个圆圈跳舞。牛老师挑选出n个小朋友参与跳舞节目,已知每个小朋友的身高h_i。为了让舞蹈看起来和谐,牛老师需要让跳舞的圆圈队形中相邻小朋友的身高差的最大值最小,牛老师犯了难,希望你能帮帮他。
如样例所示:
当圆圈队伍按照100,98,103,105顺时针排列的时候最大身高差为5,其他排列不会得到更优的解
输入描述:
输入包括两行,第一行为一个正整数n(3 ≤ n ≤ 20)
第二行为n个整数h_i(80 ≤ h_i ≤ 140),表示每个小朋友的身高。

输出描述:
输出一个整数,表示满足条件下的相邻小朋友身高差的最大值。

输入例子:
4
100 103 98 105

输出例子:
5
思路:这是一道比较有趣味的题目,看代码应该就可以看懂大致思路。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int workFirst();
int workSecond();
const int maxn = 30;
int data[maxn];
vector<int> V;

int main()
{
    int n;
    scanf("%d", &n);
    int read;
    for(int i = 0; i < n; i++) {
        scanf("%d", &read);
        V.push_back(read);
    }
    sort(V.begin(), V.end());
    int res = workFirst();
    res = max(res, workSecond());
    printf("%d\n", res);
    return 0;
}

int workFirst() {
    data[15] = V[0];
    int left = 14;
    int right = 16;
    for(unsigned i = 1; i < V.size(); i++) {
        if(i%2) {
            data[left--] = V[i];
        } else {
            data[right++] = V[i];
        }
    }
    left++;
    right--;
    int maxValue = fabs(data[right]-data[left]);
    for(int i = left; i < right; i++) {
        maxValue = max(maxValue, data[i+1]-data[i]);
    }
    return maxValue;
}
int workSecond() {
    data[15] = V[0];
    int left = 14;
    int right = 16;
    for(unsigned i = 1; i < V.size(); i++) {
        if(i%2==0) {
            data[left--] = V[i];
        } else {
            data[right++] = V[i];
        }
    }
    left++;
    right--;
    int maxValue = fabs(data[right]-data[left]);
    for(int i = left; i < right; i++) {
        maxValue = max(maxValue, data[i+1]-data[i]);
    }
    return maxValue;
}
/**
测试:
11
109 111 135 123 127 112 89 125 106 82 83
*/

黑化的牛牛

牛牛变得黑化了,想要摧毁掉地球。但他忘记了开启地球毁灭器的密码。牛牛手里有一个字符串S,牛牛还记得从S中去掉一个字符就恰好是正确的密码,请你帮牛牛求出他最多需要尝试多少次密码。
如样例所示S = “ABA”,3个可能的密码是”BA”, “AA”, “AB”.
当S = “A”, 牛牛唯一可以尝试的密码是一个空的密码,所以输出1.
输入描述:
输入包括一个字符串S,字符串长度length(1 ≤ length ≤ 50),其中都是从’A’到’Z’的大写字母。

输出描述:
输出一个整数,表示牛牛最多需要尝试的密码次数。

输入例子:
ABA

输出例子:
3
思路:其实问题是求去掉一个字母一共有多少种情况, 用set去重。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <set>
using namespace std;
int work(string str);

int main()
{
    string str;
    getline(cin, str);
    cout << work(str) << endl;
}

int work(string str) {
    set<string> passWordSet;
    string newStr;
    for(unsigned i = 0; i < str.size(); i++) {
        if(i == 0) {
            newStr = str.substr(1, str.length()-1);
            passWordSet.insert(newStr);
        } else {
            newStr = str.substr(0, i) + str.substr(i+1, str.length()-i-1);
            passWordSet.insert(newStr);
        }
    }
    return passWordSet.size();
}

膨胀的牛牛
牛牛以草料为食。牛牛有一天依次遇到n堆被施展了魔法的草料,牛牛只要遇到一堆跟他当前相同大小的草料,它就会把草料吃完,而使自己的大小膨胀一倍。一开始牛牛的大小的是A,然后给出牛牛依次遇到的n堆草料的大小。请计算牛牛最后的大小。
输入描述:
输入包括两行,第一行包含两个整数n和A(1 ≤ n ≤ 200, 1 ≤ A ≤ 1,000,000,000)
第二行包括n个整数,表示牛牛依次遇到的草料堆大小a_i(1 ≤ a_i ≤ 1,000,000,000)

输出描述:
输出一个整数,表示牛牛最后的大小。

输入例子:
5 1
2 1 3 1 2

输出例子:
4

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>
using namespace std;

int main()
{
    int n, currentSize;
    vector<int> V;
    scanf("%d%d", &n, &currentSize);
    int read;
    for(int i = 0; i < n; i++) {
        scanf("%d", &read);
        V.push_back(read);
    }
    for(unsigned i = 0; i < V.size(); i++) {
        if(currentSize == V[i]) {
            currentSize *= 2;
        }
    }
    printf("%d\n", currentSize);
    return 0;
}

牛客网题解:https://www.nowcoder.com/discuss/28544

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值