You are given an integer array nums
of length n
which represents a permutation of all the integers in the range [0, n - 1]
.
The number of global inversions is the number of the different pairs (i, j)
where:
0 <= i < j < n
nums[i] > nums[j]
The number of local inversions is the number of indices i
where:
0 <= i < n - 1
nums[i] > nums[i + 1]
Return true
if the number of global inversions is equal to the number of local inversions.
Example 1:
Input: nums = [1,0,2] Output: true Explanation: There is 1 global inversion and 1 local inversion.
Example 2:
Input: nums = [1,2,0] Output: false Explanation: There are 2 global inversions and 1 local inversion.
Constraints:
n == nums.length
1 <= n <= 105
0 <= nums[i] < n
nums
are unique.nums
is a permutation of all the numbers in the range [0, n - 1]
.The problem asks to determine if the number of global inversions equals the number of local inversions in a given permutation array. A global inversion is a pair (i, j) where i < j and nums[i] > nums[j]. A local inversion is a pair (i, i+1) where nums[i] > nums[i+1].
This solution cleverly avoids explicitly calculating global inversions. It leverages the fact that if a global inversion is not a local inversion, it must involve indices that are at least two positions apart.
Algorithm:
Initialize mx
to 0. This variable will track the maximum value encountered so far, excluding the current and next elements.
Iterate through the array starting from the third element (index 2).
In each iteration, update mx
to the maximum of mx
and nums[i-2]
.
If mx > nums[i]
, it indicates a global inversion that's not local because it involves elements that are at least two positions apart. The function immediately returns false
.
If the loop completes without finding such a case, it means all global inversions are local, and the function returns true
.
Time Complexity: O(n), where n is the length of the input array. The solution iterates through the array once.
Space Complexity: O(1), as it uses only a constant amount of extra space.
Code (Python):
class Solution:
def isIdealPermutation(self, nums: List[int]) -> bool:
mx = 0
for i in range(2, len(nums)):
mx = max(mx, nums[i - 2])
if mx > nums[i]:
return False
return True
Code (Java):
class Solution {
public boolean isIdealPermutation(int[] nums) {
int mx = 0;
for (int i = 2; i < nums.length; ++i) {
mx = Math.max(mx, nums[i - 2]);
if (mx > nums[i]) {
return false;
}
}
return true;
}
}
Code (C++):
class Solution {
public:
bool isIdealPermutation(vector<int>& nums) {
int mx = 0;
for (int i = 2; i < nums.size(); ++i) {
mx = max(mx, nums[i - 2]);
if (mx > nums[i]) return false;
}
return true;
}
};
Code (Go):
func isIdealPermutation(nums []int) bool {
mx := 0
for i := 2; i < len(nums); i++ {
mx = max(mx, nums[i-2])
if mx > nums[i] {
return false
}
}
return true
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
This solution uses a Binary Indexed Tree (BIT) to efficiently count inversions. It directly addresses the condition of checking if the global and local inversions are equal.
Algorithm:
Create a Binary Indexed Tree (BIT
) of size n+1 to store cumulative counts.
Initialize cnt
to 0, which tracks the difference between global and local inversions.
Iterate through nums
:
nums[i] > nums[i+1]
), increment cnt
.nums[i]
that have already been seen (using BIT.query(nums[i])
) from i
. This accounts for global inversions that are not local.nums[i]
using BIT.update(nums[i] + 1, 1)
.If at any point cnt
becomes negative, it means there are more global inversions not accounted for as local inversions, and we return false
.
Finally, we check if cnt
is 0, indicating an equal number of global and local inversions.
Time Complexity: O(n log n), due to the use of the Binary Indexed Tree. BIT.update
and BIT.query
operations take O(log n) time.
Space Complexity: O(n) for the Binary Indexed Tree.
Code (Python): (Binary Indexed Tree implementation included)
class BinaryIndexedTree:
# ... (implementation from above)
class Solution:
# ... (implementation from above)
(Similar implementations for Java, C++, and Go are provided above, including the Binary Indexed Tree implementation.)
Note: Solution 1 is significantly more efficient than Solution 2. Solution 2 is provided for completeness and to demonstrate an alternative approach using a more advanced data structure, but it's not the optimal solution for this problem in terms of time complexity. For most cases, the linear-time solution is preferred.