算法:2 个集合 A 和 B 形成总和集合 C。给定 A 和 C 找到 B

Posted

技术标签:

【中文标题】算法:2 个集合 A 和 B 形成总和集合 C。给定 A 和 C 找到 B【英文标题】:Algorithm: 2 sets A and B form sum set C. A and C are given find B 【发布时间】:2021-04-29 17:36:43 【问题描述】:

2 个集合 A 和 B 形成一个和集 C,即 S(A,B) = a+b 其中 a 属于 A,b 属于 B 给定 C 和 A,我们需要找到 B。 see here

所以我采取了 ai - cj = m 元素的方法,如果在 ai 的所有迭代中找到 m 元素,则添加到 B

这里有更好的解释

输入 a = 1 2 x = 3 4 5 输出 负值 a=1 c=3 匹配 2 和匹配值 2 负值 a=2 c=4 匹配 2 和匹配值 2 匹配值 2 负值 a=1 c=4 匹配 3 和匹配值 3 减值 a=2 c=5 匹配 3 和匹配值 3 匹配值 3 负值 a=1 c=5 匹配 4 和匹配值 4

结果 = 2,3 这是正确的

但是对于某些测试用例它失败了

喜欢

8 12 15 18 24 30 33 40 41 48

3 5 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 94 97 

这个测试用例失败了。预期的输出是

1 3 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 46 49

我的输出是

1 3 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 45 46 49

45这是额外的元素

代码:

import java.util.*;
class TestClass 
    public static void main(String args[] ) throws Exception 
    
    Scanner sc = new Scanner(System.in);

    int n = sc.nextInt();
    int[] a = new int[n];
    for(int i=0;i<n;i++)
        a[i] = sc.nextInt();
    int m = sc.nextInt();
    int[] c= new int[m];
    for(int i=0;i<m;i++)
        c[i] = sc.nextInt();
    
    Arrays.sort(a);
    Arrays.sort(c);
    int b[] = new int[m];
    int k=0;
    int v = 0;
    while(v!=c.length)
    
        int flag=0;
        int match = (a[0]>c[v])? a[0]-c[v] : c[v]-a[0]; //since a[0] is the first iteration all of the common elements must be present here
        for(int i=1;i<n;i++) 
        
            flag=0;
            for(int j=0;j<m;j++)
            
                int minus = (a[i]>c[j])? a[i]-c[j] : c[j]-a[i];
               
                if(minus == match)
                   //  System.out.println("Minus Value initial a "+a[i]+" c "+c[j]+" match "+ minus+ " and the match value "+ match);
                    flag = 1;
                    break;
            
            if(flag==0)
                break;
        
        if(flag==1)
         //   System.out.println("match value "+ match);
        b[k++] = match;
            
        v++;
    

    for(int i=0;i<k;i++)
        System.out.print(b[i]+" ");

    


请看一下,让我知道我的算法出了什么问题,或者是否有更好的方法。

【问题讨论】:

【参考方案1】:

所以,首先排序不会像您使用 2 个嵌套的 for 循环那样增加太多价值。

接下来,a 是一个正数数组。 a[i] - c[i] 没有意义,因为 c[i] 总是大于 a[i]。

您是说只有在所有迭代中都找到它时才需要将其添加到答案中。

但是,我认为您的代码不会那样做。

你的基本想法是正确的。

如果 a + b =c -> b = (a-c)

所以,这就是我将如何解决这个问题。相同的想法,但要维护一张地图。

现在,您需要在这里做的是维护 c 和 a 之间所有差异计数的映射。

如果这个计数与 a 的长度匹配,那么你得到了匹配,输出它。

一个简单的代码是:

Map<Integer,Integer> map = new TreeMap<>();

for(int v: c)
   for(int u: a)
      int diff = v-u;
      map.put(diff,map.getOrDefault(diff,0)+1);
   


        
for(int i: map.keySet())
   if(map.get(i)==a.length)
      System.out.print(i+" ");
   

【讨论】:

以上是关于算法:2 个集合 A 和 B 形成总和集合 C。给定 A 和 C 找到 B的主要内容,如果未能解决你的问题,请参考以下文章

js-FCC算法-Symmetric Difference

全排列算法

全排列生成器

多子集和计算

B - 整数区间

算法学习