Minimum Flips to Make a OR b Equal to c

題目描述

給定三個正整數 a, b, c。回傳翻轉 a 和 b 中位元的最少次數,使得 a OR b == c。翻轉一位算一次操作。

輸入:a = 2, b = 6, c = 5
輸出:3
解釋:翻轉後 a=1(001), b=4(100),1 OR 4 = 5

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

解題思路

1

逐位元檢查

用 a&1, b&1, c&1 取最低位,然後右移繼續檢查下一位,直到 a、b、c 都歸零

2

c 位元 = 1

需要 a|b = 1。若 a=0 且 b=0 → 翻轉 1 次(任選 a 或 b 翻一個)。否則已滿足,不翻

3

c 位元 = 0

需要 a=0 且 b=0。a 是 1 翻一次,b 是 1 翻一次,最多翻 2 次(用 bitA + bitB 計算)

4

累加翻轉數

所有位元的翻轉次數加總就是最終答案,例如 a=2(010), b=6(110), c=5(101) → 逐位分析得 flips=3

程式碼

C#

csharp
public class Solution {
    public int MinFlips(int a, int b, int c) {
        int flips = 0;
        while (a > 0 || b > 0 || c > 0) {
            int bitA = a & 1, bitB = b & 1, bitC = c & 1;
            
            if (bitC == 1) {
                // 需要 a|b = 1:至少一個是 1
                if (bitA == 0 && bitB == 0) flips += 1;
            } else {
                // 需要 a=0 且 b=0:每個 1 都要翻
                flips += bitA + bitB;
            }
            
            a >>= 1; b >>= 1; c >>= 1;
        }
        return flips;
    }
}

TypeScript

typescript
function minFlips(a: number, b: number, c: number): number {
    let flips = 0;
    while (a > 0 || b > 0 || c > 0) {
        const bitA = a & 1, bitB = b & 1, bitC = c & 1;
        
        if (bitC === 1) {
            if (bitA === 0 && bitB === 0) flips += 1;
        } else {
            flips += bitA + bitB; // 每個 1 都要翻成 0
        }
        
        a >>= 1; b >>= 1; c >>= 1;
    }
    return flips;
}

Python

python
def minFlips(a: int, b: int, c: int) -> int:
    flips = 0
    while a or b or c:
        bit_a, bit_b, bit_c = a & 1, b & 1, c & 1
        
        if bit_c == 1:
            # 需要至少一個 1
            if bit_a == 0 and bit_b == 0:
                flips += 1
        else:
            # 兩個都必須是 0
            flips += bit_a + bit_b
        
        a >>= 1; b >>= 1; c >>= 1
    
    return flips

複雜度分析

| | Time | Space | |--|------|-------| | 本解法 | O(max(log a, log b, log c)) | O(1) |

邊界情況

圖解

逐位元比較 a,b,c
c位=1
c=1: 需要 a|b=1
a=b=0
c=0: 需要 a=b=0
計數1
都是0 → 翻1次
+1
有幾個1翻幾次
+count
累加所有翻轉

圖表展示了逐位元的決策分支:根據 c 的位元值分成兩條路。 c=1 時只需確保至少一個 1(最多翻 1 次),c=0 時每個 1 都要翻掉(最多翻 2 次)。

進階觀點

💡面試追問

Q: 為什麼 c=0 時可能需要翻 2 次,但 c=1 時最多只翻 1 次? A: OR 運算的特性決定了這個不對稱。c=1 只需「至少一個 1」,a 或 b 有一個是 1 就行,都是 0 才翻 1 次。但 c=0 要求 a OR b = 0,即 a 和 b 都必須是 0,所以每個 1 都要單獨翻轉,最多 2 次。

Q: 有沒有不用逐位元迴圈的位元運算解法? A: 有。(a | b) ^ c 找出所有「需要改變」的位(OR 結果和 c 不同的位)。但這漏算了 c=0 且 a=b=1 的情況(需要翻 2 次但只計了 1 次)。用 a & b & ((a | b) ^ c) 找出這些額外翻轉位,最終答案 = popcount((a | b) ^ c) + popcount(a & b & ((a | b) ^ c))

Q: 這種逐位元分析的思路還能用在哪些題? A: 所有涉及 AND/OR/XOR 的位元操作題都可以逐位獨立分析,例如 LC 201 Bitwise AND of Numbers Range、LC 477 Total Hamming Distance。關鍵洞察是:位元運算的每一位互相獨立,可以分開處理再合併。

理解測驗

🤔 當 c 的某一位是 0,而 a 和 b 的對應位都是 1 時,需要翻轉幾次?

🤔 當 c 的某一位是 1,而 a=1, b=0 時,需要翻轉幾次?

你可能也想看

136. Single Number208. Implement Trie (Prefix Tree)

按 ← → 鍵切換課程