782. Transform to Chessboard

O texto da tarefa é traduzido do russo para o idioma selecionado. O código permanece sem alterações.

Дана бинарная сетка размером n x n. В каждом ходе можно поменять местами любые две строки или любые два столбца.

return минимальное количество ходов, чтобы преобразовать сетку в шахматную доску. Если Tarefa невыполнима, return -1.

Шахматная доска — это доска, на которой ни один 0 и ни одна 1 не соприкасаются друг с другом по вертикали и горизонтали.

Exemplo:

Input: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]

Output: 2

Explanation: One potential sequence of moves is shown.

The first move swaps the first and second column.

The second move swaps the second and third row.

C# solução

correspondente/original
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
    public int MovesToChessboard(int[][] board) {
        int N = board.Length;
        int ans = 0;
        
        foreach (var count in new List<Dictionary<string, int>> { GetCount(board), GetCount(Transpose(board)) }) {
            if (count.Count != 2 || !new List<int>(count.Values).OrderBy(v => v).SequenceEqual(new List<int> { N / 2, (N + 1) / 2 })) {
                return -1;
            }
            var lines = count.Keys.ToList();
            string line1 = lines[0];
            string line2 = lines[1];
            if (!AllOpposite(line1, line2)) {
                return -1;
            }
            List<int> starts = N % 2 == 0 ? new List<int> { 0, 1 } : new List<int> { line1.Count(c => c == '1') * 2 > N ? 1 : 0 };
            ans += starts.Select(start => line1.Where((c, i) => (c - '0') != (i % 2 == start ? 1 : 0)).Count()).Min() / 2;
        }
        
        return ans;
    }
    private Dictionary<string, int> GetCount(int[][] board) {
        var count = new Dictionary<string, int>();
        foreach (var row in board) {
            var key = string.Join("", row);
            if (count.ContainsKey(key)) {
                count[key]++;
            } else {
                count[key] = 1;
            }
        }
        return count;
    }
    private int[][] Transpose(int[][] board) {
        int N = board.Length;
        var transposed = new int[N][];
        for (int i = 0; i < N; i++) {
            transposed[i] = new int[N];
            for (int j = 0; j < N; j++) {
                transposed[i][j] = board[j][i];
            }
        }
        return transposed;
    }
    private bool AllOpposite(string line1, string line2) {
        for (int i = 0; i < line1.Length; i++) {
            if ((line1[i] ^ line2[i]) == 0) {
                return false;
            }
        }
        return true;
    }
}

C++ solução

rascunho automático, revisar antes de enviar
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public int MovesToChessboard(int[][] board) {
        int N = board.size();
        int ans = 0;
        
        foreach (var count in new List<unordered_map<string, int>> { GetCount(board), GetCount(Transpose(board)) }) {
            if (count.size() != 2 || !new List<int>(count.Values).OrderBy(v => v).SequenceEqual(new List<int> { N / 2, (N + 1) / 2 })) {
                return -1;
            }
            var lines = count.Keys.ToList();
            string line1 = lines[0];
            string line2 = lines[1];
            if (!AllOpposite(line1, line2)) {
                return -1;
            }
            List<int> starts = N % 2 == 0 ? new List<int> { 0, 1 } : new List<int> { line1.size()(c => c == '1') * 2 > N ? 1 : 0 };
            ans += starts.Select(start => line1.Where((c, i) => (c - '0') != (i % 2 == start ? 1 : 0)).size()()).Min() / 2;
        }
        
        return ans;
    }
    private unordered_map<string, int> GetCount(int[][] board) {
        var count = new unordered_map<string, int>();
        foreach (var row in board) {
            var key = string.Join("", row);
            if (count.count(key)) {
                count[key]++;
            } else {
                count[key] = 1;
            }
        }
        return count;
    }
    private int[][] Transpose(int[][] board) {
        int N = board.size();
        var transposed = new int[N][];
        for (int i = 0; i < N; i++) {
            transposed[i] = new int[N];
            for (int j = 0; j < N; j++) {
                transposed[i][j] = board[j][i];
            }
        }
        return transposed;
    }
    private bool AllOpposite(string line1, string line2) {
        for (int i = 0; i < line1.size(); i++) {
            if ((line1[i] ^ line2[i]) == 0) {
                return false;
            }
        }
        return true;
    }
}

Java solução

rascunho automático, revisar antes de enviar
import java.util.*;
import java.math.*;

// Auto-generated Java draft from the C# solution. Review API differences before LeetCode submit.
public class Solution {
    public int MovesToChessboard(int[][] board) {
        int N = board.length;
        int ans = 0;
        
        foreach (var count in new List<HashMap<String, int>> { GetCount(board), GetCount(Transpose(board)) }) {
            if (count.size() != 2 || !new List<int>(count.Values).OrderBy(v => v).SequenceEqual(new List<int> { N / 2, (N + 1) / 2 })) {
                return -1;
            }
            var lines = count.Keys.ToList();
            String line1 = lines[0];
            String line2 = lines[1];
            if (!AllOpposite(line1, line2)) {
                return -1;
            }
            List<int> starts = N % 2 == 0 ? new List<int> { 0, 1 } : new List<int> { line1.size()(c => c == '1') * 2 > N ? 1 : 0 };
            ans += starts.Select(start => line1.Where((c, i) => (c - '0') != (i % 2 == start ? 1 : 0)).size()()).Min() / 2;
        }
        
        return ans;
    }
    private HashMap<String, int> GetCount(int[][] board) {
        var count = new HashMap<String, int>();
        foreach (var row in board) {
            var key = String.Join("", row);
            if (count.containsKey(key)) {
                count[key]++;
            } else {
                count[key] = 1;
            }
        }
        return count;
    }
    private int[][] Transpose(int[][] board) {
        int N = board.length;
        var transposed = new int[N][];
        for (int i = 0; i < N; i++) {
            transposed[i] = new int[N];
            for (int j = 0; j < N; j++) {
                transposed[i][j] = board[j][i];
            }
        }
        return transposed;
    }
    private boolean AllOpposite(String line1, String line2) {
        for (int i = 0; i < line1.length; i++) {
            if ((line1[i] ^ line2[i]) == 0) {
                return false;
            }
        }
        return true;
    }
}

