添加到 arr[i] 的最小值,以便可以在索引 i 处以相等的总和拆分数组
给定一个整数数组arr[] ,任务是找到最小非负整数k使得给定数组中存在索引j使得当arr[j]更新为arr[j] + k时,从索引arr[0]到arr[j]的数组元素之和等于从arr[j + 1]到arr[n – 1]的元素之和,即
arr[0] + arr[1] + … + arr[j] = arr[j + 1] + arr[j + 2] + … + arr[n – 1]
.
如果不存在这样的k则打印-1 。
例子:
Input: arr[] = {6, 7, 1, 3, 8, 2, 4}
Output: 3
If 3 is added to 1 sum of elements from index 0 to 2 and 3 to 6 will be equal to 17.
Input: arr[] = {7, 3}
Output: -1
一个简单的方法是运行两个循环。对于每个元素,找出左右元素之和之间的差异。最后,返回两个和之间的最小差。
一种有效的方法:首先计算前缀总和并存储在数组pre[]中,其中pre[i]存储从arr[0]到arr[i]的数组元素的总和。对于每个索引,如果左侧元素的总和(包括元素本身,即 pre[i])小于或等于右侧元素的总和(pre[n – 1] – pre[i]),则更新k的值为min(k, (pre[n – 1] – pre[i]) – pre[i])
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to return the minimum value k to be added
int FindMinNum(int arr[], int n)
{
// Array to store prefix sum
int pre[n];
// Initialize the prefix value for first index
// as the first element of the array
pre[0] = arr[0];
// Compute the prefix sum for rest of the indices
for (int i = 1; i < n; i++)
pre[i] = pre[i - 1] + arr[i];
int k = INT_MAX;
for (int i = 0; i < n - 1; i++) {
// Sum of elements from arr[i + 1] to arr[n - 1]
int rightSum = pre[n - 1] - pre[i];
// If sum on the right side of the ith element
// is greater than or equal to the sum on the
// left side then update the value of k
if (rightSum >= pre[i])
k = min(k, rightSum - pre[i]);
}
if (k != INT_MAX)
return k;
return -1;
}
// Driver code
int main()
{
int arr[] = { 6, 7, 1, 3, 8, 2, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << FindMinNum(arr, n);
return 0;
}
Java
// Java implementation of the approach
class GfG
{
// Function to return the minimum value k to be added
static int FindMinNum(int arr[], int n)
{
// Array to store prefix sum
int pre[] = new int[n];
// Initialize the prefix value for first index
// as the first element of the array
pre[0] = arr[0];
// Compute the prefix sum for rest of the indices
for (int i = 1; i < n; i++)
pre[i] = pre[i - 1] + arr[i];
int k = Integer.MAX_VALUE;
for (int i = 0; i < n - 1; i++)
{
// Sum of elements from arr[i + 1] to arr[n - 1]
int rightSum = pre[n - 1] - pre[i];
// If sum on the right side of the ith element
// is greater than or equal to the sum on the
// left side then update the value of k
if (rightSum >= pre[i])
k = Math.min(k, rightSum - pre[i]);
}
if (k != Integer.MAX_VALUE)
return k;
return -1;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 6, 7, 1, 3, 8, 2, 4 };
int n = arr.length;
System.out.println(FindMinNum(arr, n));
}
}
// This code is contributed by Prerna Saini
Python3
# Python 3 implementation of the approach
import sys
# Function to return the minimum
# value k to be added
def FindMinNum(arr, n):
# Array to store prefix sum
pre = [0 for i in range(n)]
# Initialize the prefix value for first
# index as the first element of the array
pre[0] = arr[0]
# Compute the prefix sum for rest
# of the indices
for i in range(1, n, 1):
pre[i] = pre[i - 1] + arr[i]
k = sys.maxsize
for i in range(n - 1):
# Sum of elements from arr[i + 1] to arr[n - 1]
rightSum = pre[n - 1] - pre[i]
# If sum on the right side of the ith element
# is greater than or equal to the sum on the
# left side then update the value of k
if (rightSum >= pre[i]):
k = min(k, rightSum - pre[i])
if (k != sys.maxsize):
return k
return -1
# Driver code
if __name__ == '__main__':
arr = [6, 7, 1, 3, 8, 2, 4]
n = len(arr)
print(FindMinNum(arr, n))
# This code is contributed by
# Surendra_Gangwar
C#
// C# implementation of the approach
using System;
class GfG
{
// Function to return the minimum value k to be added
static int FindMinNum(int []arr, int n)
{
// Array to store prefix sum
int []pre = new int[n];
// Initialize the prefix value for first index
// as the first element of the array
pre[0] = arr[0];
// Compute the prefix sum for rest of the indices
for (int i = 1; i < n; i++)
pre[i] = pre[i - 1] + arr[i];
int k = int.MaxValue;
for (int i = 0; i < n - 1; i++)
{
// Sum of elements from arr[i + 1] to arr[n - 1]
int rightSum = pre[n - 1] - pre[i];
// If sum on the right side of the ith element
// is greater than or equal to the sum on the
// left side then update the value of k
if (rightSum >= pre[i])
k = Math.Min(k, rightSum - pre[i]);
}
if (k != int.MaxValue)
return k;
return -1;
}
// Driver code
public static void Main()
{
int []arr = { 6, 7, 1, 3, 8, 2, 4 };
int n = arr.Length;
Console.WriteLine(FindMinNum(arr, n));
}
}
// This code is contributed by Ryuga
PHP
= $pre[$i])
$k = min($k, $rightSum - $pre[$i]);
}
if ($k != PHP_INT_MAX)
return $k;
return -1;
}
// Driver code
$arr = array(6, 7, 1, 3, 8, 2, 4);
$n = sizeof($arr);
echo FindMinNum($arr, $n);
// This code is contributed by Akanksha Rai
?>
Javascript
3
时间复杂度: O(n)
辅助空间: O(n)
进一步优化:我们可以通过以下步骤避免使用额外的空间。
1) 计算所有元素的总和。
2) 不断加左和,总和减去左和就可以得到右和。
这个想法类似于平衡指数问题的优化解决方案。
时间复杂度: O(n)
辅助空间: O(1)