剑指offer——扑克牌顺子(思路,bitmap思想,位运算)

来源:互联网 发布:aipc 性能测试 知乎 编辑:程序博客网 时间:2024/05/22 06:49

题目描述
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的运气如何。为了方便起见,你可以认为大小王是0。

思路:
输入是一个int数组,需要判断这个数组的数能否凑成顺子,其中大小王可以代替任何数。
可以先将数组内的数排序,然后计算相邻数字间的差值。除了大小王(为0)之外,其他相邻数之间不能相等。其次,每两个相邻数之间的差值减1,求和后不能大于数组中大小王的个数。否则就凑不成顺子。

重做此题得到思路,除去大小王(为0的数字),剩下的数字的最大最小值之间相差<=4,就能保证得到顺子(5张牌的情况下),也就是利用bitmap那个思路的判定方法

后期总结:顺子产生的条件至少是5张。看测试用例好像固定就是5张。 然后测试用例有5个0的例子,我并没有特别去考虑全是王的情况,但思路中已经对此作出正确的判定。


public class Solution {    public boolean isContinuous(int [] numbers) {        if(numbers==null||numbers.length==0)            return false;        quickSort(numbers,0,numbers.length-1);        int king = 0;        int i = 0;        boolean result = true;        for(; i<numbers.length; i++){            if(numbers[i]==0)                king++;            else                break; // 这个break很重要,定位第一个非0的牌所在位        }        for(; i<numbers.length-1; i++){            king -= numbers[i+1]-numbers[i]-1; // 这一步一开始放在了if语句的后面,则对于{1,3,2,4,6}这个数组,判断了if语句后,没有马上判断King,下一步就直接越界跳出,所以king小于0的结果没有判断到            if(numbers[i+1]==numbers[i]||king<0){                result = false;                break;            }        }        return result;    }    public void quickSort(int[] numbers, int start, int end){        if(start>=end)            return;        int lo = start;        int hi = end;        int flag = numbers[end];                while(lo<hi){            while(lo<hi&&numbers[lo]<=flag)                lo++;            int temp = numbers[lo];            numbers[lo] = numbers[hi];            numbers[hi] = temp;            while(lo<hi&&numbers[hi]>=flag)                hi--;            temp = numbers[lo];            numbers[lo] = numbers[hi];            numbers[hi] = temp;        }        quickSort(numbers,start,lo-1); //一开始把上界写成了lo,导致一直循环以致溢出        quickSort(numbers,lo+1,end);    }}

bitmap排序:
来看一个具体的例子,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复)。那么我们就可以采用Bit-map的方法来达到排序的目的。要表示8个数,我们就只需要8个Bit(1Bytes),首先我们开辟1Byte的空间,将这些空间的所有Bit位都置为0 然后遍历这5个元素,首先第一个元素是4,那么就把4对应的位置为1(可以这样操作 p+(i/8)|(0×01<<(i%8)) 当然了这里的操作涉及到Big-ending和Little-ending的情况,这里默认为Big-ending),因为是从零开始的,所以要把第五位置为1。 然后再处理第二个元素7,将第八位置为1,,接着再处理第三个元素,一直到最后处理完所有的元素,将相应的位置为1。 然后我们现在遍历一遍Bit区域,将该位是一的位的编号输出(2,3,4,5,7),这样就达到了排序的目的。 其实就是把计数排序用的统计数组的每个单位缩小成bit级别的布尔数组

必须满足两个条件   1.0外没有重复的数   2. max - min < 5   3. 牌只有5张public class Solution {    public boolean isContinuous(int [] numbers) {        if(numbers.length != 5) return false;        int min = 14;        int max = -1;        int flag = 0;        for(int i = 0; i < numbers.length; i++) {            int number = numbers[i];            if(number < 0 || number > 13) return false;            if(number == 0) continue;            if(((flag >> number) & 1) == 1) return false; //用二进制位来判断是否有数字重复            flag |= (1 << number);  // 将对应位用或的方法设为1            if(number > max) max = number;            if(number < min) min = number;            if(max - min >= 5) return false;        }        return true;    }}
原创粉丝点击