Algorithm 如果可能有子序列和,则查找
给定一个数组Algorithm 如果可能有子序列和,则查找,algorithm,subsequence,Algorithm,Subsequence,给定一个数组A和sum,我想知道是否存在长度为K的子序列,使得子序列中所有元素的总和等于给定的sum 代码: 时间复杂度O(N^2.Sum)。有没有办法将时间复杂度提高到O(N.Sum)让Is_subset\u Sum(int set[],int N,int Sum)成为查找是否存在Sum等于Sum的set[]子集的函数n是集合[]中的元素数 是子集和问题可分为两个子问题 包括最后一个元素,n=n-1时重复,sum=sum–set[n-1] 排除最后一个元素,重复n=n-1 如果上述任何子问
A
和sum
,我想知道是否存在长度为K
的子序列,使得子序列中所有元素的总和等于给定的sum
代码:
时间复杂度O(N^2.Sum)。有没有办法将时间复杂度提高到O(N.Sum)让Is_subset\u Sum(int set[],int N,int Sum)
成为查找是否存在Sum等于Sum的set[]
子集的函数n
是集合[]
中的元素数
是子集和问题
可分为两个子问题
- 包括最后一个元素,n=n-1时重复,sum=sum–set[n-1]
- 排除最后一个元素,重复n=n-1
is_subset_sum(set, n, sum) = is_subset_sum(set, n-1, sum) || is_subset_sum(set, n-1, sum-set[n-1])
Base Cases:
is_subset_sum(set, n, sum) = false, if sum > 0 and n == 0
is_subset_sum(set, n, sum) = true, if sum == 0
我们可以用动态规划来解决这个问题。我们创建一个布尔2D表子集[],并以自下而上的方式填充它。如果集合[0..j-1]的子集和等于i,则子集[i][j]的值为真,否则为假。最后,我们返回子集[sum][n]
解的时间复杂度为O(sum*n)
用C实现
// A Dynamic Programming solution for subset sum problem
#include <stdio.h>
// Returns true if there is a subset of set[] with sun equal to given sum
bool is_subset_sum(int set[], int n, int sum) {
// The value of subset[i][j] will be true if there is a
// subset of set[0..j-1] with sum equal to i
bool subset[sum+1][n+1];
// If sum is 0, then answer is true
for (int i = 0; i <= n; i++)
subset[0][i] = true;
// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++)
subset[i][0] = false;
// Fill the subset table in botton up manner
for (int i = 1; i <= sum; i++) {
for (int j = 1; j <= n; j++) {
subset[i][j] = subset[i][j-1];
if (i >= set[j-1])
subset[i][j] = subset[i][j] || subset[i - set[j-1]][j-1];
}
}
/* // uncomment this code to print table
for (int i = 0; i <= sum; i++) {
for (int j = 0; j <= n; j++)
printf ("%4d", subset[i][j]);
printf("\n");
} */
return subset[sum][n];
}
// Driver program to test above function
int main() {
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = sizeof(set)/sizeof(set[0]);
if (is_subset_sum(set, n, sum) == true)
printf("Found a subset with given sum");
else
printf("No subset with given sum");
return 0;
}
//子集和问题的动态规划解法
#包括
//如果存在集[]的子集且sun等于给定的和,则返回true
布尔是子集和(整数集[],整数n,整数和){
//如果存在错误,则子集[i][j]的值将为真
//和等于i的集合[0..j-1]的子集
布尔子集[sum+1][n+1];
//若总和为0,则答案为真
对于(int i=0;i编辑:
这实际上可以在没有队列的情况下在线性时间内解决(允许负数)
C#代码:
bool子序列存在(int[]a,int k,int sum)
{
int currentSum=0;
如果(a.Length
原始答案:
假设您可以使用一个长度为K的队列,类似这样的队列应该在线性时间内完成任务
C#代码:
bool子序列存在(int[]a,int k,int sum)
{
int currentSum=0;
var queue=新队列();
for(int i=0;i
这背后的逻辑非常简单:
我们用第一个K
元素填充队列,同时将其总和存储在某处
如果得到的和不等于sum
,那么我们从队列中取出一个元素,并从A
中添加下一个元素(同时更新和)
我们重复步骤2,直到到达序列的末尾或找到匹配的子序列
Ta daa!我的函数在数组a
中移动一个包含k
相邻数组项的窗口,并将总和保持为数据,直到与搜索失败匹配为止
int getSubSequenceStart(int A[], size_t len, int sum, size_t k)
{
int sumK = 0;
assert(len > 0);
assert(k <= len);
// compute sum for first k items
for (int i = 0; i < k; i++)
{
sumK += A[i];
}
// shift k-window upto end of A
for (int j = k; j < len; j++)
{
if (sumK == sum)
{
return j - k;
}
sumK += A[j] - A[j - k];
}
return -1;
}
int getSubSequenceStart(int A[],size\t len,int sum,size\t k)
{
int-sumK=0;
断言(len>0);
断言(k)这应该在中,数字是正数吗?@ThisaruGuruge这不是代码复查,我已经给出了一个工作代码O(N*N*Sum)
现在我想提高它的时间复杂度,这是一种算法problem@GuillaumeG是的,所有的数字都是+V这就是codereview的目的。这在没有任何开销的情况下达到了目标。太棒了!这检查是否存在长度为k的子列表,而不是子序列。子序列和子数组是不同的
bool SubsequenceExists(int[] a, int k, int sum)
{
int currentSum = 0;
if (a.Length < k) return false;
for (int i = 0; i < a.Length; i++)
{
if (i < k)
{
currentSum += a[i];
continue;
}
if (currentSum == sum) return true;
currentSum += a[i] - a[i-k];
}
return false;
}
bool SubsequenceExists(int[] a, int k, int sum)
{
int currentSum = 0;
var queue = new Queue<int>();
for (int i = 0; i < a.Length; i++)
{
if (i < k)
{
queue.Enqueue(a[i]);
currentSum += a[i];
continue;
}
if (currentSum == sum) return true;
currentSum -= queue.Dequeue();
queue.Enqueue(a[i]);
currentSum += a[i];
}
return false;
}
int getSubSequenceStart(int A[], size_t len, int sum, size_t k)
{
int sumK = 0;
assert(len > 0);
assert(k <= len);
// compute sum for first k items
for (int i = 0; i < k; i++)
{
sumK += A[i];
}
// shift k-window upto end of A
for (int j = k; j < len; j++)
{
if (sumK == sum)
{
return j - k;
}
sumK += A[j] - A[j - k];
}
return -1;
}