782. Transform to Chessboard
Дана бинарная сетка размером n x n. В каждом ходе можно поменять местами любые две строки или любые два столбца.
return минимальное количество ходов, чтобы преобразовать сетку в шахматную доску. Если Aufgabe невыполнима, return -1.
Шахматная доска — это доска, на которой ни один 0 и ни одна 1 не соприкасаются друг с другом по вертикали и горизонтали.
Beispiel:
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# Lösung
zugeordnet/originalusing 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++ Lösung
Auto-Entwurf, vor dem Einreichen prüfen#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 Lösung
Auto-Entwurf, vor dem Einreichen prüfenimport 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 Lösung
zugeordnet/originalclass 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 Lösung
zugeordnet/originalpackage 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 минимальное количество перестановок, чтобы преобразовать эту линию в её идеальную и добавьте это к ответу. НаBeispiel, [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ы.
😎
Stellen zu dieser Aufgabe
aktive Stellen with overlapping task tags are angezeigt.