Given an integer array nums. Return the number of inversions in the array.
Two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j.
Input: nums = [2, 3, 7, 1, 3, 5]
Output: 5
Explanation: The responsible indexes are:
nums[0], nums[3], values: 2 > 1 & indexes: 0 < 3
nums[1], nums[3], values: 3 > 1 & indexes: 1 < 3
nums[2], nums[3], values: 7 > 1 & indexes: 2 < 3
nums[2], nums[4], values: 7 > 3 & indexes: 2 < 4
nums[2], nums[5], values: 7 > 5 & indexes: 2 < 5
Input: nums = [-10, -5, 6, 11, 15, 17]
Output: 0
Explanation: nums is sorted, hence no inversions present.
Input: nums = [9, 5, 4, 2]
The naive approach is pretty straightforward, which will use nested loops to solve this problem. The prerequisite is that the index i must be smaller than index j. So, fix i at one index, and with another loop say(j), which runs from i+1 to last index of the array, try to count the inversion pairs.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
// Function to find number of inversions in an array
long long int numberOfInversions(vector<int>&nums) {
//size of the array
int n = nums.size();
// Count the number of pairs:
long long int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
/*if nums[i] is greater than
nums[j], increase countby 1.*/
if (nums[i] > nums[j]) cnt++;
}
}
//return the count of inversions
return cnt;
}
};
int main() {
vector<int> nums = {5, 4, 3, 2, 1};
// Create an instance of Solution class
Solution sol;
long long int result = sol.numberOfInversions(nums);
// Print the repeating and missing numbers found
cout << "The number of inversions is: "
<< result << endl;
return 0;
}
import java.util.*;
class Solution {
// Function to find number of inversions in an array
public long numberOfInversions(int[] nums) {
// Size of the array
int n = nums.length;
// Count the number of pairs
long cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
/* If nums[i] is greater than
nums[j], increase count by 1*/
if (nums[i] > nums[j]) {
cnt++;
}
}
}
// Return the count of inversions
return cnt;
}
}
class Main {
public static void main(String[] args) {
int[] nums = {5, 4, 3, 2, 1};
// Create an instance of Solution class
Solution sol = new Solution();
long result = sol.numberOfInversions(nums);
// Print the number of inversions found
System.out.println("The number of inversions is: " + result);
}
}
from typing import List
class Solution:
# Function to find number of inversions in an array
def numberOfInversions(self, nums: List[int]) -> int:
# Size of the array
n = len(nums)
# Count the number of pairs
cnt = 0
for i in range(n):
for j in range(i + 1, n):
""" If nums[i] is greater than
nums[j], increase count by 1"""
if nums[i] > nums[j]:
cnt += 1
# Return the count of inversions
return cnt
# Main function
if __name__ == "__main__":
nums = [5, 4, 3, 2, 1]
# Create an instance of Solution class
sol = Solution()
result = sol.numberOfInversions(nums)
# Print the number of inversions found
print(f"The number of inversions is: {result}")
class Solution {
// Function to find number of inversions in an array
numberOfInversions(nums) {
// Size of the array
let n = nums.length;
// Count the number of pairs
let cnt = 0;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
/* If nums[i] is greater than
nums[j], increase count by 1*/
if (nums[i] > nums[j]) {
cnt++;
}
}
}
// Return the count of inversions
return cnt;
}
}
const nums = [5, 4, 3, 2, 1];
//Create an instance of Solution class
const sol = new Solution();
let result = sol.numberOfInversions(nums);
// Print the number of inversions found
console.log(`The number of inversions is: ${result}`);
The optimal solution uses the concept of merge sort algorithm to count the inversion pairs in an array. Try to break down the problem as finding the count of inversion pairs in two sorted arrays. Finally, combine the count and return it.
#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
/* Merge function to count
inversions and merge sorted halves*/
long long int merge(vector<int>& arr, int low, int mid, int high) {
// Temporary array for merging
vector<int> temp;
// Starting indices of left and right halves
int left = low;
int right = mid + 1;
// Count variable to count the pairs
long long int cnt = 0;
// Merge sorted halves into temp array
while (left <= mid && right <= high) {
if (arr[left] <= arr[right]) {
temp.push_back(arr[left]);
left++;
}
else {
temp.push_back(arr[right]);
// Count inversions
cnt += (mid - left + 1);
right++;
}
}
// Copy remaining elements of left half
while (left <= mid) {
temp.push_back(arr[left]);
left++;
}
// Copy remaining elements of right half
while (right <= high) {
temp.push_back(arr[right]);
right++;
}
/* Copy elements from temp
array back to original array*/
for (int i = low; i <= high; i++) {
arr[i] = temp[i - low];
}
//return the count of inversions
return cnt;
}
// Merge sort function to recursively sort and count inversions
long long int mergeSort(vector<int>& arr, int low, int high) {
long long int cnt = 0;
if (low < high) {
int mid = low + (high - low) / 2;
// Sort left half
cnt += mergeSort(arr, low, mid);
// Sort right half
cnt += mergeSort(arr, mid + 1, high);
// Merge and count inversions
cnt += merge(arr, low, mid, high);
}
return cnt;
}
public:
// Function to find number of inversions in an array
long long int numberOfInversions(vector<int>& nums) {
// Size of the array
int n = nums.size();
// Count the number of pairs
return mergeSort(nums, 0, n - 1);
}
};
int main() {
vector<int> nums = {5, 4, 3, 2, 1};
// Create an instance of Solution class
Solution sol;
long long result = sol.numberOfInversions(nums);
// Print the number of inversions found
cout << "The number of inversions are: " << result << endl;
return 0;
}
class Solution {
/* Merge function to count
inversions and merge sorted halves */
private long merge(int[] arr, int low, int mid, int high) {
// Temporary array for merging
int[] temp = new int[high - low + 1];
// Starting indices of left and right halves
int left = low;
int right = mid + 1;
int index = 0;
// Count variable to count the pairs
long cnt = 0;
// Merge sorted halves into temp array
while (left <= mid && right <= high) {
if (arr[left] <= arr[right]) {
temp[index++] = arr[left++];
} else {
temp[index++] = arr[right++];
// Count inversions
cnt += (mid - left + 1);
}
}
// Copy remaining elements of left half
while (left <= mid) {
temp[index++] = arr[left++];
}
// Copy remaining elements of right half
while (right <= high) {
temp[index++] = arr[right++];
}
/* Copy elements from temp
array back to original array */
System.arraycopy(temp, 0, arr, low, high - low + 1);
// Return the count of inversions
return cnt;
}
// Merge sort function to recursively sort and count inversions
private long mergeSort(int[] arr, int low, int high) {
long cnt = 0;
if (low < high) {
int mid = low + (high - low) / 2;
// Sort left half
cnt += mergeSort(arr, low, mid);
// Sort right half
cnt += mergeSort(arr, mid + 1, high);
// Merge and count inversions
cnt += merge(arr, low, mid, high);
}
return cnt;
}
// Public function to find number of inversions in an array
public long numberOfInversions(int[] nums) {
// Size of the array
int n = nums.length;
// Count the number of pairs
return mergeSort(nums, 0, n - 1);
}
}
class Main {
public static void main(String[] args) {
int[] nums = {5, 4, 3, 2, 1};
// Create an instance of Solution class
Solution sol = new Solution();
long result = sol.numberOfInversions(nums);
// Print the number of inversions found
System.out.println("The number of inversions are: " + result);
}
}
class Solution:
# Merge function to count
# inversions and merge sorted halves
def merge(self, arr, low, mid, high):
# Temporary array for merging
temp = []
# Starting indices of left and right halves
left = low
right = mid + 1
# Count variable to count the pairs
cnt = 0
# Merge sorted halves into temp array
while left <= mid and right <= high:
if arr[left] <= arr[right]:
temp.append(arr[left])
left += 1
else:
temp.append(arr[right])
# Count inversions
cnt += (mid - left + 1)
right += 1
# Copy remaining elements of left half
while left <= mid:
temp.append(arr[left])
left += 1
# Copy remaining elements of right half
while right <= high:
temp.append(arr[right])
right += 1
# Copy elements from temp
# array back to original array
for i in range(low, high + 1):
arr[i] = temp[i - low]
# Return the count of inversions
return cnt
# Merge sort function to recursively sort and count inversions
def mergeSort(self, arr, low, high):
cnt = 0
if low < high:
mid = low + (high - low) // 2
# Sort left half
cnt += self.mergeSort(arr, low, mid)
# Sort right half
cnt += self.mergeSort(arr, mid + 1, high)
# Merge and count inversions
cnt += self.merge(arr, low, mid, high)
return cnt
# Function to find number of inversions in an array
def numberOfInversions(self, nums):
# Size of the array
n = len(nums)
# Count the number of pairs
return self.mergeSort(nums, 0, n - 1)
if __name__ == "__main__":
nums = [5, 4, 3, 2, 1]
# Create an instance of Solution class
sol = Solution()
result = sol.numberOfInversions(nums)
# Print the number of inversions found
print(f"The number of inversions are: {result}")
class Solution {
/* Merge function to count
inversions and merge sorted halves */
merge(arr, low, mid, high) {
// Temporary array for merging
const temp = [];
// Starting indices of left and right halves
let left = low;
let right = mid + 1;
// Count variable to count the pairs
let cnt = 0;
// Merge sorted halves into temp array
while (left <= mid && right <= high) {
if (arr[left] <= arr[right]) {
temp.push(arr[left]);
left++;
} else {
temp.push(arr[right]);
// Count inversions
cnt += (mid - left + 1);
right++;
}
}
// Copy remaining elements of left half
while (left <= mid) {
temp.push(arr[left]);
left++;
}
// Copy remaining elements of right half
while (right <= high) {
temp.push(arr[right]);
right++;
}
/* Copy elements from temp
array back to original array */
for (let i = low; i <= high; i++) {
arr[i] = temp[i - low];
}
// Return the count of inversions
return cnt;
}
// Merge sort function to recursively sort and count inversions
mergeSort(arr, low, high) {
let cnt = 0;
if (low < high) {
const mid = low + Math.floor((high - low) / 2);
// Sort left half
cnt += this.mergeSort(arr, low, mid);
// Sort right half
cnt += this.mergeSort(arr, mid + 1, high);
// Merge and count inversions
cnt += this.merge(arr, low, mid, high);
}
return cnt;
}
// Function to find number of inversions in an array
numberOfInversions(nums) {
// Size of the array
const n = nums.length;
// Count the number of pairs
return this.mergeSort(nums, 0, n - 1);
}
}
const nums = [5, 4, 3, 2, 1];
// Create an instance of Solution class
const sol = new Solution();
const result = sol.numberOfInversions(nums);
// Print the number of inversions found
console.log("The number of inversions are: " + result);
Q: How does Merge Sort count inversions?
A: While merging two halves, if left[i] > right[j], all remaining elements in left contribute to inversions because they are all greater than right[j].
Q: What is the worst-case inversion count?
A: The maximum inversions occur when the array is reverse sorted, which is n(n-1)/2.
Q: How does this relate to sorting algorithms?
A: The number of inversions represents the minimum swaps needed to sort the array.
Q: How can we modify Merge Sort to also return the sorted array alongside inversion count?
A: Modify the merge function to return both sorted output and the inversion count.