LeetCode 5477. 排布二进制网格的最少交换次数(第200场周赛第3题)

目录结构

1.题目

2.题解


1.题目

给你一个 n x n 的二进制网格 grid,每一次操作中,你可以选择网格的 相邻两行 进行交换。

一个符合要求的网格需要满足主对角线以上的格子全部都是 0 。

请你返回使网格满足要求的最少操作次数,如果无法使网格符合要求,请你返回 -1 。

主对角线指的是从 (1, 1) 到 (n, n) 的这些格子。

示例:

输入:grid = [[0,0,1],[1,1,0],[1,0,0]]
输出:3

 

输入:grid = [[0,1,1,0],[0,1,1,0],[0,1,1,0],[0,1,1,0]]
输出:-1
解释:所有行都是一样的,交换相邻行无法使网格符合要求。

 

输入:grid = [[1,0,0],[1,1,0],[1,1,1]]
输出:0

提示:

扫描二维码关注公众号,回复: 11526779 查看本文章
  • n == grid.length
  • n == grid[i].length
  • 1 <= n <= 200
  • grid[i][j] 要么是 0 要么是 1 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-swaps-to-arrange-a-binary-grid
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.题解

根据题设,若只看主对角线以上的格子,则最终网格要求每一行0的个数由n递减到0。故算法步骤如下:

  • 首先计算每一行从右至左连续0的个数,得到数组num,size大小为n;
  • 然后检查num中每个数字,替换重复数值为比其小的并且数组中不存在的数字;
  • 最后,检查num中是否n~0均出现,均出现则通过冒泡排序进行降序排列,计算交换次数返回;否则返回-1。
public class Solution5477 {

    @Test
    public void test5477() {
        // int[][] grid = {{0,0,0},{1,1,0},{1,0,0}};
        // int[][] grid = {{1,0,0,0,0,0},{0,0,0,1,0,0},{0,0,0,1,0,0},{0,1,0,0,0,0},{0,0,1,0,0,0},{0,0,0,0,0,1}};
        // int[][] grid = {{1,0,0,0,0,0},{0,1,0,1,0,0},{1,0,0,0,0,0},{1,1,1,0,0,0},{1,1,0,1,0,0},{1,0,0,0,0,0}};
        int[][] grid = {{0, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0}};
        // int[][] grid = {{0,0},{0,1}};
        System.out.println(minSwaps(grid));
    }

    public int minSwaps(int[][] grid) {
        int len = grid.length;
        int[] num = new int[len];
        for (int i = 0; i < len; i++) {
            int count = 0;
            for (int j = len - 1; j >= 0; j--) {
                if (grid[i][j] == 0) {
                    count++;
                } else {
                    break;
                }
            }
            num[i] = count;
        }
        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < len; i++) {
            while (set.contains(num[i])) {
                num[i]--;
            }
            if (num[i] >= 0) {
                set.add(num[i]);
            }
        }
        if (set.size() != len) {
            return -1;
        }
        int count = 0;
        for (int i = 0; i < num.length; i++) {
            for (int j = 1; j < num.length - i; j++) {
                if (num[j - 1] < num[j]) {
                    int t = num[j - 1];
                    num[j - 1] = num[j];
                    num[j] = t;
                    count++;
                }
            }
        }
        return count;
    }
}
  • 时间复杂度:O(n^{2})
  • 空间复杂度:O(n)

猜你喜欢

转载自blog.csdn.net/HarvestWu/article/details/107744220