查找预期交换以对给定数组进行排序,其中交换任何反转对的概率相等
给定一个由前N个自然数的排列组成的数组arr[] ,任务是找到对给定数组进行排序的预期交换次数,其中交换任何反转对的概率和交换任何非反转的概率相等对为 0。
例子:
Input: arr[] = {3, 2, 1}
Output: 2.3333
Explanation: The given array can be sorted in non-decreasing order order using sequences of swaps as shown in the image below.
The expected numbers of swaps of each node can be calculated by 1 + (average of expected number of swaps of all the child nodes).
Since the nodes 3, 9, 10, 11, and 12 are already sorted, the number of expected swaps to sort them are 0.
The expected number of swaps of nodes 5, 6, 7, and 8 will be 1.
Similarly, the expected number of swaps of nodes 2 and 4 will be 2.
Hence, the expected number of swaps of node 1 is 1 + (2 + 2 + 0)/3 = 1 + 1.3333 = 2.3333
Input: arr[] = {1, 3, 2}
Output: 1.0
Explanation: Since there is only 1 inversion pair (arr[1], arr[2]), the expected number of swaps is 1.
方法:给定的问题可以在递归和回溯的帮助下使用记忆化来解决,它基于以下观察:
- 数组中的反转被定义为两个索引(i, j) ,使得i < j 和 arr[i] > arr[j] 。在一次交换每个有效反转的整数并递归调用交换之后的排列直到整个排列被排序之后,可以递归地计算预期的交换次数。
- 假设当前排列中有K个反转,并且在交换第i个反转之后,对排列进行排序的预期交换次数由P i表示。因此,交换所有可能的反转后的预期交换次数将为(P 1 + P 2 + ... + P K )/K 。
使用上述观察,可以通过以下步骤解决给定问题:
- 创建一个地图,比如存储给定排列的预期交换次数的备忘录。
- 创建一个递归函数expectedSwaps() ,它将排列作为参数并返回预期的交换次数。
- 在expectedSwaps()函数中,如果当前排列的期望交换已经计算,则返回答案。否则,遍历每个有效反转并交换当前反转的索引,并在交换后递归调用排列。
- 求变量中每次有效交换后预期交换的总和,比如res ,以及变量中的反转计数,比如K 。
- 完成以上步骤后,打印res/K的值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Stores result of each state of the
// array in a memoization table
map, double> memo;
// Recursive function to find expected
// number of swaps to sort given array
double expectedSwaps(vector a)
{
// The value for the given permutation
// is already calculated
if (memo.count(a)) {
return memo[a];
}
// Stores the expected number of ways
double res = 0;
// Stores the total operations done
int K = 0;
// Iterate for all possible pairs of
// Inversions
for (int i = 0; i < a.size(); i++) {
for (int j = i + 1; j < a.size(); j++) {
// For the current inversion
// find the expected value
if (a[i] > a[j]) {
swap(a[i], a[j]);
// Recursively Call
res += 1 + expectedSwaps(a);
// Backtrack
swap(a[i], a[j]);
K++;
}
}
}
// If permutation is already sorted
if (K == 0)
res = 0;
// Calculate expected swaps for
// current permutation
else
res /= K;
// Return answer
return memo[a] = res;
}
// Driver Code
int main()
{
int N = 3;
vector arr = { 3, 2, 1 };
cout << expectedSwaps(arr);
return 0;
}
Python3
# Python program for the above approach
# Stores result of each state of the
# array in a memoization table
memo = {}
# Recursive function to find expected
# number of swaps to sort given array
def expectedSwaps(a):
# The value for the given permutation
# is already calculated
if (tuple(a) in memo):
return memo[tuple(a)]
# Stores the expected number of ways
res = 0
# Stores the total operations done
K = 0
# Iterate for all possible pairs of
# Inversions
for i in range(len(a)):
for j in range(i + 1,len(a)):
# For the current inversion
# find the expected value
if (a[i] > a[j]):
temp = a[i]
a[i] = a[j]
a[j] = temp
# Recursively Call
res += 1 + expectedSwaps(a)
#Backtrack
temp = a[i]
a[i] = a[j]
a[j] = temp
K += 1
# If permutation is already sorted
if (K == 0):
res = 0
# Calculate expected swaps for
# current permutation
else:
res /= K;
# Return answer
memo[tuple(a)] = res
return res
# Driver Code
N = 3
arr = [ 3, 2, 1 ]
print(expectedSwaps(arr))
# This code is contributed by rohitsingh07052.
Javascript
2.33333
时间复杂度: O(N 2 N!)
辅助空间: O(N!)