Friends 系列

给你一个 api, getfriends(), 输入是一个user id, 大概是getfriends(1) - > [2, 3], 输出的user friends‘ ids,完成一个function 求出两个user 共同的朋友。写到一半,面试官说下一题。

很简单,思路349一样。虽然api返回朋友数组不会有重复,但是还是要转化为set,查询效率高O(1)。

  • 给一个user id,找出潜在朋友,这个定义是不是自己朋友的朋友的朋友(不是自己的朋友,不过是自己朋友的朋友), 有点绕,大家自己体会一下。 LZ 使用了hashmap, 和两次for loop, 最后没写完, 面试官确认了思路之后说觉得我能做出来。
  • friend recommendation。问题是给定person A 返回一个list 包含推荐给A的不认识的人。顺序按照与A的mutual friends 的数量排。return friends of friends that are not this persons friends
Solution 1: HashMap + bucket sort O(m); O(n)

m: # of person's friends' friends, n: # of legal recommend friends

一共三步:HashMap存潜在好友(不是A的好友,但是是A的好友的好友)和其频率(和A共同好友的数量),然后对HashMap的key进行桶排序,排序后获得前k个潜在好友。

    public class Person {
        int id;
        HashSet<Person> friends = new HashSet<>();
    }

    private List<Integer> friendsRecommend(Person person, int k) { //assume person is A
        List<Integer> result = new ArrayList<>();
        if (person == null)    return result;
        // id : frequency
        Map<Integer, Integer> map = new HashMap<>(); // recommend id -> count
        int highestFreq = 0;
        for (Person friend : person.friends)
            for (Person recommend : friend.friends) {
                int id = recommend.id;
                if (person.friends.contains(id) || id == person.id) // don't forget 'id == person.id'
                    continue; //person A knows id, not recommend
                map.put(id, map.getOrDefault(id, 0) + 1);
                highestFreq = Math.max(highestFreq, map.get(id));
            }
        // bucket sort 'recommend list'
        List<Integer>[] buckets = new List[highestFreq]; //index is freq, value is id.
        for (int id : map.keySet()) {
            if (buckets[map.get(id)] == null)
                buckets[map.get(id)] = new ArrayList<Integer>();
            buckets[map.get(id)].add(id);
        }
        //this two loops are O(k) time, when result has k nums, return it
        for (int i = highestFreq; i >= 0; i--)
            for (int j = 0; j < buckets[i].size(); j++) {
                result.add(buckets[i].get(j));
                if (result.size() == k)    return result;
            }
        return result;
    }
Solution 2: Quick Select average O(m), O(m + n^2) worst case; O(1)
    public class Person {
        int id;
        HashSet<Integer> friends = new HashSet<>();
    }
    private List<Integer> friendsRecommend(Person person, int k) {
        List<Integer> res = new ArrayList<>();
        if (person == null)    return res;
        Map<Integer, Integer> map = new HashMap<>();
        // O(m)
        for (int friend : person.friends) 
            for (int recommend : friend.friends) {
               int id = recommend.id;
               if (person.friends.contains(id) || id == person.id)    continue;
               map.put(id, map.getOrDefault(id, 0) + 1);
           }
        // O(n) average, O(n^2) worst case
        List<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet()); // important
        int left = 0, right = list.size() - 1, pos = -1;
        while (true) {
            pos = partition(list, left, right);
            if (pos == k - 1) {
                index = pos;
                break;
            } else if (pos > k - 1)   right = pos - 1;
            else    left = pos + 1;
        }
        if (pos == -1)    return res;
        for (int i = 0; i <= pos; i++) {
            int id = list.get(i).getKey();
            res.add(id);
        }
        return res;
    }
    private int partition(List<Map.Entry<Integer, Integer>> list, int left, int right) {
        shuffle(list);
        int idx = left;//remember to add + left !!!
        Map.Entry<Integer, Integer> pivot = list.get(idx);
        int pVal = pivot.getValue();
        swap(list, right, idx);
        for (int i = left; i < right; i++) 
            if (list.get(i).getValue() > pVal)  swap(list, i, idx++);
        swap(list, right, idx);
        return idx;
    }
    private void swap(List<Map.Entry<Integer, Integer>> list, int left, int right) {
        Map.Entry<Integer, Integer> temp = list.get(left);
        list.set(left, list.get(right));
        list.set(right, temp);
    }
    private void shuffle(List<Map.Entry<Integer, Integer>> list) {
        final Random random = new Random();
        for(int ind = 1; ind < list.size(); ind++) {
            final int r = random.nextInt(ind + 1);
            swap(a, ind, r);
        }
    }

results matching ""

    No results matching ""