给你一个长度为 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 <= 10^50 <= nums[i] <= n - 1nums是从0到n - 1的一个排列。
分析: 由于 nums 是 0 到 n-1 的一个排列,因此排序后的数组应当满足 numsi = i。
对于已经满足 numsi = i 的元素,不需要参与交换,只需要考虑那些不在正确位置上的元素。
根据题意,只有当两个元素的按位与结果等于 k 时,才能交换它们。由于每个不在正确位置上的元素最终都必须参与交换,因此,k 的二进制表示中为 1 的位,必须在所有这些元素中也为 1。因此k 的最大可能值就是所有不在正确位置上的元素的按位与结果。
设所有错位元素的按位与结果为 k,由于 nums 是一个排列,数组中一定存在值为 k 的元素。并且对于任意错位元素 x,都有 x & k = k,因此可以利用值为 k 的元素作为交换的中转,将所有错位元素调整到正确位置。
因此只需要遍历数组,找出所有满足 numsi != i 的元素,并对它们进行按位与运算,最终得到的结果就是答案。
具体实现时,使用 ans 记录按位与结果,初始值设为 -1。
遍历数组时:
-
如果 numsi = i,说明该元素已经位于正确位置,直接跳过。
-
否则,如果 ans = -1,说明这是第一个需要调整的元素,将 ans 赋值为 numsi。
-
如果 ans != -1,则将 ans 与 numsi 进行按位与运算,不断更新答案。
遍历结束后,如果 ans 仍然为 -1,说明数组原本已经有序,根据题意返回 0;否则返回 ans。
cpp
class Solution {
public:
int sortPermutation(vector<int>& nums) {
int n=nums.size(),ans=-1;
for(int i=0;i<n;++i)
if(nums[i]!=i)
ans=(ans==-1?nums[i]:(ans&nums[i]));
if(ans==-1)return 0;
return ans;
}
};