如何使用Java从两个字符串中打印出唯一的字母?

时间:2015-04-22 10:08:13

标签: java

最近,我参加了一次采访。他们让我写一个程序来打印两个字符串中的唯一字母和常用字符。我编写了下面的代码来打印常见字符:

String s1 = "I am living in india";
String s2 = "india is a beautiful country";

char[] s1Array = s1.toCharArray();
char[] s2Array = s2.toCharArray();

LinkedHashSet<Character> s1CharSet = new LinkedHashSet<Character>();
LinkedHashSet<Character> s2CharSet = new LinkedHashSet<Character>();

for(char kc : s1Array){
    s1CharSet.add(kc);
}

for(char c: s2Array){
    s2CharSet.add(c);
}

s1CharSet.retainAll(s2CharSet);

if(s1CharSet.size()==0){
    System.out.println("There are no common characters between the two strings");
}
else{
    System.out.println(s1CharSet);
}
}

但是他们说他们对我的回答并不满意。我想这是因为他们没有期待retainAll。所以,请告诉我正确的编程方式,以便将来满足它们。

我甚至用谷歌搜索,但我找不到任何好的,可理解的链接。

那么,如何在不使用retainAll的情况下从两个字符串中打印唯一且常用的字符?

任何代码都将受到赞赏。

9 个答案:

答案 0 :(得分:3)

面试官可能希望检查您对如何有效解决此问题的内部理解,并且retainAll()的使用有点错过了此任务的目的。

要“从头开始”实施它,可以使用几种方法:

  1. 与您的解决方案类似 - 填充两个Set个对象 - 每个字符串一个,然后通过以下方式检查它们之间的差异/公共元素:

    for (Character c : set1) {
        if (set2.contains(c)) {
            System.out.println(c);
        }
    }
    

    如果已知字母表是常量(并且足够小),您甚至可以使用bitset,否则HashSet很好并且将达到O(n)平均大小写性能。

  2. 排序和迭代:对两个char数组进行排序并一起迭代以查找常见(和唯一)字符。虽然在java中没有真正的好处(因为String是不可变的,所以你需要创建一个新的char[]) - 在其他语言中,它可以节省空间并且可以在真正的地方完成额外的空间。

答案 1 :(得分:2)

