当前位置:编程学习 > JAVA >>

一道java算法题

假设你现在在玩单色麻将(只有一种类别),给你一个数n,0<n<=13,和int[]数组,求出所有能胡牌的牌;
例子:n=5,int[] = {1,2,3,4,5};    结果:3,6
java 算法 --------------------编程问答-------------------- 这是一道笔试题,求大家帮帮忙,要java版本的,可以不要源代码,但是要给出正确的思路和理由;
ps:麻将胡牌的规则大家知道不?还要我贴出来不?
这里的规则只要考虑 
3个连续,比如:1,2,3
3个相同,比如:1,1,1
2个相同,比如:1,1

--------------------编程问答-------------------- ps:如果能在3天内给出能运行正确的源代码的,我再给50分! --------------------编程问答-------------------- 自己顶下   求大神  ~   求犀利哥 ~ --------------------编程问答-------------------- 例子:n=5,int[] = {1,2,3,4,5};    结果:3,6  结果为啥是3,6啊?你这规则说的也有点太不明了额 --------------------编程问答-------------------- 看不懂,你给的例题看不懂 --------------------编程问答-------------------- 假设你在玩只有筒子(麻将的一种花色)的麻将,给你两个参数,int n(当前剩下的牌数),0<n<=13,int[]majiangs(当前剩下的牌的组合、已经按升序排列),里面存放的是1到9这9个数字的组合,按麻将的规则,相同的数字最多能出现4次,
让你根据这两个参数求出所有能胡牌的结果;
麻将胡牌规则:
如果数字是3个连续的比如123,或者3个相同的比如111,这叫做“砍”,如果数字是2个相同的,比如说是11,这叫做“眼”
当最后剩下的牌组能组成N个“砍”和1个“眼”的组合,那么就能胡牌;
因为:加上摸到的最后一张牌,最多是14张,14%3=2,或者11%3或8%3类推,所以,肯定是N个“砍”对应一个“眼”胡牌。
测试数据:
int n = 7, int[] ={2,3,4,5,6,7,7}
结果:1,4,7; 
理由:
如果是1,那么可以排列成:123、456、77
如果是4,那么可以排列成:234、456、77
如果是7,那么可以排列成:234、567、77

求解函数callHu(int n,int[] majiangs); --------------------编程问答-------------------- 大家没看懂问题的,我在6楼进行了详细的解释,大家可以看看6楼,前面的题目不用管了,是我没说清楚,麻烦大家了 --------------------编程问答-------------------- 1 那个字叫“和”
2 为什么只有3,6?多举点例子 --------------------编程问答-------------------- 递归,最终都可以变成1和4的情况。
思路如下,代码你自己整吧。
	public List callHu(int[] mj) {
int n = mj.length;
if (n < 1 || n > 13 || n % 3 != 1) {
System.out.println("错牌");
return null;
}

List huList;//用来存放胡牌

if(n==1){//如果只剩一张牌,一种情况,胡眼
huList.add(mj[0]);
return huList;
}

if(n==4){//4张牌有两种情况,有眼胡砍,或者有砍胡眼
找出所有可能的砍;
for(每个砍){
List tempList=callHu(去掉这个砍的数组tempmj);
判断tempList的每一个是否在mj中出现超过4次,或者是否已经在huList中;
将tempList符合要求的元素加入huList;
}

找出所有可能的眼;
for(每个眼){
判断剩下的两张牌是否能通过加1张牌(h)构成砍;
判断符合条件的h是否在mj中出现超过4次,或者是否已经在huList中;
将符合条件的h加入huList中;
}
return huList;
}

//其他情况,都可以通过抽出一个或多个砍变成4张牌的情况
找出所有可能的砍;
for(每个砍){
List tempList=callHu(去掉这个砍的数组tempmj);
判断tempList的每一个是否在mj中出现超过4次,或者是否已经在huList中;
将tempList符合要求的元素加入huList;
}
return huList;
}


--------------------编程问答-------------------- LZ会玩麻将不?
当n=1,4,7,10,13的时候才能胡牌,其他情况都是“相公”
--------------------编程问答-------------------- 当前剩下的牌数是什么意思 如果是后面的int数组的长度这个参数可以不用给的 --------------------编程问答-------------------- 同新手写的代码乱七八糟将就着看吧。
因为只有一种花色,所以就算将1到9测试遍,
胡眼的位置不确定,用外层循环m来测试,不同组合可能会出现重复,尚未优化。

