↓快轉到主要內容
  1. LeetCode/

LeetCode 3644: Maximum K to Sort a Permutation

·1 分鐘· ·
LeetCode Medium Bit-Manipulation Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2025-08-10

  • 提交紀錄:Wrong Answer → Accepted

解題思路
#

交換 nums[i] 和 nums[j] 的條件是 nums[i] & nums[j] == k,所以參與交換的數一定包含 k 的所有位元(Bit Manipulation 模板一)。

  • 不在正確位置的數一定要被交換至少一次,所以 k 的每一位,這些數都要有:k 最大只能是它們全部 AND 起來。
  • 這個值也做得到:k 本身也在陣列裡(值是 0..n-1,而 k 不會比任何要移動的數大),而 k & x == k 對每個要移動的 x 都成立,所以可以把 k 當成「中轉站」,每次都跟它交換,就能把每個循環排好。
  • 已經排好就回傳 0。

我的嘗試
#

第一版想模擬:每個位置 i 如果不對,就取 i & nums[i] 的最大值,再把正確的數換過來。但 k 是同一個值,要讓所有要移動的數都能交換,取最大值是錯的。例如 [2, 3, 0, 1]:四個數都要移動,2 & 3 & 0 & 1 = 0,答案 0;這版回傳 1。改成全部 AND 起來就 AC 了。

正確解法
#

class Solution:
    def sortPermutation(self, nums: List[int]) -> int:
        k = -1                                     # -1 的每一位都是 1
        for i, x in enumerate(nums):
            if x != i:
                k &= x
        return 0 if k == -1 else k

複雜度
#

時間 O(n),空間 O(1)。

要特別避免的錯誤
#

  • k 要讓每一個要移動的數都能交換,所以是 AND,不是對每個位置取最大值。
  • AND 的初始值是 -1(每一位都是 1),不是 0。

面試口說整理
#

每個不在正確位置的數都一定要參與交換,而交換的兩個數 AND 要等於 k,所以 k 的每一位這些數都要有。最大的 k 就是所有要移動的數的 AND,已經排好就是 0。時間 O(n)。

相關文章

LeetCode 473: Matchsticks to Square
·1 分鐘
LeetCode Medium Array Dynamic-Programming Backtracking Bit-Manipulation
LeetCode 473 解題筆記:總和要能被 4 整除;由大到小把每根火柴放進四個邊之一,超過邊長或跟前一個邊長度相同就跳過
LeetCode 137: Single Number II
·1 分鐘
LeetCode Medium Array Bit-Manipulation
LeetCode 137 解題筆記:其他數都出現三次,逐位元統計 1 的個數取 mod 3,剩下的位元就是答案;注意負數
LeetCode 287: Find the Duplicate Number
·1 分鐘
LeetCode Medium Array Two-Pointers Binary-Search Bit-Manipulation
LeetCode 287 解題筆記:把 i -> nums[i] 看成鏈結串列,重複的值就是環的入口,用 Floyd 判圈;O(1) 空間、不改陣列
LeetCode 78: Subsets
·1 分鐘
LeetCode Medium Array Backtracking Bit-Manipulation
LeetCode 78 解題筆記:每個元素選或不選;迭代寫法是每加入一個數,就把現有的每個子集合複製一份並加上它
LeetCode 90: Subsets II
·1 分鐘
LeetCode Medium Array Backtracking Bit-Manipulation
LeetCode 90 解題筆記:先排序;遇到跟前一個相同的數,只延伸上一步新產生的那些子集合
LeetCode 3638: Maximum Balanced Shipments
·1 分鐘
LeetCode Medium Dynamic-Programming Greedy Monotonic-Stack Array
LeetCode 3638 解題筆記:貪心,一段一旦出現比這段最大值小的數就馬上切;因為切之前的那段是非遞減的,最大值就是前一個數