Tag: Print ref pause using data void view strong details
This article transferred from: http://blog.csdn.net/zhuimengzh/article/details/6720388
Array A[n], which holds a number of 1 to N-1, one of which repeats once.
Write a function to find the number that is repeated. The time complexity must be an O (N) function prototype:
int do_dup (int a[],int N)
Method One:
[CPP]View PlainCopy
- A good algorithm, because the second repetition of the number of its position will certainly not change, and a[a[0]] just can access to each location of data.
- int do_dup (int a[],int N) {
- int temp;
- //a[0] For the surveillance whistle .
- While (A[0]!=a[a[0]])
- {
- TEMP=A[0];
- A[0]=A[TEMP];
- A[temp]=temp;
- }
- return a[0];
- }
- void Main () {
- int a[5]={1,2,3,2,0};
- Cout<<do_dup (a,5);
- System ("pause");
- }
Method Two:
[CPP]View PlainCopy
- #include <iostream>
- Using namespace std;
- int do_dup (int a[],int N) {
- int *p=new int[n];
- int i;
- For (i=0;i<n;i++)
- P[i]=-1;
- For (i=0;i<n;i++)
- {
- if (p[a[i]]==-1)
- P[a[i]]=a[i];
- else{
- cout<<a[i]<<endl;
- }
- }
- Delete [] p;
- return 0;
- }
- void Main () {
- int a[5]={1,2,3,2,0};
- Do_dup (a,5);
- System ("pause");
- }
The problem is that the array is unordered, there may not be a duplicate number, but there can be at most one duplicate number, requiring the quickest way to find out if there is a duplicate number.
At first glance, it's hard, but it's really simple.
Workaround:
Array a[n],1 to N-1 this N-1 number is stored in a[n], where a number repeats once. Write a function to find the number that is repeated. The time complexity must be an O (N) function prototype:
int do_dup (int a[],int N)
Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The mathematical thought of false gold bars
This algorithm for reference to the idea of false gold bar, but more simple than that process, storage 1 to N-1, is equivalent to remove from each bag from 1 to N-1 gold bars, but there is a heavy, calculate the n number of the sum will be equivalent to the total weight, minus 1 to N-1 and (in mathematical method) can be obtained by repeating the number. In short, we should make full use of mathematical knowledge
const int N = 5;
int a[n]={2,1,3,1,4};
int TMP1 = 0;
int TMP2 = 0;
for (int i=0; i<n; ++i)
{
tmp1+= (i+1);
Tmp2+=a[i];
}
printf ("Number of repetitions:%d\n", N-(TMP1-TMP2));
The above method is 1~n and minus the sum of the array, which is the difference of n-x, X is the number to be searched.
Can be optimized is 1-n and not program calculation, mathematical method directly forget
You can define a macro,
#define SUM (x) (x (x+1)/2)
Of course, the multiplication operation is more complex, and when n is smaller, it may be more efficient to add several numbers.
Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Flag Array Method
Apply for a string of length n-1 and all ' 0 '. Then iterate through the A[n] array, take the value of each array element A[i], place its corresponding string in the corresponding position 1, if it has been placed 1, then the number is the number of repetitions. is implemented using bitmaps.
In fact, as long as the number is 0-n-1 inside the number, then you can use this method to determine the position and value of all the repetitions.
For example, an array like this
{2,3,1,2}
We generate a string "000";
Then start traversing, a[0] = 2;
So, the second bit of the string is "0", then we set it to "1"
The string is "010"
Repeat, the string is "011",,,,, "111"
Then, Judge a[3] = 2 Then the second bit is "1"
Therefore, A[3] is the number of repetitions, and the position is the 4th bit.
The idea of the map and other methods is consistent, that is, after the visit to mark, re-visit to know whether to repeat. If space complexity is considered, its space O (N)
int do_dup (int arr[],int NUM)
{
int *arrayflag = malloc (num*sizeof (int));
while (I++<num)
Arrayflag[i] = false;
for (int i=0; i<num; i++)
{
if (Arrayflag[arr[i]] >= false)
Arrayflag[arr[i]] >= true; Sign in place
Else
return arr[i]; Returns the value that has occurred
}
}
Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Fixed offset marking method
It is not difficult to write an O (N) method using the notation method, the key is how to guarantee two points:
Do not change the initial value of a[]
No additional O (N) memory space is opened within the function.
It is obvious that the above method applies an O (n) memory space, and when N is too large, performance is reduced
Therefore, you should use the a[n] itself to mark the relationship between the value and subscript, and then clear the mark after processing is complete.
A[n], inside is 1 to N-1. The original array A[i] The largest is N-1, if a[i]=k in a certain place, will a[k] add a N, Mark, when a place a[i]=k again, view A[k] can know K has appeared. A[i] In the program is only the largest n-1+n=2n-1 (overflow how to do ah??? ), which is a restrictive condition
int do_dup (int arr[],int NUM)
{
int temp=0;
for (int i=0; i<num; i++)
{
if (arr[i]>=num)
Temp=arr[i]-num; This value is repeated because it was added once.
Else
Temp=arr[i];
if (arr[temp]<num)
{
Arr[temp]+=num; Mark it up.
}
Else
{
printf ("duplicates");
return temp;
}
}
printf ("No Duplicates");
return-1;
}
Above is the time complexity O (N), Space complexity O (1) algorithm!
Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Symbolic Sign Method
The above method marks the element with a fixed num, which can cause overflow. Sign bits are used in the following methods because 1~n are positive, so there is no limit. The basic idea is to use the sign bits of an int array as a hash table. (not unsigned int symbol bit idle is idle)
BOOL DUP (int array[],int N)
{
for (int i=0;i<n;i++)
{
if (array[i]>0)//can be used as subscript to determine the other values
{
if (array[array[i]]<0)
{
Return array[i];//has been marked negative, there is repetition
}
Else
{
Array[array[i]]=-array[array[i]]; Otherwise marked as negative
}
}
else//|array[i]| represents a value that has been present once.
{
if (array[-array[i]]<0)
{
return-array[i];//There is repetition
}
Else
{
Array[-array[i]]=-array[-array[i]];
}
}
}
return-1;//no repetition.
}
Used to repair arrays
void Restorearray (int array[],int N)
{
for (int i=0;i<n;i++)
{
if (array[i]<0) array[i]=-array[i];
}
}
Time complexity O (n) spatial complexity O (1)
But time complexity O (n) spatial complexity O (1) More than one reuse of this method can also be achieved
Attached to my modified algorithm
BOOL Do_dup_mal (int arr[], int n, int *pre, int *back)
{
int MAX =-1;
int i = 0;
int sameval =-1;
ASSERT (pre && back);
*pre = *back =-1;
for (int j=0; j<n; j + +)
{
if (Arr[j] > max) max = arr[j];
}
Char *arrayflag = new char[max+1];
if (NULL = = Arrayflag)
return-1;
while (i++ < MAX) Arrayflag[i] = ' n ';
memset (arrayflag, 0, max+1); ' + ' = = 0
for (i=0; i<n; i++)
{
if (arrayflag[arr[i]] = = ' + ')
Arrayflag[arr[i]] = ' \1 '; Sign in place
Else
{
Sameval = Arr[i]; Returns the value that has occurred
*back = i;
Break
}
}
Delete[] Arrayflag;
if (I < n)
{
for (int j=0; j<n; j + +)
{
if (Sameval = = Arr[j])
{
*pre = j;
return true;
}
}
}
return false;
}
int main (int argc, char *argv[])
{
int prepos =-1, Backpos =-1;
int myarry[n];
Myarry[0] = 1;
MYARRY[1] = 23;
MYARRY[2] = 3;
MYARRY[3] = 4;
MYARRY[4] = 5;
MYARRY[5] = 22;
MYARRY[6] = 7;
MYARRY[7] = 8;
MYARRY[8] = 9;
MYARRY[9] = 22;
MYARRY[10] = 12;
if (Do_dup_mal (Myarry, one, &prepos, &backpos))
printf ("\ n
Array A[n], holding the number of 1~n-1, where a number repeats a "turn"