给定大小为NxN的矩阵A ,我们需要找到其中的求反对的数量。矩阵中的反转计数定义为满足以下条件的对数:
- X 1≤×2
- Y 1≤Y 2
- A [x 2 ] [y 2 ] 1 ] [y 1 ]
限制条件:
- 1≤A i, j≤10 9
- 1≤N≤10 3
例子:
For simplicity, let's take a 2x2 matrix :
A = {{7, 5},
{3, 1}};
The inversion pairs are : (7, 5), (3, 1), (7, 3), (5, 1) and (7, 1)
Output : 5
为了解决这个问题,我们需要了解以下几点:
- 使用二进制索引树(BIT)查找一维数组中的反转对数
https://www.geeksforgeeks.org/count-inversions-array-set-3-using-bit - 2D BIT
https://www.geeksforgeeks.org/two-Dimension-binary-indexed-tree-or-fenwick-tree
因为我们需要找到一个矩阵中的反转对数,所以我们要做的第一件事是将矩阵中的元素存储在另一个数组中,例如v并对数组v进行排序,以便我们可以比较未排序的矩阵中的元素与v并使用BIT查找反转对的数量。但是假设元素的值非常大(10 9 ),所以我们不能将矩阵中元素的值用作BIT中的索引。因此,我们需要使用元素的位置作为2D BIT中的索引。
我们将对矩阵的每个元素使用元组(-A [i] [j],i,j),并将其存储在数组中,例如’v’。然后,我们需要根据-A [i] [j]的值以升序对v进行排序,以便将矩阵的最大元素存储在索引0处,将最小元素存储在v的最后一个索引处。问题被简化为在1D数组中查找反转对,唯一的例外是我们将使用2D BIT。
请注意,这里我们使用A [i] [j]的负值,只是因为我们要从左到右遍历v,即从矩阵中的最大数到最小的数(因为这是当使用BIT查找一维数组中的反转对)。也可以使用正值并从右向左遍历v,最终结果将保持不变。
算法 :
1. Initialize inv_pair_cnt = 0, which will store the number of inversion pairs.
2. Store the tuple (-A[i][j], i, j) in an array, say v, where A[i][j] is the
element of the matrix A at position (i, j).
3. Sort the array v according to the first element of the tuple, i.e.,
according to the value of -A[i][j].
4. Traverse the array v and do the following :
- Initialize an array, say 'pairs' to store the position (i, j)
of the tuples of v.
- while the current tuple of v and all its adjacent tuples whose
first value, i.e., -A[i][j] is same, do
- Push the current tuple's position pair (i, j) into 'pairs'.
- Add to inv_pair_cnt, the number of elements which are less than
the current element(i.e., A[i][j]) and lie on the right side
in the sorted array v, by calling the query operation of BIT and
passing i and j as arguments.
- For each position pair (i, j) stored in the array 'pairs',
update the position (i, j) in the 2D BIT by 1.
5. Finally, inv_pair_cnt will contain the number of inversion pairs.
这是实现:
C++
// C++ program to count the number of inversion
// pairs in a 2D matrix
#include
using namespace std;
// for simplicity, we are taking N as 4
#define N 4
// Function to update a 2D BIT. It updates the
// value of bit[l][r] by adding val to bit[l][r]
void update(int l, int r, int val, int bit[][N + 1])
{
for (int i = l; i <= N; i += i & -i)
for (int j = r; j <= N; j += j & -j)
bit[i][j] += val;
}
// function to find cumulative sum upto
// index (l, r) in the 2D BIT
long long query(int l, int r, int bit[][N + 1])
{
long long ret = 0;
for (int i = l; i > 0; i -= i & -i)
for (int j = r; j > 0; j -= j & -j)
ret += bit[i][j];
return ret;
}
// function to count and return the number
// of inversion pairs in the matrix
long long countInversionPairs(int mat[][N])
{
// the 2D bit array and initialize it with 0.
int bit[N+1][N+1] = {0};
// v will store the tuple (-mat[i][j], i, j)
vector > > v;
// store the tuples in the vector v
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
// Note that we are not using the pair
// (0, 0) because BIT update and query
// operations are not done on index 0
v.push_back(make_pair(-mat[i][j],
make_pair(i+1, j+1)));
// sort the vector v according to the
// first element of the tuple, i.e., -mat[i][j]
sort(v.begin(), v.end());
// inv_pair_cnt will store the number of
// inversion pairs
long long inv_pair_cnt = 0;
// traverse all the tuples of vector v
int i = 0;
while (i < v.size())
{
int curr = i;
// 'pairs' will store the position of each element,
// i.e., the pair (i, j) of each tuple of the vector v
vector > pairs;
// consider the current tuple in v and all its
// adjacent tuples whose first value, i.e., the
// value of –mat[i][j] is same
while (curr < v.size() &&
(v[curr].first == v[i].first))
{
// push the position of the current element in 'pairs'
pairs.push_back(make_pair(v[curr].second.first,
v[curr].second.second));
// add the number of elements which are
// less than the current element and lie on the right
// side in the vector v
inv_pair_cnt += query(v[curr].second.first,
v[curr].second.second, bit);
curr++;
}
vector >::iterator it;
// traverse the 'pairs' vector
for (it = pairs.begin(); it != pairs.end(); ++it)
{
int x = it->first;
int y = it->second;
// update the position (x, y) by 1
update(x, y, 1, bit);
}
i = curr;
}
return inv_pair_cnt;
}
// Driver program
int main()
{
int mat[N][N] = { { 4, 7, 2, 9 },
{ 6, 4, 1, 7 },
{ 5, 3, 8, 1 },
{ 3, 2, 5, 6 } };
long long inv_pair_cnt = countInversionPairs(mat);
cout << "The number of inversion pairs are : "
<< inv_pair_cnt << endl;
return 0;
}
Python3
# Python3 program to count the number of inversion
# pairs in a 2D matrix
# for simplicity, we are taking N as 4
N = 4
# Function to update a 2D BIT. It updates the
# value of bit[l][r] by adding val to bit[l][r]
def update(l, r, val, bit):
i = l
while(i <= N):
j = r
while(j <= N):
bit[i][j] += val
j += j & -j
i += i & -i
# function to find cumulative sum upto
# index (l, r) in the 2D BIT
def query(l, r, bit):
ret = 0
i = l
while(i > 0):
j = r
while(j > 0):
ret += bit[i][j]
j -= j & -j
i -= i & -i
return ret
# function to count and return the number
# of inversion pairs in the matrix
def countInversionPairs(mat):
# the 2D bit array and initialize it with 0.
bit = [[0 for i in range(N + 1)] for j in range(N + 1)]
# v will store the tuple (-mat[i][j], i, j)
v = []
# store the tuples in the vector v
for i in range(N):
for j in range(N):
# Note that we are not using the pair
# (0, 0) because BIT update and query
# operations are not done on index 0
v.append([-mat[i][j], [i + 1, j + 1]])
# sort the vector v according to the
# first element of the tuple, i.e., -mat[i][j]
v.sort()
# inv_pair_cnt will store the number of
# inversion pairs
inv_pair_cnt = 0
# traverse all the tuples of vector v
i = 0
while (i < len(v)):
curr = i
# 'pairs' will store the position of each element,
# i.e., the pair (i, j) of each tuple of the vector v
pairs = []
# consider the current tuple in v and all its
# adjacent tuples whose first value, i.e., the
# value of –mat[i][j] is same
while (curr < len(v) and (v[curr][0] == v[i][0])):
# push the position of the current element in 'pairs'
pairs.append([v[curr][1][0], v[curr][1][1]])
# add the number of elements which are
# less than the current element and lie on the right
# side in the vector v
inv_pair_cnt += query(v[curr][1][0], v[curr][1][1], bit)
curr += 1
# traverse the 'pairs' vector
for it in pairs:
x = it[0]
y = it[1]
# update the position (x, y) by 1
update(x, y, 1, bit)
i = curr
return inv_pair_cnt
# Driver code
mat = [[4, 7, 2, 9 ],[ 6, 4, 1, 7 ],
[ 5, 3, 8, 1 ],[3, 2, 5, 6]]
inv_pair_cnt = countInversionPairs(mat)
print("The number of inversion pairs are :", inv_pair_cnt)
# This code is contributed by shubhamsingh10
输出:
The number of inversion pairs are : 43
时间复杂度:O(log(NxN)),其中N是矩阵的大小
空间复杂度:O(NxN)