Problem Source: Find All Numbers disappeared in an Array
After a long time without a brush, I felt the brain was beginning to slow down, so I decided to regain the pleasure of brushing the question.
Do not be too difficult at the beginning, choose some high-rate problems to do, and then see the topic. I'm a little surprised that I know two solutions to this problem. But it is still difficult. Unexpectedly pass rate so high. Then search for related pages. See a topic very close to it "Find all duplicates in an Array". And then it was relieved. These two topics have the same problem, only slightly different problems, the solution has similarities.
It is expected that the number is too close and will be the first one after. The second one is also very easy to do right.
This paper mainly analyzes "find all Numbers disappeared in an array", by the way a simple explanation of "find all duplicates in an array".
The meaning of this question is: given an array of length n, the array element is 1~n. But some elements appear once. Some elements appear two times. This can also cause some elements to not appear.
Now let's find out which elements are not present. Another topic is to let us find the elements that appear two times. Time complexity O (n), Spatial complexity O (1).
Solution One
The first approach is to use the method described in the previous blog, "a method of array statistical analysis"-element homing method. The element homing method is easy to understand, which is to swap n elements to where it should be.
Like what. Element 5 is placed in position 4 (subscript starts from 0).
It is important to note that exchanging an element in the correct position may cause the element in the current position not to be in the correct position, and to continue swapping until it cannot be exchanged, such as the following pseudo-code:
fori=1:n while canSwap(i) do swap(i);
After the element is returned to the position. We are very easy to get which elements are not present. When a location is not the correct element, it means that the element does not appear.
that is, we just need to return the subscript for elements that are not present, and we just need to return the value of that position for the element that appears two times.
Here is a question, pseudo code has two for loop, complexity is not O ( < Span class= "Mi" id= "mathjax-span-4" style= "font-family:mathjax_math-italic;" >n 2 ?)? No, the complexity is still O (n), which can be explained by averaging analysis: assuming that the exchange condition is met. Each time an element is placed in the correct position. Because of the total common ownership of n elements. So at most the need to n-1 Exchange (exchange of n-1 elements, the nth element of their own initiative to meet) can make all the elements in the correct position, that is, while the loop runs at most O (n) times, each time the cost is O (1). So the complexity of the above switching operation is O (n).
The C language version of the code is as follows:
void Swap (int *a,int *b) {inttemp=*a;*a=*b;*b=temp; }int* Finddisappearednumbers (int* Nums,intNumssize,int* returnsize) {int* Result= (int*)malloc (sizeof (int)*numssize); for(intI=0; i<numssize;i++) { while(nums[i]!=i+1&&nums[nums[i]-1]!=nums[i]) {Swap (&nums[i],&nums[nums[i]-1]); } }*returnsize=0; for(intI=0; i<numssize;i++) {if(nums[i]!=i+1) {result[*returnsize]=i+1;*returnsize=*returnsize+1; } }returnResult;}
Solution Two
In the spinster public number "Array statistical analysis", Chenli teacher previously gave the second solution-take the remainder method, the truth is also better understanding. The array has an element range of 1~n, and the first loop first adds the corresponding position of each element (n+1). The second cycle divides each position by (n+1), assuming that the position is 0, indicating that an element does not appear, assuming that the position equals 2, indicating that two times occurs.
What is the principle? In the first loop, we actually turn each position into a k* (n+1) +i, where k indicates the number of times the position was added (n+1). Values are 0, 1, 2. I represents the original element of the position. In the second cycle, because the range of I is 1~n. So dividing (n+1) is equal to 0, so we get the value of K.
according to the value of K. We are very easy to know which elements are not present. Which elements appear more than once.
The C language version of the code is as follows:
int* Finddisappearednumbers (int* Nums,intNumssize,int* returnsize) {int* Result= (int*)malloc (sizeof (int)*numssize);*returnsize=0; for(intI=0; i<numssize;i++) {nums[nums[i]%(Numssize+1)-1]+= (numssize+1); } for(intI=0; i<numssize;i++) {if(Nums[i]/(numssize+1)==0) {result[*returnsize]=i+1;*returnsize=*returnsize+1; } }returnResult;}
Solution Three
In top solution, some netizens share a very singular solution-take negative method.
The meaning is: take the corresponding position of the element negative. A simple sentence may not be easy to understand, let's give a sample example.
Assuming that element I is placed at position K, there are two possible values for I in the negative process: positive, indicating that the element k is not currently encountered minus the position, and negative, which means that the element k is currently present and takes the element negative.
But we don't care about K, we care about element I.
Since the element I appears, we'll look at position I: positive, indicating that this is the first occurrence of element I, we take position I negative; Indicates that the element I has appeared once, we do not do whatever operation. no matter whether an element occurs once or two times, it will be negative only if it appears in its corresponding position.
When an element does not appear, the corresponding location of the element is always not available, so it is a positive value, and in this way we can find which elements are not present.
Through the above analysis we are also very easy to know, in the process of taking negative. Assume that the position you want to take negative is already negative. This means that the element has been present, that is, the element has appeared two times, and we are able to preserve that element.
The C language version of the code is as follows:
int* Finddisappearednumbers (int* Nums,intNumssize,int* returnsize) {int* Result= (int*)malloc (sizeof (int)*numssize); for(intI=0; i<numssize;i++) {int Index=ABS(Nums[i])-1;if(nums[Index]>0) nums[Index]=-nums[Index]; }*returnsize=0; for(intI=0; i<numssize;i++) {if(nums[i]>0) {result[*returnsize]=i+1;*returnsize=*returnsize+1; } }returnResult;}
For the Find all duplicates in an Array, the C language code implemented using the negative method is as follows:
int* Findduplicates (int* Nums,intNumssize,int* returnsize) {int* Result= (int*)malloc (sizeof (int)*numssize);*returnsize=0; for(intI=0; i<numssize;i++) {int Index=ABS(Nums[i])-1;if(nums[Index]>0) {nums[Index]=-nums[Index]; }Else{result[*returnsize]=Index+1;*returnsize=*returnsize+1; } }returnResult;}
Leetcode Find all Numbers disappeared in an Array