【劍指offer】:撲克牌的順序
阿新 • • 發佈:2018-12-09
題目:從撲克牌中隨機抽取5張牌,判斷是不是一個順子
,既這5張牌是不是連續的。2-10位數字本身
,A為1,J為11,Q為12,K為13
,大王和小王可以看出是任何數
。
解決思路:
- 1.把大王和小王看做是0
- 2.對所給序列進行排序
- 3.統計差值的個數(如果相鄰的兩個值差1,則差值為0,如果差大於1,則插入為n-1)
- 4.統計0的個數
- 5.比較。如果差值的個數大於0,則必然不是順子,否則是順子
程式碼實現:
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//直接插入排序
int InsertSort(int *num, int len)
{
assert(num);
int i = 0;
//第一個元素已經為有序序列,所以要進行len-1次排序
for (; i < len - 1; i++)
{
int end = i;
int tmp = num[i + 1];//儲存非有序區間第一個元素,否則在後邊的移動中會改變
//比較後移
while (end >= 0 && num[end]>tmp)
{
num[end + 1] = num[end];
--end;
}
//插入到適當位置
num[end + 1] = tmp;
}
}
int Compare(const void* arg1, const void* arg2)
{
return *(int*)arg1 - *(int*)arg2;
}
//判斷是否為一個順子(是返回1,不是返回0)
int CheckContiuos(int *num, int len)
{
assert(num);
if (len <= 0)
return 0;
//1.排序
/*InsertSort(num, len);*/
//直接呼叫庫函式qsort(時間複雜度為O(nlogn))
qsort(num, len, sizeof(int), Compare);
//0代表大小王,可以隨意替換
int number_zero = 0;//記錄0的個數
//2.統計0的個數
for (int i = 0; i < len; i++)
{
if (num[i] == 0)
++number_zero;
}
//3.統計差值的個數
int number_gap = 0;//記錄差值的個數
int low = number_zero;//非0第一個值的下標
int high = low + 1;//low後邊那個值得下標,為了計算差值
while (high < len)
{
//如果存在對子,絕對不是對子
if (num[low] == num[high])
return 0;
//每個相鄰的數間隔1是正常的,多出來的就算差值
number_gap += num[high] - num[low] - 1;
low++;//繼續向後查詢
high++;
}
//差值的個數如果比0的個數多,則肯定不是順子
return (number_gap > number_zero) ? 0 : 1;
}
int main()
{
int num[] = { 1, 2, 3, 6, 6, 0, 0 };
int len = sizeof(num) / sizeof(num[0]);
int ret = CheckContiuos(num, len);
printf("%d\n", ret);
return 0;
}
注意:排序可以採用不同的做法,如果要效率高的話,也可以考慮用雜湊表做,上邊的程式碼是用的是插入排序和直接呼叫庫函式qsort。