【C语言刷LeetCode】822 翻转卡片游戏(M)

在桌子上有 N 张卡片,每张卡片的正面和背面都写着一个正数(正面与背面上的数有可能不一样)。

我们可以先翻转任意张卡片,然后选择其中一张卡片。

如果选中的那张卡片背面的数字 X 与任意一张卡片的正面的数字都不同,那么这个数字是我们想要的数字。

哪个数是这些想要的数字中最小的数(找到这些数中的最小值)呢?如果没有一个数字符合要求的,输出 0。

其中, fronts[i] 和 backs[i] 分别代表第 i 张卡片的正面和背面的数字。

如果我们通过翻转卡片来交换正面与背面上的数,那么当初在正面的数就变成背面的数,背面的数就变成正面的数。

示例:

输入:fronts = [1,2,4,4,7], backs = [1,3,4,1,3]
输出:2
解释:假设我们翻转第二张卡片,那么在正面的数变成了 [1,3,4,4,7] , 背面的数变成了 [1,2,4,1,3]。
接着我们选择第二张卡片,因为现在该卡片的背面的数是 2,2 与任意卡片上正面的数都不同,所以 2 就是我们想要的数字。
 

提示:

1 <= fronts.length == backs.length <= 1000
1 <= fronts[i] <= 2000
1 <= backs[i] <= 2000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/card-flipping-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1)明确一个重要观念,双面一致的数字一定不是我们想要的数字
2)与上面相似但需要理解的,只要这个数字没有出现过双面一致,就是我们想要的数字之一
例子: //第一点很好理解,重点是第二点
1 2 7 3 2 2
1 3 2 2 6 3
把握住1已经不能取,2没有出现过双面一致
我们就可以想办法调换,把2全部盖在下面
1 3 7 3 6 3
1 2 2 2 2 2//这就实现了2最小

其他同理,只要不是双面一致,就能取到

注意点:
1. noselarr 可以排升序,如果x < noselarr[i],肯定不会有相等的,返回0
2. qsort 可以值排序前n个数

方法一如下:先找出哪些数字不能选,放入一个数组,然后遍历,把正面和反面可选择的放入一个数组,排序后最小的便是所需。

/*方法一 :三个for循环,两个qsort */
int Cmp(const void *a, const void *b)
{
    return *(int *)a - *(int *)b;
}

int Innosel(int x, int *noselarr, int size)
{
    int i;

    for (i = 0; i < size; i++) {
        if (x == noselarr[i]) {
            return 1;
        } else if (x < noselarr[i]) {
            return 0;
        }
    }

    return 0;
}

int flipgame(int* fronts, int frontsSize, int* backs, int backsSize){
    int i;
    int min = INT_MAX;
    int *noselarr = malloc(sizeof(int) * frontsSize);
    int noidx = 0;
    int selarr[frontsSize * 2];
    int sidx = 0;

    memset(noselarr, 0, sizeof(int) * frontsSize);

    for (i = 0; i < frontsSize * 2; i++) {
        selarr[i] = INT_MAX;
    }

    for (i = 0; i < frontsSize; i++) {
        if (fronts[i] == backs[i]) {
            noselarr[noidx++] = fronts[i];
        }
    }

    qsort(noselarr, noidx, sizeof(int), Cmp);

    for (i = 0; i < frontsSize; i++) {
        if (Innosel(fronts[i], noselarr, frontsSize) == 0) {
            selarr[sidx++] = fronts[i];
        }

        if (Innosel(backs[i], noselarr, frontsSize) == 0) {
            selarr[sidx++] = backs[i];
        } 
    }

    if (sidx == 0) {
        return 0;
    }

    qsort(selarr, sidx, sizeof(int), Cmp);

    return selarr[0];
}

方法二:

我们发现最大值只有2000,那么可以用哈希,代码会更少些

/* 方法二: */
int flipgame(int* fronts, int frontsSize, int* backs, int backsSize){
    int i;
    int hash[2001] = {0}; // 最大值只有 2000

    for (i = 0; i < frontsSize; i++) {
        if (fronts[i] == backs[i]) { // 正反面相等赋值为 -1,不可能是返回值
            hash[fronts[i]] = -1;
            continue;
        }

        if (hash[fronts[i]] == 0) { // 如果这个数之前没出现过,那么赋值1表示已经出现了
            hash[fronts[i]] = 1; 
        } 

        if (hash[backs[i]] == 0) { // 反面数也需要考虑
            hash[backs[i]] = 1;
        }
    }

    for (i = 0; i < 2001; i++) { // 遍历已出现过的数,如果存在就是这个数了
        if (hash[i] == 1) {
            return i;
        }
    }


    return 0;
}

你可能感兴趣的:(LeetCode,leetcode)