import java.util.Arrays;
public class Test
{public static void main(String []args){
int[] arr={1,1,1,2,2,3,3,3,3,4,4,4,5};
callHu(13,arr);
}

static void callHu(int n,int[] majiangs){
int temp=0,test=0;
int arr[]=new int[14];
for(int i=1;i<10;i++){
System.arraycopy(majiangs,0,arr,0,13);
arr[13]=i;
Arrays.sort(arr);
for(int m=0;m<5;m++){
temp=0;test=0;
for(int j=0;j<5;j++){
        if (m==j)
           {if(arr[3*j]==arr[3*j+1]){temp=1;test++;continue;}else break;
            }
else if((arr[3*j-temp]==arr[3*j+1-temp]&&arr[3*j-temp]==arr[3*j+2-temp])||(arr[3*j-temp]+1==arr[3*j+1-temp])&&arr[3*j-temp]-temp+2==arr[3*j+2-temp])
               {test++;continue;}//else break;


}
if (test==5)
{System.out.print(i+"\t");
    }

}

 }
}
}
--------------------编程问答-------------------- 顶楼上的楼上的楼上,首先,胡牌肯定是1,4,7,10,13所以
if(hunum/3==1 && hunum>0 && hunum<14){
         switch(hunum){
                 case 1:
                        if(hunum==mopai){
                             System.out.println("胡牌");
                         }else{
                             System.out.println("未胡牌");
                         }
                      break;
                 case 4:
                       if(){
                           
                       }
                      break;
                 case 7:
                      break;
                 case 10:
                      break;
                 default:
                      break;
           }
}else{
    System.out.println("相公");
}


主要是逻辑问题,如果不介意,可以晚上有时间探讨,QQ1769497505 --------------------编程问答--------------------
引用 10 楼 zyc13701469860 的回复:
LZ会玩麻将不?
当n=1,4,7,10,13的时候才能胡牌,其他情况都是“相公”
那如果我有一个杠呢、就是4个一样的,不就又多了一张牌。 --------------------编程问答--------------------
引用 6 楼 prince_li_ 的回复:
假设你在玩只有筒子(麻将的一种花色)的麻将,给你两个参数,int n(当前剩下的牌数),0<n<=13,int[]majiangs(当前剩下的牌的组合、已经按升序排列),里面存放的是1到9这9个数字的组合,按麻将的规则,相同的数字最多能出现4次,
让你根据这两个参数求出所有能胡牌的结果;
麻将胡牌规则:
如果数字是3个连续的比如123,或者3个相同的比如111,这叫……

2也能组成2,3,4啊,怎么就不行呢? --------------------编程问答-------------------- 第一,剩下的牌必须是1,4,7,10,13张,其他的牌就是相公
第二,必须已经听牌,也就是只要一张就和牌,只是有不同的和法,楼上有人说4张牌成杠的,那样的话就还没听牌
--------------------编程问答-------------------- 俺不会打麻将,怎么做题? --------------------编程问答-------------------- 哈哈,这句话说得经典 --------------------编程问答-------------------- 例子:n=5,int[] = {1,2,3,4,5};    结果:3,6

