zoukankan      html  css  js  c++  java
  • [LeetCode] 911. Online Election 在线选举

    In an election, the i-th vote was cast for persons[i] at time times[i].

    Now, we would like to implement the following query function: TopVotedCandidate.q(int t) will return the number of the person that was leading the election at time t.  

    Votes cast at time t will count towards our query.  In the case of a tie, the most recent vote (among tied candidates) wins. 

    Example 1:

    Input: ["TopVotedCandidate","q","q","q","q","q","q"], [[[0,1,1,0,0,1,0],[0,5,10,15,20,25,30]],[3],[12],[25],[15],[24],[8]]
    Output: [null,0,1,1,0,0,1]
    Explanation: 
    At time 3, the votes are [0], and 0 is leading.
    At time 12, the votes are [0,1,1], and 1 is leading.
    At time 25, the votes are [0,1,1,0,0,1], and 1 is leading (as ties go to the most recent vote.)
    This continues for 3 more queries at time 15, 24, and 8.

    Note:

    1. 1 <= persons.length = times.length <= 5000
    2. 0 <= persons[i] <= persons.length
    3. times is a strictly increasing array with all elements in [0, 10^9].
    4. TopVotedCandidate.q is called at most 10000 times per test case.
    5. TopVotedCandidate.q(int t) is always called with t >= times[0].

    在一个选举中第i次投票的情况为persons[i]和times[i],实现一个函数能实现在时间t返回得票数多的lead。

    解法:设置一个目前得票最多的变量count,先循环得票人和时间,用hashmap或数组数组统计每个人的得票数,如果次数大于count,则更新count,用数组记录到目前时间得票最多的人(按时间顺序排列的目前得票多的人)。查找某一时间点得票最多的人时,用二分法查找按时间排序的数组。

    G家:给一个vote list=[(a, 100), (b, 150), (a, 200)] #(name, timestamp) 和时间T 找T时间之前, 得票数最高的人(或任一得票数最高的人) ex: T=100 -> a, T=150 -> a or b, T=200 -> a. 用map去存每个char对应的频率,如果当前的timestamp小于给定的时间T,就把当前char的频率 + 1,  最后找出map里面value最大的key

    Followup1: 多给一个input K, 找T时间之前, Top K 得票数的人. 和上一个题目一样只是找出map里面前K个value最大的key

    Followup2: 一样给vote list, K, 但这次给Top K list, 找时间T. 每次添加一张票以后,map里取topk个和topklist比较一下

    Java: Basic, easy to understand.

    class TopVotedCandidate {
        int[] leading;
        int[] time;
        public TopVotedCandidate(int[] persons, int[] times) {
            time = times;
            leading = new int[persons.length];
            Map<Integer, Integer> map = new HashMap<>();
            for (int n : persons){
                map.put(n, 0);
            }
            int max = persons[0]; 
            for (int i = 0; i < times.length; i++){
                if (i == 0){
                    map.put(persons[i], 1);
                    leading[i] = persons[i];
                }else{
                    map.put(persons[i], map.get(persons[i]) + 1);
                    if (max != persons[i] && map.get(persons[i]) >= map.get(max)){
                        max = persons[i];
                    }
                    leading[i] = max;
                }
                //System.out.print(leading[i]);
            }
            
        }
        
        public int q(int t) {
            int i = 0, j = time.length;
            while (i < j){
                int mid = i + (j - i) / 2;
                if (time[mid] <= t){
                    i = mid + 1;
                }else{
                    j = mid;
                }
            }
            return leading[i - 1];
        }
    }  

    Java:

    class TopVotedCandidate {
        List<List<Vote>> A;
        public TopVotedCandidate(int[] persons, int[] times) {
            A = new ArrayList();
            Map<Integer, Integer> count = new HashMap();
            for (int i = 0; i < persons.length; ++i) {
                int p = persons[i], t = times[i];
                int c = count.getOrDefault(p, 0) + 1;
    
                count.put(p, c);
                while (A.size() <= c)
                    A.add(new ArrayList<Vote>());
                A.get(c).add(new Vote(p, t));
            }
        }
    
        public int q(int t) {
            // Binary search on A[i][0].time for smallest i
            // such that A[i][0].time > t
            int lo = 1, hi = A.size();
            while (lo < hi) {
                int mi = lo + (hi - lo) / 2;
                if (A.get(mi).get(0).time <= t)
                    lo = mi + 1;
                else
                    hi = mi;
            }
            int i = lo - 1;
    
            // Binary search on A[i][j].time for smallest j
            // such that A[i][j].time > t
            lo = 0; hi = A.get(i).size();
            while (lo < hi) {
                int mi = lo + (hi - lo) / 2;
                if (A.get(i).get(mi).time <= t)
                    lo = mi + 1;
                else
                    hi = mi;
            }
            int j = Math.max(lo-1, 0);
            return A.get(i).get(j).person;
        }
    }
    
    class Vote {
        int person, time;
        Vote(int p, int t) {
            person = p;
            time = t;
        }
    }  

    Java:

    Map<Integer, Integer> m = new HashMap<>();
        int[] time;
        public TopVotedCandidate(int[] persons, int[] times) {
            int n = persons.length, lead = -1;
            Map<Integer, Integer> count = new HashMap<>();
            time = times;
            for (int i = 0; i < n; ++i) {
                count.put(persons[i], count.getOrDefault(persons[i], 0) + 1);
                if (i == 0 || count.get(persons[i]) >= count.get(lead)) lead = persons[i];
                m.put(times[i], lead);
            }
        }
    
        public int q(int t) {
            int i = Arrays.binarySearch(time, t);
            return i < 0 ? m.get(time[-i-2]) : m.get(time[i]);
        }  

    Python:

    class TopVotedCandidate(object):
    
        def __init__(self, persons, times):
            self.A = []
            self.count = collections.Counter()
            for p, t in zip(persons, times):
                self.count[p] = c = self.count[p] + 1
                while len(self.A) <= c: self.A.append([])
                self.A[c].append((t, p))
    
        def q(self, t):
            lo, hi = 1, len(self.A)
            while lo < hi:
                mi = (lo + hi) / 2
                if self.A[mi][0][0] <= t:
                    lo = mi + 1
                else:
                    hi = mi
            i = lo - 1
            j = bisect.bisect(self.A[i], (t, float('inf')))
            return self.A[i][j-1][1]  

    Python:

    def __init__(self, persons, times):
            self.leads, self.times, count = [], times, {}
            lead = -1
            for t, p in zip(times, persons):
                count[p] = count.get(p, 0) + 1
                if count[p] >= count.get(lead, 0): lead = p
                self.leads.append(lead)
    
        def q(self, t):
            return self.leads[bisect.bisect(self.times, t) - 1] 

    Python:

    class TopVotedCandidate:
    
        def __init__(self, persons, times):
            votes = collections.defaultdict(int)
            winner = 0
            self.winners = [None] * len(times)
            self.times = times
            for i, person in enumerate(persons):
                votes[person] += 1 
                if votes[person] >= votes[winner]:
                    winner = person
                self.winners[i] = winner
    
        def q(self, t):
            return self.winners[bisect.bisect(self.times, t) - 1]  

    C++:

    map<int, int> m;
        TopVotedCandidate(vector<int> persons, vector<int> times) {
            int n = persons.size(), lead = -1;
            unordered_map<int, int> count;
            for (int i = 0; i < n; ++i) m[times[i]] = persons[i];
            for (auto it : m) {
                if (++count[it.second] >= count[lead])lead = it.second;
                m[it.first] = lead;
            }
        }
    
        int q(int t) {
            return (--m.upper_bound(t))-> second;
        }
    

     

    G家:

    Give a vote list = [(a, 100), (b, 150), (a, 200)] # (name, timestamp) and time T. Find the highest number of votes (or anyone with the highest number of votes) at T

    ex: T = 100 -> a, T = 150 -> a or b, T = 200 -> a

    Followup1: give one more input K, find Top K votes at T

    Followup2: the same vote list, K, but given the Top K votes list, find the time T.

    For the first question, just travers the vote list and if vote.T <= T increment
    the vote for person vote.Name. While doing that maximize the vote number.
    (O(n*l) time, O(c*l) space, c is the number of candidates, l is average length of name)

    follow-up 1: instead of maximizing one, keep the hashtable with votes[person] = no. votes
    now, put that into a vector and find the k-th element (using e.g. quicksort's partion
    method which is linear)
    (O(n*l) time, O(c*l) space)

    follow-up 2: I assume given are the top K candidates at a certain time T I have to find.
    I have to keep all candidates sorted at each step and compare the top k of them with
    the given list. The first part (keeping candidates sorted at each step) can be done
    using a balanced binary-tree, so I have O(n*lg(n)+n*l) for creating and maintaining that tree.
    (I will have to transpose the name into an integer, and have a nameId instead of the
    string in the tree)
    Then I would have k compare's per iteration, which is then O(k*n*lg(n)+n*l). the factor k
    I can get rid of if I implement the tree in a way, so I monitor when elements enter and
    leave the top k. If one of the desired candidates enters top k, I reduce the amount of
    candidates I need in top k, if one leaves, I increment back. If that counter (which
    starts with k) is 0 I'm done, I found the first time where the desired condition happend.

    C:

    #include <string>
    #include <vector>
    #include <unordered_map>
    
    using namespace std;
    
    struct Vote
    {
    	int time_;
    	string name_;
    };
    
    string find_top_at_time(const vector<Vote>& votes, int time) {
    	unordered_map<string, int> votes_per_name;
    	string max_votes_name;
    	int max_votes_count = -1;
    	for (const Vote& vote : votes) { // O(n)
    		if (vote.time_ <= time) {
    			auto it = votes_per_name.find(vote.name_); // O(l)
    			if (it == votes_per_name.end()) {
    				it = votes_per_name.insert({ vote.name_, 0 }).first; // O(l) compensated
    			}
    			it->second++;
    			if (it->second > max_votes_count) {
    				max_votes_count = it->second;
    				max_votes_name = vote.name_; // O(l)
    			}
    		}
    	}
    	return max_votes_name;
    }
    

      

    类似题目: 

    [LeetCode] 155. Min Stack 最小栈

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    谈谈SpringFramework与IoC依赖查找
    监控微博、论坛的“棱镜计划”
    输出质数的方法改进
    参数解构
    直接插入排序
    理解迭代
    异常处理
    函数
    continue语句
    break语句
  • 原文地址:https://www.cnblogs.com/lightwindy/p/9758238.html
Copyright © 2011-2022 走看看