Off Topic
Recently some netizens letter asked me how not to update the blog, is not to brush the question, is really ashamed of ah, the problem is still in the brush, but the frequency of the brush question is not high, after reading the "Introduction to the algorithm" feel online a lot of discussion topics in fact in the introduction has a very good algorithm and mathematical proof, Just copy the words as if the meaning is not very large, I hope to find some representative of the topic in the update, in addition, I hope to be able to go ahead of the "exhaustive recursion and backtracking algorithm," a series of such as dynamic programming, greedy algorithm of the end of the class, in combing their knowledge structure can also help readers more systematic learning algorithm ideas. Well, don't say much, get to the point.
Problem description
Given an array of a[n], define the main element of the array (Majority element) to an element that exceeds N/2 in number of occurrences. Design an efficient algorithm to find the main elements of an array. The source of the topic is here.
Solution One
The easiest way to do this is to facilitate an array of element counts, and then return elements greater than N/2, which require O (n) time complexity and O (n) space complexity, not a good approach.
Solution Two
The spatial complexity of O (n) is considered to be eliminated on the basis of solution one, if the number of elements is more than N/2, then the median is the number we are looking for if the array is already sorted. In addition to our median, we do not need to order the number of other rows. The problem is further converted to the median of the array, the promotion version is in the O (n) time to find the number I, which in the introduction of the algorithm is discussed in detail, there are many online data. Basically, it is the use of the partition array of the Fast row division, divided into [..., pivot, ...] three parts, assuming that after the division pivot is the first M element, if m = = I, then pivot is the first large element; Conversely, if the position of pivot At greater than I (M > i), the left part is recursively searched for the large element I, whereas the right part is recursively searched for the large element (I-M). The code is as follows, however this algorithm times out in the case of large arrays.
1#include <iostream>2#include <string>3#include <vector>4#include <Set>5#include <unordered_set>6#include <map>7#include <unordered_map>8#include <queue>9#include <stack>Ten#include <algorithm> One#include <functional> A#include <utility> -#include <cstdio> -#include <cstdlib> the using namespacestd; - - /* - * Return a position k, such that all the elements in [left, K] + * is smaller than or equal to Num[k] && all the elements in - * (k, right] is larger than num[k] + * A * Note that this is the randomize version of partition, every time at * We choose a random number as the pivot. - */ - intRandompartition (vector<int> &num,intLeftintRight ) - { - //Random Partition - intRnd = rand ()% (Right-left +1) +Left ; in swap (Num[rnd], num[right]); - to //Pivot + intx =Num[right]; - inti = left-1; the for(intj = left; J < Right; ++j) * { $ if(Num[j] <=x)Panax Notoginseng { -Swap (Num[j], num[i +1]); thei + =1; + } A } theSwap (Num[right], num[i+1]); + returni +1; - } $ $ /* - * Return The i-th ordered element in Num[left, right] but without - * Sorting the array. the */ - Wuyi intRandomselect (vector<int> &num,intLeftintRightinti) the { - if(Right-left +1< I | | Left > right)return-1; Wu - //partition the num[], return the pivot position m About intm =randompartition (num, left, right); $ - //K is the number of an element in Num[left, M] - intK = M-left +1; - A if(k = =i) + { the returnNum[m]; - } $ Else if(k >i) the { the //find the i-th ordered element in Num[left, M-1] the returnRandomselect (num, left, M-1, i); the } - Else in { the //Find the (i-k)-th ordered element in Num[m+1, right] the returnRandomselect (num, M +1, right, I-k); About } the } the the /* + * Return the median of num[] - */ the intMajorityelement (vector<int> &num)Bayi { the intn =num.size (); the intMID = n/2; - returnRandomselect (NUM,0, N-1, mid); - } the the intMain () the { the intA[] = {3,2,2}; - intB[] = {3,2,2,2}; the thevector<int> v1 (A, A +3); thevector<int> v2 (b, B +4);94 thecout << majorityelement (v1) <<Endl; thecout << majorityelement (v2) <<Endl; the 98 return 0; About}
Solution Three
The idea of this approach is to think of the majority element as 1, and the other elements as 1. The algorithm first takes the first element x as the majority element, counts Mark = 1, and then iterates through all the elements, if the element and X are equal, Mark + +, otherwise, Mark--, if Mark = = 0, reset mark = 1, and update x for the current element. Since the number of majority element is greater than half, the last remaining must be the majority element. The AC code is as follows.
1#include <iostream>2#include <string>3#include <vector>4#include <Set>5#include <unordered_set>6#include <map>7#include <unordered_map>8#include <queue>9#include <stack>Ten#include <algorithm> One#include <functional> A#include <utility> -#include <cstdio> -#include <cstdlib> the using namespacestd; - - intMajorityelement (vector<int>&num) - { + intn =num.size (); - if(N <0)return-1; + if(n = =1)returnnum[0]; A at intx = num[0]; - intMark =1; - for(inti =1; I < n; ++i) - { - if(Mark = =0) - { inMark =1; -x =Num[i]; to } + Else if(Num[i] = =x) - { themark++; * } $ Else if(Num[i]! =x)Panax Notoginseng { -mark--; the } + } A returnx; the } + - intMain () $ { $ intA[] = {3,2,2}; - intB[] = {3,2,2,2}; - thevector<int> v1 (A, A +3); -vector<int> v2 (b, B +4);Wuyi thecout << majorityelement (v1) <<Endl; -cout << majorityelement (v2) <<Endl; Wu - return 0; About}
Reference documents
[1] The second edition of the introduction to algorithms, the Nineth chapter, "Median and sequential statistics".
[2] Http://people.cis.ksu.edu/~subbu/Papers/Majority%20Element.pdf
"Algorithm 31" looks for the main element of the array (Majority element)