剑指Offer面试题44:扑克牌的顺子 Java实现

本文介绍了一种判断五张扑克牌是否构成顺子的算法。通过排序、统计大小王数量及非0数字间的空缺来判断连续性,并确保没有重复的非0数字。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:扑克牌的顺子
         从扑克牌中随机抽出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数字反复出现,则该数组不是连续的。换成扑克牌的描述方式就是如果一副牌里含有对子,则不可能是顺子。

算法源程序:
/**************************************************************      
* Copyright (c) 2016, 
* All rights reserved.                   
* 版 本 号:v1.0                   
* 题目描述:扑克牌的顺子
* 			 从扑克牌中随机抽出5张牌,判断是不是一个顺子,即这五张牌是不是连续的。2——10为数字本身,
* 			A为1,J为11,Q为12,K为13,而大小王为任意数字。
* 输入描述:请输入五张牌:
*			0 0 3 4 7
* 程序输出: 这是一张顺子扑克牌
* 问题分析: 无
* 算法描述: 于是我们需要做3件事:首先把数组排序,再统计数组中0的个数,最后统计排序之后数组中相邻的数字之间的空缺总数。
* 			如果空缺综述小于或者等于0的个数,那么这个数组就是连续的;反之则不连续。
* 完成日期:2016-09-27
***************************************************************/
package org.marsguo.offerproject44;

import java.util.Scanner;

class SolutionMethod1{
	
public void sortfun(int[] arrays,int start, int end){
		int numOfZero=0;
		if(start>=end){								//判断数组的起始和终止是否相同,相同表示已经都全部排完,返回
			return;
		}
		int i = start;								//i指向数组的起始位
		int j = end;								//j指向数组的末位
		int key = arrays[i];						//选取数组的第一位为关键字key,基准元素
		boolean flag = true;						//设置标志位,用于判断是i++还是j--;这个很重要
		while(i != j){								//如果i≠j,表示还没有比较完,即即关键字左右两侧还不是最小与最大
			if(flag){					
				if(key>arrays[j]){					//从后向前遍历,找到小于key的值,
					swap(arrays,i,j);				//找到小于key的值后将arrays[i]与此值交换
					flag = false;
				}else{								//如果没有找到的话j--,向前遍历
					j--;
				}
			}else{								
				if(key<arrays[i]){					//从前向后遍历,找到大于key的值
					swap(arrays,i,j);				//将此值与arrays[j]进行交换
					flag = true;
				}else{								//如果没有找到话就将i++,向后遍历
					i++;
				}
			}
		}
		//sprint(arrays);								//打印每次排序后的数组
		sortfun(arrays,start,j-1);					//递归调用,将基准元素的前半段数组再用此方法进行排序,直到所有都排完为止。
		sortfun(arrays,i+1,end);					//递归调用,将基准元素的后半段数组再用此方法进行排序,直到所有都排完为止。
		
		//System.out.println("排序后的数组是:");
		for(int k = 0; k < arrays.length; k++){
			if(arrays[k] == 0){
				numOfZero++;
			}
			//System.out.print("numOfZero= " + numOfZero + ";"+arrays[k] + ", ");
			//System.out.print(arrays[k] + ", ");
		}
		
		IsContinuousFun(arrays, numOfZero);
	}
	public void swap(int[] array,int i,int j){			
		int temp;
		temp = array[i];
		array[i] = array[j];
		array[j] = temp;
	}
	
	public void IsContinuousFun(int[] array,int numOfZero){
		int numOfGap = 0;				//判断数字中间空了多少个0
		//System.out.println("numberOfZero = " + numOfZero);
		for(int j = 1; j < array.length; j++){
			int flag = array[j] - array[j-1];		//用排序数组中后一个数字-前一个数字
			if(array[j] == array[j-1] && array[j] != 0){		//如果数组中有重复的非0数字,则不是顺子,退出
				System.out.println("有重复数字,不是顺子牌");
				return;
			}
			else if(flag != 1 && flag != 0 && array[j-1] != 0){			//判断不是连续的数字,也不是0,
				numOfGap += flag-1; 								//非0数字间缺少的数字的个数
			}
		}
		if(numOfZero != numOfGap){
			System.out.println("这不是一个顺子扑克牌");
		}
		else{
			System.out.println("这是一张顺子扑克牌");
		}
	}
	
	
}
public class IsContinuous {
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);						//扫描键盘输入
		System.out.println("请输入五张牌:");
		String str = scanner.nextLine();								//将键盘输入转化为字符串
		String[] temp = str.split(" ");									//将字符串用“ ”分开转化为字符串数组
		scanner.close();
		int[] array = new int[temp.length];								//定义一个整型数组array
		for(int i = 0; i< temp.length; i++){							//将字符串数组强制转化为整型数组
			array[i] = Integer.parseInt(temp[i]);						//这种方法非常巧妙
		}
		
		SolutionMethod1 solution1 = new SolutionMethod1();
		//solution1.quicksort(array, 0, array.length-1);
		solution1.sortfun(array, 0, array.length-1);
	}
}

程序运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值