将数组拆分为 K 个子数组,使所有子数组的最大值之和最大化
给定一个大小为N的数组arr[]和一个数字K ,任务是对给定的数组进行分区 分成K个连续的子数组,使得每个子数组的最大值之和是可能的最大值。如果可以以这种方式拆分数组,则打印最大可能的总和。否则,打印“ -1 ”。
例子:
Input: arr[] = {5, 3, 2, 7, 6, 4}, N = 6, K = 3
Output: 18
5
3 2 7
6 4
Explanation:
One way is to split the array at indices 0, 3 and 4.
Therefore, the subarrays formed are {5}, {3, 2, 7} and {6, 4}.
Therefore, sum of the maximum of each subarray = 5 + 7 + 6 =18 ( which is the maximum possible).
Input: arr[] = {1, 4, 5, 6, 1, 2}, N = 6, K = 2
Output: 11
方法:基于以下观察,可以使用 Map 数据结构和排序技术来解决给定的问题:
- The maximum obtainable sum would be the sum of the K-largest elements of the array as it is always possible to divide the array into K segments in such a way that the maximum of each segment is one of the K-largest elements.
- One way would be to break a segment as soon as one of the K-largest element is encountered.
请按照以下步骤解决问题:
- 首先,如果N小于K则打印“ -1 ”然后返回。
- 将数组复制到另一个数组中,例如temp[]并按降序对数组 temp[] 进行排序。
- 将变量ans初始化为0 ,以存储可能的最大总和。
- 此外,初始化一个地图说mp ,以存储K 最大元素的频率。
- 使用变量i在[0, K-1]范围内迭代,并且在每次迭代中将ans增加temp[i]并增加 map mp中temp[i]的计数。
- 初始化一个向量的向量,比如说P来存储一个可能的分区,一个向量说V来存储一个分区的元素。
- 在[0, N-1]范围内迭代并使用变量 say i并执行以下步骤:
- 将当前元素arr[i]推入向量V中。
- 如果mp[arr[i]]大于0 ,则执行以下操作:
- 将映射mp中的K和arr[i]的计数减1 。
- 如果K等于0 ,即它是最后一段,则将数组arr[]的所有剩余元素推入V。
- 现在将当前段V推入P 。
- 最后,完成上述步骤后,将最大和存储在变量ans中,然后分区存储在P中。
下面是上述方法的实现:
C++
// C++ program for tha above approach
#include
using namespace std;
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
void partitionIntoKSegments(int arr[],
int N, int K)
{
// If N is less than K
if (N < K) {
cout << -1 << endl;
return;
}
// Map to store the K
// largest elements
map mp;
// Auxiliary array to
// store and sort arr[]
int temp[N];
// Stores the maximum sum
int ans = 0;
// Copy arr[] to temp[]
for (int i = 0; i < N; i++) {
temp[i] = arr[i];
}
// Sort array temp[] in
// descending order
sort(temp, temp + N,
greater());
// Iterate in the range [0, K - 1]
for (int i = 0; i < K; i++) {
// Increment sum by temp[i]
ans += temp[i];
// Increment count of
// temp[i] in the map mp
mp[temp[i]]++;
}
// Stores the partitions
vector > P;
// Stores temporary subarrays
vector V;
// Iterate over the range [0, N - 1]
for (int i = 0; i < N; i++) {
V.push_back(arr[i]);
// If current element is
// one of the K largest
if (mp[arr[i]] > 0) {
mp[arr[i]]--;
K--;
if (K == 0) {
i++;
while (i < N) {
V.push_back(arr[i]);
i++;
}
}
if (V.size()) {
P.push_back(V);
V.clear();
}
}
}
// Print the ans
cout << ans << endl;
// Print the partition
for (auto u : P) {
for (auto x : u)
cout << x << " ";
cout << endl;
}
}
// Driver code
int main()
{
// Input
int A[] = { 5, 3, 2, 7, 6, 4 };
int N = sizeof(A) / sizeof(A[0]);
int K = 3;
// Function call
partitionIntoKSegments(A, N, K);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
public class GFG
{
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
static void partitionIntoKSegments(int arr[], int N, int K)
{
// If N is less than K
if (N < K)
{
System.out.println(-1);
return;
}
// Map to store the K
// largest elements
HashMap mp = new HashMap();
// Auxiliary array to
// store and sort arr[]
Integer []temp = new Integer[N];
// Stores the maximum sum
int ans = 0;
// Copy arr[] to temp[]
for(int i = 0; i < N; i++)
{
temp[i] = arr[i];
}
// Sort array temp[] in
// descending order
Arrays.sort(temp,Collections.reverseOrder());
//Array.Reverse(temp);
// Iterate in the range [0, K - 1]
for(int i = 0; i < K; i++)
{
// Increment sum by temp[i]
ans += temp[i];
// Increment count of
// temp[i] in the map mp
if (mp.containsKey(temp[i]))
mp.get(temp[i]++);
else
mp.put(temp[i], 1);
}
// Stores the partitions
ArrayList> P = new ArrayList>();
// Stores temporary subarrays
ArrayList V = new ArrayList();
// Iterate over the range [0, N - 1]
for(int i = 0; i < N; i++)
{
V.add(arr[i]);
// If current element is
// one of the K largest
if (mp.containsKey(arr[i]) && mp.get(arr[i]) > 0)
{
mp.get(arr[i]--);
K--;
if (K == 0)
{
i++;
while (i < N)
{
V.add(arr[i]);
i++;
}
}
if (V.size() > 0)
{
P.add(new ArrayList(V));
V.clear();
}
}
}
// Print the ans
System.out.println(ans);
// Print the partition
for (ArrayList subList : P)
{
for(Integer item : subList)
{
System.out.print(item+" ");
}
System.out.println();
}
}
// Driver code
public static void main(String args[])
{
// Input
int []A = { 5, 3, 2, 7, 6, 4 };
int N = A.length;
int K = 3;
// Function call
partitionIntoKSegments(A, N, K);
}
}
// This code is contributed by SoumikMondal
Python3
# Python program for tha above approach
# Function to split the array into K
# subarrays such that the sum of
# maximum of each subarray is maximized
def partitionIntoKSegments(arr, N, K):
# If N is less than K
if (N < K):
print(-1)
return
# Map to store the K
# largest elements
mp = {}
# Auxiliary array to
# store and sort arr[]
temp = [0]*N
# Stores the maximum sum
ans = 0
# Copy arr[] to temp[]
for i in range(N):
temp[i] = arr[i]
# Sort array temp[] in
# descending order
temp = sorted(temp)[::-1]
# Iterate in the range [0, K - 1]
for i in range(K):
# Increment sum by temp[i]
ans += temp[i]
# Increment count of
# temp[i] in the map mp
mp[temp[i]] = mp.get(temp[i], 0) + 1
# Stores the partitions
P = []
# Stores temporary subarrays
V = []
# Iterate over the range [0, N - 1]
for i in range(N):
V.append(arr[i])
# If current element is
# one of the K largest
if (arr[i] in mp):
mp[arr[i]] -= 1
K -= 1
if (K == 0):
i += 1
while (i < N):
V.append(arr[i])
i += 1
# print(V)
if (len(V) > 0):
P.append(list(V))
V.clear()
# Print ans
print(ans)
# Print partition
for u in P:
for x in u:
print(x,end=" ")
print()
# Driver code
if __name__ == '__main__':
# Input
A = [5, 3, 2, 7, 6, 4]
N = len(A)
K = 3
# Function call
partitionIntoKSegments(A, N, K)
# This code is contributed by mohit kumar 29.
C#
// C# program for tha above approach
using System;
using System.Collections.Generic;
class GFG{
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
static void partitionIntoKSegments(int []arr,
int N, int K)
{
// If N is less than K
if (N < K)
{
Console.WriteLine(-1);
return;
}
// Map to store the K
// largest elements
Dictionary mp = new Dictionary();
// Auxiliary array to
// store and sort arr[]
int []temp = new int[N];
// Stores the maximum sum
int ans = 0;
// Copy arr[] to temp[]
for(int i = 0; i < N; i++)
{
temp[i] = arr[i];
}
// Sort array temp[] in
// descending order
Array.Sort(temp);
Array.Reverse(temp);
// Iterate in the range [0, K - 1]
for(int i = 0; i < K; i++)
{
// Increment sum by temp[i]
ans += temp[i];
// Increment count of
// temp[i] in the map mp
if (mp.ContainsKey(temp[i]))
mp[temp[i]]++;
else
mp.Add(temp[i],1);
}
// Stores the partitions
List> P = new List>();
// Stores temporary subarrays
List V = new List();
// Iterate over the range [0, N - 1]
for(int i = 0; i < N; i++)
{
V.Add(arr[i]);
// If current element is
// one of the K largest
if (mp.ContainsKey(arr[i]) && mp[arr[i]] > 0)
{
mp[arr[i]]--;
K--;
if (K == 0)
{
i++;
while (i < N)
{
V.Add(arr[i]);
i++;
}
}
if (V.Count > 0)
{
P.Add(new List(V));
V.Clear();
}
}
}
// Print the ans
Console.WriteLine(ans);
// Print the partition
foreach (List subList in P)
{
foreach (int item in subList)
{
Console.Write(item+" ");
}
Console.WriteLine();
}
}
// Driver code
public static void Main()
{
// Input
int []A = { 5, 3, 2, 7, 6, 4 };
int N = A.Length;
int K = 3;
// Function call
partitionIntoKSegments(A, N, K);
}
}
// This code is contributed by SURENDRA_GANGWAR
Javascript
输出:
18
5
3 2 7
6 4
时间复杂度: O(N*log(N))
辅助空间: O(N)