尝试答一个网络见到的面试题


题目:

@宝玉xp

最近我面试常问的一道题是“Remove Duplicates from an Array”,给个姓名字符串数组排重,基本上都能做出来,尤其是刷过题的,很快就能用HashMap或者Set给出最优解。

但接下来我会继续问:“如果把数组里面的项改成数字和字符串混合怎么办?”那么一些JS代码可能就不正确执行了。

接下来我又会问:“如果数组里的是一个User对象而不是字符串,怎么只根据id属性排重?”到这一步很多只会刷题的已经卡住了,完全无法根据之前HashMap的方案变通。

再接下来的问题会是:“如果要根据多个属性排重,比如id/name/age”,那么怎么办?这一步又要卡住一些人,又回到了原始的遍历查询,而不能坚持原本HashMap的方案。

前面的如果都通过了,最后还会问:“是否可以将这个方法变成一个通用的方法?即使不同的对象类型,不同的key组合,也可以共用”,如果有候选人能将获取key的方法作为参数,那应该可以得到一个比较高的评价。

这其实也是我面试时喜欢用的一种策略:

  1. 从简单的问题开始,让候选人可以轻松进入状态
  2. 逐步变更需求,考察候选人是不是在日常工作学习中对这些问题有过深入思考,能去解决一类问题而不是一个问题
  3. 尽可能贴近实际项目——比如上面的例子,如果写过Cache的get和set,其实不复杂

解答:

1,

public class WeiboExercise {

    public static void main(String[] args) {
        String[] array = new String[10];
        array[0] = "Xiao Fei";
        array[1] = "Zhang Wei";
        array[2] = "Xiao Ming";
        array[3] = "Li Si";
        array[4] = "Wang Wu";
        array[5] = "Zhang Wei";
        array[6] = "Xiao Fei";
        array[7] = "Xiao Ming";
        array[8] = "Zhang San";
        array[9] = "Mao Mao";

        System.out.println(Arrays.toString(array));
        String[] newArray = removeDuplicateStrings(array);
        System.out.println(Arrays.toString(newArray));
    }

    public static String[] removeDuplicateStrings(String[] array) {
        HashSet<String> set = new HashSet<String>();
        for(String s : array) {
            set.add(s);
        }
        String[] newArray = new String[set.size()];
        int i = 0;
        for(String s : set) {
            newArray[i] = s;
            i++;
        }
        return newArray;
    }
}

2,

这个有点虚,不知道对不对。

public class WeiboExercise2 {

    public static void main(String[] args) {
        User[] array = new User[10];
        array[0] = new User("100", "Xiao Fei");
        array[1] = new User("90", "Zhang Wei");
        array[2] = new User("10", "Xiao Ming");
        array[3] = new User("110", "Li Si");
        array[4] = new User("110", "Wang Wu");
        array[5] = new User("130", "Zhang Wei");
        array[6] = new User("10", "Xiao Fei");
        array[7] = new User("50", "Xiao Ming");
        array[8] = new User("30", "Zhang San");
        array[9] = new User("200", "Mao Mao");

        System.out.println(Arrays.toString(array));
        User[] newArray = removeDuplicateStrings(array);
        System.out.println(Arrays.toString(newArray));
    }

    public static User[] removeDuplicateStrings(User[] array) {
        HashMap<String, User> map = new HashMap<String, User>();
        for(User user : array) {
            map.put(user.getId(), user);
        }
        User[] newArray = new User[map.size()];
        int i = 0;
        for(Map.Entry e : map.entrySet()) {
            newArray[i] = (User)e.getValue();
            i++;
        }
        return newArray;
    }
}

class User {
    private String id;
    private String name;

    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return id + " " + name;
    }
}

3,

答1:

这个就不写代码了,我想就把问题拆成,先根据id排重,然后把得到的新array作为参数,传到根据name排重的函数,再把结果传到根据age排重的函数。排重3次。我觉得肯定能运行,但算是个笨办法吧。

答2:

看了这个:https://www.geeksforgeeks.org/internal-working-of-hashmap-java/ 。我想到一个新办法,就是如果根据id/name/age去重的话,先根据id生成hashCode(),现在id一样的都在一个bucket里面,然后根据id/name/age重写equals()方法,如果三个都一样就return true。

这样3个都一样的情况下,就是碰撞的情况下,map.put()的时候,会判断equals(),如果equals()也return true,后面的User会replace掉前面的User,达到去重的目的。