Source of question: "waiting for words", original @ Chen liren. You are welcome to continue to pay attention to the Public Account "" waiting for words"
For an integer array a [], find the subset that contains the maximum number of consecutive numbers, for example, 15, 7, 12, 6, 14, 13, 9, 11, then return: 5: [11, 12, 13, 14, 15].
Analysis: the simplest method is sort and scan it again, but O (nlgn) is required. Is there any O (n) method? Some people use map or set on the Internet, but the complexity of map or set is O (nlgn ). The query set can be O (n). The query set is simple.
Refer to Region
The query set is a simple and widely used algorithm and data structure. The query set is a set of several non-intersecting sets, which allows you to quickly merge and determine the set where elements are located. There are many applications, such as finding the number of connected components in an undirected graph and implementing the Kruskal algorithm.
The query set allows you to perform the following three operations:
1. Make (x): initializes each element into a set. After initialization, the parent node of each element is itself.
2. Find (x): searches for the set where an element is located. The set where an element is located is identified by the ancestor node of this set. To determine whether two elements belong to the same set, you only need to check whether the ancestor nodes of the set are the same.
3. Union (x, y): merge the two sets where X and Y are located. First, use find () to find the ancestor of the two sets. If these two ancestor nodes are not the same node, point one of the ancestor nodes to another. (The specific ancestor points to which ancestor can be determined based on the actual situation)
Optimization of query set: In the find function, the complexity of searching for ancestor nodes is O (n ). When we recursively find the ancestor node, we direct all the child nodes in this path to the ancestor, so that the complexity of the next find will become O (1 ).
Back to the question, call make (X) to convert each element into a query set, scan a [I] at a time, and check whether a [I]-1 exists, if Union (a [I], a [I]-1) is called, check whether a [I] + 1 exists. If Union (a [I] + 1, A [I]). Update the size of the set while merging. The next question is how to determine whether a [I]-1 and a [I] + 1 exist, which can be solved by hash and the complexity is O (1 ).
The operations for checking the set in this question are based on the underlying standards. We use P [I] to represent the subscript of the parent node of a [I], and Len [I] to represent the size of the set with a [I] as the root, when merging, we always point the ancestor of a smaller value set to the ancestor of a smaller value set. In this way, we only need to record the length of the ancestor node of the smaller value set. Finally, scan the arrays A [] and Len [] to find the [I] corresponding to maxlen with the maximum length. The final result is: A [I]-maxlen + 1, a [I]-maxlen + 2,..., a [I].
For details, refer to the Code. This Code uses map for hash tables, which is superior to the original vector in that it can process negative numbers.
# Include <iostream> # include <map> # include <vector> # include <assert. h> using namespace STD; void make (vector <int> & P, vector <int> & Len, int X) {P [x] = X; len [x] = 1;} int find (vector <int> & P, int X) {If (P [x]! = X) P [x] = find (p, p [x]); Return P [X];} // ensure that x> = yvoid Union (vector <int> & P, vector <int> & Len, int X, int y) {int p1 = find (p, X ); int P2 = find (p, Y); If (p1 = P2) return; P [P2] = p1; Len [P1] + = Len [P2];} bool exist (Map <int, int> & hash, int value, int X) {Map <int, int >:: iterator iter = hash. begin (); While (ITER! = Hash. end () {If (ITER-> first = Value & ITER-> second = x) return true; ITER ++;} return false ;} bool exist (Map <int, int> & hash, int value) {Map <int, int >:: iterator iter = hash. begin (); While (ITER! = Hash. end () {If (ITER-> first = value) return true; ITER ++;} return false;} void longest (vector <int> & ivec, int & MAX, Int & maxlen) {assert (! Ivec. empty (); int size = ivec. size (); vector <int> P (size); // query the parent subscript of the set. Vector <int> Len (size ); // Map <int, int> hash of the root node and check the size of the Set; // It is used to determine whether the Adjacent Elements of a value exist in int I; for (I = 0; I <size; I ++) Make (p, Len, I); for (I = 0; I <size; I ++) hash [ivec [I] = I; // If duplicate data exists, the subsequent data overwrites the previous data, which prevents repeated calculations for (I = 0; I <size; I ++) {If (exist (hash, ivec [I], I) // Add I to process duplicate numbers {If (exist (hash, ivec [I]-1) Union (p, Len, I, hash [ivec [I]-1]); // duplicate numbers do not need to be processed here Because hash [ivec [I]-1] is definitely the last if (exist (hash, ivec [I] + 1) selected )) union (p, Len, hash [ivec [I] + 1], I); // The exchange position ensures the Union's x> y} max = ivec [0]; maxlen = Len [0]; for (I = 1; I <size; I ++) {If (LEN [I]> Len [0]) {max = ivec [I]; maxlen = Len [I] ;}} int main () {int N; while (CIN> N) {vector <int> data (n); int I; for (I = 0; I <n; I ++) CIN> data [I]; int Max, maxlen; longest (data, Max, maxlen); for (I = 1; I <= maxlen; I ++) cout <max-maxlen + I <""; cout <Endl;} return 0 ;}
If any error occurs, please correct it. Thank you.