通过用一些 d 中的余数替换将数组转换为 1 到 N 的排列的最小操作
给定一个大小为N的数组arr[] ,任务是找到将数组转换为[1, n]的排列的最小操作数,在每个操作中,元素a[i]可以替换为a[ i] % d其中 d 在执行的每个操作中可能不同。如果不可能打印-1 。
例子:
Input: arr[] = {5, 4, 10, 8, 1}
Output: 2
Explanation: In first operation choosing d = 7 , 10 can be replaced by 10 % 7 ,
In second operation d = 6, 8 can be replaced by 8 %6 so two operations.
Input : arr[] = {1, 2, 3, 7}
Output: -1
方法:可以使用贪心方法来解决任务。这种方法基于这样一个事实,即当要获得余数r 时, a[i] > 2*r即r位于[0, a[i]-1 /2]范围之间
Let us take an example: 8 for different d
Taking, 8 % 7= 1
8%6 = 2
8%5 = 3
8%4 = 0
8%3 = 2
8%2 = 0
8%1=0
So maximum number that can be obtained is 3 using mod operation, so when we want to obtain a number i in a permutation then the number should a[i] > 2* i+1
请按照以下步骤解决此问题:
- 初始化一个集合
- 遍历数组arr[]并将 arr[] 的所有元素插入到集合中。
- 初始化变量ops = 0
- 现在从 n 迭代到 1
- 检查 s 是否已经 i 是否已将其从集合中删除。
- 否则增加操作并检查集合的最大元素是否 < 2* i +1
- 如果集合中的最大值 < 2* i +1则设置ops = -1并跳出循环。
- 否则将其从集合中删除,因为我们可以使用 mod 操作使其成为。
- 打印操作
`下面是上述方法的实现:
C++
// C++ code for the above approach
#include
using namespace std;
// Function to find the minimum operations
// to convert the array into a permutation of [1, n]
void minimum_operations(int arr[], int n)
{
// Initialize the set
set s;
// Insert all the elements into the set
for (int i = 0; i < n; i++) {
s.insert(arr[i]);
}
// Initialize ops to count the operations
int ops = 0;
// Traverse from [n to 1]
for (int i = n; i >= 1; i--) {
// If we already have i in our
// array erase it from the set
if (s.find(i) != s.end()) {
s.erase(s.find(i));
}
// count the ops because there is no element
else {
ops++;
// Check the largest element of the set
auto it = s.end();
it--;
// If it is < 2*i +1 we cant get that i
// using % operation so there is no way to
// create a permutation
if (*it < 2 * i + 1) {
ops = -1;
break;
}
// Erase it if we have processed
// it to i by % operation
s.erase(it);
}
}
// Print the result
cout << ops << endl;
}
// Driver Code
int main()
{
// Initialize the value n
int arr[] = { 5, 4, 10, 8, 1 };
int n = sizeof(arr) / sizeof(arr[0]);
minimum_operations(arr, n);
return 0;
}
Java
// Java code for the above approach
import java.util.*;
class GFG{
// Function to find the minimum operations
// to convert the array into a permutation of [1, n]
static void minimum_operations(int arr[], int n)
{
// Initialize the set
SortedSet s = new TreeSet();
// Insert all the elements into the set
for (int i = 0; i < n; i++) {
s.add(arr[i]);
}
// Initialize ops to count the operations
int ops = 0;
// Traverse from [n to 1]
for (int i = n; i >= 1; i--) {
// If we already have i in our
// array erase it from the set
if (s.contains(i)) {
s.remove(i);
}
// count the ops because there is no element
else {
ops++;
// Check the largest element of the set
Integer it = s.last();
it--;
// If it is < 2*i +1 we cant get that i
// using % operation so there is no way to
// create a permutation
if (it < 2 * i + 1) {
ops = -1;
break;
}
// Erase it if we have processed
// it to i by % operation
s.remove(it);
}
}
// Print the result
System.out.print(ops +"\n");
}
// Driver Code
public static void main(String[] args)
{
// Initialize the value n
int arr[] = { 5, 4, 10, 8, 1 };
int n = arr.length;
minimum_operations(arr, n);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python 3 code for the above approach
# Function to find the minimum operations
# to convert the array into a permutation of [1, n]
def minimum_operations(arr, n):
# Initialize the set
s = set([])
# Insert all the elements into the set
for i in range(n):
s.add(arr[i])
# Initialize ops to count the operations
ops = 0
# Traverse from [n to 1]
for i in range(n, 0, -1):
# If we already have i in our
# array erase it from the set
if (i in s):
list(s).remove(i)
# count the ops because there is no element
else:
ops += 1
# Check the largest element of the set
it = len(s)
it -= 1
# If it is < 2*i +1 we cant get that i
# using % operation so there is no way to
# create a permutation
if (list(s)[it] < 2 * i + 1):
ops = -1
break
# Erase it if we have processed
# it to i by % operation
list(s).pop(it)
# Print the result
print(ops)
# Driver Code
if __name__ == "__main__":
# Initialize the value n
arr = [5, 4, 10, 8, 1]
n = len(arr)
minimum_operations(arr, n)
# This code is contributed by ukasp.
C#
// C# code for the above approach
using System;
using System.Collections.Generic;
public class GFG
{
// Function to find the minimum operations
// to convert the array into a permutation of [1, n]
static void minimum_operations(int []arr, int n)
{
// Initialize the set
SortedSet s = new SortedSet();
// Insert all the elements into the set
for (int i = 0; i < n; i++) {
s.Add(arr[i]);
}
// Initialize ops to count the operations
int ops = 0;
// Traverse from [n to 1]
for (int i = n; i >= 1; i--) {
// If we already have i in our
// array erase it from the set
if (s.Contains(i)) {
s.Remove(i);
}
// count the ops because there is no element
else {
ops++;
// Check the largest element of the set
int it = s.Max;
it--;
// If it is < 2*i +1 we cant get that i
// using % operation so there is no way to
// create a permutation
if (it < 2 * i + 1) {
ops = -1;
break;
}
// Erase it if we have processed
// it to i by % operation
s.Remove(it);
}
}
// Print the result
Console.Write(ops +"\n");
}
// Driver Code
public static void Main(String[] args)
{
// Initialize the value n
int []arr = { 5, 4, 10, 8, 1 };
int n = arr.Length;
minimum_operations(arr, n);
}
}
// This code is contributed by 29AjayKumar
Javascript
2
时间复杂度: O(nlogn)
辅助空间: O(n)