1. 程式人生 > >【劍指offer】:撲克牌的順序

【劍指offer】:撲克牌的順序

題目:從撲克牌中隨機抽取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。