最小化溶解操作以使除第一个和最后一个之外的所有元素都为 0
给定一个长度为N的数组arr , 任务是找到使所有数组元素为 0 所需的最小操作次数,除了第一个和最后一个,使用给定的操作任意次数:
- 在每个操作中选择 3 个索引1 ≤ i < j < k ≤ n,使得arr[j]>=2,并且
- 从 arr[j] 中减去 2,并将 arr[i] 和 arr[k] 加 1。
例子
Input : arr = {1, 2, 2, 3, 6}
Output: 4
Explanation:
Select (i,j,k)=(1,2,5), array = {2,0,2,3,7}.
Select (i,j,k)=(1,3,4), array = [3,0,0,4,7].
Select (i,j,k)=(1,4,5) twice.
array = [5,0,0,0,9].
All elements except the first and last element becomes equal to zero.
Input : arr = { 3, 1, 1, 2}
Output: -1
Explanation : It’s impossible to perform any operation,since it is not possible to select j because all middle elements are 1
方法:考虑以下观察结果:
There are only two cases when the answer is not possible
- Case 1 : When all elements except first and last are 1
- Case 2 : When the array size is 3 and there is an odd number on middle position.
Now consider other cases:
- Number on jth position, can convert two odd numbers ( on ith and kth indices) into even by transferring 1
- and even number let’ s say x will require x/2 operations to convert into zero.
- If there are odd numbers , they will be first converted into even and then they are converted into zero ,
- If there are no odd numbers left always select first and last indices as i and j.
因此,借助上述观察,可以使用以下步骤解决此问题:
- 对于偶数(假设 x),所需的最小操作数为 x/2
- 对于奇数(假设 y),所需的最小操作数为 (y+1)/2
下面是上述方法的实现:
C++
// C++ implementation of above approach
#include
using namespace std;
void solver(int n, int arr[])
{
int ans = 0;
int cnt = 0;
int i = 0;
// Check case 1
if (n == 3 && arr[1] % 2 == 1) {
cout << -1;
return;
}
// Check case 2
for (i = 1; i < n - 1; i++) {
if (arr[i] == 1)
cnt++;
}
if (cnt == n - 2)
cout << (-1);
else {
for (i = 1; i < n - 1; i++) {
// if number is odd
// we have to first make it even
// and then increased by one
ans += (arr[i] + 1) / 2;
}
cout << (ans);
}
}
// Driver code
int main()
{
int N = 5;
int arr[] = { 1, 2, 2, 3, 6 };
solver(N, arr);
return 0;
}
// This code is contributed by rakeshsahni
Java
// Java implementation of above approach
import java.io.*;
class GFG {
public static void solver(int n, int arr[])
{
int ans = 0;
int cnt = 0;
int i = 0;
// Check case 1
if (n == 3 && arr[1] % 2 == 1) {
System.out.println(-1);
return;
}
// Check case 2
for (i = 1; i < n - 1; i++) {
if (arr[i] == 1)
cnt++;
}
if (cnt == n - 2)
System.out.println(-1);
else {
for (i = 1; i < n - 1; i++) {
// if number is odd
// we have to first make it even
// and then increased by one
ans += (arr[i] + 1) / 2;
}
System.out.println(ans);
}
}
// Driver code
public static void main(String[] args)
{
int N = 5;
int arr[] = { 1, 2, 2, 3, 6 };
solver(N, arr);
}
}
Python
# Python implementation of above approach
def solver(n, arr):
ans = 0
cnt = 0
i = 0
# Check case 1
if (n == 3 and arr[1] % 2 == 1):
print(-1)
return
# Check case 2
for i in range(1, n - 1):
if (arr[i] == 1):
cnt += 1
if (cnt == n - 2):
print(-1)
else:
for i in range(1, n - 1):
# if number is odd
# we have to first make it even
# and then increased by one
ans += (arr[i] + 1) // 2
print(ans)
# Driver code
N = 5
arr = [ 1, 2, 2, 3, 6 ]
solver(N, arr)
# This code is contributed by Samim Hossain Mondal.
C#
// C# implementation of above approach
using System;
class GFG {
public static void solver(int n, int []arr)
{
int ans = 0;
int cnt = 0;
int i = 0;
// Check case 1
if (n == 3 && arr[1] % 2 == 1) {
Console.WriteLine(-1);
return;
}
// Check case 2
for (i = 1; i < n - 1; i++) {
if (arr[i] == 1)
cnt++;
}
if (cnt == n - 2)
Console.WriteLine(-1);
else {
for (i = 1; i < n - 1; i++) {
// if number is odd
// we have to first make it even
// and then increased by one
ans += (arr[i] + 1) / 2;
}
Console.WriteLine(ans);
}
}
// Driver code
public static void Main()
{
int N = 5;
int []arr = { 1, 2, 2, 3, 6 };
solver(N, arr);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
4
时间复杂度:O(N)
辅助空间:O(1)