胡个屁,大相公!!! --------------------编程问答--------------------
引用 9 楼 abc41106 的回复:
递归,最终都可以变成1和4的情况。
思路如下,代码你自己整吧。
Java code?12345678910111213141516171819202122232425262728293031323334353637383940public List callHu(int[] mj) {    int n = mj.length;    if (n < 1 || n >……

大哥,我就是要这种递归的算法,能更详尽点不?for(每个砍)是什么情况?循环遍历
123,234这种情况么?for(每个眼)就是遍历1到9?还有啊,最后一个return huList是什么情况? --------------------编程问答--------------------
引用 19 楼 sweat89 的回复:
例子:n=5,int[] = {1,2,3,4,5};    结果:3,6

胡个屁,大相公!!!

sorry,前面的题目是错的,忽略,看六楼的题目 --------------------编程问答--------------------

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PlayerMajiang {

public static void main(String[] args) throws Exception {
int[][] test = {
{1,1,2,2,3,4,5,6,7,8,9,9,9},
{1,1,2,2},
{1,1,2,2,3,3,3},
{1,1,2,2,3,3,4},
{1,2,3,4,5,6,7},
{5,6,6,7,7,8,8},
};
for(int[] array : test){
callHu(array);
}
}

private static void callHu(int[] majiangs) {
if (majiangs.length != 1 && majiangs.length != 4
&& majiangs.length != 7 && majiangs.length != 10
&& majiangs.length != 13) {
System.out.println("相公哦!亲");
return;
}
int[] countArray = getCountArray(majiangs);
int[] templateArray = new int[majiangs.length + 1];
System.arraycopy(majiangs, 0, templateArray, 0, majiangs.length);
System.out.print(Arrays.toString(majiangs) + ":");
for(int i = 1; i <= 9; i ++){
if(countArray[i - 1] < 4){
templateArray[templateArray.length - 1] = i;
int[] majiang = Arrays.copyOf(templateArray, templateArray.length);
Arrays.sort(majiang);
if(checkMajiang(majiang)){
System.out.print(i + ",");
}
}
}
System.out.println("可以胡!");
}

private static int[] getCountArray(int[] majiangs){
int[] countArray = new int[9];
for(int i = 0; i < majiangs.length; i ++){
if(majiangs[i] > 0){
countArray[majiangs[i] - 1] ++;
}
}
return countArray;
}

private static boolean checkMajiang(int[] array){
List<int[]> arrayWithoutEye = cutEye(array);
for(int[] combination : arrayWithoutEye){
if(checkCombination(combination, 0)){
return true;
}
}
return false;
}

private static boolean checkCombination(int[] array, int index){
if(index == array.length){
return true;
}
if(array[index] == 0){
return checkCombination(array, index + 1);
}
int currentValue = array[index];
int count = findCountByValue(array, currentValue);
//如果大于等于3,删除3张一样的,否则删除连续的3张
if(count >= 3){
array[index] = 0;
array[findIndex(array, currentValue)] = 0;
array[findIndex(array, currentValue)] = 0;
}else{
int nextPos1 = findIndex(array, currentValue + 1);
int nextPos2 = findIndex(array, currentValue + 2);
if(nextPos1 == -1 || nextPos2 == -1)
return false;
array[index] = 0;
array[nextPos1] = 0;
array[nextPos2] = 0;
}
return checkCombination(array, index + 1);
}

private static int findCountByValue(int[] array, int value){
int[] countArray = getCountArray(array);
return countArray[value - 1];
}

private static int findIndex(int[] array, int value){
for(int i = 0; i < array.length; i ++){
if(array[i] == value){
return i;
}
}
return -1;
}

private static List<int[]> cutEye(int[] array){
List<int[]> list = new ArrayList<int[]>();
int[] countArray = getCountArray(array);
for(int i = 0; i < countArray.length; i ++){
if(countArray[i] > 1){
int[] newArray = Arrays.copyOf(array, array.length);
int count = 0;
for(int j = 0; j < newArray.length; j ++){
if(newArray[j] == i + 1){
newArray[j] = 0;
count ++;
if(count == 2){
break;
}
}
}
list.add(newArray);
}
}
return list;
}
}

试试这个能用不?我随便试了试,ms没问题 --------------------编程问答--------------------
引用 20 楼 prince_li_ 的回复:
引用 9 楼 abc41106 的回复:递归,最终都可以变成1和4的情况。
思路如下,代码你自己整吧。
Java code?12345678910111213141516171819202122232425262728293031323334353637383940public List callHu(int[] mj) {    int n = mj.length;……

for(每个砍)的前提是你要找到所有可能的砍,然后对每个砍都要处理。
比如1234:就有123、234两种种情况
拿第一个砍来说,去掉123,剩下4就是1张牌的情况,即胡4(当然还要检查)

for(每个眼)就是找出所有可能的眼,然后对每个眼都要处理。
比如2233:就有22、33两种情况。
拿第一个眼来说,去掉22,剩下的就是33,遍历1到9,看有没有能和33组成砍的,有3,所以胡3

return huList就是把所有可能胡的牌返回啊,你不想返回就改成void,在这里输出就可以了。 --------------------编程问答-------------------- 闲着没事写了一下,仅供参考
import java.util.ArrayList;
import java.util.List;

public class test9 {
public List<Integer> callHu(int[] mj) {
int n = mj.length;
if (n < 1 || n > 13 || n % 3 != 1) {
System.out.println("错牌");
return null;
}

List<Integer> huList = new ArrayList<Integer>();// 用来存放胡牌

if (n == 1) {// 如果只剩一张牌,一种情况,胡眼
huList.add(mj[0]);
return huList;
}

if (n == 4) {// 4张牌有两种情况,有眼胡砍,或者有砍胡眼
List<Integer> kan = findKan(mj);//找出所有可能的砍;
for (Integer k : kan) {
int[] tempmj = cutKan(mj, k);//去掉砍之后的牌
List<Integer> tempList = callHu(tempmj);//递归
for (Integer i : tempList) {
if (gtFour(mj, i) || huList.contains(i))
continue;
huList.add(i);
}
}

List<Integer> yan = findYan(mj);//找出所有可能的眼;
for (Integer y : yan) {
int[] tempmj = cutYan(mj, y);//去掉眼之后的牌
if (tempmj[0] == tempmj[1]) {//剩下是一个眼
if (!gtFour(mj, tempmj[0]) && !huList.contains(tempmj[0]))
huList.add(tempmj[0]);
}
if (tempmj[1] - tempmj[0] == 1) {//剩下是两张连续的牌
int left = tempmj[0] - 1;
if (left >= 1 && !gtFour(mj, left)
&& !huList.contains(left))
huList.add(left);

int right = tempmj[1] + 1;
if (left <= 9 && !gtFour(mj, right)
&& !huList.contains(right))
huList.add(right);
}
}
return huList;
}

// 其他情况,都可以通过抽出一个或多个砍变成4张牌的情况
List<Integer> kan = findKan(mj);
for (Integer k : kan) {
int[] tempmj = cutKan(mj, k);
List<Integer> tempList = callHu(tempmj);
for (Integer i : tempList) {
if (gtFour(mj, i) || huList.contains(i))
continue;
huList.add(i);
}
}

return huList;
}

private List<Integer> findKan(int[] mj) {//找砍
List<Integer> kan = new ArrayList<Integer>();
for (int i = 0; i < mj.length - 2; i++)
for (int j = i + 1; j < mj.length - 1; j++)
for (int k = j + 1; k < mj.length; k++)
if ((mj[i] == mj[j] && mj[i] == mj[k])
|| (mj[j] - mj[i] == 1 && mj[k] - mj[j] == 1)) {
Integer value = mj[i] * 100 + mj[j] * 10 + mj[k];
if (!kan.contains(value))
kan.add(value);
}
return kan;
}

private List<Integer> findYan(int[] mj) {//找眼
List<Integer> yan = new ArrayList<Integer>();
for (int i = 0; i < mj.length - 1; i++)
for (int j = i + 1; j < mj.length; j++)
if (mj[i] == mj[j]) {
Integer value = mj[i] * 10 + mj[j];
if (!yan.contains(value))
yan.add(value);
}
return yan;
}

private int[] cutKan(int[] mj, int kan) {//去砍
int[] newmj = new int[mj.length - 3];
int i = 0, j = 0, k = 100;
for (i = 0; i < newmj.length;) {
if (k > 0 && mj[i + j] == kan / k) {
j++;
kan %= k;
k /= 10;
continue;
}
newmj[i] = mj[i + j];
i++;
}
return newmj;
}

private int[] cutYan(int[] mj, int yan) {//去眼
int[] newmj = new int[mj.length - 2];
int i = 0, j = 0, k = 10;
for (i = 0; i < newmj.length;) {
if (k > 0 && mj[i + j] == yan / k) {
j++;
yan %= k;
k /= 10;
continue;
}
newmj[i] = mj[i + j];
i++;
}
return newmj;
}

private boolean gtFour(int[] mj, int m) {//判断一张牌m在mj中是否超过4次
int sum = 0;
for (int i = 0; i < mj.length; i++)
if (mj[i] == m)
sum++;
if (sum >= 4)
return true;
return false;
}

public static void main(String[] args) {

int[] mj = { 1, 2, 3, 3, 3, 3, 4 };
test9 test = new test9();
List<Integer> huList = test.callHu(mj);
for (Integer i : huList)
System.out.println(i.intValue());

}

}
--------------------编程问答--------------------
引用 24 楼 abc41106 的回复:
闲着没事写了一下,仅供参考


Java code
?



12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485……

不好意思,写错了一个地方。
可能还有错的地方,慎用!!
import java.util.ArrayList;
import java.util.List;

public class test9 {
public List<Integer> callHu(int[] mj) {
int n = mj.length;
if (n < 1 || n > 13 || n % 3 != 1) {
System.out.println("错牌");
return null;
}

List<Integer> huList = new ArrayList<Integer>();// 用来存放胡牌

if (n == 1) {// 如果只剩一张牌,一种情况,胡眼
huList.add(mj[0]);
return huList;
}

if (n == 4) {// 4张牌有两种情况,有眼胡砍,或者有砍胡眼
List<Integer> kan = findKan(mj);// 找出所有可能的砍;
for (Integer k : kan) {
int[] tempmj = cutKan(mj, k);// 去掉砍之后的牌
List<Integer> tempList = callHu(tempmj);// 递归
for (Integer i : tempList) {
if (gtFour(mj, i) || huList.contains(i))
continue;
huList.add(i);
}
}

List<Integer> yan = findYan(mj);// 找出所有可能的眼;
for (Integer y : yan) {
int[] tempmj = cutYan(mj, y);// 去掉眼之后的牌
if (tempmj[0] == tempmj[1]) {// 剩下是一个眼
if (!gtFour(mj, tempmj[0]) && !huList.contains(tempmj[0]))
huList.add(tempmj[0]);
}
if (tempmj[1] - tempmj[0] == 1) {// 剩下是两张连续的牌
int left = tempmj[0] - 1;
if (left >= 1 && !gtFour(mj, left)
&& !huList.contains(left))
huList.add(left);

int right = tempmj[1] + 1;
if (right <= 9 && !gtFour(mj, right)//这里应该是right,太粗心了。。。。
&& !huList.contains(right))
huList.add(right);
}
}
return huList;
}

// 其他情况,都可以通过抽出一个或多个砍变成4张牌的情况
List<Integer> kan = findKan(mj);
for (Integer k : kan) {
int[] tempmj = cutKan(mj, k);
List<Integer> tempList = callHu(tempmj);
for (Integer i : tempList) {
if (gtFour(mj, i) || huList.contains(i))
continue;
huList.add(i);
}
}

return huList;
}

private List<Integer> findKan(int[] mj) {// 找砍
List<Integer> kan = new ArrayList<Integer>();
for (int i = 0; i < mj.length - 2; i++)
for (int j = i + 1; j < mj.length - 1; j++)
for (int k = j + 1; k < mj.length; k++)
if ((mj[i] == mj[j] && mj[i] == mj[k])
|| (mj[j] - mj[i] == 1 && mj[k] - mj[j] == 1)) {
Integer value = mj[i] * 100 + mj[j] * 10 + mj[k];
if (!kan.contains(value))
kan.add(value);
}
return kan;
}

private List<Integer> findYan(int[] mj) {// 找眼
List<Integer> yan = new ArrayList<Integer>();
for (int i = 0; i < mj.length - 1; i++)
for (int j = i + 1; j < mj.length; j++)
if (mj[i] == mj[j]) {
Integer value = mj[i] * 10 + mj[j];
if (!yan.contains(value))
yan.add(value);
}
return yan;
}

private int[] cutKan(int[] mj, int kan) {// 去砍
int[] newmj = new int[mj.length - 3];
int i = 0, j = 0, k = 100;
for (i = 0; i < newmj.length;) {
if (k > 0 && mj[i + j] == kan / k) {
j++;
kan %= k;
k /= 10;
continue;
}
newmj[i] = mj[i + j];
i++;
}
return newmj;
}

private int[] cutYan(int[] mj, int yan) {// 去眼
int[] newmj = new int[mj.length - 2];
int i = 0, j = 0, k = 10;
for (i = 0; i < newmj.length;) {
if (k > 0 && mj[i + j] == yan / k) {
j++;
yan %= k;
k /= 10;
continue;
}
newmj[i] = mj[i + j];
i++;
}
return newmj;
}

private boolean gtFour(int[] mj, int m) {// 判断一张牌m在mj中是否超过4次
int sum = 0;
for (int i = 0; i < mj.length; i++)
if (mj[i] == m)
sum++;
if (sum >= 4)
return true;
return false;
}

public static void main(String[] args) {

int[] mj = { 1, 2, 3, 3, 3, 3, 4, 5, 6, 7, 7, 8, 9 };
test9 test = new test9();
List<Integer> huList = test.callHu(mj);
for (Integer i : huList)
System.out.println(i.intValue());

}

}
--------------------编程问答-------------------- 譬如剩下{2,3,6,6}
但是1,4都杠了···
然后呢····
--------------------编程问答-------------------- 对麻将的规则不是很熟悉,所以搞不懂
补充:Java ,  Java相关
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,