或運算的最小翻轉次數

或運算的最小翻轉次數

描述:

給你三個正整數 a、b 和 c。

你可以對 a 和 b 的二進制表示進行位翻轉操作,返回能夠使按位或運算 a OR b == c 成立的最小翻轉次數。

「位翻轉操作」是指將一個數的二進制表示任何單個位上的 1 變成 0 或者 0 變成 1 。

示例 1:
或運算最小翻轉

輸入:a = 2, b = 6, c = 5
輸出:3
解釋:翻轉後 a = 1 , b = 4 , c = 5 使得 a OR b == c

示例 2:

輸入:a = 4, b = 2, c = 7
輸出:1

示例 3:

輸入:a = 1, b = 2, c = 3
輸出:0

提示:

1 <= a <= 10^9
1 <= b <= 10^9
1 <= c <= 10^9

分析

從a和b的 或運算 等於c,可以得出:

  1. c的二進制表示上的0,對應a和b上的該位的值一定都要轉爲0;
  2. c的二進制表示上的1,對應a和b上的該位的值至少要有一個轉爲1,即:若a和b對應該位上的值都爲0,則只需翻轉一次即可,否則無需翻轉。

因此,最小翻轉次數=(c的二進制表示爲0的位對應a的該位上爲1的個數)+(c的二進制表示爲0的位對應b的該位上爲1的個數)+(c的二進制表示爲1的位對應a和b上該位都爲0的個數)

而:

  1. c的二進制表示爲0的位對應a的該位上爲1的值 = c的非運算再跟a的與運算
  2. c的二進制表示爲0的位對應b的該位上爲1的值 = c的非運算再跟b的與運算
  3. c的二進制表示爲1的位對應a爲0的值 = c和a的與運算再跟c的異或運算
  4. c的二進制表示爲1的位對應a和b上該位都爲0的值 = 3得到的結果和b進行與運算再和3進行異或運算

解答:

class Solution {

    /**
     * @param Integer $a
     * @param Integer $b
     * @param Integer $c
     * @return Integer
     */
    function minFlips($a, $b, $c) {
        $count1 = $this->_countNum(~$c & $a); // c的二進制表示爲0的位對應a的該位上爲1的個數
        $count2 = $this->_countNum(~$c & $b); // c的二進制表示爲0的位對應b的該位上爲1的個數
        $tmp = $c & $a ^ $c; // c的二進制表示爲1的位對應a爲0的值
        $count3 = $this->_countNum($tmp & $b ^ $tmp); // c的二進制表示爲1的位對應a和b上該位都爲0的個數
        return $count1 + $count2 + $count3;
    }
    
    /**
     * 統計二進制數中1的個數
     * @param byte $num [二進制數]
     * @return Integer
     */
    private function _countNum($num) {
        $count = 0;
        $flag = 1;
        while ($flag != 0) {
            if (($num & $flag) != 0) {
                $count += 1;
            }
            $flag = $flag << 1;
        }
        return $count;
    }
}

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/minimum-flips-to-make-a-or-b-equal-to-c

發佈了28 篇原創文章 · 獲贊 20 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章