java输出一副扑克牌_Day45:扑克牌顺子

java输出一副扑克牌_Day45:扑克牌顺子_第1张图片

剑指Offer_编程题——扑克牌顺子

题目描述:

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

具体要求:

时间限制: C/C++ 1秒,其他语言2秒
空间限制: C/C++32M,其他语言64M

具体实现:

思路一:

这个题可以先把整数数组排序,然后由于左端可能是大小王,所以右端开始往左判断。首尾各一个指针,当尾部指针的值比它左面的值恰好大1的情况下。不需要大小王,如果差值比1大的话,左端恰好有一个大小王的话,则把当前的尾部指针向后移一个位置。也就是用掉一个王,这样知道首尾指针相等的情况下,则该这幅牌就是顺子,如果不是顺子的话早就返回了。具体用java实现如下:

import java.util.*;
public class Solution{
      
   public boolean isContinuous(int []numbers){
      
     if(numbers.length <= 1)
        return false;
     Arrays.sort(numbers);
     int begin = 0;
     int end = numbers.length - 1;
     boolean flag = false;
     while(begin < end){
      
       if(numbers[end] - numbers[end - 1]  == 1)
          end--;
       else{
      
          if(numbers[begin] == 0){
      
             begin++;
             numbers[end]--;
           }else
             break;
         }
      }
      if(begin == end)
         return true;
      return flag;
   }
}

代码效果图如图所示:

java输出一副扑克牌_Day45:扑克牌顺子_第2张图片

思路二:

接下来给大家介绍一种判断五个数字是否为连续的经典方法。最直观的就是把数组排序。值得注意的是:由于0可以当做任意的数字,我们可以用0区补充数组的空缺,如果排序之后的数组不是连续的。即相邻的两个数字相隔若干个数字,但只要我们有足够的0可以补满这两个数字的空缺,这个数字实际上还是连续的。例如:数组排序之后为{0,1,3,4,5},在1和3之间空缺了一个2,刚好我们有一个0,也就是我们可以把它当成2去填补这个空缺。因此我们还需要做以下几件是事:首先把数组排序,在统计数组中0的个数,最后统计排序之后的数组中相邻数字之间的空缺总数。如果空缺的总数小于或者等于0的个数,那么这个数组就是连续的,反之则不连续。另外,我们需要注意的是,如果数组中的非0数字重复出现,则该数组不是连续的。换成扑克牌的描述方式就是如果一副牌里含有对子,则肯定不是顺子。具体我们用java以及python两种语言将其实现:

1、首先我们用java实现以上思路:

import java.util.Arrays;
public class Solution{
      
  public boolean isContinuous(int []numbers){
      
      if(numbers == null || numbers.length == 0)
        return false;
      Arrays.sort(numbers);
      int numberOfZero = 0;
      int numberOfGap = 0;
      for(int i = 0; i < numbers.length && numbers[i] == 0; i++){
      
          numberOfZero++;
      }
      int low = numberOfZero;
      int high = low + 1;
      while(high < numbers.length){
      
         if(numbers[low] == numbers[high])
           return false;
         numberOfGap += numbers[high]- numbers[low] - 1;
         low = high;
         high++; 
       }
       return numberOfGap <= numberOfZero ? true:false;
   }
}

代码效果图如图所示:

java输出一副扑克牌_Day45:扑克牌顺子_第3张图片

2、接下来我们用python将其实现:

class Solution:
    def IsContinuous(self, numbers):
        if not numbers:
            return False
        numbers.sort()
        zeros = numbers.count(0)
        gaps = 0
        small = zeros
        big = small + 1
        while big < len(numbers):
            if numbers[small] == numbers[big]:
                return False
            gaps += numbers[big] - numbers[small] - 1
            small = big
            big += 1
        return gaps <= zeros

代码效果图如图所示:

java输出一副扑克牌_Day45:扑克牌顺子_第4张图片

在这里需要注意的是:代码中为什么是numbers[big] - numbers[small] - 1。因为0是来填补空缺的,如果空缺是1则不用填补。这个做法是我们看出不等于1的空缺有多少。

思路三:

在以上思路的基础上,我们首先对排序数组,然后统计数组中0的个数,最后就是统计排序后数组中相邻数字之间的空缺总数。如果空缺的总数小于或者等于0的个数,那么数组就是连续的,反之不连续。接下来我们用python将其实现:

class Solution:
    def IsContinuous(self, numbers):
        if not numbers:
            return False
        numbers.sort()
        zeros = 0
        pre = None
        for num in numbers:
            if num == 0:
                zeros += 1
            if not pre:
                pre = num
            elif num == pre:
                return False
            else:
                diff = num - pre - 1
                zeros -= diff
                pre =num
            if zeros < 0:
                return False
        return True

代码效果图如图所示:

java输出一副扑克牌_Day45:扑克牌顺子_第5张图片

思路四:

统计数组中最大值和最小值,0的个数和非0数字的个数。如果最大值和最小值之间的空位可以被0和剩余非0数字填满,则数组是连续的,否则不连续。我们用python将其实现:

class Solution:
    def IsContinuous(self, numbers):
        if not numbers:
            return False
        zeros, maxi, mini = 0, -1, 14
        counts = 0
        exist = set()
        for num in numbers:
            if num == 0:
                zeros += 1
                continue
            if num in exist:
                return False
            if num > maxi:
                maxi = num
            if num < mini:
                mini = num
            counts += 1
            exist.add(num)
        return maxi - mini + 1 - counts <= zeros

代码效果图如图所示:

java输出一副扑克牌_Day45:扑克牌顺子_第6张图片

总结

本道题通过与上一道题类似,均是通过实际问题来考察我们对字符串的理解,我们对本题给出了四种解题思路,均分别用java和python将其实现。首先就是正常的思路解题。其次给大家介绍了一种很常用的思路。最后是统计数组中最大值和最小值,0的个数和非0数字的个数。如果最大值和最小值之间的空位可以被0和剩余非0数字填满,则数组是连续的,否则不连续。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1]扑克牌顺子

[2]qq_27668313

[3]负雪明烛

你可能感兴趣的:(java输出一副扑克牌)