题解 | #扑克牌大小#

扑克牌大小

http://www.nowcoder.com/practice/d290db02bacc4c40965ac31d16b1c3eb

题目的主要信息:

总的来说就是比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR。牌与牌之间比较的规则如下:

  • 炸弹和对王可以和所有牌,其他类型的牌只能跟相同类型的比较。
  • 个子、对子、三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌;

方法一:

首先将输入分成两副手牌,然后遍历两副手牌,用getLen函数分别计算两副手牌的长度,便于后续的比较。

  1. 如果任意一方有王炸,直接输出王炸即可。
  2. 若没有王炸,且两副手牌长度相同,如果有大王,则输出大王。否则用Value函数获得第一张牌面的值,比较两副牌第一个牌面的大小。
  3. 若没有王炸,且两幅手牌长度不同,如果有一方是炸弹,则输出炸弹,否则无法比较,输出ERROR。 alt 具体做法:
#include<iostream>
#include<string>

using namespace std;

int getLen(string s)//得到出牌的张数
{
    int len = 1;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == ' ') len++;
    }
    return len;
}

int Value(string s)//比较第一个牌面的大小
{
    int res;
    if (s[0] == '1') res = 10;
    else if (s[0] == '3') res = 3;
    else if (s[0] == '4') res = 4;
    else if (s[0] == '5') res = 5;
    else if (s[0] == '6') res = 6;
    else if (s[0] == '7') res = 7;
    else if (s[0] == '8') res = 8;
    else if (s[0] == '9') res = 9;
    else if (s[0] == 'J') res = 11;
    else if (s[0] == 'Q') res = 12;
    else if (s[0] == 'K') res = 13;
    else if (s[0] == 'A') res = 14;
    else if (s[0] == '2') res = 15;
    return res;
}

int main()
{
    string str;
    while (getline(cin, str))
    {
        string s1 = str.substr(0, str.find('-'));//第一手牌
        string s2 = str.substr(str.find('-') + 1);//第二手牌
        int n1 = getLen(s1);//第一手牌的个数
        int n2 = getLen(s2);//第二手牌的个数
        string Joker = "joker JOKER";//王炸!

        if (s1 == Joker || s2 == Joker){//如果有一手牌是王炸则王炸最大
            cout << Joker << endl;
        }else if(n1 == n2){//两手牌张数相同时
            if(s1 == "JOKER" || s2 == "JOKER"){//大王最大
                cout<<"JOKER"<<endl;
                continue;
            }
            int v1 = Value(s1);
            int v2 = Value(s2);
            if(v1 > v2){//比较第一张牌的大小,输出更大的那个
                cout<<s1<<endl;
            }else{
                cout<<s2<<endl;
            }
        }else if(n1 == 4) cout<<s1<<endl;//若两手牌张数不同,炸弹最大
        else if(n2 == 4) cout<<s2<<endl;
        else cout<<"ERROR"<<endl;//手牌张数不同,也没有炸弹则无法比较
    }

    return 0;
}

复杂度分析:

  • 时间复杂度:O(1)O(1),判断语句只花费常数时间,字符串的长度为常数,getLen函数也只花费常数时间。
  • 空间复杂度:O(1)O(1),只用了常数空间。

方法二:

整体思想和方法一相同,但在这里使用类对卡牌进行分装,用defineType函数获得手牌的类型,defineWeight函数获取手牌的权重,用compareCard函数比较牌面大小。用类封装的好处是便于拓展。

具体做法:

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

enum cardType{ JOKERPAIR, BOOM, STRING, PAIR, SINGLE, JOKER };
const int count = 3;

//规定每张牌的权重
unordered_map<char, int>weightIdx = {
	make_pair('3', 0),
	make_pair('4', 1),
	make_pair('5', 2),
	make_pair('6', 3),
	make_pair('7', 4),
	make_pair('8', 5),
	make_pair('9', 6),
	make_pair('1', 7),
	make_pair('J', 8),
	make_pair('Q', 9),
	make_pair('K', 10),
	make_pair('A', 11),
	make_pair('2', 12) };

//判断手牌的类型
cardType defineType(string str){
	if (str == "JOKER" || str == "joker"){//大王或小王
        return JOKER;
    }
	if (str.size() == 11 && (str[0] == 'j' || str[0] == 'J')){//对王
        return JOKERPAIR;
    }
	if (str.size() == 7 || str.size() == 11){//炸弹,例如4 4 4 4或10 10 10 10
        return BOOM;
    }
	if (str.size() <= 2 || str == "JOKER" || str == "joker"){//个子
        return SINGLE;
    }
	if (str.size() == 9 || str.size() == 10){//顺子
        return STRING;
    }
	return PAIR;//对子
}

//判断权重
int defineWeight(string str, cardType type){
    int w = 0;
	switch (type){
        case JOKERPAIR:
            w = 100;
            break;
        case BOOM:
        case STRING:
        case PAIR:
        case SINGLE:
            w = weightIdx[str[0]]; 
            break;
        case JOKER:
            w = (str[0] == 'J' ? 1 : 0); 
            break;//区别大王小王
        default:break;
	}
    return w;
}

//牌组类
class Card{
public:
	string value;//牌面内容
	cardType type;//牌组类型
	int weight;//牌组权重

public:
	explicit Card(string value) : value(value){//初始化
		type = defineType(value);//获得类型
		weight = defineWeight(value, type);//获得权重
	}
};

//输出较大牌组
void compareCard(const Card&c1, const Card&c2){
	if(c1.type == JOKERPAIR || c2.type == JOKERPAIR){//有对王存在时,对王最大
        cout<<"joker JOKER"<<endl;
    }
	else if (c1.type == BOOM&&c2.type == BOOM){//比较两个炸弹的大小
        if(c1.weight > c2.weight){
            cout << c1.value << endl;
        }else{
            cout << c2.value << endl;
        }
    }else if (c1.type == BOOM || c2.type == BOOM){//有一方为炸弹时,输出炸弹
        if(c1.type == BOOM){
            cout << c1.value << endl;
        }else{
            cout << c2.value << endl;
        }
    }else if (c1.type != c2.type){//两副手牌类型不同时
        if(c1.type == JOKER){
            cout << c1.value << endl;
        }else if(c2.type == JOKER){
            cout << c2.value << endl;
        }else{
            cout << "ERROR" << endl;
        }
    }else{//相同类型的比较
        if(c1.weight > c2.weight){
           cout << c1.value << endl;
       }else{
           cout << c2.value << endl;
       } 
    }
}
    

int main(){
	string str;
	while (getline(cin, str)){
		int len = str.size();
		int i = len;
        string s1 = str.substr(0, str.find('-'));//第一手牌
        string s2 = str.substr(str.find('-') + 1);//第二手牌
		Card crd1(s1), crd2(s2);
		compareCard(crd1, crd2);
	}
    return 0;
}


复杂度分析:

  • 时间复杂度:O(1)O(1),判断语句只花费常数时间。
  • 空间复杂度:O(1)O(1),只用了常数空间。
全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务