题目:扑克牌的顺子 从扑克牌中随机抽出5张牌,判断是不是一个顺子,即这五张牌是不是连续的。2——10为数字本身,A为1,J为11,Q为12,K为13,而大小王为任意数字。

题目:扑克牌的顺子
         从扑克牌中随机抽出5张牌,判断是不是一个顺子,即这五张牌是不是连续的。2——10为数字本身,A为1,J为11,Q为12,K为13,而大小王为任意数字。

算法分析:
我们需要把扑克牌的背景抽象成计算机语言。不难想象,我们可以把五张牌看成由五个数字组成的数组。大小王是特殊的数字,我们不妨把他们定义为0,这样就能和其他牌区分开来了。
接下来我们分析判断5个数字是不是连续的,最直观的方法是把数组排序。值得注意的是,由于0可以当成任意的数字,我们可以用0去补满数组中的空缺。如果排序之后的数组不是连续的,即相邻的两个数字像个若干个数字,但只要我们有足够的0可以补满这两个空缺的数字,这个数组实际上还是连续的。举个例子,数组排序之后为{0,1,3,4,5},在1和3之间空缺一个2,刚好我们有一个0,也就是我们可以把它当成2去填补这个空缺。
于是我们需要做3件事:首先把数组排序,再统计数组中0的个数,最后统计排序之后数组中相邻的数字之间的空缺总数。如果空缺综述小于或者等于0的个数,那么这个数组就是连续的;反之则不连续。
最后我们还需要注意一点:如果数组中的非0数字反复出现,则该数组不是连续的。换成扑克牌的描述方式就是如果一副牌里含有对子,则不可能是顺子。

算法源程序:
[java]  view plain  copy
  1. /**************************************************************       
  2. * Copyright (c) 2016,  
  3. * All rights reserved.                    
  4. * 版 本 号:v1.0                    
  5. * 题目描述:扑克牌的顺子 
  6. *            从扑克牌中随机抽出5张牌,判断是不是一个顺子,即这五张牌是不是连续的。2——10为数字本身, 
  7. *           A为1,J为11,Q为12,K为13,而大小王为任意数字。 
  8. * 输入描述:请输入五张牌: 
  9. *           0 0 3 4 7 
  10. * 程序输出: 这是一张顺子扑克牌 
  11. * 问题分析: 无 
  12. * 算法描述: 于是我们需要做3件事:首先把数组排序,再统计数组中0的个数,最后统计排序之后数组中相邻的数字之间的空缺总数。 
  13. *           如果空缺综述小于或者等于0的个数,那么这个数组就是连续的;反之则不连续。 
  14. * 完成日期:2016-09-27 
  15. ***************************************************************/  
  16. package org.marsguo.offerproject44;  
  17.   
  18. import java.util.Scanner;  
  19.   
  20. class SolutionMethod1{  
  21.       
  22. public void sortfun(int[] arrays,int start, int end){  
  23.         int numOfZero=0;  
  24.         if(start>=end){                              //判断数组的起始和终止是否相同,相同表示已经都全部排完,返回  
  25.             return;  
  26.         }  
  27.         int i = start;                              //i指向数组的起始位  
  28.         int j = end;                                //j指向数组的末位  
  29.         int key = arrays[i];                        //选取数组的第一位为关键字key,基准元素  
  30.         boolean flag = true;                        //设置标志位,用于判断是i++还是j--;这个很重要  
  31.         while(i != j){                              //如果i≠j,表示还没有比较完,即即关键字左右两侧还不是最小与最大  
  32.             if(flag){                     
  33.                 if(key>arrays[j]){                   //从后向前遍历,找到小于key的值,  
  34.                     swap(arrays,i,j);               //找到小于key的值后将arrays[i]与此值交换  
  35.                     flag = false;  
  36.                 }else{                              //如果没有找到的话j--,向前遍历  
  37.                     j--;  
  38.                 }  
  39.             }else{                                
  40.                 if(key<arrays[i]){                   //从前向后遍历,找到大于key的值  
  41.                     swap(arrays,i,j);               //将此值与arrays[j]进行交换  
  42.                     flag = true;  
  43.                 }else{                              //如果没有找到话就将i++,向后遍历  
  44.                     i++;  
  45.                 }  
  46.             }  
  47.         }  
  48.         //sprint(arrays);                               //打印每次排序后的数组  
  49.         sortfun(arrays,start,j-1);                  //递归调用,将基准元素的前半段数组再用此方法进行排序,直到所有都排完为止。  
  50.         sortfun(arrays,i+1,end);                    //递归调用,将基准元素的后半段数组再用此方法进行排序,直到所有都排完为止。  
  51.           
  52.         //System.out.println("排序后的数组是:");  
  53.         for(int k = 0; k < arrays.length; k++){  
  54.             if(arrays[k] == 0){  
  55.                 numOfZero++;  
  56.             }  
  57.             //System.out.print("numOfZero= " + numOfZero + ";"+arrays[k] + ", ");  
  58.             //System.out.print(arrays[k] + ", ");  
  59.         }  
  60.           
  61.         IsContinuousFun(arrays, numOfZero);  
  62.     }  
  63.     public void swap(int[] array,int i,int j){            
  64.         int temp;  
  65.         temp = array[i];  
  66.         array[i] = array[j];  
  67.         array[j] = temp;  
  68.     }  
  69.       
  70.     public void IsContinuousFun(int[] array,int numOfZero){  
  71.         int numOfGap = 0;               //判断数字中间空了多少个0  
  72.         //System.out.println("numberOfZero = " + numOfZero);  
  73.         for(int j = 1; j < array.length; j++){  
  74.             int flag = array[j] - array[j-1];       //用排序数组中后一个数字-前一个数字  
  75.             if(array[j] == array[j-1] && array[j] != 0){        //如果数组中有重复的非0数字,则不是顺子,退出  
  76.                 System.out.println("有重复数字,不是顺子牌");  
  77.                 return;  
  78.             }  
  79.             else if(flag != 1 && flag != 0 && array[j-1] != 0){         //判断不是连续的数字,也不是0,  
  80.                 numOfGap += flag-1;                                 //非0数字间缺少的数字的个数  
  81.             }  
  82.         }  
  83.         if(numOfZero != numOfGap){  
  84.             System.out.println("这不是一个顺子扑克牌");  
  85.         }  
  86.         else{  
  87.             System.out.println("这是一张顺子扑克牌");  
  88.         }  
  89.     }  
  90.       
  91.       
  92. }  
  93. public class IsContinuous {  
  94.     public static void main(String[] args){  
  95.         Scanner scanner = new Scanner(System.in);                       //扫描键盘输入  
  96.         System.out.println("请输入五张牌:");  
  97.         String str = scanner.nextLine();                                //将键盘输入转化为字符串  
  98.         String[] temp = str.split(" ");                                 //将字符串用“ ”分开转化为字符串数组  
  99.         scanner.close();  
  100.         int[] array = new int[temp.length];                             //定义一个整型数组array  
  101.         for(int i = 0; i< temp.length; i++){                         //将字符串数组强制转化为整型数组  
  102.             array[i] = Integer.parseInt(temp[i]);                       //这种方法非常巧妙  
  103.         }  
  104.           
  105.         SolutionMethod1 solution1 = new SolutionMethod1();  
  106.         //solution1.quicksort(array, 0, array.length-1);  
  107.         solution1.sortfun(array, 0, array.length-1);  
  108.     }  
  109. }  
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值