位图(位集),0b 和 C# Convert.ToInt32("字符串", 2) 表示二进制数字,求解《782. 变为棋盘》

2022-08-23 20:05:35

位图(位集),0b 和 C#  Convert.ToInt32("字符串", 2) 表示二进制数字,求解《782. 变为棋盘》 

例题
### 782. 变为棋盘

一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置。
返回 将这个矩阵变为 “棋盘” 所需的最小移动次数 。如果不存在可行的变换,输出 -1。
“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。
示例 1:
782. 变为棋盘 示例 1 二维网络 [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]] 的表示
输入: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
输出: 2
解释:一种可行的变换方式如下,从左到右:
第一次移动交换了第一列和第二列。
第二次移动交换了第二行和第三行。
示例 2: 782. 变为棋盘 示例 2 二维网络 [[0, 1], [1, 0]] 的表示
输入: board = [[0, 1], [1, 0]] 输出: 0 解释: 注意左上角的格值为0时也是合法的棋盘,也是合法的棋盘. 示例 3: 782. 变为棋盘 示例 3 二维网络 [[1, 0], [1, 0]] 的表示
输入: board = [[1, 0], [1, 0]] 输出: -1 解释: 任意的变换都不能使这个输入变为合法的棋盘。

答案

位图(位集)

var movesToChessboard = function(board) {
  const n = board.length
  let firstRow = 0, firstCol = 0, firstRowCnt = 1, firstColCnt = 1
  for (let i = 0; i < n; i++) {
    firstRow |= board[0][i] << i
    firstCol |= board[i][0] << i
  }
  const firstRowReverse = ((1 << n) - 1) ^ firstRow, firstColReverse = ((1 << n) - 1) ^ firstCol
  for (let i = 1; i < n; i++) {
    let row = 0, col = 0
    for (let j = 0; j < n; j++) {
      row |= board[i][j] << j
      col |= board[j][i] << j
    }
    if (row !== firstRow && row !== firstRowReverse) return -1
    if (row === firstRow) firstRowCnt++
    if (col !== firstCol && col !== firstColReverse) return -1
    if (col === firstCol) firstColCnt++
  }
  if (Math.abs((firstRowCnt << 1) - n) > 1 || Math.abs((firstColCnt << 1) - n) > 1) return -1 
  return count(firstRow, n) + count(firstCol, n)
};
const count = (num, n) => {
  const b1 = 0b10101010101010101010101010101010, b2 = 0b01010101010101010101010101010101, oneNum = countOne(num)
  if (n & 1)  {
    if (oneNum === n >> 1) return oneNum - countOne(num & b1)
    return oneNum - countOne(num & b2)
  }
  return oneNum - Math.max(countOne(num & b1), countOne(num & b2))
}
const countOne = n => {
  let cnt = 0
  while (n) {
    n &= n - 1
    cnt++
  }
  return cnt
}
function movesToChessboard(board: number[][]): number {
  const n = board.length
  let firstRow = 0, firstCol = 0, firstRowCnt = 1, fristColCnt = 1
  for (let i = 0; i < n; i++) {
    firstRow |= board[0][i] << i
    firstCol |= board[i][0] << i
  }
  const firstRowReverse = ((1 << n) - 1) ^ firstRow, firstColReverse = ((1 << n) - 1) ^ firstCol
  for (let i = 1; i < n; i++) {
    let row = 0, col = 0
    for (let j = 0; j < n; j++) {
      row |= board[i][j] << j
      col |= board[j][i] << j
    }
    if (row === firstRow) firstRowCnt++
    else if (row !== firstRowReverse) return -1
    if (col === firstCol) fristColCnt++
    else if (col !== firstColReverse) return -1
  }
  if (Math.abs(firstRowCnt * 2 - n) > 1 || Math.abs(fristColCnt * 2 - n) > 1) return -1
  return count(firstRow, n) + count(firstCol, n) 
};
const count = (num: number, n: number): number => {
  const b0 = 0b10101010101010101010101010101010, b1 = 0b01010101010101010101010101010101, oneCnt = count1(num)
  if (n & 1) {
    if (oneCnt === n >> 1) return oneCnt - count1(num & b0)
    return oneCnt - count1(num & b1)
  }
  return oneCnt - Math.max(count1(num & b0), count1(num & b1))
}
const count1 = (n: number): number => {
  let r = 0
  while (n) {
    n &= n - 1
    r++
  }
  return r
}
class Solution {
  function movesToChessboard($board) {
    $n = count($board);
    $firstRow = 0;
    $firstCol = 0;
    $firstRowCnt = 1;
    $firstColCnt = 1;
    for ($i = 0; $i < $n; $i++) {
      $firstRow |= $board[0][$i] << $i;
      $firstCol |= $board[$i][0] << $i;
    }
    $firstRowReverse = ((1 << $n) - 1) ^ $firstRow;
    $firstColReverse = ((1 << $n) - 1) ^ $firstCol;
    for ($i = 1; $i < $n; $i++) {
      $row = 0;
      $col = 0;
      for ($j = 0; $j < $n; $j++) {
        $row |= $board[$i][$j] << $j;
        $col |= $board[$j][$i] << $j;
      }
      if ($row === $firstRow) $firstRowCnt++;
      elseif ($row !== $firstRowReverse) return -1;
      if ($col === $firstCol) $firstColCnt++;
      elseif ($col !== $firstColReverse) return -1;
    }
    if (abs($firstRowCnt * 2 - $n) > 1 || abs($firstColCnt * 2 - $n) > 1) return -1;
    return $this->count($firstRow, $n) + $this->count($firstCol, $n);
  }
  function count($num, $n) {
    $b0 = 0b10101010101010101010101010101010;
    $b1 = 0b01010101010101010101010101010101;
    $oneCnt = $this->count1($num);
    if ($n & 1) {
      if ($oneCnt === $n >> 1) return $oneCnt - $this->count1($num & $b0);
      return $oneCnt - $this->count1($num & $b1);
    }
    return $oneCnt - max($this->count1($num & $b0), $this->count1($num & $b1));
  }
  function count1($n) {
    $r = 0;
    while ($n) {
      $n &= $n - 1;
      $r++;
    }
    return $r;
  }
}
func movesToChessboard(board [][]int) int {
  n, firstRow, firstCol, firstRowCnt, firstColCnt := len(board), 0, 0, 1, 1
  for i := 0; i < n; i++  {
    firstRow |= board[0][i] << i
    firstCol |= board[i][0] << i
  }
  firstRowReverse, firstColReverse := (1 << n - 1) ^ firstRow, (1 << n - 1) ^ firstCol
  for i := 1; i < n; i++ {
    row, col := 0, 0
    for j := 0; j < n; j++ {
      row |= board[i][j] << j
      col |= board[j][i] << j
    }
    if row == firstRow {
      firstRowCnt++
    } else if row != firstRowReverse {
      return -1
    }
    if col == firstCol {
      firstColCnt++
    } else if col != firstColReverse {
      return -1
    }
  }
  if math.Abs(float64(firstRowCnt * 2 - n)) > 1 || math.Abs(float64(firstColCnt * 2 - n)) > 1 {
    return -1
  }
  return count(firstRow, n) + count(firstCol, n)
}
func count(num int, n int) int {
  b0, b1, oneCnt := 0b10101010101010101010101010101010, 0b01010101010101010101010101010101, count1(num)
  if n & 1 == 1 {
    if oneCnt == n >> 1 {
      return oneCnt - count1(num & b0)
    }
    return oneCnt - count1(num & b1)
  }
  return oneCnt - int(math.Max(float64(count1(num & b0)), float64(count1(num & b1))))
}
func count1(n int) int {
  r := 0
  for n > 0 {
    n &= n - 1
    r++
  }
  return r
}
class Solution {
  public int movesToChessboard(int[][] board) {
    int n = board.length, firstRow = 0, firstCol = 0, firstRowCnt = 1, firstColCnt = 1;
    for (int i = 0; i < n; i++) {
      firstRow |= board[0][i] << i;
      firstCol |= board[i][0] << i;
    }
    int firstRowReverse = ((1 << n) - 1) ^ firstRow, firstColReverse = ((1 << n) - 1) ^ firstCol;
    for (int i = 1; i < n; i++) {
      int row = 0, col = 0;
      for (int j = 0; j < n; j++) {
        row |= board[i][j] << j;
        col |= board[j][i] << j;
      }
      if (row == firstRow) firstRowCnt++;
      else if (row != firstRowReverse) return -1;
      if (col == firstCol) firstColCnt++;
      else if (col != firstColReverse) return -1;
    }
    if (Math.abs(firstRowCnt * 2 - n) > 1 || Math.abs(firstColCnt * 2 - n) > 1) return -1;
    return count(firstRow, n) + count(firstCol, n);
  }
  private int count(int num, int n) {
    int b0 = 0b10101010101010101010101010101010, b1 = 0b01010101010101010101010101010101, oneCnt = count1(num);
    if ((n & 1) == 1) { // java 和 c # 不能省略 ()
      if (oneCnt == n >> 1) return oneCnt - count1(num & b0);
      return oneCnt - count1(num & b1);
    }
    return oneCnt - Math.max(count1(num & b0), count1(num & b1));
  }
  private int count1(int n) {
    int r = 0;
    while (n > 0) {
      n &= n - 1;
      r++;
    }
    return r;
  }
}
public class Solution { // Convert.ToInt32("", 2)
  public int MovesToChessboard(int[][] board) {
    int n = board.Length, firstRow = 0, firstCol = 0, firstRowCnt = 1, firstColCnt = 1;
    for (int i = 0; i < n; i++) {
      firstRow |= board[0][i] << i;
      firstCol |= board[i][0] << i;
    }
    int firstRowReverse = ((1 << n) - 1) ^ firstRow, firstColReverse = ((1 << n) - 1) ^ firstCol;
    for (int i = 1; i < n; i++) {
      int row = 0, col = 0;
      for (int j = 0; j < n; j++) {
        row |= board[i][j] << j;
        col |= board[j][i] << j;
      }
      if (row == firstRow) firstRowCnt++;
      else if (row != firstRowReverse) return -1;
      if (col == firstCol) firstColCnt++;
      else if (col != firstColReverse) return -1;
    }
    if (Math.Abs(firstRowCnt * 2 - n) > 1 || Math.Abs(firstColCnt * 2 - n) > 1) return -1;
    return Count(firstRow, n) + Count(firstCol, n);
  }
  private int Count(int num, int n) {
    int b0 = Convert.ToInt32("10101010101010101010101010101010", 2), b1 = Convert.ToInt32("01010101010101010101010101010101", 2), oneCnt = Count1(num);
    if ((n & 1) == 1) { // java 和 c # 不能省略 ()
      if (oneCnt == n >> 1) return oneCnt - Count1(num & b0);
      return oneCnt - Count1(num & b1);
    }
    return oneCnt - Math.Max(Count1(num & b0), Count1(num & b1));
  }
  private int Count1(int n) {
    int r = 0;
    while (n > 0) {
      n &= n - 1;
      r++;
    }
    return r;
  }
}
public class Solution { // int -> uint
  public int MovesToChessboard(int[][] board) {
    int n = board.Length, firstRow = 0, firstCol = 0, firstRowCnt = 1, firstColCnt = 1;
    for (int i = 0; i < n; i++) {
      firstRow |= board[0][i] << i;
      firstCol |= board[i][0] << i;
    }
    int firstRowReverse = ((1 << n) - 1) ^ firstRow, firstColReverse = ((1 << n) - 1) ^ firstCol;
    for (int i = 1; i < n; i++) {
      int row = 0, col = 0;
      for (int j = 0; j < n; j++) {
        row |= board[i][j] << j;
        col |= board[j][i] << j;
      }
      if (row == firstRow) firstRowCnt++;
      else if (row != firstRowReverse) return -1;
      if (col == firstCol) firstColCnt++;
      else if (col != firstColReverse) return -1;
    }
    if (Math.Abs(firstRowCnt * 2 - n) > 1 || Math.Abs(firstColCnt * 2 - n) > 1) return -1;
    return (int)(Count((uint)firstRow, n) + Count((uint)firstCol, n));
  }
  private uint Count(uint num, int n) {
    uint b0 = 2863311530, b1 = 1431655765;
    uint oneCnt = Count1(num);
    if ((n & 1) == 1) { // java 和 c # 不能省略 ()
      if (oneCnt == n >> 1) return oneCnt - Count1(num & b0);
      return oneCnt - Count1(num & b1);
    }
    return oneCnt - Math.Max(Count1(num & b0), Count1(num & b1));
  }
  private uint Count1(uint n) {
    uint r = 0;
    while (n > 0) {
      n &= n - 1;
      r++;
    }
    return r;
  }
}
#define MAX(a, b) (a > b ? a : b) // 不省略括号,避免出现 1 - MAX(a, b) = 1 的问题
int count1(int n){
  int r = 0;
  while (n > 0) {
    n &= n - 1;
    r++;
  }
  return r;
}
int count(int num, int n){
  int b0 = 0b10101010101010101010101010101010, b1 = 0b01010101010101010101010101010101, oneCnt = count1(num);
  if (n & 1 == 1) {
    if (oneCnt == n >> 1) return oneCnt - count1(num & b0);
    return oneCnt - count1(num & b1);
  }
  return oneCnt - MAX(count1(num & b0), count1(num & b1));
}
int movesToChessboard(int** board, int boardSize, int* boardColSize){
  int firstRow = 0, firstCol = 0, firstRowCnt = 1, fristColCnt = 1;
  for (int i = 0; i < boardSize; i++) {
    firstRow |= board[0][i] << i;
    firstCol |= board[i][0] << i;
  }
  int firstRowReverse = ((1 << boardSize) - 1) ^ firstRow, firstColReverse = ((1 << boardSize) - 1) ^ firstCol;
  for (int i = 1; i < boardSize; i++) {
    int row = 0, col = 0;
    for (int j = 0; j < boardSize; j++) {
      row |= board[i][j] << j;
      col |= board[j][i] << j;
    }
    if (row == firstRow) firstRowCnt++;
    else if (row != firstRowReverse) return -1;
    if (col == firstCol) fristColCnt++;
    else if (col != firstColReverse) return -1;
  }
  if (abs(firstRowCnt * 2 - boardSize) > 1 || abs(fristColCnt * 2 - boardSize) > 1) return -1;
  return count(firstRow, boardSize) + count(firstCol, boardSize);
}
class Solution {
private:
  int count1(int n) {
    int r = 0;
    while (n) {
      n &= n - 1;
      r++;
    }
    return r;
  }
  int count(int num, int n) {
    int b0 = 0b10101010101010101010101010101010, b1 = 0b01010101010101010101010101010101, oneCnt = count1(num);
    if (n & 1 == 1) {
      if (oneCnt == n >> 1) return oneCnt - count1(num & b0);
      return oneCnt - count1(num & b1);
    }
    return oneCnt - max(count1(num & b0), count1(num & b1));
  }
public:
  int movesToChessboard(vector<vector<int>>& board) {
    int n = board.size(), firstRow = 0, firstCol = 0, firstRowCnt = 1, firstColCnt = 1;
    for (int i = 0; i < n; i++) {
      firstRow |= board[0][i] << i;
      firstCol |= board[i][0] << i;
    }
    int firstRowReverse = ((1 << n) - 1) ^ firstRow, firstColReverse = ((1 << n) - 1) ^ firstCol;
    for (int i = 1; i < n; i++) {
      int row = 0, col = 0;
      for (int j = 0; j < n; j++) {
        row |= board[i][j] << j;
        col |= board[j][i] << j; 
      }
      if (row == firstRow) firstRowCnt++;
      else if (row != firstRowReverse) return -1;
      if (col == firstCol) firstColCnt++;
      else if (col != firstColReverse) return -1;
    }
    if (abs(firstRowCnt * 2 - n) > 1 || abs(firstColCnt * 2 - n) > 1) return -1;
    return count(firstRow, n) + count(firstCol, n);
  }
};
class Solution:
  def movesToChessboard(self, board: List[List[int]]) -> int:
    n, firstRow, firstCol, firstRowCnt, firstColCnt = len(board), 0, 0, 1, 1
    for i in range(0, n):
      firstRow |= board[0][i] << i
      firstCol |= board[i][0] << i
    firstRowReverse, firstColReverse = ((1 << n) - 1) ^ firstRow, ((1 << n) - 1) ^ firstCol
    for i in range(1, n):
      row, col = 0, 0
      for j in range(0, n):
        row |= board[i][j] << j
        col |= board[j][i] << j
      if row == firstRow: firstRowCnt += 1
      elif row != firstRowReverse: return -1
      if col == firstCol: firstColCnt += 1
      elif col != firstColReverse: return -1
    if abs(firstRowCnt * 2 - n) > 1 or abs(firstColCnt * 2 - n) > 1: return -1
    return self.count(firstRow, n) + self.count(firstCol, n)
  def count(self, num: int, n: int) -> int:
    b0, b1, oneCnt = 0b10101010101010101010101010101010, 0b01010101010101010101010101010101, self.count1(num)
    if n & 1:
      if oneCnt == n >> 1: return oneCnt - self.count1(num & b0)
      return oneCnt - self.count1(num & b1)
    return oneCnt - max(self.count1(num & b0), self.count1(num & b1))
  def count1(self, n: int) -> int:
    r = 0
    while n:
      n &= n - 1
      r += 1
    return r

顺序遍历 + 拼接字符串,倒序遍历 + 顺序遍历 + 双指针,repeat / str_repeat / strings.Repeat / new string() / string / * 重复字符串,join / implode / accumulate 数组列表转字符串,2 解法求解《1592. 重新排列单词间的空格》
顺序遍历 + 拼接字符串,倒序遍历 + 顺序遍历 + 双指针,repeat / str_repeat / strings.Repeat / new string() / string / * 重复字符串,join / implode / accumulate 数组列表转字符串,2 解法求解《1592. 重新排列单词间的空格》
定长列表(数组),原地修改,2 解法求解《1582. 二进制矩阵中的特殊位置》
定长列表(数组),原地修改,Python 使用 zip 旋转矩阵,2 解法求解《1582. 二进制矩阵中的特殊位置》
顺序遍历,用 Label 或 continue 2 继续外层循环,单调栈(顺序遍历 / 倒序遍历),3 解法求解《1475. 商品折扣后的最终价格》
顺序遍历,用 Label 或 continue 2 继续外层循环,单调栈(顺序遍历 / 倒序遍历),3 解法求解《1475. 商品折扣后的最终价格》