LeetCode Solution Sharing: 911. Online Election

Problem

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].
Thoughts on Problem Solving

The purpose of this question is to get the highest ticket before finding a time node (or exactly that time node), because the search operation needs to run many times, so we must optimize the search operation. It is time-consuming to search by traversing from beginning to end. Considering the ascending order of time, it is easy to think of binary search. In this block, the C++ language has been encapsulated and called directly.

The first step to solve the problem is to compute the person who gets the highest ticket corresponding to each time node and save it in an array in chronological order. This step is done in the constructor. In the lookup function, we use the lower_boundlowerboundlower_bound function to find the first data greater than or equal to the lookup value in an ordered array and return an iterator. If the current iterator is endendend, indicating that no data can be greater than the value to be looked up, then return to the last person with the highest votes. If the value pointed by the iterator is equal to the value to be searched, the person whose corresponding position is found directly in the array of the person who gets the highest number of votes can be returned. If the value pointed by the iterator is larger than the value to be looked up, the previous value of the current iterator is the correct data needed. Therefore, the iterator is subtracted by one and the corresponding person is returned.

The code is as follows:

class candidate
{
public:
	int count;
	int time;
};

class TopVotedCandidate {
public:
	vector<int> time;
	vector<int> leading;
	TopVotedCandidate(vector<int>& persons, vector<int>& times) 
	{
		
		int num = *max_element(persons.begin(), persons.end()) + 1;
		
		time = times;

		vector<candidate> cands(num);

		for (size_t i = 0; i < times.size(); ++i)
		{
			cands[persons[i]].count += 1;
			cands[persons[i]].time = times[i];

			int pos = 0;
			for (size_t j = 1; j < cands.size(); ++j)
			{
				if (cands[j].count > cands[pos].count || 
					(cands[j].count == cands[pos].count && cands[j].time > cands[pos].time))
				{
					pos = j;
				}
			}
			
			leading.push_back(pos);

		}

	}

	int q(int t) 
	{
		auto p = lower_bound(time.begin(), time.end(), t);
        if (p == time.end())
		{
			return leading.back();
		}
		if (*p == t)
		{
			return leading[p - time.begin()];
		}
		if (*p > t)
		{
			return leading[(p - 1) - time.begin()];
		}
		return 0;
	}
};

/**
 * Your TopVotedCandidate object will be instantiated and called as such:
 * TopVotedCandidate* obj = new TopVotedCandidate(persons, times);
 * int param_1 = obj->q(t);
 */

Posted by sentback on Tue, 20 Aug 2019 05:37:02 -0700