给定大小为N的数组arr [] ,该数组包含范围为[0,N-1]的唯一元素,任务是找到K ,这是通过选择三个不同的元素并重新排列它们来对给定数组进行排序所需的步骤数。并且,在K行中打印在那K个步骤中选择的索引。
For example, in the array {5, 4, 3, 2, 1, 0}, one possible way to sort the given array by selecting three distinct elements is to select the numbers {2, 1, 0} and sort them as {0, 1, 2} thereby making the array {5, 4, 3, 0, 1, 2}. Similarly, the remaining operations are performed and the indices selected ({3, 4, 5} in the above case) are printed in separate lines.
例子:
Input: arr[] = {0, 5, 4, 3, 2, 1}
Output:
2
1 2 5
2 5 4
Explanation:
The above array can be sorted in 2 steps:
Step I: We change the order of elements at indices 1, 2, 5 then the array becomes {0, 1, 5, 3, 2, 4}.
Step II: We again change the order of elements at the indices 2, 5, 4 then the array becomes {0, 1, 2, 3, 4, 5} which is sorted.
Input: arr[] = {0, 3, 1, 6, 5, 2, 4}
Output: -1
Explanation:
The above array cannot be sorted in any number of steps.
Suppose we choose indices 1, 3, 2 then the array becomes {0, 1, 6, 3, 5, 2, 4}
After that, we choose indices 2, 6, 4 then the array becomes {0, 1, 5, 3, 4, 2, 6}.
Now only two elements are left unsorted so we cannot choose 3 elements so the above array cannot be sorted. We can try with any order of indices and we will always be left with 2 elements unsorted.
方法:想法是首先计算未排序的元素,然后将它们插入无序集合中。如果count为0,那么我们不需要对数组进行排序的任何步骤,因此我们输出0并退出。否则,我们首先擦除集合中i = A [A [i]]的所有元素,然后执行以下操作,直到集合为空:
- 我们选择所有可能的索引组合(如果有),以使至少两个元素得到排序。
- 现在,如果i = A [i],则更改元素的顺序并将其从集合中删除。
- 然后,只剩下那些元素,使得i = A [A [i]],并且这些元素的计数必须是4的倍数,否则无法对元素进行排序。
- 然后,我们选择任意两对,并执行两次更改元素的顺序。然后,所有四个选择的元素将被排序。
- 我们将与元素顺序更改有关的所有索引存储在向量中,并将其打印为答案。
让我们通过一个例子来理解上述方法。令数组arr [] = {0,8,9,10,1,7,12,4,4,3,2,6,5,11}。然后:
- 最初,该集合将包含所有12个元素,并且不存在i = A [A [i]]的元素。
- 现在,选择{11,5,7}并更改元素的顺序。然后,arr [] = {0,8,9,10,1,5,12,7,7,3,2,6,4,11}。
- 现在,选择{11,4,1}并更改元素的顺序。然后,arr [] = {0、1、9、10、4、5、12、7、3、2、6、8、11}。
- 现在,选择{11,8,3}并更改元素的顺序。然后,arr [] = {0,1,9,3,4,5,12,7,8,2,2,6,10,11}。
- 现在,选择{11,10,6}并更改元素的顺序。然后,arr [] = {0、1、9、3、4、5、6、7、8、2、10、12、11}。
- 完成上述步骤后,剩下两对未排序的元素,使得i = A [A [i]]。
- 最后,选择{2,11,9}和{11,9,5}并重新排序。然后,将arr [] = {0、1、2、3、4、5、6、7、8、9、10、11、12}进行排序。
下面是上述方法的实现:
// C++ program to sort the array
// by changing the order of
// three elements
#include
using namespace std;
// Function to change the order of
// the elements having a temporary
// vector and the required indices
// as the arguments
void cngorder(vector& v, int i,
int j, int k)
{
int temp = v[k];
v[k] = v[j];
v[j] = v[i];
v[i] = temp;
}
// Function to sort the elements having
// the given array and its size.
void sortbyorder3(vector& A, int n)
{
// Flag to check whether the sorting
// is possible or not
bool flag = 0;
int count = 0;
// Set that will contains unsorted
// elements
unordered_set s;
// Iterating through the elements
for (int i = 0; i < n; i++) {
// Inserting the required elements
// in the set
if (i != A[i])
count++, s.insert(i);
}
// When the given array is
// already sorted
if (count == 0)
cout << "0" << endl;
else {
// Vector that will contain
// the answer
vector > ans;
// Temporary vector to store
// the indices
vector vv;
int x, y, z;
count = 0;
// Loop that will execute till the
// set becomes empty
while (!s.empty()) {
auto it = s.begin();
int i = *it;
// Check for the condition
if (i == A[A[i]]) {
s.erase(i);
s.erase(A[i]);
continue;
}
// Case when the minimum two
// elements will get sorted
else {
x = A[i], y = A[A[i]], z = A[A[A[i]]];
vv.push_back(x), vv.push_back(y),
vv.push_back(z);
// Changing the order of elements
cngorder(A, x, y, z);
// Pushing the indices to the
// answer vector
ans.push_back(vv);
// If the third element also
// gets sorted
if (vv[0] == A[vv[0]])
s.erase(vv[0]);
// Erasing the two sorted elements
// from the set
s.erase(vv[1]), s.erase(vv[2]);
vv.clear();
}
}
count = 0;
// The count of the remaining
// unsorted elements
for (int i = 0; i < n; i++) {
if (i != A[i])
count++;
}
// If the count of the left
// unsorted elements is not
// a multiple of 4, then
// sorting is not possible
if (count % 4 != 0)
flag = 1;
// Only the elements such that
// i = A[A[i]] are left
// for sorting
else {
// Indices of any one element
// from the two pairs that
// will be sorted in 2 steps
int i1 = -1, i2 = -1;
for (int i = 0; i < n; i++) {
// Index of any element of
// the pair
if (A[i] != i && i1 == -1) {
i1 = i;
}
// When we find the second
// pair and the index of
// any one element is stored
else if (A[i] != i && i1 != -1
&& i2 == -1) {
if (i1 == A[i])
continue;
else
i2 = i;
}
// When we got both the pair
// of elements
if (i1 != -1 && i2 != -1) {
// Remaining two indices
// of the elements
int i3 = A[i1], i4 = A[i2];
// The first order of indices
vv.push_back(i1),
vv.push_back(i2),
vv.push_back(A[i1]);
// Pushing the indices to the
// answer vector
ans.push_back(vv);
vv.clear();
// The second order of indices
vv.push_back(i2),
vv.push_back(A[i1]),
vv.push_back(A[i2]);
// Pushing the indices to the
// answer vector
ans.push_back(vv);
vv.clear();
// Changing the order of the
// first combination of
// the indices
cngorder(A, i1, i2, i3);
// Changing the order of the
// second combination of
// the indices after which all
// the 4 elements will be sorted
cngorder(A, i2, i3, i4);
i1 = -1, i2 = -1;
}
}
}
// If the flag value is 1
// the sorting is not possible
if (flag == 1)
cout << "-1" << endl;
else {
// Printing the required number
// of steps
cout << ans.size() << endl;
// Printing the indices involved
// in the shifting
for (int i = 0; i < ans.size(); i++) {
cout << ans[i][0]
<< " " << ans[i][1]
<< " " << ans[i][2]
<< endl;
}
}
}
}
// Driver code
int main()
{
int n;
vector A{ 0, 8, 9, 10, 1, 7, 12,
4, 3, 2, 6, 5, 11 };
n = A.size();
// Calling the sorting function
sortbyorder3(A, n);
return 0;
}
6
11 5 7
11 4 1
11 8 3
11 10 6
2 11 9
11 9 12
时间复杂度: O(N) ,其中N是数组的大小。