Related
I'm trying to write a program whose input is an array of integers, and its size. This code has to delete the elements which are smaller than the element to the left. We want to find number of times that we have repeat this action to not be able to delete any more elements. Here is my code, it works but I want it to be faster.
Do you have any idea to make this code faster, or another way that is faster than this?
For example, given the array [10, 9, 7, 8, 6, 5, 3, 4, 2, 1], the function should return 2 because [10,9,7,8,6,5,3,4,2,1] → [10,8,4] → [10]
int numberOfTimes(int array[] , int n) {
int count = 0;
int flag = 0;
int sizeCounter = 0;
while (true){
for (int i = 0; i < n-1; ++i) {
if (array[i]<= array[i+1]){
sizeCounter++;
array[sizeCounter] = array[i+1];
} else{
flag = 1;
}
}
if (flag == 0)
return count;
count++;
flag = 0;
n = (sizeCounter+1);
sizeCounter = 0;
}
}
This problem can be solved in O(n) time and O(n) space using "monotonic stack".
For each element of the array we will find the number of "actions/turns" it takes to delete the element. In other words, how many turns have to pass, so that all elements between current element (inclusive) and the closest larger element to the left are deleted.
If we know that number (let's call it turns) then we can find maximum of this value for all elements of our array and we'll know the number of turns it takes to remove all elements from the array that can be removed. We'll have our answer.
Now, how do we find that turns value? It's easy, if we have these turns values computed for all elements to the left of the current element. We just find the closest element that is greater than current element and find the maximum number of turns for every element in between that element and the current element. I.e. if current element is at index i, and closest greater element is at index j (j < i and array[j] > array[i]), turns[i] = max(turns[k]+1), for k in [j+1..i-1].
If we do this naively, finding turns for each element would be O(n). Fortunately, it's easy to see, that when we've found j for some i, we won't ever need to consider elements between j and i ever again. Remember, array[j] > array[i] and everything in between j and i is smaller than array[i]. We're looking for the closest array element that is greater than some value, so, if array[i] is not an answer, the whole [j+1..i-1] range is also not an answer, we can go straight to j.
Having this in mind, we arrive to the monotonic stack. Instead of storing turns for every element of array, we store it only for the strictly decreasing subsequence of array that we've visited so far.
Before adding new element to the stack, first we need to remove every element that is smaller than the current element. Then the top of the stack will be our array[j].
As each element is added to the stack and removed exactly once, amortized cost of finding turns for each element is O(1), so the whole algorithm is O(n). In worst case the size of the stack grows to the same size as the array (if array is strictly decreasing). So the space complexity is O(n).
Here is the code (python):
array = [10, 9, 7, 8, 6, 5, 3, 4, 2, 1]
s = [] # monotonic stack of pairs (array[j],turns[j])
count = 0 # result: number of turns to delete all deletable elements
for el in array:
# initially assuming current element can be deleted
turns = 1
# peeking at the top of the stack
while len(s) > 0 and s[-1][0] <= el:
_,t = s.pop()
turns = max(t+1, turns)
# corner case: current element is the largest so far, cant be deleted
if len(s) == 0:
turns = 0
s.append( (el, turns) )
count = max(count, turns)
print(count)
Tests:
[10, 9, 7, 8, 6, 5, 3, 4, 2, 1] → 2
[10, 9, 7, 8, 6, 5, 3, 4, 2, 1, 9] → 3
[10, 9, 7, 8, 6, 5, 3, 4, 2, 1, 11] → 2
[] → 0
[1, 2, 3] → 0
[1, 2, 3, 1] → 1
[10, 1, 2, 3, 4, 5] → 5
UPD: I've just read the comments and I'd like to give kudos to #wLui155, who came up with the same core idea before me.
This is a follow up question to my previous issue to do with 2d array processing techqniques with o(1) complexity.
That is to get the average of a subset of an array but if this subset extends beyond the bounds of an array taking those as zero. This is with a 2D array.
In reality the array can go up to [2000][2000] but lets take a 2D array that is sized [4][4] for simplicity.
array[4][4] = {0, 1, 2, 3
4, 5, 6, 7
8, 9, 10, 11
12, 13, 14, 15}
Now let's say I want to get the sum of the array between [2][2] and [3][3], i.e. adding 10 + 11 + 14 + 15 and dividing by four. This can be made in a o(1) solution by using a 'summed area table' or 'integral image' techniques.
However I am little confused about how to keep this o(1) complexity providing/when:
the array subset extends outside the actual array
the array indices outside the actual array are taken as zero.
The algorithm computation is still o(1)
So for example lets say for this pixel sum I am asked to get the sum of [2][2] to [4][4]. This has a theoretical array of, numbers outside actual are denoted f (for fake) but are taken as zero:
array_theory[5][5] = {0, 1, 2, 3, 0f
4, 5, 6, 7, 0f
8, 9, 10, 11, 0f
12, 13, 14, 15, 0f
0f, 0f, 0f, 0f, 0f}
or in an image:
So now the average between [2][2] and [4][4] is (10 + 11 + 0f + 14 + 15 + 0f + 0f + 0f + 0f)/ 9
I think I have to use some sort of filter or image processing technique that I can't seem to a key word to allow me to find/implement it and am flirting with it in my search results.
Any help would be greatly appreciated!
The solution you have been given previously to compute the sum of the elements in a subarray with one corner at array[i0][j0] and another corner at array[i1][j1] in O(1) time after prior preparation is to prepare an array sums in which sums[i][j] is the sum of all elements in the subarray array[0][0] to array[i][j], after which the sum of an arbitrary subarray may be computed as sums[i1][j1] - sums[i1][j0-1] - sums[i0-1][j1] + sums[i0-1][j0-1], except that any of those terms is replaced with 0 if either of its subscripts is less than zero.
To extend this beyond the greater edges of the array, simply clamp the terms to their maximums: If any subscript exceeds the last valid index of the array, replace it with the last valid index of the array.
We might define an auxiliary function to access sums:
/* Return sums[i][j] from an array that is physically r rows and c columns
but is conceptually extended infinitely on all four sides as if
arrays[i][j] contained zeros for all elements outside the physical
array.
*/
Type Sums(ssize_t r, ssize_t c, Type sums[r][c], ssize_t i, ssize_t j)
{
if (i < 0 || j < 0) return 0;
if (r <= i) i = r-1;
if (c <= j) j = c-1;
return sums[i][j];
}
Then the sum of the elements in the subarray from array[i0][j0] to array[i1][j1] is simply Sums[i1][j1] - Sums[i1][j0-1] - Sums[i0-1][j1] + Sums[i0-1][j0-1], and the average is of course (Sums[i1][j1] - Sums[i1][j0-1] - Sums[i0-1][j1] + Sums[i0-1][j0-1]) / ((j1-j0+1) * (i1-i0+1)).
I want to iterate over an array in a certain fashion:
Starting with the first and the last element of the array, the next element I want to visit is the one furthest from all previously visited elements.
For an array of length n+1, the sequence would be
0,
n,
n/2 (furthest from 0 and n),
n/4 and n*3/4 (furthest from all 3 previous indices),
n/8, n*3/8, n*5/8, n*7/8, (furthest from all 5 previous indices)
n*1/16, n*3/16, n*5/16, n*7/16, n*9/16, n*11/16, n*13/16, n*15/16
...
if n is not a power of two, then some of these numbers will have to be rounded up or down, but I am not sure how to avoid duplicates when rounding.
At the end I want an integer sequence that contains all the numbers between 0 and n exactly once. (For any n, not just powers of two)
Is there a name for this permutation?
How would a function that generates these numbers work?
I am looking for a function that can generate these numbers on-the-fly.
If there are a billion elements, I do not want to manage a giant list of all previously visited elements, or generate the whole permutation list in advance.
The idea is that I can abort the iteration once I have found an element that fits certain criteria, so I will in most cases not need the whole permutation sequence.
So I am looking for a function f(int currentIndex, int maxIndex) with the following properties:
To interate over an array of size 8, i would call
f(0,8) returns 0, to get the index of the first element
f(1,8) returns 8
f(2,8) returns 4
f(3,8) returns 2
f(4,8) returns 6
f(5,8) returns 1
f(6,8) returns 3
f(7,8) returns 5
f(8,8) returns 7
(I am not quite sure how to extend this example to numbers that are not a power of two)
Is there a function with these properties?
The hopping about you describe is a feature of the Van der Corput sequence, as mentioned in a task I wrote on Rosetta Code.
I have an exact function to re-order an input sequence, but it needs arrays as large as the input array.
What follows is an approximate solution that yields indices one by one and only takes the length of the input array, then calculates the indices with constant memory.
The testing gives some indication of how "good" the routine is.
>>> from fractions import Fraction
>>> from math import ceil
>>>
>>> def vdc(n, base=2):
vdc, denom = 0,1
while n:
denom *= base
n, remainder = divmod(n, base)
vdc += remainder / denom
return vdc
>>> [vdc(i) for i in range(5)]
[0, 0.5, 0.25, 0.75, 0.125]
>>> def van_der_corput_index(sequence):
lenseq = len(sequence)
if lenseq:
lenseq1 = lenseq - 1
yield lenseq1 # last element
for i in range(lenseq1):
yield ceil(vdc(Fraction(i)) * lenseq1)
>>> seq = list(range(23))
>>> seq
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
>>> list(van_der_corput_index(seq))
[22, 0, 11, 6, 17, 3, 14, 9, 20, 2, 13, 7, 18, 5, 16, 10, 21, 1, 12, 7, 18, 4, 15]
>>> len(set(van_der_corput_index(seq)))
21
>>> from collections import Counter
>>>
>>> for listlen in (2, 3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 1023,
1024, 4095, 4096, 2**16 - 1, 2**16):
out = list(van_der_corput_index( list(range(listlen) )))
outcount = Counter(out)
if outcount and outcount.most_common(1)[0][1] > 1:
print("Duplicates in %i leaving %i unique nums." % (listlen, len(outcount)))
outlen = len(out)
if outlen != listlen:
print("Length change in %i to %i" % (listlen, outlen))
Duplicates in 23 leaving 21 unique nums.
Duplicates in 43 leaving 37 unique nums.
Duplicates in 47 leaving 41 unique nums.
Duplicates in 53 leaving 49 unique nums.
Duplicates in 59 leaving 55 unique nums.
Duplicates in 71 leaving 67 unique nums.
Duplicates in 79 leaving 69 unique nums.
Duplicates in 83 leaving 71 unique nums.
Duplicates in 89 leaving 81 unique nums.
>>> outlen
65536
>>> listlen
65536
>>>
Could you not use an array such that array[n][i]
such that
Array [0][i] = "1,2,3,4,5,6,7" 'start
Array [1][i] = "1,2,3,4" '1st gen split 1
Array [2][i] = "4,5,6,7" '1st gen split 2
Array [3][i] = "1,2" '2nd gen split 1 split 1
Array [4][i] = "3,4" '2nd gen split 1 split 2
Array [5][i] = "4,5" '2nd gen split 2 split 1
Array [6][i] = "6,7" '2nd gen split 2 split 1
'use dynamic iteration such that you know the size going into the array i.e. nextGen=Toint(Ubound(Array)/2)
If(
last(Array[n][i]) = first(Array[n+1][i]
then Pop(Array[n+1][i])
)
I see how to do this, but it's tricky to describe.. bear with me.
The key idea is to logically partition your array into two sets: One contains a number of elements equal to the greatest power of two still less than the size of the array, and the other contains everything else. (So, if your array holds 29 elements, you'd have one with 16 and the other with 13.) You want these to be mixed as fairly as possible, and you want:
A function to find the "Real" index of the i-th element of the first
logical set (equivalently: How many elements of the second set come before the i-th element of the first set)
A function to tell you whether some index i belongs
to the first or second logical set.
You then run the "Ideal" function you described over the first set (mapping with function 1, above), then do a single pass over the remaining elements. So long as you distribute fairly between the logical set, this will do as you describe.
To (logically) describe which indices belong to which partition: Call the size of the first logical partition k and the size of the second partition j. Assume that every element of the first set has j/k units of "credit" associated with it. Begin filling the true array with elements of the logical array, adding up credit as you go, but every time you would get to more than one unit of credit, place an element from the second array instead, and reduce the stored credit by one. This will fairly distribute exactly j elements from the second array between k elements of the first array. NOTE: You don't actually perform this calculation, it's just a logical definition.
With a little arithmetic, you can use this to implement the functions I described above. Before the i-th element of the first set will be exactly floor(i * j/k) elements of the second set. You only run the second function during the final pass, so you can run that exactly from the definition.
Does this make sense? I'm sure this will work, but it's difficult to describe.
Yes, it is called partitioning.
It is a very common methodology for searching in an ordered array.
also, it is used by QuickSort algorithm.
it mostly being implemented as a Recursive function that samples the "center" element, and then recurse on the "left" collection, then the "right" collection.
if the array is of length 1, sample it and don't recurse.
in the following example, i just search the array in the order you describe,
if the array was ordered, after checking the first pivot, i would have skipped checking the RightPart, or the LeftPart depending on the pivot value.
int partition(int* arr, int min, int max, int subject)
{ // [min, max] inclusive!
int pivot = (max - min + 1) >> 1; // (max - min)/2
if(arr[pivot] == subject)
return pivot;
if(pivot > 0)
{
int leftPart = partition(arr, min, pivot - 1, subject);
if(leftPart >= 0)
return leftPart;
}
if(max - pivot > 0)
{
int rightPart = partition(arr, pivot + 1, max, subject);
if(rightPart >= 0)
return rightPart;
}
return -1; // not found
}
int myArr[10] = {4,8,11,7,2,88,42,6,5,11 };
int idxOf5 = partition(myArr, 0, 9, 5);
I was able to solve this myself, with the tips given by Paddy3118 and Edward Peters.
I now have a method that generates a Van der Corput permutation for a given range, with no duplicates and no missed values, and with constant and negligible memory requirements and good performance.
The method uses a c# iterable to generate the sequence on the fly.
The method VanDerCorputPermutation() takes two parameters, the upper exclusive bound of the range, and the base that should be used for generating the sequence. By default, base 2 is used.
If the range is not a power of the given base, then the next larger power is used internally, and all indices that would be generated outside the range are simply discarded.
Usage:
Console.WriteLine(string.Join("; ",VanDerCorputPermutation(8,2)));
// 0; 4; 2; 6; 1; 3; 5; 7
Console.WriteLine(string.Join("; ",VanDerCorputPermutation(9,2)));
// 0; 8; 4; 2; 6; 1; 3; 5; 7
Console.WriteLine(string.Join("; ",VanDerCorputPermutation(10,3)));
// 0; 9; 3; 6; 1; 2; 4; 5; 7; 8
Console.WriteLine(VanDerCorputPermutation(Int32.MaxValue,2).Count());
// 2147483647 (with constant memory usage)
foreach(int i in VanDerCorputPermutation(bigArray.Length))
{
// do stuff with bigArray[i]
}
for (int max = 0; max < 100000; max++)
{
for (int numBase = 2; numBase < 1000; numBase++)
{
var perm = VanDerCorputPermutation(max, numBase).ToList();
Debug.Assert(perm.Count==max);
Debug.Assert(perm.Distinct().Count()==max);
}
}
The code itself uses only integer arithemtic and very few divisions:
IEnumerable<int> VanDerCorputPermutation(int lessThan, int numBase = 2)
{
if (numBase < 2) throw new ArgumentException("numBase must be greater than 1");
// no index is less than zero
if (lessThan <= 0) yield break;
// always return the first element
yield return 0;
// find the smallest power-of-n that is big enough to generate all values
int power = 1;
while (power < lessThan / numBase + 1) power *= numBase;
// starting with the largest power-of-n, this loop generates all values between 0 and lessThan
// that are multiples of this power, and have not been generated before.
// Then the process is repeated for the next smaller power-of-n
while (power >= 1)
{
int modulo = 0;
for (int result = power; result < lessThan; result+=power)
{
if (result < power) break; // overflow, bigger than MaxInt
if (++modulo == numBase)
{
//we have used this result before, with a larger power
modulo = 0;
continue;
}
yield return result;
}
power /= numBase; // get the next smaller power-of-n
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
The following code is an algorithm for searching for the maximum occurrence of an element in an array. This solution assumes that an element ranges from 0 to n-1.
void MaxRepetitions( int A[], int n ) {
int i=0; max=0, maxIndex;
for(i=0, i<n, i++)
A[A[i]%n] +=n;
for( i=0, i<n, i++)
if (A[i]/n > max) {
max = A[i]/n;
maxIndex=i;
}
return maxIndex;
}
How is A[A[i]%n] +=n; expanded?
Is A[A[i]%n] = A[A[i]%n] + n correct?
--
Edit
For the example where A = [2, 4, 7, 5, 4, 11], where n=6
A[0]%n = 2
A[1]%n = 4
A[2]%n = 1
A[3]%n = 5
A[4]%n = 4
A[5]%n = 5
After this loop:
for(i=0, i<n, i++)
A[A[i]%n] = A[A[i]%n] + n;
Iteration 1:
A[A[0]%n] = A[A[0]%n] + 6 --> A[2] = A[2] + 6 --> A[2] = 13
The array is now: A = [2, 4, 13, 5, 4, 11]
Iteration 2:
A[A[1]%n] = A[A[1]%n] + 6 --> A[4] = A[4] + 6 --> A[4] = 10
The array is now: A = [2, 4, 13, 5, 10, 11]
Iteration 3:
A[A[2]%n] = A[A[2]%n] + 6 --> A[1] = A[1] + 6 --> A[1] = 10
The array is now: A = [2, 10, 13, 5, 10, 11]
Iteration 4:
A[A[3]%n] = A[A[3]%n] + 6 --> A[5] = A[5] + 6 --> A[5] = 17
The array is now: A = [2, 10, 13, 5, 10, 17]
Iteration 5:
A[4] now is 10
A[A[4]%n] = A[A[4]%n] + 6 --> A[4] = A[4] + 6 --> A[4] = 16
The array is now: A = [2, 10, 13, 5, 16, 17]
Iteration 6:
A[5] now is 17
A[A[5]%n] = A[A[5]%n] + 6 --> A[5] = A[5] + 6 --> A[5] = 23
The array is now: A = [2, 10, 13, 5, 16, 23]
Now, once the second loop runs, A[i]/n for each of the elements is: A [0, 1, 2, 0, 2, 3 ]
It looks like this algorithm will choose 11 as the element with most occurrences which isn't true. Any help?
As others have said, <anything> += <value> is equivalent to <anything> = <anything> + <value> except that <anything> is evaluated only once.
Your analysis of the running of the algorithm is correct, but the problem is that the input violates the stated constraint that all elements are between 0 and n-1. In effect, since 11 % 6 = 5, the answer produced by the algorithm isn't completely wrong (modulo 6, the value 5 occurs the same number of times as the value 4). However, there is a further problem in that because the input constraint is violated, the counts are off for reasons that I explain in a comment below.
The best way to understand how this works is to look at another algorithm which, while seemingly quite different, is actually the same thing. This other algorithm is:
Allocate a separate array C[n]. (C for "count".)
Loop through each element A[i] of A and set C[A[i]] += 1. It's not too hard to see that, since each A[i] is between 0 and n-1, when this step finishes, C[j] for any j will be the number of times that the value j occurs among all the A[i].
Thus, the position of the largest element of C is the most frequently occurring value in A (with ties being resolved arbitrarily). Simply loop through C to find where this occurs and return the result.
Now the algorithm you posted is exactly that, but cleverly making use of two facts, both of which rely on the original values of A[i] being between 0 and n-1:
The value of A[i]%n will be exactly equal to the original value of A[i] regardless of how many times n has been added to A[i].
The value of A[i]/n will be exactly equal to the number of times n has been added to A[i], regardless of the original value of A[i].
So if we modify the second algorithm by adding n instead of 1, and by using %n and /n as is done in your posted algorithm, we can make A serve for both holding the original values and for holding the counts.
This:
A[A[i]%n] +=n
Is expanded to be equivalent to this:
A[A[i]%n] = A[A[i]%n] + n
Except that side-effects are only evaluated once. In other words, if the left expression had employed operators with side-effects like ++ and --, then these side-effects would only occur once, contrary to what had happened if you had actually written out the whole x = x + y expression, where side-effects in x would be evaluated twice.
A[A[i]%n] +=n
A[i] : value contained in array A at position i
A[i]%n : remainder of dividing this value by n (used to not allow this index go beyond the size of A
A[A[i]%n] : the value contained in that new position
A[A[i]%n] += n : add n to this value
Numerical example :
A[3] = {7, 10, 24}
n = 3
i = 0
A[A[0]%3] = A[7%3] // 7 = 2*3 + 1
= A[1]
= 10
add 3 ==> A[1] = 13
i = 1
A[A[1]%3] = A[13%3] // 13 = 4*3 +1
= A[1]
= 13
add 3 ==> A[1] = 16
i = 2
A[A[2]%3] = A[24%3] // 24 = 8*3 + 0
= A[1]
= 7
add 3 ==> A[1] = 10
I have a piece of code which will find out the repeating elements in an array of size n where the elements satisfy 1 <= arr[i] <= n, the code is given below:
#include<stdio.h>
#include<stdlib.h>
void printTwoElements(int arr[], int size)
{
int i;
printf("\n The repeating element is");
for(i = 0; i < size; i++)
{
if(arr[abs(arr[i])-1] > 0)
{
arr[abs(arr[i])-1] = -arr[abs(arr[i])-1];
}
else
{
printf(" %d ", abs(arr[i]));
}
}
}
/* Driver program to test above function */
int main()
{
int arr[] = {7, 3, 4, 5, 5, 6, 2};
int n = sizeof(arr)/sizeof(arr[0]);
printTwoElements(arr, n);
return 0;
}
I would like to know the use of abs() in this given code?
In the course of the algorithm, some array entries are set to negative values as a marker. Therefore the entries' absolute value has to be taken when they are used as indices into the array.
In the hope of not spoiling anything:
The algorithm requires that the array entries of an n-element array all are between 1 and n inclusive.
If any entry is larger than n or smaller than -n or 0, it will access invalid addresses, and if any element is negative, the marking logic will fail.
The logic of the algorithm is:
for each array element e:
if the value at (e-1) is positive, e has not yet been seen,
negate the value at (e-1) to mark e as seen
otherwise, e has already been seen, so print it
So since array entries become negative in the course of running the algorithm, the absolute value has to be taken to obtain valid indices.
Let us follow the algorithm for a modified example to see how it works:
before: arr = { 7, 3, 4, 5, 5, 3, 2}
i == 0: arr[0] = 7
arr[7-1] is 2 > 0 ~> negate
arr = { 7, 3, 4, 5, 5, 3, -2}
i == 1: arr[1] = 3
arr[3-1] is 4 > 0 ~> negate
arr = { 7, 3, -4, 5, 5, 3, -2}
i == 2: arr[2] is -4 ~> abs for indexing
arr[4-1] is 5 > 0 ~> negate
arr = { 7, 3, -4,-5, 5, 3, -2}
i == 3: arr[3] is -5 ~> abs for indexing
arr[5-1] is 5 > 0 ~> negate
arr = { 7, 3, -4, -5, -5, 3, -2}
i == 4: arr[4] is -5 ~> abs for indexing
arr[5-1] is -5 < 0 ~> print abs(-5) as duplicate
i == 5: arr[5] is 3
arr[3-1] is -4 < 0 ~> print abs(3) as duplicate
i == 6: arr[6] is -2 ~> abs for indexing
arr[2-1] is 3 > 0 ~> negate
arr = { 7, -3, -4, -5, -5, 3, -2}
indices of positive entries: 0, 5 ~> 1 and 6 not in original array
indices of negative entries: 1, 2, 3, 4, 6 ~> 2, 3, 4, 5, 7 in original array
If you had started with the most straightforward way to solve this, given additional O(n) space, you would have probably thought about storing "already encountered" flags in a separate (auxiliary) array to look them up afterwards:
// pseudocode (zero based indexing ignored for now)
for each value in array
if (already_encountered[value] == true)
print "found a duplicate of " + value
else
already_encountered[value] = true
Your algorithm goes a little further. Given the fact that an integer is (probably) 32-bit, and you only need to store a limited (small) range of values, each array member actually has sufficient free bits to store the "already encountered" flag.
This means that you can drop the auxiliary already_encountered array given above, and use this extra space to store the flags with no extra memory allocation.
Using some bit twiddling, you could, for example, choose to store this value at the highest bit (leaving you with 31 bits to store your numbers). Whenever you want to check if the flag is set, you would need to extract this highest bit and check it, and then finally clear the bit before printing out the value:
// pseudocode (zero based indexing ignored)
for each value in array
{
// this value might already have a flag previously encoded
// for some other element, so remove it before continuing
plain_value = remove_flag(value)
// check if the flag is set for the actual value,
// if not, set it now
if (is_flag_set(array[plain_value]) == true)
print "found a duplicate of " + plain_value
else
array[plain_value] = set_flag(array[plain_value])
}
The only thing left to do is to define set_flag, is_flag_set and remove_flag functions.
In your case, the algorithm "sets the flag" by negating the value, "tests for flag" by checking if the value is negative, and "removes the flag" by using the absolute value (hence the abs function).
This can be safely achieved because signed integers use a single bit to store their sign information, allowing the transformation to leave the original value intact (provided it is small enough).
This leaves you with your final C code:
void printTwoElements(int arr[], int size)
{
int i;
printf("\n The repeating element is");
for(i = 0; i < size; i++)
{
// remove the flag
int plain_value = abs(arr[i]);
// is flag set?
if(arr[plain_value-1] < 0)
{
printf(" %d ", plain_value);
}
else
{
// set the flag by negating
arr[plain_value-1] = -arr[plain_value-1];
}
}
}
It's trying to ensure that the program never attempts a negative array index while walking through the elements.
abs() is the absolute value function in C. It makes sure your array index is not negative.