计算向量中的反转次数
Counting the number of inversions in a vector
背景资料:
This is a daily coding problem from Google.
We can determine how "out of order" an array A is by counting the number of inversions it has. Two elements
A[i] and A[j] form an inversion if A[i] > A[j] but i < j.That is, a smaller element appears after a larger element.
Given an array, count the number of inversions it has.Do this faster than O(N ^ 2) time.
You may assume each element in the array is distinct.
For example, a sorted list has zero inversions.The array[2, 4, 1, 3, 5] has three inversions:
(2, 1), (4, 1), and (4, 3).The array[5, 4, 3, 2, 1] has ten inversions : every distinct pair forms
// an inversion.
暴力破解:
auto num_inversions(std::vector<int>& nums)
{
int count = 0;
for (int i = 0; i <= nums.size(); ++i)
{
for (int j = i + 1; j < nums.size(); ++j)
{
if (nums[i] > nums[j])
++count;
}
}
return count;
}
可能更好的解决方案想法:
我的想法是使用 priority_queue 来达到这样的目的:
auto num_inversions1(std::vector<int>& nums)
{
auto compare = [](int lhs, int rhs)
{
return lhs > rhs;
};
std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);
for (auto num : nums)
q.push(num);
print_queue(q);
}
现在,如果我知道比较 lambda 使用了多少次,那么我认为这将决定我的反转次数。是否可以统计lambda表达式在优先级队列中被使用的次数?如果是这样,这种方法行得通吗?
更新:
按照 link 提供的建议,除了一个修改合并排序之外,没有过多地查看答案,我尝试了一下,但没有得到正确的结果。
这是我的代码:
#include <iostream>
#include <vector>
int merge(std::vector<int>& data, std::vector<int>& temp, int low, int middle, int high) {
// create a temporary array ... O(N) memory complexity !!!
// copy the data to a temporary array
for (int i = low; i <= high; i++) {
temp[i] = data[i];
}
int i = low;
int j = middle + 1;
int k = low;
int inv_count = 0;
// Copy the smallest values from either the left or the right side back
// to the original array
while ((i <= middle) && (j <= high)) {
if (temp[i] <= temp[j]) {
data[k] = temp[i];
i++;
}
else {
data[k] = temp[j];
j++;
inv_count = inv_count + (middle - i);
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
data[k] = temp[i];
k++;
i++;
}
// Copy the rest of the right side of the array into the target array
while (j <= high) {
data[k] = temp[j];
k++;
j++;
}
return inv_count;
}
int merge_sort(std::vector<int>& data, std::vector<int>& temp, int low, int high)
{
int mid, inv_count = 0;
if (high > low)
{
mid = (low + high) / 2;
inv_count = merge_sort(data, temp, low, mid);
inv_count += merge_sort(temp, temp, mid + 1, high);
inv_count += merge(data, temp, low, mid, high);
}
return inv_count;
}
int sort(std::vector<int>& data, std::vector<int>& temp)
{
return merge_sort(data, temp, 0, data.size() - 1);
}
int main()
{
std::vector<int> data = { 2, 4, 1, 3, 5 };
auto n = data.size();
std::vector<int> temp(n, 0);
std::cout << "The number of inversions is " << sort(data, temp);
std::cin.get();
}
答案应该是 3 但我只得到 1
使用计数器:
auto num_inversions1(std::vector<int>& nums)
{
int cmpCounter = 0;
auto compare = [&cmpCounter](int lhs, int rhs)
{
cmpCounter++;
return lhs > rhs;
};
std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);
for (auto num : nums)
q.push(num);
print_queue(q);
}
背景资料:
This is a daily coding problem from Google.
We can determine how "out of order" an array A is by counting the number of inversions it has. Two elements A[i] and A[j] form an inversion if A[i] > A[j] but i < j.That is, a smaller element appears after a larger element.
Given an array, count the number of inversions it has.Do this faster than O(N ^ 2) time.
You may assume each element in the array is distinct.
For example, a sorted list has zero inversions.The array[2, 4, 1, 3, 5] has three inversions: (2, 1), (4, 1), and (4, 3).The array[5, 4, 3, 2, 1] has ten inversions : every distinct pair forms // an inversion.
暴力破解:
auto num_inversions(std::vector<int>& nums)
{
int count = 0;
for (int i = 0; i <= nums.size(); ++i)
{
for (int j = i + 1; j < nums.size(); ++j)
{
if (nums[i] > nums[j])
++count;
}
}
return count;
}
可能更好的解决方案想法:
我的想法是使用 priority_queue 来达到这样的目的:
auto num_inversions1(std::vector<int>& nums)
{
auto compare = [](int lhs, int rhs)
{
return lhs > rhs;
};
std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);
for (auto num : nums)
q.push(num);
print_queue(q);
}
现在,如果我知道比较 lambda 使用了多少次,那么我认为这将决定我的反转次数。是否可以统计lambda表达式在优先级队列中被使用的次数?如果是这样,这种方法行得通吗?
更新:
按照 link 提供的建议,除了一个修改合并排序之外,没有过多地查看答案,我尝试了一下,但没有得到正确的结果。
这是我的代码:
#include <iostream>
#include <vector>
int merge(std::vector<int>& data, std::vector<int>& temp, int low, int middle, int high) {
// create a temporary array ... O(N) memory complexity !!!
// copy the data to a temporary array
for (int i = low; i <= high; i++) {
temp[i] = data[i];
}
int i = low;
int j = middle + 1;
int k = low;
int inv_count = 0;
// Copy the smallest values from either the left or the right side back
// to the original array
while ((i <= middle) && (j <= high)) {
if (temp[i] <= temp[j]) {
data[k] = temp[i];
i++;
}
else {
data[k] = temp[j];
j++;
inv_count = inv_count + (middle - i);
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
data[k] = temp[i];
k++;
i++;
}
// Copy the rest of the right side of the array into the target array
while (j <= high) {
data[k] = temp[j];
k++;
j++;
}
return inv_count;
}
int merge_sort(std::vector<int>& data, std::vector<int>& temp, int low, int high)
{
int mid, inv_count = 0;
if (high > low)
{
mid = (low + high) / 2;
inv_count = merge_sort(data, temp, low, mid);
inv_count += merge_sort(temp, temp, mid + 1, high);
inv_count += merge(data, temp, low, mid, high);
}
return inv_count;
}
int sort(std::vector<int>& data, std::vector<int>& temp)
{
return merge_sort(data, temp, 0, data.size() - 1);
}
int main()
{
std::vector<int> data = { 2, 4, 1, 3, 5 };
auto n = data.size();
std::vector<int> temp(n, 0);
std::cout << "The number of inversions is " << sort(data, temp);
std::cin.get();
}
答案应该是 3 但我只得到 1
使用计数器:
auto num_inversions1(std::vector<int>& nums)
{
int cmpCounter = 0;
auto compare = [&cmpCounter](int lhs, int rhs)
{
cmpCounter++;
return lhs > rhs;
};
std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);
for (auto num : nums)
q.push(num);
print_queue(q);
}