算法初探LeetCode-行相等的最少多米诺旋转

159 阅读1分钟

LeetCode1007. 行相等的最少多米诺旋转

在一排多米诺骨牌中,tops[i] 和 bottoms[i] 分别代表第 i 个多米诺骨牌的上半部分和下半部分。(一个多米诺是两个从 1 到 6 的数字同列平铺形成的 —— 该平铺的每一半上都有一个数字。)

我们可以旋转第 i 张多米诺,使得 tops[i] 和 bottoms[i] 的值交换。

返回能使 tops 中所有值或者 bottoms 中所有值都相同的最小旋转次数。

如果无法做到,返回 -1.

示例 1:

输入: tops = [2,1,2,4,2,2], bottoms = [5,2,6,2,3,2]
输出: 2
解释: 
图一表示:在我们旋转之前, tops 和 bottoms 给出的多米诺牌。 
如果我们旋转第二个和第四个多米诺骨牌,我们可以使上面一行中的每个值都等于 2,如图二所示。 

示例 2:

输入: tops = [3,5,1,2,3], bottoms = [3,6,3,3,4]
输出: -1
解释: 在这种情况下,不可能旋转多米诺牌使一行的值相等。

提示:

  • 2<=tops.length<=21042 <= tops.length <= 2 * 10^4
  • bottoms.length == tops.length
  • 1 <= tops[i], bottoms[i] <= 6

思路分析

翻转 a = 以第一排为主,翻转 不能反转的返回Integer.MAX_VALUE 如果可以翻转 把第一排的数字放入第二排 看是否可以翻转 对比两次那个小 返回 b = 以第二排为主,翻转 不能反转的返回Integer.MAX_VALUE 如果可以翻转 把第一排的数字放入第一排 看是否可以翻转 对比两次那个小 返回

用最少的旋转次数,使A或B的数字一样 首先要使A或B数字一样,那么这个数字的数量必须大于等于A或B(A和B长度是一样的),即大于等于总长度的一半,然后,必须每一列都包含这个数字(假设为X),这两个条件都满足,说明可以达成目标 最小的旋转次数就是往A旋转还是往B旋转,遍历A和B的每列,只要不等于X,那么就需要旋转一次

算法代码

public int minDominoRotations(int[] A, int[] B) {
    int[] countArr = new int[7];

    for (int a: A) {
        countArr[a] ++;
    }
    for (int b: B) {
        countArr[b] ++;
    }
    int num = -1;
    //找到数量最多的数字,如果这个数字大于等于A的长度,就是最多的(已经超过总数量的一半了)
    for (int i = 0; i < countArr.length; i++) {
        if (countArr[i] >= A.length) {
            num = i;
            break;
        }
    }
    if (num == -1) {
        return -1;
    }
    int counta = 0;
    int countb = 0;
    //计算A和B数组各自需要旋转的次数
    for (int i = 0; i < A.length; i++) {
        if (A[i] != num && B[i] != num) {
            return -1;
        }
        if (A[i] == num && B[i] != num) {
            countb++;
        } else if (A[i] != num && B[i] == num) {
            counta++;
        }

    }

    //返回最小值即可
    return counta < countb ? counta : countb;

}

结果详情

Snipaste_2023-06-02_22-44-46.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!