不使用retainAll打印两个字符串中的唯一和常用字符。

        String firstString = "I am living in india";
        String secondString = "india is a beautiful country";

        HashSet<Character> h1 = new HashSet<Character>(), h2 = new HashSet<Character>();
        for(int i = 0; i < firstString.length(); i++) {
            h1.add(firstString.charAt(i));
        }
        for(int i = 0; i < secondString.length(); i++){
            h2.add(secondString.charAt(i));
        }

        StringBuffer commonSB = new StringBuffer();
        StringBuffer uniqueSB = new StringBuffer();

        for(Character i : h1){
            if(!h2.contains(i)){
               uniqueSB.append(i);
            }else{
               commonSB.append(i);
            };
         }

         for(Character i : h2){
            if(!h1.contains(i)){
               uniqueSB.append(i);
            };
         }

         System.out.println("Common:"+commonSB.toString().replace(" ", ""); 
         System.out.println("Unique:"+uniqueSB.toString().replace(" ", ""); 

结果:

Common:danli
Unique:gvmIfebcoutsry

答案 2 :(得分:2)

当你去面试时,如果他们要求你说的那个愚蠢的问题,那么他们就不会寻找复杂的Collection框架。他们正在研究你是否可以在草根阶段用你的编码能力做同样的事情,记住如何编写一个能够处理案例的代码,即使所提供的数据达到数百万。

通过使用byte []可以轻松解决此问题。我们知道char在内部由数字表示。

所以在第一次迭代中,只迭代第一个字符串(str1)的字符并将字节位置设置为某个常量,比如说1。

for (int i=0; i<str1.length; i++) {
     byteArr[(int)str.charAt(i)] = 1; // O(1)
}

所以在第二次迭代中,只需遍历第二个字符串的字符,并将字节位置设置为某个常量,如果设置为1则设置为2,而3表示它对于str2是唯一的。

在第三次迭代中,只需遍历字节arr并打印字符(将索引转换为char),其中常见的是2,唯一的是1/3。

最终解决方案O(n)和可扩展。

答案 3 :(得分:1)

  

s1CharSet.retainAll(s2CharSet);

似乎上面一行只给了intersection (A intersection B)

要获得所有独特的特征,您需要获得UNION。  A-B + A交叉点B + B-A。

更新:参考:Intersect and Union

public class Test {

public static void main(String... args) throws Exception {

    List<String> list1 = new ArrayList<String>(Arrays.asList("A", "B", "C"));
    List<String> list2 = new ArrayList<String>(Arrays.asList("B", "C", "D", "E", "F"));

    System.out.println(new Test().intersection(list1, list2));
    System.out.println(new Test().union(list1, list2));
}

public <T> List<T> union(List<T> list1, List<T> list2) {
    Set<T> set = new HashSet<T>();

    set.addAll(list1);
    set.addAll(list2);

    return new ArrayList<T>(set);
}

public <T> List<T> intersection(List<T> list1, List<T> list2) {
    List<T> list = new ArrayList<T>();

    for (T t : list1) {
        if(list2.contains(t)) {
            list.add(t);
        }
    }

    return list;
}
   }

答案 4 :(得分:1)

我会做类似的事情:

//assume questions treats I and i as the same.
    String s1 = "I am living in india".toLowerCase();
    String s2 = "india is a beautiful country".toLowerCase();

    //Since character is comparable this will maintain the set in alphabetical order when we print it. - well based on the numerical chacacter anyway.
    Set<Character> unique = new TreeSet<Character>(); 
    Set<Character> common = new TreeSet<Character>();

    unique.addAll(Arrays.<Character>asList(ArrayUtils.toObject(s1.toCharArray()))); //Oh java !?!?!
    for(Character c : s2.toCharArray()){
        if(!unique.add(c)){
            common.add(c);
        }
    }

    //Assume question didnt mean to include whitespace
    unique.remove(' ');
    common.remove(' ');

    System.out.println("Unique: " + unique.toString());
    System.out.println("Common: " + common.toString());

这基本上只是利用set add函数的行为,如果元素不在集合中,则返回true,如果是,则返回false。该集避免了重复。

给出输出:

Unique: [a, b, c, d, e, f, g, i, l, m, n, o, r, s, t, u, v, y]
Common: [a, d, i, l, n, t, u]

面试官可能会提到一些小问题:

1)您在LinkedHashSet定义中使用了类而不是接口。这被广泛认为是不好的做法,并且可能被视为表明您对Java-ofc的熟悉程度有限,这是否是一个问题取决于他们感兴趣的经验水平。

2)你的变量命名。如果你的候选人一直在命名对象,那么你作为一名面试官就不会高兴了#34; thingy&#34;或函数&#34; someFunction&#34;,一个自然的程序员在运行中为对象和函数生成有用的名称。同样,根据他们想要的经验水平,这可能是也可能不是问题。

3)他们可能一直在寻找解释问题的想象力,例如:询问空白是否是一个&#34;字符&#34;在问题中,或者对输出进行排序以使其更具可读性。或者询问是否将I和i视为相同或不同的字符。

4)他们可能一直期待Java开发时间表的一些知识,例如:说'#34;在这里我使用了Autoboxing,因此需要1.7或更高版本的编译器。&#34;

5)您可能花了太长时间,或者需要太多语法提示/更正。

答案 5 :(得分:0)

class uniqueCharInTwoString{
    public static void unique(String a, String b){
        HashSet<Character> unique = new HashSet<Character>();
        HashSet<Character> common = new HashSet<Character>();
        for(Character c : a.toCharArray()){
            unique.add(c);
        }
        for(Character c : b.toCharArray()){
            if(!unique.add(c)){
                common.add(c);
            }
        }
        unique.removeAll(common);
        unique.remove(' ');
        common.remove(' ');
        System.out.println(unique);
        System.out.println(common);
    }
    public static void main(String args[]){
        String a = "abdedf";
        String b = "cdfang";
        unique(a,b);
    }
}

答案 6 :(得分:0)

这是我实现LinkedHashSet以维护字符串中字符顺序的解决方案。

externals

答案 7 :(得分:0)

为简单起见,我们的字符串只包含小写字符。 现在我们可以构造两个长度为26的数组,并计算字符的出现次数。 现在比较两个数组,如果两个数组都有> 0,那么它对两个数组都是通用的。如果count在一个中为零而在另一个中为非零,则其对于该特定字符串是唯一的。如果两者都为零,则字符串中不存在该字符。

上述方法可用于许多类似的问题。

答案 8 :(得分:0)

打印出所有常见字符:

public class Test10 {
    public static void main(String[] args) {
        String a = "Gini Gina Protijayi".toLowerCase();
        String b = "Soudipta".toLowerCase();
        // print out all the common characters
        a.chars()
        .distinct()
        .mapToObj(ch -> String.valueOf((char) ch))
        .filter(b::contains)
        .forEach(System.out::println);

    }// main

}