LeetCode 3644.排序排列:不对则与(脑筋急转弯)

【LetMeFly】3644.排序排列:不对则与(脑筋急转弯)

力扣题目链接:https://leetcode.cn/problems/maximum-k-to-sort-a-permutation/

给你一个长度为 n 的整数数组 nums,其中 nums 是范围 [0..n - 1] 内所有数字的一个 排列。

你可以在满足条件 nums[i] AND nums[j] == k 的情况下交换下标 i 和 j 的元素,其中 AND 表示按位与操作,k 是一个非负整数。

返回可以使数组按 非递减 顺序排序的最大值 k(允许进行任意次这样的交换)。如果 nums 已经是有序的,返回 0。

排列是数组所有元素的一种重新排列。

示例 1:
输入: nums = 0,3,2,1

输出: 1

解释:

选择 k = 1。交换 nums[1] = 3 和 nums[3] = 1,因为 nums[1] AND nums[3] == 1,从而得到一个排序后的排列:[0, 1, 2, 3]。

示例 2:
输入: nums = 0,1,3,2

输出: 2

解释:

选择 k = 2。交换 nums[2] = 3 和 nums[3] = 2,因为 nums[2] AND nums[3] == 2,从而得到一个排序后的排列:[0, 1, 2, 3]。

示例 3:
输入: nums = 3,2,1,0

输出: 0

解释:

只有当 k = 0 时,才能进行排序,因为没有更大的 k 能够满足 nums[i] AND nums[j] == k 的交换条件。

提示:

  • 1 <= n == nums.length <= 105
  • 0 <= nums[i] <= n - 1
  • nums 是从 0 到 n - 1 的一个排列。

解题方法:遍历

首先一定是有办法交换为递增数组的:

例如令 k = 0 k=0 k=0,则元素 0 0 0与任意元素都可以交换位置,最终一定可以交换为递增数组。

所以我们看有没有一个更大的合法 k k k。

已经在正确位置上的元素是不需要在移动的(例如 n u m s i = i numsi=i numsi=i),所以我们只需要考虑不在正确位置上的元素。

假设不在自己正确位置上的元素有 a a a、 b b b、 c c c、 ... \ldots ...,则它们一定要与某个元素(假设为 A A A等)交换位置,也就是说:

a & A = k , b & B = k , c & C = k , ⋮ \begin{aligned} a\ \&\ A &= k,\\ b\ \&\ B &= k,\\ c\ \&\ C &= k,\\ &\vdots \end{aligned} a & Ab & Bc & C=k,=k,=k,⋮

先不管 A A A、 B B B、 C C C等是什么, k = a & A k=a \& A k=a&A得出 k k k中为 1 1 1的位在 a a a中也一定为 1 1 1,同理 k k k中为 1 1 1的位在 b b b、 c c c等中也一定为 1 1 1,也就是说 k k k中为 1 1 1的位在 a a a、 b b b、 c c c等中也一定为 1 1 1(这里的位指的是 b i t bit bit),即 k ∡ a & b & c k\ \measuredangle\ a\& b \& c k ∡ a&b&c。

这里的 ∡ \measuredangle ∡是我自定义的一个符号,表示按位来看的话, k k k一定"属于" a a a、 b b b、 c c c等按位与的结果。

也就是说从上述几个等式可以得到 k k k的最大值是 a & b & c a\& b \& c a&b&c。

那么 k k k可不可以等于 a & b & c a\& b \& c a&b&c这个上界 呢?还是说 k k k需要更小呢?

答案是可以的,用等于 k k k的那个数和 a a a、 b b b、 c c c等不断交换位置即可。

  • 时间复杂度 O ( l e n ( n u m s ) ) O(len(nums)) O(len(nums))
  • 空间复杂度 O ( 1 ) O(1) O(1)

AC代码

C++
cpp 复制代码
/*
 * @LastEditTime: 2026-10-23 20:30:31
 */
class Solution {
public:
    int sortPermutation(vector<int>& nums) {
        if (nums[0]) {
            return 0;
        }
        int ans = -1;
        for (int i = 0, n = nums.size(); i < n; i++) {
            if (nums[i] != i) {
                ans &= i;
            }
        }
        return ans == -1 ? 0 : ans;
    }
};
Python
python 复制代码
'''
LastEditTime: 2026-10-23 20:32:12
'''
from typing import List

class Solution:
    def sortPermutation(self, nums: List[int]) -> int:
        if nums[0]:
            return 0
        ans = -1
        for i, t in enumerate(nums):
            if t != i:
                ans &= i
        return 0 if ans == -1 else ans
Java
java 复制代码
/*
 * @LastEditTime: 2026-10-23 20:34:40
 */
class Solution {
    public int sortPermutation(int[] nums) {
        if (nums[0] != 0) {
            return 0;
        }
        int ans = -1;
        for (int i = 0, n = nums.length; i < n; i++) {
            if (i != nums[i]) {
                ans &= i;
            }
        }
        return ans == -1 ? 0 : ans;
    }
}
Go
go 复制代码
/*
 * @LastEditTime: 2026-10-23 20:33:11
 */
package main

func sortPermutation(nums []int) int {
    if nums[0] != 0 {
        return 0
    }
    ans := -1
    for i, t := range nums {
        if t != i {
            ans &= i
        }
    }
    return max(ans, 0)
}
Rust
rust 复制代码
/*
 * @LastEditTime: 2026-10-23 20:39:42
 */
impl Solution {
    pub fn sort_permutation(nums: Vec<i32>) -> i32 {
        if nums[0] != 0 {
            return 0;
        }
        let mut ans = -1;
        for (i, &t) in nums.iter().enumerate() {
            if t != i as i32 {
                ans &= i as i32;
            }
        }
        ans.max(0)
    }
}

End

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
文丑颜不良啊2 小时前
LeetCode576~600题目解析
java·leetcode
lisw052 小时前
分岔论揭示演化突变密码
开发语言·算法·数学建模
aqiu1111113 小时前
C++ TopK:使用 nth_element 快速求最小 K 个数(蓝桥杯 / LeetCode 可用)
算法
H.莓飛3 小时前
【数据结构】快速排序专题
linux·服务器·c语言·数据结构·visual studio
Suprman3 小时前
平面排版问题的数学建模与算法设计
算法·数学建模·排序算法·排版套料
FPGA信号处理3 小时前
【应用随机过程】:更新过程与马尔可夫链入门
算法·概率论
重生之小比特3 小时前
【算法拾光】二分查找|在排序数组中查找元素的第一个和最后一个位置 + 搜索旋转排序数组
数据结构·算法·排序算法
吴可可1233 小时前
DXF与AAMA格式转换模块推荐
算法
重生之小比特3 小时前
【算法拾光】二分查找|搜索旋转排序数组 + 寻找旋转排序数组中的最小值
算法