leetcode 1007. Minimum Domino Rotations For Equal Row(行相等的最少多米诺旋转)

博客探讨了如何通过交换骰子的上下两半以使得所有上半部分或下半部分的点数相同,给出了一种算法,该算法首先统计每个点数出现的次数,然后寻找能使得一行点数一致的可能,并计算最少的旋转次数。当无法达成目标时返回-1。示例展示了具体的应用和计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In a row of dominoes, tops[i] and bottoms[i] represent the top and bottom halves of the ith domino. (A domino is a tile with two numbers from 1 to 6 - one on each half of the tile.)

We may rotate the ith domino, so that tops[i] and bottoms[i] swap values.

Return the minimum number of rotations so that all the values in tops are the same, or all the values in bottoms are the same.

If it cannot be done, return -1.

Example 1:
Input: tops = [2,1,2,4,2,2], bottoms = [5,2,6,2,3,2]
Output: 2
Explanation:
The first figure represents the dominoes as given by tops and bottoms: before we do any rotations.
If we rotate the second and fourth dominoes, we can make every value in the top row equal to 2, as indicated by the second figure.
Example 2:

Input: tops = [3,5,1,2,3], bottoms = [3,6,3,3,4]
Output: -1
Explanation:
In this case, it is not possible to rotate the dominoes to make one row of values equal.

Constraints:

2 <= tops.length <= 2 * 104
bottoms.length == tops.length
1 <= tops[i], bottoms[i] <= 6

有上下两行骰子的点数,交换点数使上或下行的点数都一样,返回最少的交换次数,无法得到一行一样时返回-1。
上下行点数可以是一样的。

思路:
满足交换后整行点数一样的前提是,该点数出现在上下任一行的次数==tops的长度。
其中,上下两行都出现该点数时算一次。

因为点数只有1~6,可用一个数组保存每个点数出现过的次数(上下行都出现算一次)。
然后遍历这些次数,次数==tops的长度时认为可以达到条件。

最后要计算最小交换次数,
当上下两行出现一样的点数时不需要交换,那只需要看上下两行不一样的点数就行了,
比如
在这里插入图片描述
去掉最后一列点数一样的,点数2在上一行出现了3次,在下一行出现了2次。
显而易见最小交换次数是2次,也就是min(3, 2)。

用一个数组top存入每个点数在上一行出现的次数(上下行一样的不计入),
数组down存入每个点数在下一行出现的次数(上下行一样的不计入),它们中较小的就是需要交换的次数。

    public int minDominoRotations(int[] tops, int[] bottoms) {
        int[] cnt = new int[7];
        int[] top = new int[7];
        int[] down = new int[7];
        int result = 20000;
        int n = tops.length;
        
        for(int i = 0; i < n; i ++) {
            int id1 = tops[i];
            int id2 = bottoms[i];
            cnt[id1] ++;
            if(id1 != id2) {
                cnt[id2] ++;
                top[id1] ++;
                down[id2] ++;
            }
            
        }
        
        for(int i = 1; i <= 6; i ++) {
            if(cnt[i] == n) {
                int min = Math.min(top[i], down[i]);
                result = Math.min(result, min);
            }
        }
        return result == 20000 ? -1 : result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值