通过将元素分成两部分来最小化以非降序对数组进行排序的移动
给定一个由N个整数组成的arr[]数组,任务是通过将任何数组元素分成两部分以使部分之和与元素。
例子:
Input: arr[] = {3, 4, 2}
Output: 2
Explanation: The moevs are:
Split 4 into two parts {2, 2}. Array becomes arr[] = {3, 2, 2, 2}
Split 3 into two parts {1, 2}. Array becomes arr[] = {1, 2, 2, 2, 2}
Input: arr[] = {3, 2, 4}
Output: 1
Explanation: Split 3 into two parts {1, 2}. [3, 2, 4] -> [1, 2, 2, 4]
方法:问题的解决基于以下观察:
As there is need to minimize the operations so keep the rightmost elements as large as possible, i.e., don;t split it.
To minimze operations, split a number into numbers as large as possible and as close to the element just right to it.
请按照以下步骤解决此问题:
- 从数组 i = N-2 最右边的元素遍历到 0。
- 将数组元素拆分为尽可能大的两部分,并且不超过右侧的元素,并增加拆分的计数。
- 继续此操作,直到拆分 arr[i] 获得的值不小于其右侧获得的最小值。
- 更新此过程中得到的最小值。
- 返回拆分的总数作为答案。
下面是上述方法的实现:
C++
// C++ code to implement the approach
#include
#include
using namespace std;
// Function to find the minimum
// number of split
int minimumSplits(vector arr)
{
int totalSplits = 0;
// Get the value at the last index
int prevVal = arr.back();
for (int idx = arr.size() - 2;
idx >= 0; idx--) {
totalSplits
+= (arr[idx] - 1) / prevVal;
int numGroups
= ((arr[idx] - 1) / prevVal + 1);
prevVal = arr[idx] / numGroups;
}
return totalSplits;
}
// Driver Code
int main()
{
vector arr{ 3, 2, 4 };
// Function call
int minSplit = minimumSplits(arr);
cout << minSplit << endl;
return 0;
}
Java
// Java code to implement the approach
import java.lang.*;
import java.util.*;
class GFG {
// Function to count the minimum
// number of splits
public static int minimumSplits(int arr[],
int n)
{
int totalSplits = 0;
// Get the value at the last index
int prevVal = arr[n - 1];
for (int idx = n - 2; idx >= 0;
idx--) {
totalSplits
+= (arr[idx] - 1) / prevVal;
int numGroups
= ((arr[idx] - 1)
/ prevVal
+ 1);
prevVal = arr[idx] / numGroups;
}
return totalSplits;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 3, 2, 4 };
int N = arr.length;
int minSplit = minimumSplits(arr, N);
System.out.print(minSplit);
}
}
Python3
# Python code to implement the approach
# Function to find the minimum
# number of split
def minimumSplits(arr):
totalSplits = 0
# Get the value at the last index
prevVal = arr[len(arr) - 1]
for idx in range(len(arr) - 2,-1,-1):
totalSplits += (arr[idx] - 1) // prevVal
numGroups = ((arr[idx] - 1) // prevVal + 1)
prevVal = arr[idx] // numGroups
return totalSplits
# Driver Code
arr = [ 3, 2, 4 ]
# Function call
minSplit = minimumSplits(arr)
print(minSplit)
# This code is contributed by shinjanpatra
C#
// C# code to implement the approach
using System;
using System.Collections.Generic;
public class GFG
{
// Function to count the minimum
// number of splits
public static int minimumSplits(int[] arr, int n)
{
int totalSplits = 0;
// Get the value at the last index
int prevVal = arr[n - 1];
for (int idx = n - 2; idx >= 0; idx--) {
totalSplits += (arr[idx] - 1) / prevVal;
int numGroups = ((arr[idx] - 1) / prevVal + 1);
prevVal = arr[idx] / numGroups;
}
return totalSplits;
}
// Driver Code
public static void Main(string[] args)
{
int[] arr = { 3, 2, 4 };
int N = arr.Length;
// function call
int minSplit = minimumSplits(arr, N);
Console.Write(minSplit);
}
}
// This code is contributed by phasing17
Javascript
1
时间复杂度: O(N)
辅助空间: O(1)