牛客一题讲解

Alice 和 Bob 很喜欢一起打牌,与扑克牌不同,他们打的牌的牌名只由单个大写字母组成,并没有 1−10 的数字牌。

今天,他们又约着一起玩打对子,打对子的规则是:每个人会得到一定数量的牌,然后每个人可以任意次将两张相同牌名的牌作为对子打出,最后剩下牌少的人将获得胜利,如果剩余牌数相同,则收获平局,双方都无法获胜。

由于牌太多,Alice 整理牌整理不过来了,因此她决定向你求助,询问自己最后会剩下多少张牌,以及自己是否能战胜 Bob 。

输入描述:

第一行输入一个正整数 n (1<n<1000000 ) ,代表两人各得到了多少张牌。

第二行输入一个长度为 n 的字符串,代表 Alice 得到的牌。

第三行输入一个长度为 n 的字符串,代表 Bob 得到的牌。

输出描述:

第一行输出一个整数,代表 Alice 最终剩下的牌数。

第二行输出一个字符串,若 Alice 能战胜 Bob ,输出" YES"(不带引号);否则,输出 "NO"(不带引号)。

其余的请看上图:

一、题的解释:

问题理解:打对子游戏怎么玩?
想象你和朋友玩牌,每人有一堆牌(每张牌是A-Z的字母)。规则很简单:
每次可以把两张一样的牌扔出去(比如两个"A"),这叫"打对子"。
打完所有能打的对子后,剩下牌少的人赢;一样多就平局。
现在需要算:

Alice最后剩几张牌?
Alice能不能赢Bob?
解题步骤:3步轻松搞定
第1步:数清楚每张牌有多少张

比如Alice的牌是"AABBB",那她的牌数量就是:

A:2张,B:3张
第2步:算能打多少对子,剩多少牌

每张牌能打多少对子?数量÷2(取整数)。比如B有3张,能打1对(2张),剩下1张。

总剩余牌数 = 总牌数 - 2×(所有对子数总和)
👉 例:Alice总牌数5张,对子数=1(A)+1(B)=2对,剩余=5 - 2×2=1张。
第3步:比较Alice和Bob的剩余牌数
如果Alice剩的 < Bob剩的 → 输出"YES"(Alice赢)
否则 → 输出"NO"
举个例子

输入:

5  
AABBB (Alice的牌)  
ABCDE (Bob的牌)  

Alice的计算:

A:2张→1对,B:3张→1对,总对子数=2 → 剩余=5-2×2=1张

Bob的计算:

A/B/C/D/E各1张→0对 → 剩余=5-0=5张

结果:
Alice剩1张,Bob剩5张 → Alice赢,输出"YES"

代码思路(简单版)
用两个数组(大小26,对应A-Z)统计每张牌的数量。
分别算Alice和Bob的剩余牌数。
比较并输出结果。

✨ 核心就是:数清楚、算对子、比多少,三步搞定!

本人代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>
int main()
{
    int n, i, j, t = 0, k = 0, c[100] = { 0 }, d[100] = { 0 };
    scanf("%d", &n);
    char* a = (char*)malloc((n + 2) * sizeof(char));
    char* b = (char*)malloc((n + 2) * sizeof(char));
    getchar();
    scanf("%s %s", a, b);
    i = 0;
    for(i=0;i<n;i++)
    {
        c[a[i]]++;
    }
    for (j = 0; j < 99; j++)
    {
        t += c[j] / 2;
    } 
    i = 0;
    for (i = 0; i < n; i++)
    {
        d[b[i]]++;
    }
    for (j = 0; j < 99; j++)
    {
        k += d[j] / 2;
    }
    
    printf("%d\n", n - t * 2);
    if (t > k)
    {printf("YES\n");
    }
    else
    {printf("NO\n");
}
    free(a);
    free(b);
}

我写的变量有些随意,请见谅:

二、代码分析:

int main()
{
    int n, i, j, t = 0, k = 0, c[100] = { 0 }, d[100] = { 0 };

  • n:牌的总张数(Alice和Bob各有n张)。
  • i, j:循环计数器。
  • t:Alice能打出的对子总数
  • k:Bob能打出的对子总数
  • c[100]:统计Alice每张牌的数量(下标对应ASCII值)。
  • d[100]:统计Bob每张牌的数量。

    char* a = (char*)malloc((n + 2) * sizeof(char));  // Alice的牌(+2防越界)
    char* b = (char*)malloc((n + 2) * sizeof(char));  // Bob的牌
    getchar();  // 吸收输入n后的回车(避免干扰后续输入)
    scanf("%s %s", a, b);  // 读取Alice和Bob的牌(如 "AABBB" "ABCDE")

    i = 0;
    for(i=0; i < n; i++)  // 遍历Alice的n张牌
    {
        c[a[i]]++;  // a[i]是当前牌面(如 'A'),c['A']统计'A'的数量
    }

我是打算通过对字符的ASCLL来对值进行接收,

例:若a = "AABBB"(n=5)

  • c['A'](ASCII值65)会自增2次 → c[65] = 2
  • c['B'](ASCII值66)会自增3次 → c[66] = 3

接收完值后,可以数对子数了:(Alice)

    for (j = 0; j < 99; j++)  // 遍历所有可能的字符(ASCII 0~98)
    {
        t += c[j] / 2;  // 每张牌的对子数 = 数量 // 2(取整数)
    } 

  • 举例c['A']=2 → 2/2=1对;c['B']=3 → 3/2=1对(共2对,t=2)。

统计Bob的牌并计算对子数 k(与Alice逻辑相同),不过多解释:

    i = 0;
    for (i = 0; i < n; i++)  // 遍历Bob的n张牌
    {
        d[b[i]]++;  // 统计Bob每张牌的数量
    }
    for (j = 0; j < 99; j++)
    {
        k += d[j] / 2;  // 计算Bob的总对子数k
    }

根据:

输出描述:

第一行输出一个整数,代表 Alice 最终剩下的牌数。

第二行输出一个字符串,若 Alice 能战胜 Bob ,输出" YES"(不带引号);否则,输出 "NO"(不带引号)。

所以:

    printf("%d\n", n - t * 2);  // Alice剩余牌数 = 总牌数 - 2*对子数(每张对子2张牌)
    if (t > k)  // 对子数越多,剩余牌越少(t越大越可能赢)
    {
        printf("YES\n");  // Alice对子数多 → 剩余少 → 赢
    }
    else
    {
        printf("NO\n");   // 否则输或平局
    }

因为数组通过malloc而来,所以应将内存释放:

    free(a);  // 释放动态分配的内存(避免内存泄漏)
    free(b);
}
 

核心思想:

  1. 核心思想

    • 剩余牌数 = 总牌数 - 2×对子数(每张对子消耗2张牌)。
    • 胜负判断:对子数多的人剩余牌少 → 若t > k,Alice赢。

输入牌面后,程序会输出Alice剩余牌数,并判断是否能赢Bob。例如输入:
5
AABBB ABCDE
会输出 1(Alice剩1张)和 YES(Alice赢)。

总结

以上就是今天要讲的内容,本文介绍了牛客题讲解的相关内容,为本章节知识的内容,希望大家能喜欢我的文章,谢谢各位。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值