给定一个由N个非负整数和一个整数S组成的数组arr [] ,任务是找到通过加或减数组元素来获得总和S的方法。
注意:所有数组元素都需要包含在生成和中。
例子:
Input: arr[] = {1, 1, 1, 1, 1}, S = 3
Output: 5
Explanation:
Following are the possible ways to obtain the sum S:
- -1 + 1 + 1 + 1 + 1 = 3
- 1 -1 + 1 + 1 + 1 = 3
- 1 + 1 – 1 + 1 + 1 = 3
- 1 + 1 + 1 – 1 + 1 = 3
- 1 + 1 + 1 + 1 – 1 = 3
Input: arr[] = {1, 2, 3, 4, 5}, S = 3
Output: 3
Explanation:
Following are the possible ways to obtain the sum S:
- -1 -2 -3 + 4 + 5 = 3
- -1 + 2 + 3 + 4 – 5 = 3
- 1 – 2 + 3 – 4 + 5 = 3
递归方法:可以观察到,可以将每个数组元素相加或相减以获得总和。因此,对于每个数组元素,在到达数组末尾后获得和S时,递归检查可能性和增加计数。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to count the number of ways
int dfs(int nums[], int S, int curr_sum,
int index, int n)
{
// Base Case: Reached the
// end of the array
if (index == n)
{
// Sum is equal to the
// required sum
if (S == curr_sum)
return 1;
else
return 0;
}
// Recursively check if required sum
// can be obtained by adding current
// element or by subtracting the
// current index element
return dfs(nums, S, curr_sum + nums[index],
index + 1, n) +
dfs(nums, S, curr_sum - nums[index],
index + 1, n);
}
// Function to call dfs() to
// calculate the number of ways
int findWays(int nums[], int S, int n)
{
return dfs(nums, S, 0, 0, n);
}
// Driver Code
int main()
{
int S = 3;
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
int answer = findWays(arr, S, n);
cout << (answer);
return 0;
}
// This code is contributed by chitranayal
Java
// Java Program to implement
// the above approach
import java.io.*;
class GFG {
// Function to call dfs() to
// calculate the number of ways
static int findWays(int[] nums, int S)
{
return dfs(nums, S, 0, 0);
}
// Function to count the number of ways
static int dfs(int[] nums, int S,
int curr_sum, int index)
{
// Base Case: Reached the
// end of the array
if (index == nums.length) {
// Sum is equal to the
// required sum
if (S == curr_sum)
return 1;
else
return 0;
}
// Recursively check if required sum
// can be obtained by adding current
// element or by subtracting the
// current index element
return dfs(nums, S, curr_sum + nums[index],
index + 1)
+ dfs(nums, S, curr_sum - nums[index],
index + 1);
}
// Driver Code
public static void main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = findWays(arr, S);
System.out.println(answer);
}
}
Python3
# Python3 program to implement
# the above approach
# Function to count the number of ways
def dfs(nums, S, curr_sum, index):
# Base Case: Reached the
# end of the array
if (index == len(nums)):
# Sum is equal to the
# required sum
if (S == curr_sum):
return 1;
else:
return 0;
# Recursively check if required sum
# can be obtained by adding current
# element or by subtracting the
# current index element
return (dfs(nums, S, curr_sum + nums[index],
index + 1) +
dfs(nums, S, curr_sum - nums[index],
index + 1));
# Function to call dfs() to
# calculate the number of ways
def findWays(nums, S):
return dfs(nums, S, 0, 0);
# Driver Code
if __name__ == '__main__':
S = 3;
arr = [1, 2, 3, 4, 5];
answer = findWays(arr, S);
print(answer);
# This code is contributed by amal kumar choubey
C#
// C# Program to implement
// the above approach
using System;
class GFG{
// Function to call dfs() to
// calculate the number of ways
static int findWays(int[] nums, int S)
{
return dfs(nums, S, 0, 0);
}
// Function to count the number of ways
static int dfs(int[] nums, int S,
int curr_sum, int index)
{
// Base Case: Reached the
// end of the array
if (index == nums.Length)
{
// Sum is equal to the
// required sum
if (S == curr_sum)
return 1;
else
return 0;
}
// Recursively check if required sum
// can be obtained by adding current
// element or by subtracting the
// current index element
return dfs(nums, S, curr_sum +
nums[index], index + 1) +
dfs(nums, S, curr_sum -
nums[index], index + 1);
}
// Driver Code
public static void Main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = findWays(arr, S);
Console.WriteLine(answer);
}
}
// This code is contributed by Rajput-Ji
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to perform the DFS to calculate the
// number of ways
int dfs(vector> memo, int nums[], int S,
int curr_sum, int index, int sum, int N)
{
// Base case: Reached the end of array
if (index == N) {
// If current sum is obtained
if (S == curr_sum)
return 1;
// Otherwise
else
return 0;
}
// If previously calculated
// subproblem occurred
if (memo[index][curr_sum + sum]
!= INT_MIN) {
return memo[index][curr_sum + sum];
}
// Check if the required sum can
// be obtained by adding current
// element or by subtracting the
// current index element
int ans = dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum, N)
+ dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum, N);
// Store the count of ways
memo[index][curr_sum + sum] = ans;
return ans;
}
// Function to call dfs
// to calculate the number of ways
int findWays(int nums[], int S, int N)
{
int sum = 0;
// Iterate till the length of array
for (int i = 0; i < N; i++)
sum += nums[i];
// Initialize the memorization table
vector> memo(N + 1, vector (2 * sum + 1, INT_MIN));
return dfs(memo, nums, S, 0, 0, sum, N);
}
// Driver code
int main()
{
int S = 3;
int arr[] ={ 1, 2, 3, 4, 5 };
int N = sizeof(arr) / sizeof(arr[0]);
int answer = findWays(arr, S, N);
cout << answer << endl;
return 0;
}
// This code is contributed by divyesh072019
Java
// Java Program to implement
// the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to call dfs
// to calculate the number of ways
static int findWays(int[] nums, int S)
{
int sum = 0;
// Iterate till the length of array
for (int i = 0; i < nums.length; i++)
sum += nums[i];
// Initialize the memorization table
int[][] memo
= new int[nums.length + 1][2 * sum + 1];
for (int[] m : memo) {
Arrays.fill(m, Integer.MIN_VALUE);
}
return dfs(memo, nums, S, 0, 0, sum);
}
// Function to perform the DFS to calculate the
// number of ways
static int dfs(int[][] memo, int[] nums, int S,
int curr_sum, int index, int sum)
{
// Base case: Reached the end of array
if (index == nums.length) {
// If current sum is obtained
if (S == curr_sum)
return 1;
// Otherwise
else
return 0;
}
// If previously calculated
// subproblem occurred
if (memo[index][curr_sum + sum]
!= Integer.MIN_VALUE) {
return memo[index][curr_sum + sum];
}
// Check if the required sum can
// be obtained by adding current
// element or by subtracting the
// current index element
int ans = dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum)
+ dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum);
// Store the count of ways
memo[index][curr_sum + sum] = ans;
return ans;
}
// Driver Code
public static void main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = findWays(arr, S);
System.out.println(answer);
}
}
Python3
# Python3 program to implement
# the above approach
import sys
# Function to call dfs to
# calculate the number of ways
def findWays(nums, S):
sum = 0
# Iterate till the length of array
for i in range(len(nums)):
sum += nums[i]
# Initialize the memorization table
memo = [[-sys.maxsize - 1 for i in range(2 * sum + 1)]
for j in range(len(nums) + 1)]
return dfs(memo, nums, S, 0, 0, sum)
# Function to perform the DFS to calculate the
# number of ways
def dfs(memo, nums, S, curr_sum, index, sum):
# Base case: Reached the end of array
if (index == len(nums)):
# If current sum is obtained
if (S == curr_sum):
return 1
# Otherwise
else:
return 0
# If previously calculated
# subproblem occurred
if (memo[index][curr_sum + sum] != -sys.maxsize - 1):
return memo[index][curr_sum + sum]
# Check if the required sum can
# be obtained by adding current
# element or by subtracting the
# current index element
ans = (dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum) +
dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum))
# Store the count of ways
memo[index][curr_sum + sum] = ans
return ans
# Driver Code
if __name__ == '__main__':
S = 3
arr = [ 1, 2, 3, 4, 5 ]
answer = findWays(arr, S)
print(answer)
# This code is contributed by bgangwar59
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Function to call dfs
// to calculate the number of ways
static int findWays(int[] nums, int S)
{
int sum = 0;
// Iterate till the length of array
for(int i = 0; i < nums.Length; i++)
sum += nums[i];
// Initialize the memorization table
int[,] memo = new int[nums.Length + 1,
2 * sum + 1];
for(int i = 0; i < memo.GetLength(0); i++)
{
for(int j = 0; j < memo.GetLength(1); j++)
{
memo[i, j] = int.MinValue;
}
}
return dfs(memo, nums, S, 0, 0, sum);
}
// Function to perform the DFS to calculate the
// number of ways
static int dfs(int[,] memo, int[] nums, int S,
int curr_sum, int index, int sum)
{
// Base case: Reached the end of array
if (index == nums.Length)
{
// If current sum is obtained
if (S == curr_sum)
return 1;
// Otherwise
else
return 0;
}
// If previously calculated
// subproblem occurred
if (memo[index, curr_sum + sum] != int.MinValue)
{
return memo[index, curr_sum + sum];
}
// Check if the required sum can
// be obtained by adding current
// element or by subtracting the
// current index element
int ans = dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum) +
dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum);
// Store the count of ways
memo[index, curr_sum + sum] = ans;
return ans;
}
// Driver Code
public static void Main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = findWays(arr, S);
Console.WriteLine(answer);
}
}
// This code is contributed by Amit Katiyar
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to call dfs
// to calculate the number of ways
int knapSack(int nums[], int S, int n)
{
int sum = 0;
for(int i = 0; i < n; i++)
sum += nums[i];
// If target + sum is odd or
// S exceeds sum
if (sum < S || -sum > -S ||
(S + sum) % 2 == 1)
// No sultion exists
return 0;
int dp[(S + sum) / 2 + 1];
for(int i = 0; i <= (S + sum) / 2; i++)
dp[i] = 0;
dp[0] = 1;
for(int j = 0; j < n; j++)
{
for(int i = (S + sum) / 2;
i >= nums[j]; i--)
{
dp[i] += dp[i - nums[j]];
}
}
// Return the answer
return dp[(S + sum) / 2];
}
// Driver Code
int main()
{
int S = 3;
int arr[] = { 1, 2, 3, 4, 5 };
int answer = knapSack(arr, S, 5);
cout << answer << endl;
}
// This code is contributed by amal kumar choubey
Java
// Java Program to implement
// the above approach
import java.io.*;
class GFG {
// Function to call dfs
// to calculate the number of ways
static int knapSack(int[] nums, int S)
{
int sum = 0;
for (int i : nums)
sum += i;
// If target + sum is odd or S exceeds sum
if (sum < S || -sum > -S || (S + sum) % 2 == 1)
// No sultion exists
return 0;
int[] dp = new int[(S + sum) / 2 + 1];
dp[0] = 1;
for (int num : nums) {
for (int i = dp.length - 1; i >= num; i--) {
dp[i] += dp[i - num];
}
}
// Return the answer
return dp[dp.length - 1];
}
// Driver Code
public static void main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = knapSack(arr, S);
System.out.println(answer);
}
}
Python3
# Python3 Program to implement
# the above approach
# Function to call dfs
# to calculate the number of ways
def knapSack(nums, S):
sum = 0;
for i in range(len(nums)):
sum += nums[i];
# If target + sum is odd or S exceeds sum
if (sum < S or -sum > -S or
(S + sum) % 2 == 1):
# No sultion exists
return 0;
dp = [0]*(((S + sum) // 2) + 1);
dp[0] = 1;
for j in range(len(nums)):
for i in range(len(dp) - 1, nums[j] - 1, -1):
dp[i] += dp[i - nums[j]];
# Return the answer
return dp[len(dp) - 1];
# Driver Code
if __name__ == '__main__':
S = 3;
arr = [1, 2, 3, 4, 5 ];
answer = knapSack(arr, S);
print(answer);
# This code is contributed by Princi Singh
C#
// C# Program to implement
// the above approach
using System;
class GFG{
// Function to call dfs
// to calculate the number of ways
static int knapSack(int[] nums, int S)
{
int sum = 0;
foreach (int i in nums)
sum += i;
// If target + sum is odd or S exceeds sum
if (sum < S || -sum > -S ||
(S + sum) % 2 == 1)
// No sultion exists
return 0;
int[] dp = new int[(S + sum) / 2 + 1];
dp[0] = 1;
foreach (int num in nums)
{
for (int i = dp.Length - 1; i >= num; i--)
{
dp[i] += dp[i - num];
}
}
// Return the answer
return dp[dp.Length - 1];
}
// Driver Code
public static void Main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = knapSack(arr, S);
Console.WriteLine(answer);
}
}
// This code is contributed by Rajput-Ji
输出:
3
时间复杂度: O(2 N )
辅助空间: O(1)
动态编程方法:可以通过使用记忆化来优化上述递归方法。
下面是上述方法的实现:
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to perform the DFS to calculate the
// number of ways
int dfs(vector> memo, int nums[], int S,
int curr_sum, int index, int sum, int N)
{
// Base case: Reached the end of array
if (index == N) {
// If current sum is obtained
if (S == curr_sum)
return 1;
// Otherwise
else
return 0;
}
// If previously calculated
// subproblem occurred
if (memo[index][curr_sum + sum]
!= INT_MIN) {
return memo[index][curr_sum + sum];
}
// Check if the required sum can
// be obtained by adding current
// element or by subtracting the
// current index element
int ans = dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum, N)
+ dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum, N);
// Store the count of ways
memo[index][curr_sum + sum] = ans;
return ans;
}
// Function to call dfs
// to calculate the number of ways
int findWays(int nums[], int S, int N)
{
int sum = 0;
// Iterate till the length of array
for (int i = 0; i < N; i++)
sum += nums[i];
// Initialize the memorization table
vector> memo(N + 1, vector (2 * sum + 1, INT_MIN));
return dfs(memo, nums, S, 0, 0, sum, N);
}
// Driver code
int main()
{
int S = 3;
int arr[] ={ 1, 2, 3, 4, 5 };
int N = sizeof(arr) / sizeof(arr[0]);
int answer = findWays(arr, S, N);
cout << answer << endl;
return 0;
}
// This code is contributed by divyesh072019
Java
// Java Program to implement
// the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to call dfs
// to calculate the number of ways
static int findWays(int[] nums, int S)
{
int sum = 0;
// Iterate till the length of array
for (int i = 0; i < nums.length; i++)
sum += nums[i];
// Initialize the memorization table
int[][] memo
= new int[nums.length + 1][2 * sum + 1];
for (int[] m : memo) {
Arrays.fill(m, Integer.MIN_VALUE);
}
return dfs(memo, nums, S, 0, 0, sum);
}
// Function to perform the DFS to calculate the
// number of ways
static int dfs(int[][] memo, int[] nums, int S,
int curr_sum, int index, int sum)
{
// Base case: Reached the end of array
if (index == nums.length) {
// If current sum is obtained
if (S == curr_sum)
return 1;
// Otherwise
else
return 0;
}
// If previously calculated
// subproblem occurred
if (memo[index][curr_sum + sum]
!= Integer.MIN_VALUE) {
return memo[index][curr_sum + sum];
}
// Check if the required sum can
// be obtained by adding current
// element or by subtracting the
// current index element
int ans = dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum)
+ dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum);
// Store the count of ways
memo[index][curr_sum + sum] = ans;
return ans;
}
// Driver Code
public static void main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = findWays(arr, S);
System.out.println(answer);
}
}
Python3
# Python3 program to implement
# the above approach
import sys
# Function to call dfs to
# calculate the number of ways
def findWays(nums, S):
sum = 0
# Iterate till the length of array
for i in range(len(nums)):
sum += nums[i]
# Initialize the memorization table
memo = [[-sys.maxsize - 1 for i in range(2 * sum + 1)]
for j in range(len(nums) + 1)]
return dfs(memo, nums, S, 0, 0, sum)
# Function to perform the DFS to calculate the
# number of ways
def dfs(memo, nums, S, curr_sum, index, sum):
# Base case: Reached the end of array
if (index == len(nums)):
# If current sum is obtained
if (S == curr_sum):
return 1
# Otherwise
else:
return 0
# If previously calculated
# subproblem occurred
if (memo[index][curr_sum + sum] != -sys.maxsize - 1):
return memo[index][curr_sum + sum]
# Check if the required sum can
# be obtained by adding current
# element or by subtracting the
# current index element
ans = (dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum) +
dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum))
# Store the count of ways
memo[index][curr_sum + sum] = ans
return ans
# Driver Code
if __name__ == '__main__':
S = 3
arr = [ 1, 2, 3, 4, 5 ]
answer = findWays(arr, S)
print(answer)
# This code is contributed by bgangwar59
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Function to call dfs
// to calculate the number of ways
static int findWays(int[] nums, int S)
{
int sum = 0;
// Iterate till the length of array
for(int i = 0; i < nums.Length; i++)
sum += nums[i];
// Initialize the memorization table
int[,] memo = new int[nums.Length + 1,
2 * sum + 1];
for(int i = 0; i < memo.GetLength(0); i++)
{
for(int j = 0; j < memo.GetLength(1); j++)
{
memo[i, j] = int.MinValue;
}
}
return dfs(memo, nums, S, 0, 0, sum);
}
// Function to perform the DFS to calculate the
// number of ways
static int dfs(int[,] memo, int[] nums, int S,
int curr_sum, int index, int sum)
{
// Base case: Reached the end of array
if (index == nums.Length)
{
// If current sum is obtained
if (S == curr_sum)
return 1;
// Otherwise
else
return 0;
}
// If previously calculated
// subproblem occurred
if (memo[index, curr_sum + sum] != int.MinValue)
{
return memo[index, curr_sum + sum];
}
// Check if the required sum can
// be obtained by adding current
// element or by subtracting the
// current index element
int ans = dfs(memo, nums, index + 1,
curr_sum + nums[index], S, sum) +
dfs(memo, nums, index + 1,
curr_sum - nums[index], S, sum);
// Store the count of ways
memo[index, curr_sum + sum] = ans;
return ans;
}
// Driver Code
public static void Main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = findWays(arr, S);
Console.WriteLine(answer);
}
}
// This code is contributed by Amit Katiyar
输出:
3
时间复杂度: O(N * S)
辅助空间: O(N * S)
背包法:这个想法是要实现0/1背包问题。请按照以下步骤操作:
- 原始问题简化为找到找到全部为正的arr []子集而其余元素为负的方法的数量,以使它们的总和等于S。
- 因此,问题是从给定的数组中不找到具有和(S + totalSum)/ 2的子集。 。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to call dfs
// to calculate the number of ways
int knapSack(int nums[], int S, int n)
{
int sum = 0;
for(int i = 0; i < n; i++)
sum += nums[i];
// If target + sum is odd or
// S exceeds sum
if (sum < S || -sum > -S ||
(S + sum) % 2 == 1)
// No sultion exists
return 0;
int dp[(S + sum) / 2 + 1];
for(int i = 0; i <= (S + sum) / 2; i++)
dp[i] = 0;
dp[0] = 1;
for(int j = 0; j < n; j++)
{
for(int i = (S + sum) / 2;
i >= nums[j]; i--)
{
dp[i] += dp[i - nums[j]];
}
}
// Return the answer
return dp[(S + sum) / 2];
}
// Driver Code
int main()
{
int S = 3;
int arr[] = { 1, 2, 3, 4, 5 };
int answer = knapSack(arr, S, 5);
cout << answer << endl;
}
// This code is contributed by amal kumar choubey
Java
// Java Program to implement
// the above approach
import java.io.*;
class GFG {
// Function to call dfs
// to calculate the number of ways
static int knapSack(int[] nums, int S)
{
int sum = 0;
for (int i : nums)
sum += i;
// If target + sum is odd or S exceeds sum
if (sum < S || -sum > -S || (S + sum) % 2 == 1)
// No sultion exists
return 0;
int[] dp = new int[(S + sum) / 2 + 1];
dp[0] = 1;
for (int num : nums) {
for (int i = dp.length - 1; i >= num; i--) {
dp[i] += dp[i - num];
}
}
// Return the answer
return dp[dp.length - 1];
}
// Driver Code
public static void main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = knapSack(arr, S);
System.out.println(answer);
}
}
Python3
# Python3 Program to implement
# the above approach
# Function to call dfs
# to calculate the number of ways
def knapSack(nums, S):
sum = 0;
for i in range(len(nums)):
sum += nums[i];
# If target + sum is odd or S exceeds sum
if (sum < S or -sum > -S or
(S + sum) % 2 == 1):
# No sultion exists
return 0;
dp = [0]*(((S + sum) // 2) + 1);
dp[0] = 1;
for j in range(len(nums)):
for i in range(len(dp) - 1, nums[j] - 1, -1):
dp[i] += dp[i - nums[j]];
# Return the answer
return dp[len(dp) - 1];
# Driver Code
if __name__ == '__main__':
S = 3;
arr = [1, 2, 3, 4, 5 ];
answer = knapSack(arr, S);
print(answer);
# This code is contributed by Princi Singh
C#
// C# Program to implement
// the above approach
using System;
class GFG{
// Function to call dfs
// to calculate the number of ways
static int knapSack(int[] nums, int S)
{
int sum = 0;
foreach (int i in nums)
sum += i;
// If target + sum is odd or S exceeds sum
if (sum < S || -sum > -S ||
(S + sum) % 2 == 1)
// No sultion exists
return 0;
int[] dp = new int[(S + sum) / 2 + 1];
dp[0] = 1;
foreach (int num in nums)
{
for (int i = dp.Length - 1; i >= num; i--)
{
dp[i] += dp[i - num];
}
}
// Return the answer
return dp[dp.Length - 1];
}
// Driver Code
public static void Main(String[] args)
{
int S = 3;
int[] arr = new int[] { 1, 2, 3, 4, 5 };
int answer = knapSack(arr, S);
Console.WriteLine(answer);
}
}
// This code is contributed by Rajput-Ji
输出:
3
时间复杂度: O(n *(sum + S)),其中sum表示数组的和
辅助空间: O(S + sum)