【问题标题】:Intersection of n Stringsn 个字符串的交集
【发布时间】:2019-02-07 17:07:34
【问题描述】:

我正在编写一个程序来查找 n 个字符串的交集的字符。我编写了以下代码:

import java.util.ArrayList;
import java.util.Scanner;
public class TestJoin {

public static void main(String[] args) {

  Scanner sc=new Scanner(System.in);


      int n=sc.nextInt();  // no of strings
      String s1 =sc.next().toLowerCase();
      ArrayList<Character> set1 = new ArrayList<Character>();
      while(n-->1)
      {
          String s2 =sc.next().toLowerCase();
          ArrayList<Character> set2 = new ArrayList<Character>();
          for(char c : s1.toCharArray()) {
                set1.add(c);
            }
          for(char c : s2.toCharArray()) {
                set2.add(c);
            }
          set1.retainAll(set2);
          for(char c : set1)
          {
              s1=Character.toString(c);
          }
      }
       for(char c :set1)
      System.out.println(c);


  }
}

当我尝试打印字符时,它给出了错误的输出。

输入-

 3
 aabcde
 abazx
 yuabna

预期输出:aab

实际输出:aabb

【问题讨论】:

  • 你没有问问题!
  • 你所说的“交叉点”是什么意思?你如何从给定的输入中得到aab?为什么不ababaa
  • 另外请发布一个完整的代码示例,它编译时没有任何错误。
  • @Code-Apprentice 顺序无所谓 (aab,aba,baa) 都是一样的。交集是指所有字符串中的共同字符
  • 我建议您退后一步,用文字描述解决问题所需的步骤。这将帮助您弄清楚如何修改代码以遵循这些步骤。那么如果还是有错误的输出,可以使用一些调试技巧来找出问题所在。有关如何调试代码的一些提示,请参阅 ericlippert.com/2014/03/05/how-to-debug-small-programs

标签: java string algorithm


【解决方案1】:

使用单独的方法通常会使问题变得更小,更容易解决。

我建议你先做一个方法来计算2个String的交集,然后你可以在你的while循环中使用它来计算传入字符串与当前交集的交集。

我试图保持你的逻辑,我编写了自己的保留循环,因为我不确定 List.retainAll 做了什么

该方法计算2个String的交集:

private static String intersectionOf(String s1, String s2) {
    List<Character> list1 = new ArrayList<>();
    for(char c : s1.toCharArray()) {
        list1.add(c);
    }
    List<Character> list2 = new ArrayList<>();
    for(char c : s2.toCharArray()) {
        list2.add(c);
    }

    StringBuilder intersection = new StringBuilder();
    for(Character c : list1) {
        if(list2.contains(c)) {
            intersection.append(c);
            list2.remove(c); // remove it so it is not counted twice
        }
    }
    return intersection.toString();
}

您现在可以在循环中使用它,逻辑看起来更简单

public static void main(String[] args) {
    Scanner sc=new Scanner(System.in);

    int n = sc.nextInt();  // no of strings

    String result = sc.next().toLowerCase();
    String s;
    while(n-- > 1) {
        s = sc.next().toLowerCase();
        result = intersectionOf(result, s);
    }
    for(char c : result.toCharArray())
        System.out.println(c);
}

【讨论】:

  • 如果您的字符串又长又多,但交叉点相对较小,这种方法会带来额外的速度优势。
【解决方案2】:
public static void intersect(String... input) {
    HashMap<Character, Integer> mins = new HashMap<Character, Integer>();
    HashMap<Character, Integer> current = new HashMap<Character, Integer>();

    for (String s : input) {
        current.clear();
        char[] chars = s.toCharArray();
        //Next loop remembers how many time every char occurs
        for (char c : chars) {
            Integer value = current.get(c);
            if (value == null) value = 0;
            current.put(c, value + 1);
        }

        if (mins.size() == 0) {
            mins.putAll(current); //First time just copy
        } else {
           //If not the first time then compare with previous results
            for (Character c : mins.keySet()) {
                Integer min = mins.get(c);
                Integer cur = current.get(c);
                if (cur != null) {
                    if (min > cur) {
                        //If has less than all previous
                        mins.put(c, cur);
                    }
                } else {
                    //If doesn't have at all
                    mins.put(c, 0);
                }
            }
        }
    }

    //Output every char that occurs in every string
    //more that 0 times
    for (Character c : mins.keySet()) {
        Integer count = mins.get(c);
        for (int i = 1; i <= count; i++) {
            System.out.print(c);
        }
    }
}

和调用:

public static void main(String[] args) {
   intersect("aabcdeabazx", "abazx", "yuabna");
}

您可以更改参数以将它们作为数组传递。该算法的计算复杂度约为O(n)。

【讨论】:

  • 这绝对不是 O(n),因为您在这里使用嵌套循环。他也可能有助于不要更改太多的 OP 代码。
  • @NicholasK 说 O 总是意味着复杂性增长函数。随着输入数据的增加,该算法的增长函数是线性的(至少非常接近线性)。因此复杂度为 O(n)。
  • @NicholasK 第二个循环的长度不会超过 26(对于英文字母的小写字母),无论我们输入多少字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多