【剑指offer】第六十一题(扑克牌中的顺子) 和 第六十二题(圆圈中最后剩下的数字)

第六十一题:扑克牌中的顺子

题目:从扑克牌中随机抽取 5 张牌,判断是不是一个顺子,即这张牌是不是连续的。2 ~ 10 为数字本身, A 为 1,J 为 11,Q 为 12,K 为 13,而大、小王也可以看成任意数字。

解题程序:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<list>
using namespace std;

int compare(const void *arg1,const void *arg2)
{
    return *(int*)arg1 - *(int*)arg2;
}

bool isContinuous(int *numbers,int length)
{
    if( numbers == NULL || length <1 )
        return false;

    // 先把数组排序
    qsort(numbers,length,sizeof(int),compare);
   
    int numberOfZero = 0;
    int numberOfGap = 0;

    // 统计数组中 0 的个数
    for(int i =0;i<length && numbers[i] == 0;i++)
        numberOfZero++;
   
    // 统计数组中空缺总数
    int small = numberOfZero;
    int big = small+1;

    // 统计排序后的相邻数字之间的空缺总数
    while(big<length)
    {
       // 两个数字不相等,有对子,不可能是顺序
        if(numbers[small] == numbers[big])
            return false;

        numberOfGap += numbers[big] - numbers[small] - 1;
        small = big;
        big++;
    }

    return (numberOfGap>numberOfZero) ? false : true;
}


// 测试用例:

void test()
{
    int num1[] = {1,3,2,5,4}; 
    if(isContinuous(num1,5))
        printf("num1 中的五张扑克牌是连续的!\n");
    else
        printf("num1 中的五张扑克牌是不连续的!\n");

    int num2[] = {1,3,2,6,4};
    if(isContinuous(num2,5))
         printf("num2 中的五张扑克牌是连续的!\n");
    else
       printf("numk 中的五张扑克牌是不连续的!\n");

    int num3[] = {0,3,2,6,4};
    if(isContinuous(num3,5))
        printf("num2 中的五张扑克牌是连续的!\n");
    else
        printf("num3 中的五张扑克牌是不连续的!\n");

    int num4[] = {0,3,1,6,4};
    if(isContinuous(num4,5))
        printf("num4 中的五张扑克牌是连续的!\n");
    else
        printf("num4 中的五张扑克牌是不连续的!\n");

    int num5[] = {1,3,0,5,0};
    if(isContinuous(num5,5))
        printf("num5 中的五张扑克牌是连续的!\n");
    else
        printf("num5 中的五张扑克牌是不连续的!\n");

    int num6[] = {1,3,0,7,0};
    if(isContinuous(num6,5))
         printf("num6 中的五张扑克牌是连续的!\n");
    else
        printf("num6 中的五张扑克牌是不连续的!\n");
}

int main(void)
{
    test();
    return 0;
}

第六十二题:圆圈中最后剩下的数字

题目:0,1,2,3,4,....... ,n - 1 这 n 个数字排成一个圆圈,从数字 0 开始,每次从这个圆圈里删除第 m 个数字。求出这个圈里剩下的最后一个数字。

解题程序:

include<iostream>
#include<stdio.h>
#include<list>
using namespace std;

// 经典解法,用环形链表模拟

int LastRemaining(unsigned int n,unsigned int m)
{
    if(n<1||m<1) 
        return -1;
    unsigned int i = 0;

    list<int> numbers;

    for(i=0;i<n;i++)
        numbers.push_back(i);

    list<int>::iterator current = numbers.begin();
    while(numbers.size()>1)
    {
       for( i =1;i<m;i++ )
        {
            current++;
            if( current == numbers.end() )
                current = numbers.begin();
        }
        
        list<int>::iterator next = ++current;
        if(next == numbers.end())
            next = numbers.begin();

        --current;
        numbers.erase(current);
        current = next;
    }
    return *current;
}

// 创新的解法

int LastRemaining1(int n,int m)
{
    if(n<1||m<1)
        return -1;
    int last = 0;
    for(int i =2;i<=n;i++)
        last = (last+m) % i;
    return last;
}


// 测试用例:

void test()
{
    int n,m;
    printf("请输入数字 n 和 m :\n");
    scanf("%d%d",&n,&m);

    printf("解法一:\n");
    int ret = LastRemaining(n,m);
    if( ret == -1 )
        printf("输入有误!\n");
    else
        printf("最后一个数字是:%d\n",ret);

    printf("解法二:\n");
    ret = LastRemaining1(n,m);
    if( ret == -1 )
        printf("输入有误!\n");
    else
        printf("最后一个数字是:%d\n",ret);


}

int main(void)
{
    test();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35396127/article/details/80017249