华为笔试题--麻将和牌问题

题目描述:
清一色是麻将番种之一,指由一种花色的序数牌组成的和牌.
数字1-9,每个数字最多有4张牌
我们不考虑具体花色,我们只看数字组合。
刻子:三张一样的牌;如: 111, 222, 333, ..., 999
顺子:三张连续的牌;如: 123, 234, 345, ..., 789
对子:两张相同的牌;如: 11, 22, 33, ..., 99
需要实现一个程序,判断给定牌,是否可以和牌(胡牌)。
和牌要求:
- 麻将牌张数只能是 2, 5, 8, 11, 14
- 给定牌可以组合成,除1个对子以外其他都是刻子或顺子
举例: - "11" -> "11", 1对子,可以和牌
- "11122233" -> "111"+"222"+"33", 2刻子,1对子,可以
- "11223344567" -> "11"+"234"+"234"+"567", 1对子,3顺子,可以
-> "123"+"123"+"44"+"567", 另一种组合,也可以
输入描述:
合法C字符串,只包含'1'-'9',且已经按从小到大顺序排好;字符串长度不超过15。同一个数字最多出现4次,与实际相符。
输出描述:
C字符串,"yes"或者"no"
示例1
输入
2244
输出
24 //此处是试题原本模样,应该输出no

思路:

重点在于理解和牌时出牌的顺序问题,代码实现采用了组合分类思想,暂时未想到技巧性的方式

代码:

import java.util.Scanner;
import java.util.regex.Pattern;

/**
 * Created by [email protected] since 2018年9月12日 下午11:23:21.
 */
public class Mahjong {
	static final String duizi = "[1][1]|[2][2]|[3][3]|[4][4]|[5][5]|[6][6]|[7][7]|[8][8]|[9][9]";
	static final String shunzi = "[9][8][7]|[8][7][6]|[7][6][5]|[6][5][4]|[5][4][3]|[4][3][2]|[3][2][1]";
	static final String kezi = "[1]{3}|[2]{3}|[3]{3}|[4]{3}|[5]{3}|[6]{3}|[7]{3}|[8]{3}|[9]{3}";

	public static void main(String[] args) {
		Mahjong mahjong = new Mahjong();
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNextLine()) {
			String input = scanner.nextLine();
			int len = input.length();
			if (len > 15 || len < 1 || !input.matches("^[1-9]{1,15}$")) {
				System.out.println("输入数据有误,no");
				continue;
			}
			// 可以和牌的输入数据长度只有2/5/8/11/14
			if (len == 2 || len == 5 || len == 8 || len == 11 || len == 14) {
				String reverse = new StringBuilder(input).reverse().toString();
				System.out.println(mahjong.judge(reverse) ? "yes" : "no");
			} else {
				System.out.println("输入数据长度无法胡牌,no");
			}
		}
		scanner.close();
	}

	/**
	 * 判断是否可以和牌,输入数据已经过校验且被反转
	 *
	 * @param data
	 * @return
	 */
	public boolean judge(String data) {
		System.out.println(data);
		if (data.length() == 0) {
			return true;
		} else { // 判断输入是否有对子/刻子/顺子,若有则移除
			boolean hasDuizi = hasDuizi(data);
			boolean hasShunzi = hasShunzi(data);
			boolean hasKezi = hasKezi(data);

			if (hasDuizi) { // 有对子
				if (hasShunzi) { // 有顺子
					if (hasKezi) { // 有刻子--->三种都有
						String middle = data.replaceAll(shunzi, "");
						return judge(middle);
					} else { // 没有刻子--->只有对子和顺子
						String middle = data.replaceAll(duizi, "");
						return judge(middle);
					}
				} else { // 没有顺子
					// 1.有刻子--->只有对子和刻子eg:45556/22266 2.没有刻子--->只有对子
					String middle = data.replaceAll(duizi, "");
					return judge(middle);
				}
			} else { // 没有对子
				if (hasShunzi) { // 有顺子
					// 1.有刻子--->只有顺子和刻子 2.没有刻子--->只有顺子
					String middle = data.replaceAll(shunzi, "");
					return judge(middle);
				} else { // 没有顺子
					if (hasKezi) { // 有刻子--->只有刻子
						String middle = data.replaceAll(kezi, "");
						return judge(middle);
					} else { // 没有刻子--->三种都没有
						return false;
					}
				}
			}
		}
	}

	public boolean hasDuizi(String data) {
		return Pattern.compile(duizi).matcher(data).find();
	}

	public boolean hasShunzi(String data) {
		return Pattern.compile(shunzi).matcher(data).find();
	}

	public boolean hasKezi(String data) {
		return Pattern.compile(kezi).matcher(data).find();
	}
}

 

你可能感兴趣的:(Java,算法)