获取两个字符串之间的公共字符数

时间:2018-04-16 16:39:51

标签: java arraylist

  

给定两个字符串,找到它们之间的公共字符数。

     

实施例

     

对于s1 =" aabcc"和s2 =" adcaa",输出应该是   commonCharacterCount(s1,s2)= 3。

     

字符串有3个常用字符 - 2" a" s和1" c"。

我已经坚持这个问题很多了,我已经尝试了很多方法来解决这个问题,但我无法弄明白。我有如何解决它的主要想法,但我不能将其转移到代码。

我的方法是将字符串的字符放在它们自己的ArrayList中,并使用嵌套循环来迭代它们,比较相似的字符并将计数存储在int值中。我没有任何代码,因为我尝试了许多不同的尝试来改变我的代码,但没有运气。

我使用了两个嵌套的for循环,它们彼此分开:

for(int i = 0; i<firstString.size(); i++){
    for(int j = 0; j<secondString.size(); j++){
        if(firstString.get(i) == secondString.get(j){
            lettersInCommon++;
            secondString.remove(j);
            }
        }
}

for(int i = 0; i<secondString.size(); i++){
    for(int j = 0; j<firstString.size(); j++){
        if(firstString.get(i) == secondString.get(j){
            lettersInCommon2++;
            firstString.remove(i);
            }
        }
}

所以在这些循环运行之后,我会根据它们的大小返回两个lettersinCommon int之间的差异以避免负面。所以如果lettersInCommon&gt; lettersInCommon2 - return lettersInCommon - lettersInCommon2;反之亦然。

我不希望任何人告诉我如何对此进行编码,我只想建议我的逻辑,看看我是否可以简化这个问题,或者我是否遗漏了什么。

我还想声明这段代码适用于某些测试用例,但不是全部。

我一直在考虑我收到的评论,并且到目前为止:

ArrayList<Character> firstString = new ArrayList<Character>();
ArrayList<Character> secondString = new ArrayList<Character>();
int lettersInCommon = 0;

for(int i = 0; i<s1.length(); i++){
    firstString.add(s1.charAt(i));
}

for(int i = 0; i<s2.length(); i++){
    secondString.add(s2.charAt(i));
}
Collections.sort(firstString);
Collections.sort(secondString);
for(char c : firstString){
    if(firstString.contains(c) && secondString.contains(c)){
        lettersInCommon++;
        secondString.remove(s2.indexOf(c));
    }
}

我非常接近,但是我得到的错误是这一行的超出界限 secondString.remove(s2.indexOf(c));

有没有人对此有任何见解?

4 个答案:

答案 0 :(得分:2)

你可以去寻找地图。它可能不是性能方面的最佳解决方案,而是直观易懂的解决方案。首先,迭代每个字符串并使用它们的外观计数收集每个(不同的)字符。然后,比较两个地图(即字符)的键集以及在两个地图中找到的每个字符,将它与两个地图中的最小外观数一起存储。所以像这样:

// first collect characters with their appearance count in maps:
"aabcc" -> 2xa, 1xb, 2xc
"adcaa" -> 3xa, 1xc, 1xd

// now, get all shared characters with their minimum count from both maps:
a -> min(2,3) = 2
b -> not shared
c -> min(2,1) = 1
d -> not shared

我想这可以使用Stream API以很酷的方式实现,但这将是一个非常复杂的声明,不确定您是否有使用Streams的经验。

编辑:这是使用Streams的一个解决方案。我打赌有更好的,无论是表现方面还是方法,但它是我尝试过的第一件事:

public static void main(String[] args) {
    System.out.println(commonCharacterCount("aabcc","adcaa"));
}

public static int commonCharacterCount(String s1, String s2) {
    Map<Character, Integer> s1CharacterCount = getCharacterCount(s1);
    Map<Character, Integer> s2CharacterCount = getCharacterCount(s2);
    return s1CharacterCount.keySet().stream()
            .filter(s2CharacterCount.keySet()::contains)
            .mapToInt(c -> Math.min(s1CharacterCount.get(c), s2CharacterCount.get(c)))
            .sum();
}

public static Map<Character, Integer> getCharacterCount(String s) {
    Map<Character, Integer> characterCount = new HashMap<>();
    for (char c: s.toCharArray()) {
        characterCount.put(c, characterCount.computeIfAbsent(c, count -> 0) + 1);
    }
    return characterCount;
}

答案 1 :(得分:1)

  1. 不要将对象与==
  2. 进行比较
  3. 不要重新发明轮子:您不需要遍历列表来知道它是否包含元素。有contains()为你做这件事。
  4. 您甚至不需要contains(),因为remove()会告诉您是否删除了某些内容。所以你需要的只是:

    1. 从string2
    2. 创建List<Character>
    3. 循环遍历string1的字符,或直到列表为空
    4. 在每次迭代中,从列表中删除当前字符。如果删除了,请递增计数

答案 2 :(得分:0)

使用s1.charAt(i) == s2.charAt(i)比较。没有必要将字符串放入arrayList。

编辑:您需要添加条件语句,以确保在字符串长度不同时不会超出范围。

答案 3 :(得分:0)

为您提供的每个字符串创建字母计数的映射。然后将键相互比较,如果两个单词中都包含字母,则从两个地图中获取最低计数。试试这个

public static void main(String[] args)
{
    String str1 = "aabbcc";
    String str2 = "abcddc";
    HashMap<Character, Integer> str1LetterCounts = createLetterCountMap(str1);
    HashMap<Character, Integer> str2LetterCounts = createLetterCountMap(str2);

    HashMap<Character, Integer> commonCounts = new HashMap<>();

    Set<Character> possibleCommonCharacterList = str1LetterCounts.keySet();

    for(Character letter : possibleCommonCharacterList)
    {
        if(str2LetterCounts.containsKey(letter))
        {
            Integer count1 = str1LetterCounts.get(letter);
            Integer count2 = str2LetterCounts.get(letter);
            commonCounts.put(letter, count1 <= count2 ? count1 : count2);
            System.out.println("Common Character " + letter + " : " + (count1 <= count2 ? count1 : count2));
        }
    }

}

public static HashMap<Character, Integer> createLetterCountMap(String word)
{
    HashMap<Character, Integer> letterCountsForWord = new HashMap<>();
    for(int i = 0; i < word.length(); i++)
    {
        Character key = word.charAt(i);
        if(letterCountsForWord.containsKey(key))
        {
            letterCountsForWord.put(key, letterCountsForWord.get(key) + 1);
        }
        else
            letterCountsForWord.put(key, 1);
    }

    return letterCountsForWord;
}

输出

Common Character a : 1
Common Character b : 1
Common Character c : 2
相关问题