[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 题目汇总

 

posted @ 2018-10-09 04:47  轻风舞动  阅读(1347)  评论(0编辑  收藏  举报