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
如果上述任何子问题返回true,则返回true

下面是is\u subset\u sum()问题的递归公式。

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;
    }