【问题标题】:compare 2 strings, see if they are containing common items or not比较2个字符串,看看它们是否包含共同项目
【发布时间】:2014-02-23 00:14:48
【问题描述】:

假设我有 2 个字符串, Boolean hasName = false;

String employeeNames = "lee,anne,peter,sam,paul";
String managerNames = "ken,lee,sue,tim,alex";

那么,遍历2个字符串并找出两个字符串都包含“lee”的最佳方法是什么,然后我可以设置

hasName = true;

这些只是一个简单的示例.. 我不想要诸如 employeeNames.contains("lee") 之类的答案,因为我在真实产品中的数据都是动态的,并且可能是很长的字符串……我不会知道我得到了什么,但是一旦我收到 2 个字符串,我需要找出它们是否包含至少一个常见项目... 这个算法的最佳方法是什么? 还有一件事,字符串中的项目都用“,”分隔 那么有什么我可以做的吗? 谢谢

【问题讨论】:

  • 你可以使用hashmap,你考虑过吗?
  • 你试过什么?您是否检查过 String API 的有用功能? docs.oracle.com/javase/7/docs/api
  • 一个明显的方法是用逗号分割它们,将结果粘贴到Sets,然后计算intersection

标签: java string list boolean compare


【解决方案1】:

这个复杂度是O(N*M),其中N和M是两个字符串中的字符串个数

public Boolean hasNames(String s1, String s2){
    List<String> s1List = Arrays.asList(s1.split(","));
    List<String> s2List = Arrays.asList(s2.split(","));

    for(String s : s1List)
        if(s2List.indexOf(s)>=0)
            return true;
    for(String s : s2List)
        if(s1List.indexOf(s)>=0)
            return true;
    return false;
}

另一种选择

public Boolean hasNames(String s1, String s2){
    Set<String> s1Set = new HashSet<String>();
    List<String> s2List = Arrays.asList(s2.split(","));
    for(String s : s1.split(","))
        s1Set.add(s);
    s1Set.retainAll(s2List);
    return !s1Set.isEmpty();
}

【讨论】:

  • 由于indexOf遍历列表,实际复杂度为O(M*N)。
  • 在什么情况下?最好使用您使用的 costructor,然后使用 isEmpty()?编辑:我发现了问题,让我们编辑它
【解决方案2】:

试试这样的:

public static boolean hasName()
{
    boolean value = false;
    String[] empArr = employeeNames.split(",");
    String[] manArr = managerNames.split(",");

    for (int i = 0; i < empArr.length; i++)
    {
        String s = empArr[i];

        for int j = 0, j < manArr.length; j++)
        {
            String t = manArr[j];
            if (s.equals(t)) { value = true; }
        }
    }

    return value;
}

这将遍历两个列表并尝试查找第一个和第二个列表中的内容!

【讨论】:

  • 这个复杂度是 N*M,不是 N+M
  • 我没有对时间复杂度做出任何声明。解决方案很容易理解。此算法也无法实现线性复杂度,因为您需要检查列表中的每个值与另一个列表中的每个值。
【解决方案3】:

您可以使用 Sets 的去重属性来比较两个名称列表的内容:

public static boolean hasNames(String s1, String s2) {
    List<String> s1List = Arrays.asList(s1.split(","));
    List<String> s2List = Arrays.asList(s2.split(","));
    HashSet<String> names = new HashSet<>(s1List);
    names.addAll(s2List);
    return names.size() < s1List.size() + s2List.size();
}

解释:如果两个列表中的名称不同,它们都将被添加到集合中,因此集合的大小将等于两个列表的总和。但是,如果它们有一个或多个公共术语,则该集合会将它们擦掉,因此包含的元素少于两个列表的总和。

另外,HashSets 正在使用哈希码,这使得它们比使用 List 的 contains()(在 O(N) 中)快得多。

【讨论】:

    【解决方案4】:

    使用 StringTokenizer 类拆分第一个字符串中的所有单词,并将它们全部插入到 HashSet 中。 对于第二个字符串,检查是否有任何单词在 hashSet 中。这段代码的复杂度是 O(max(N, M)) ~= O(N)。

    String employeeNames = "lee,anne,peter,sam,paul";
    String managerNames = "ken,lee,sue,tim,alex";
    boolean hasName = false;
    
    HashSet<String> hash = new HashSet<>();
    StringTokenizer st1 = new StringTokenizer(employeeNames);
    while (st1.hasMoreTokens()) {
        hash.add(st1.nextToken());
    }
    
    StringTokenizer st2 = new StringTokenizer(managerNames);
    while (st2.hasMoreTokens()) {
        if (hash.contains(st2.nextToken())) {
            hasName = true;
            break;
        }
    }
    

    【讨论】:

      【解决方案5】:
      public Boolean hasNames(String s1, String s2){
        List<String> s1List = Arrays.asList(s1.split(","));
        List<String> s2List = Arrays.asList(s2.split(","));
        HashSet set=new HashSet(s1List);
        set.retainAll(s2List);
        return !set.isEmpty();
      }
      

      复杂度为 O(M*ln(N))。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多