JavaScript solução

correspondente/original
class Solution {
    movesToChessboard(board) {
        const N = board.length;
        let ans = 0;
        
        for (const count of [this.getCount(board), this.getCount(this.transpose(board))]) {
            const values = Object.values(count).sort((a, b) => a - b);
            if (values.length !== 2 || values[0] !== Math.floor(N / 2) || values[1] !== Math.floor((N + 1) / 2)) {
                return -1;
            }

            const [line1, line2] = Object.keys(count);
            if (!this.allOpposite(line1, line2)) {
                return -1;
            }

            const starts = N % 2 === 0 ? [0, 1] : [line1.split('1').length * 2 > N ? 1 : 0];
            
            ans += Math.min(...starts.map(start => {
                return line1.split('').reduce((sum, c, i) => sum + ((c - '0') !== (i % 2 === start ? 1 : 0)), 0);
            })) / 2;
        }
        
        return ans;
    }

    getCount(board) {
        const count = {};
        for (const row of board) {
            const key = row.join('');
            count[key] = (count[key] || 0) + 1;
        }
        return count;
    }

    transpose(board) {
        const N = board.length;
        const transposed = Array.from({ length: N }, () => Array(N).fill(0));
        for (let i = 0; i < N; i++) {
            for (let j = 0; j < N; j++) {
                transposed[j][i] = board[i][j];
            }
        }
        return transposed;
    }

    allOpposite(line1, line2) {
        for (let i = 0; i < line1.length; i++) {
            if ((line1[i] ^ line2[i]) === 0) {
                return false;
            }
        }
        return true;
    }
}

Go solução

correspondente/original
package main

import (
    "math"
    "sort"
    "strconv"
)

type Solution struct{}

func (Solution) movesToChessboard(board [][]int) int {
    N := len(board)
    ans := 0
    
    for _, count := range []map[string]int{getCount(board), getCount(transpose(board))} {
        if len(count) != 2 {
            return -1
        }

        values := make([]int, 0, len(count))
        for _, v := range count {
            values = append(values, v)
        }
        sort.Ints(values)
        if !equal(values, []int{N / 2, (N + 1) / 2}) {
            return -1
        }

        keys := make([]string, 0, len(count))
        for k := range count {
            keys = append(keys, k)
        }
        line1, line2 := keys[0], keys[1]
        if !allOpposite(line1, line2) {
            return -1
        }

        starts := []int{0, 1}
        if N%2 != 0 {
            starts = []int{boolToInt(countBits(line1)%2 == 1)}
        }

        minSwaps := math.MaxInt32
        for _, start := range starts {
            swaps := 0
            for i := 0; i < N; i++ {
                if int(line1[i]-'0') != i%2 {
                    swaps++
                }
            }
            minSwaps = min(minSwaps, swaps/2)
        }
        ans += minSwaps
    }
    
    return ans
}

func getCount(board [][]int) map[string]int {
    count := make(map[string]int)
    for _, row := range board {
        key := ""
        for _, v := range row {
            key += strconv.Itoa(v)
        }
        count[key]++
    }
    return count
}

func transpose(board [][]int) [][]int {
    N := len(board)
    transposed := make([][]int, N)
    for i := range transposed {
        transposed[i] = make([]int, N)
    }
    for i := 0; i < N; i++ {
        for j := 0; j < N; j++ {
            transposed[j][i] = board[i][j]
        }
    }
    return transposed
}

func allOpposite(line1, line2 string) bool {
    for i := range line1 {
        if (line1[i] ^ line2[i]) == 0 {
            return false
        }
    }
    return true
}

func equal(a, b []int) bool {
    if len(a) != len(b) {
        return false
    }
    for i := range a {
        if a[i] != b[i] {
            return false
        }
    }
    return true
}

func boolToInt(b bool) int {
    if b {
        return 1
    }
    return 0
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

Algorithm

Для каждого набора строк (и столбцов соответственно) убедитесь, что существует только 2 вида линий в правильных количествах, которые являются противоположностями друг друга.

Затем для каждой возможной идеальной трансформации этой линии find минимальное количество перестановок, чтобы преобразовать эту линию в её идеальную и добавьте это к ответу. НаExemplo, [0, 1, 1, 1, 0, 0] имеет два идеала [0, 1, 0, 1, 0, 1] или [1, 0, 1, 0, 1, 0]; но [0, 1, 1, 1, 0] имеет только один идеал [1, 0, 1, 0, 1].

В Java мы используем целые числа для представления строк как двоичных чисел. Мы проверяем количество различий с [1, 0, 1, 0, 1, 0, ...] с помощью побитового исключающего ИЛИ с 0b010101010101.....01 = 0x55555555. Чтобы убедиться, что мы не добавляем излишне большие elementы.

😎

Vacancies for this task

vagas ativas with overlapping task tags are mostradas.

Todas as vagas
Ainda não há vagas ativas.