Handling duplicated array elements - arrays

I am in trouble handling duplicated elements in arrays. For example, in the problem of finding all pairs of integers within an array which sum to a specified value, here is my implementation:
vector<pair<int, int>> find_all_pairs_with_sum(int data[], int length, int sum)
{
assert(data && length>1);
vector<pair<int, int>> res;
sort(data, data+length);
int first = 0;
int last = length - 1;
while (first < last)
{
int s = data[first] + data[last];
if (s == sum)
{
res.push_back(make_pair(data[first], data[last]));
++first;
--last;
}
else
{
if (s < sum)
++first;
else
--last;
}
}
return res;
}
The problem will occur when the array contains duplicated elements. For example, when
int data[] = {3, 4, 3, 4};
int sum = 7;
The program will only give two pairs (3,4) (3,4). However, in this case, the correct answer should be four pairs (3,4) (3,4) (3,4) (3,4) (as 4=2x2). How can I modify the code in order to correctly handle such cases (hopefully still in O(n logn))? It seems the change should be made in if (s==sum) scope while updating first and last, but I just cannot make it right.
Note that: I know another way that can handle this correctly by using a hash table to record occurrences of each elements. Please suggest how to work through this problem without using a hash table.

Your array gets sorted as
Index: 0 1 2 3
Element: 3 3 4 4
When you find a sum, you increment first and decrement last, so each pair is only added once, not twice. Additionally, steping inward at any rate will always prevent you from getting both 1-3 and 0-2 (by index). You could make a preliminary pass to find duplicates, and use that information to add the pairs correctly:
vector<pair<int, int>> find_all_pairs_with_sum(int data[], int length, int sum)
{
assert(data && length>1);
vector<pair<int, int>> res;
int i;
sort(data, data+length);
// there is more than one way to skin this cat...
vector<pair<int, int>> vettedData;
for(i = 0; i < length; i++) {
if(i == 0 || vettedData[vettedData.size() - 1].first != data[i])
vettedData.push_back(make_pair(data[i], 1));
else
vettedData[vettedData.size() - 1].second++;
}
int first = 0;
int last = vettedData.size() - 1;
while (first < last)
{
int s = vettedData[first].first + vettedData[last].first;
if (s == sum)
{
int iterations = vettedData[first].second * vettedData[last].second;
for(i = 0; i < iterations; i++)
res.push_back(make_pair(vettedData[first].first, vettedData[last].first));
++first;
--last;
}
else
{
if (s < sum)
++first;
else
--last;
}
}
return res;
}

Related

How to replace a recursive function to using stack or iteration?

I have a recursive function that I wrote in C that looks like this:
void findSolutions(int** B, int n, int i) {
if (i > n) {
printBoard(B, n);
} else {
for (int x = 1; x <= n; x++) {
if (B[i][x] == 0) {
placeQueen(B, n, i, x);
findSolutions(B, n, i + 1);
removeQueen(B, n, i, x);
}
}
}
}
The initial call is (size is an integer given by user and B is a 2D array):
findSolutions(B, size, 1);
I tried to convert it into a iteration function but there is another function called removeQueen after findSolutions. I got stuck on where to put this function call. How to solve this problem? Stack is also fine but I'm also having trouble doing that.
I'm going to assume that placeQueen(B, n, i, x) makes a change to B and that removeQueen(B, n, i, x) undoes that change.
This answer shows how to approach the problem generically. It doesn't modify the algorithm like Aconcagua has.
Let's start by defining a state structure.
typedef struct {
int **B;
int n;
int i;
} State;
The original code is equivalent to the following:
void _findSolutions(State *state) {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = 1; x <= state->n; ++x) {
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
findSolutions(state2);
}
}
}
State_free(state); // Frees the board too.
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
Now, we're in position to eliminate the recursion.
void _findSolutions(State *state) {
StateStack *S = StateStack_new();
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(&state));
StateStack_free(S);
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
We can eliminate the helper we no longer need.
void findSolutions(int** B, int n, int i) {
StateStack *S = StateStack_new();
State *state = State_new(B, n, i); // Deep clones B.
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(S, &state));
StateStack_free(S);
}
Functions you need to implement:
StateStack *StateStack_new(void)
void StateStack_free(StateStack *S)
void StateStack_push(StateStack *S, State *state)
int StateStack_pop(StateStack *S, State **p)
State *State_new(int **B, int n, int i) (Note: Clones B)
State *State_clone(const State *state) (Note: Clones state->B)
void State_free(State *state) (Note: Frees state->B)
Structures you need to implement:
StateStack
Tip:
It would be best if you replaced
int **B = malloc((n+1)*sizeof(int*));
for (int i=1; i<=n; ++i)
B[i] = calloc(n+1, sizeof(int));
...
for (int x = 1; x <= n; ++x)
...
B[i][x]
with
char *B = calloc(n*n, 1);
...
for (int x = 0; x < n; ++x)
...
B[(i-1)*n+(x-1)]
What you get by the recursive call is that you get stored the location of the queen in current row before you advance to next row. You will have to re-produce this in the non-recursive version of your function.
You might use another array storing these positions:
unsigned int* positions = calloc(n + 1, sizeof(unsigned int));
// need to initialise all positions to 1 yet:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
}
I reserved a dummy element so that we can use the same indices...
You can now count up last position from 1 to n, and when reaching n there, you increment next position, restarting with current from 1 – just the same way as you increment numbers in decimal, hexadecimal or octal system: 1999 + 1 = 2000 (zero based in this case...).
for(;;)
{
for(unsigned int i = 1; i <= n; ++i)
{
placeQueen(B, n, i, positions[i]);
}
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
}
for(unsigned int i = 1; i <= n; ++i)
{
if(++positions[i] <= n)
// break incrementing if we are in between the numbers:
// 1424 will get 1431 (with last position updated already before)
goto CONTINUE;
positions[i] = 1;
}
// we completed the entire positions list, i. e. we reset very
// last position to 1 again (comparable to an overflow: 4444 got 1111)
// so we are done -> exit main loop:
break;
CONTINUE: (void)0;
}
It's untested code, so you might find a bug in, but it should clearly illustrate the idea. It's the naive aproach, always placing the queens and removing them again.
You can do it a bit cleverer, though: place all queens at positions 1 initially and only move the queens if you really need:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
placeQueen(B, n, i, 1);
}
for(;;)
{
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
++positions[i]
if(++positions[i] <= n)
{
placeQueen(B, n, i, positions[i]);
goto CONTINUE;
}
placeQueen(B, n, i, 1);
positions[i] = 1;
}
break;
CONTINUE: (void)0;
}
// cleaning up the board again:
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, 1);
}
Again, untested...
You might discover that now the queens move within first row first, different to your recursive approach before. If that disturbs you, you can count down from n to 1 while incrementing the positions and you get original order back...
At the very end (after exiting the loop), don't forget to free the array again to avoid memory leak:
free(positions);
If n doesn't get too large (eight for a typical chess board?), you might use a VLA to prevent that problem.
Edit:
Above solutions will print any possible combinations to place eight queens on a chess board. For an 8x8 board, you get 88 possible combinations, which are more than 16 millions of combinations. You pretty sure will want to filter out some of these combinations, as you did in your original solution as well (if(B[i][x] == 0)), e. g.:
unsigned char* checks = malloc(n + 1);
for(;;)
{
memset(checks, 0, (n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[positions[i]] != 0)
goto SKIP;
checks[positions[i]] = 1;
}
// place queens and print board
SKIP:
// increment positions
}
(Trivial approach! Including the filter in the more elaborate approach will get more tricky!)
This will even be a bit more strict than your test, which would have allowed
_ Q _
Q _ _
_ Q _
on a 3x3 board, as you only compare against previous column, whereas my filter wouldn't (leaving a bit more than 40 000 boards to be printed for an 8x8 board).
Edit 2: The diagonals
To filter out those boards where the queens attack each other on the diagonals you'll need additional checks. For these, you'll have to find out what the common criterion is for the fields on the same diagonal. At first, we have to distinguish two types of diagonals, those starting at B[1][1], B[1][2], ... as well as B[2][1], B[3][1], ... – all these run from top left to bottom right direction. On the main diagonal, you'll discover that the difference between row and column index does not differ, on next neighbouring diagonals the indices differ by 1 and -1 respectively, and so on. So we'll have differences in the range [-(n-1); n-1].
If we make the checks array twice as large and shift all differences by n, can re-use do exactly the same checks as we did already for the columns:
unsigned char* checks = (unsigned char*)malloc(2*n + 1);
and after we checked the columns:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[n + i - positions[i]] != 0)
goto SKIP;
checks[n + i - positions[i]] = 1;
}
Side note: Even if the array is larger, you still can just memset(checks, 0, n + 1); for the columns as we don't use the additional entries...
Now next we are interested in are the diagonals going from bottom left to top right. Similarly to the other direction, you'll discover that the difference between n - i and positions[i] remains constant for fields on the same diagonal. Again we shift by n and end up in:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[2 * n - i - positions[i]] != 0)
goto SKIP;
checks[2 * n - i - positions[i]] = 1;
}
Et voilà, only boards on which queens cannot attack each other.
You might discover that some boards are symmetries (rotational or reflection) of others. Filtering these, though, is much more complicated...

How to use divide and conquer and the fact that if one subarray has a majority, the combined array has a majority to find majority element?

In the question we were told that the crux of the algorithm is the fact that
"When we get down to single elements, that single
element is returned as the majority of its (1-element) array. At every other level, it will get return values from its
two recursive calls. The key to this algorithm is the fact that if there is a majority element in the combined array,
then that element must be the majority element in either the left half of the array, or in the right half of the array."
My implementation was this, probably very buggy but the general idea was this:
#include <stdio.h>
int merge(int *input, int left, int middle, int right, int maj1, int maj2)
{
// determine length
int length1 = middle - left + 1;
int length2 = right - middle;
// create helper arrays
int left_subarray[length1];
int right_subarray[length2];
// fill helper arrays
int i;
for (i=0; i<length1; ++i)
{
left_subarray[i] = input[left + i];
}
for (i=0; i<length2; ++i)
{
right_subarray[i] = input[middle + 1 + i];
}
left_subarray[length1] = 100;
right_subarray[length2] = 100;
//both return majority element
int count1 = 0;
int count2 = 0;
for (int i = 0; i < length1; ++i) {
if (left_subarray[i] == maj1) {
count1++;
}
if (right_subarray[i] == maj1) {
count1++;
}
}
for (int i = 0; i < length2; ++i) {
if (right_subarray[i] == maj2) {
count2++;
}
if (left_subarray[i] == maj2) {
count2++;
}
}
if (count1 > ((length1+length2) - 2)/2){
return maj1;
}
else if (count2 > ((length1+length2) - 2)/2){
return maj2;
}
else
return 0;
}
int merge_sort(int *input, int start, int end, int maj1, int maj2)
{
//base case: when array split to one
if (start == end){
maj1 = start;
return maj1;
}
else
{
int middle = (start + end ) / 2;
maj1 = merge_sort(input, start, middle, maj1, maj2);
maj2 = merge_sort(input, middle+1, end, maj1, maj2);
merge(input, start, middle, end, maj1, maj2);
}
return 0;
}
int main(int argc, const char* argv[])
{
int num;
scanf("%i", &num);
int input[num];
for (int i = 0; i < num; i++){
scanf("%i", &input[i]);
}
int maj;
int maj1 = -1;
int maj2 = -1;
maj = merge_sort(&input[0], 0, num - 1, maj1, maj2);
printf("%d", maj);
return 0;
}
This obviously isn't divide and conquer. I was wondering what is the correct way to implement this, so I can have a better understanding of divide and conquer implementations. My main gripe was in how to merge the two sub-array to elevate it to the next level, but I am probably missing something fundamental on the other parts too.
Disclaimer: This WAS for an assignment, but I am analyzing it now to further my understanding.
The trick about this particular algorithm, and why it ends up O(n log n) time is that you still need to iterate over the array you are dividing in order to confirm the majority element. What the division provides is the correct candidates for this iteration.
For example:
[2,1,1,2,2,2,3,3,3,2,2]
|maj 3| maj 2
maj 2 | maj None
<-------------------> still need to iterate
This is implicit in the algorithm statement: "if there is a majority element in the combined array, then that element must be the majority element in either the left half of the array." That "if" indicates confirmation is still called for.

Recursive finding the indexes of 2 biggest nums in massive (C)

I have broken my head trying to solve this question on an exam. I'm stil shocked by it.
Can anybody help me write a function:
void get2(int a[], int n, *i1, *i2)
that receives the massive a[] of integers and his length n and saves to pointers i1 and i2 the indexes of the two biggest numbers in the massive (i1 - the biggest, i2 - the second biggest).
The solution must be recursive and can not contain loops. It has be done by the complextiy of O(n). The numbers in the massive are all diffrent. We cant use any helper functions.
There aren't any additional conditions. I tried some solutions, but they werent good enough.
I dont know how to save the indexes without losing there values when I recurse.
There was additional hint, that I should pay attention to how I use the *i1, *i2 to pass information between recursive steps, but i tried to use it some how and it didn't work for me anything I tried. Help somebody ?
There is only one trick to play on this exercise: Recognize when we are in the outermost recursive call and when we are not, or simpler terms when the current call of get2 is the first one and when it is not.
Using the pointers and the n parameter to do some basic Divide et Impera strategy is straightforward and require no further explanation.
We need to tell the first and subsequent calls because in the first, and only there, call we need to initialize the pointers.
We cannot rely on i1 or i2 values as they are uninitialized.
Only n has enough structure to carry some information: When we are called from the extern, i.e. not by recurring, then n >= 0.
We can then perform the one-time initialization and then negate n. This way if n<=0 we know that we are in the recursive calls.
However we still have a problem: if n >= 0 then it's opposite is n <= 0. The two condition overlaps for n == 0.
This will make the initialization happen two time and further worst the second one at the end of the recursion stack thereby voiding the state calculated.
In order to avoid them, the n is not simply negated but negated and decremented by 1, so the 5 becomes -6.
We can then recover the usable value of n by again negating and decrementing by 1. In the code below this is done and stored in m.
The else part is straightforward as pointed above. We only additionally check that the second maximal element is not equal to the maximal element in the second if.
If one index is -1 it means that it is not pointing to any element and can be assigned unconditionally.
When the function return, i1 cannot point to -1 unless the array is empty.
i2 can point to -1 if all elements are the same.
#include <stdio.h>
void get2(int a[], int n, int* i1, int* i2)
{
/* Transform from encoded n to actual length */
int m = -n-1;
/* Is this the first call? */
if (n >= 0)
{
/* Initialize the pointer to -1, i.e. no elements */
*i1 = *i2 = -1;
/* Start the recursion, encode the length */
get2(a, -n-1, i1, i2);
}
/* Here we are in the subsequent calls, we use m and not n */
else if (m-- > 0)
{
/* Assign i1 */
if (*i1 == -1 || a[m] > a[*i1])
{
*i2 = *i1; /* Don't forget to update i2 too! */
*i1 = m;
}
/* Opportunity to assign i2, check that the second max != max */
else if ((*i2 == -1 || a[m] > a[*i2]) && a[m] != a[*i1])
{
*i2 = m;
}
/* Tail recursion, do proper encoding of the n parameter */
get2(a, -m-1, i1, i2);
}
}
This function can be tested with this code
void test(int a[], int n)
{
int max, smax, i;
get2(a, n, &max, &smax);
printf("------------------------------\n");
for (i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\nMax is ");
if (max >= 0)
printf("%d", a[max]);
else
printf("NOT FOUND");
printf("\nSecond Max is ");
if (smax >= 0)
printf("%d\n", a[smax]);
else
printf("NOT FOUND\n");
}
int main()
{
int v1[] = {};
int v2[] = {1};
int v3[] = {1,2};
int v4[] = {2, 1};
int v5[] = {2, 2};
int v6[] = {1,2,3,4};
int v7[] = {4,3,2,1};
int v8[] = {2,1,4,3};
int v9[] = {2,2,2,2};
int v10[] = {1,2,3,4,3,2,1};
int v11[] = {1,1,2,3,4,4};
test(v1, 0);
test(v2, 1);
test(v3, 2);
test(v4, 2);
test(v5, 2);
test(v6, 4);
test(v7, 4);
test(v8, 4);
test(v9, 4);
test(v10, 7);
test(v11, 6);
return 0;
}
With the below output
------------------------------
Max is NOT FOUND
Second Max is NOT FOUND
------------------------------
1
Max is 1
Second Max is NOT FOUND
------------------------------
1 2
Max is 2
Second Max is 1
------------------------------
2 1
Max is 2
Second Max is 1
------------------------------
2 2
Max is 2
Second Max is NOT FOUND
------------------------------
1 2 3 4
Max is 4
Second Max is 3
------------------------------
4 3 2 1
Max is 4
Second Max is 3
------------------------------
2 1 4 3
Max is 4
Second Max is 3
------------------------------
2 2 2 2
Max is 2
Second Max is NOT FOUND
------------------------------
1 2 3 4 3 2 1
Max is 4
Second Max is 3
------------------------------
1 1 2 3 4 4
Max is 4
Second Max is 3
I will give you another hint instead of writing the actual code for you:
You have 4 arguments, use all of them to pass the relevant data to the recursive calls. What I mean by that is - the first 2 arguments can describe the part of the array that is interesting for us, the pointers store the largest integers we have found, you modify them each time you find a bigger one.
And here lies the trap that most likely caught you - those are int *, that is a pointer to an integer. What the function receives is simply an address in memory. If you set that pointer to point to anything, the caller will not receive that data. You can simply write directly to that address instead of setting the pointer, like so:
int myInteger;
int *ptr = &myInteger;
*ptr = 123;
Here is a non-threadsafe way to do it: by keeping track of the original start of the array using a static variable. The addresses of the largest elements are stored in the pointers, which are used as pointers to pointers, and right at the end they are replaced by the indexes of the elements by using some pointer arithmetic aided by the static variable.
void get2(int a[], int n, int *one, int *two) {
static int *arr_start = 0;
if (n > 0) {
if (arr_start == 0) {
arr_start = a;
}
if (a[0] > **((int **)one)) {
*one = a;
} else if (a[0] > **((int **)two)) {
*two = a;
}
get2(a + 1, n - 1, one, two);
} else {
*one = *((int **)one) - arr_start;
*two = *((int **)two) - arr_start;
}
}
EDIT
Without using static variables: Use the second pointer as an indicator of whether or not we have already allocated space to keep track of the the start of the array and the indexes. Use the allocated space to keep track of the initial array size and the two largest indexes, then assign them to the correct pointers at the end:
#include <stdlib.h>
void get2(int a[], int n, int *one, int *two) {
int **pp_one = (int **)one;
if (*two != NULL) {
*pp_one = malloc(sizeof(int) * 3);
(*pp_one)[0] = n;
(*pp_one)[1] = 0;
(*pp_one)[2] = 0;
}
if (n > 0) {
if (a[0] > (*pp_one)[1]) {
(*pp_one)[1] = a;
} else if (a[0] > (*pp_one)[2]) {
(*pp_one)[2] = a;
}
get2(a + 1, n - 1, one, two);
} else {
int *t = *one;
*two = (*pp_one)[1] - (*pp_one)[0];
*one = (*pp_one)[2] - (*pp_one)[0];
free(t);
}
}
Thanks for the brain teaser. It sounded like an interesting problem. Even though it's homework, I decided to solve it.
This gets a bit annoying to do without having the indices pre-initialized somehow, but it's doable. Sounds like an artificial restriction to create artificial pain.
void
get2(int a[], int n, int *i1, int *i2) {
if (n == 0) {
*i1 = *i2 = -1;
return;
}
get2(&a[1], n - 1, i1, i2);
if (*i1 != -1)
(*i1)++;
if (*i2 != -1)
(*i2)++;
if (*i1 == -1) {
*i1 = 0;
} else if (*i2 == -1 || a[*i2] < a[0]) {
*i2 = 0;
if (a[*i1] < a[0]) {
*i2 = *i1;
*i1 = 0;
}
}
}
Here we just recurse until we have no array left to look at, then initialize the indices and on the way back we figure out the indices we're interested in. On the way back through all the recursions we update the indices i1 and i2 if they are initialized to properly point into the array we have in this iteration, then if i1 isn't initialized yet, then we know that n == 0 and must be the biggest element. On iterations after that we know that is the only interesting element of the array is element 0, if that's not bigger than a[*i2], then it's not bigger than a[*i1] either. If it is (or we're just initializing i2), we compare to see if we need to swap i1 and i2.
"But wait!", you might yell. "You're not doing tail recursion, if the array is massive you will run out of stack.". Glad you mentioned it, in fact, C doesn't say anything about the compiler having to do optimizations for tail recursion so I'd like to argue that any solution has to account for this problem. Here's a solution that works on the same principles (run out of array before we initialize the indices) that solves this in O(log n) stack space:
void
get2(int a[], int n, int *i1, int *i2) {
/*
* Reset the indices at the end of the recursion.
*/
switch (n) {
case 0:
*i1 = -1;
*i2 = -1;
return;
case 1:
*i1 = 0;
*i2 = -1;
return;
}
/*
* Number of elements in the lower and upper halves of the array.
* Notice the '+ (n & 1)' which is there to add one element to the
* upper half of the array if n is odd.
*
* The asserts document the invariants.
*/
int lower_half = n / 2, upper_half = (n / 2) + (n & 1);
int li1, li2, ui1, ui2;
assert(lower_half >= 1);
assert(upper_half >= 1);
assert(lower_half + upper_half == n);
get2(&a[0], n - upper_half, &li1, &li2);
get2(&a[lower_half], n - lower_half, &ui1, &ui2);
ui1 += lower_half;
if (ui2 != -1)
ui2 += lower_half;
assert(li1 != -1);
assert(ui1 != -1);
assert(li2 == -1 || a[li2] < a[li1]);
assert(ui2 == -1 || a[ui2] < a[ui1]);
if (a[li1] < a[ui1]) {
*i1 = ui1;
if (ui2 == -1 || a[li1] > a[ui2])
*i2 = li1;
else
*i2 = ui2;
} else if (a[li1] > a[ui1]) {
*i1 = li1;
if (li2 == -1 || a[ui1] > a[li2])
*i2 = ui1;
else
*i2 = li2;
} else {
*i1 = li1;
if (li2 == -1 || a[ui2] > a[li2])
*i2 = ui2;
else
*i2 = li2;
}
}
I'm not going to explain it, the comments and asserts should be enough to show what's going on. I'm pretty sure that the big block of ifs at the end can be written much more efficiently, but I didn't bother.
It might not be perfectly correct, it worked on the first try with a few test cases taken from the previous answers and I didn't do more testing. There might be some edge cases I haven't considered, but the general idea works.
Here is a nice answer I got. The next few strokes are just to get enough characters to publish my answer with this image. this it requieres 30 characters, so i wiil write anything.
It's brilliant as simple as it is. Isnt it ))?
* This code need a little correction, with one more condition, if one of the pointers is NULL, not to loop.
Here's my take on it. This implementation is pretty concise.
void get2(int a[], int n, int *i1, int *i2)
{
if (n == 0) return;
if (*i1 == -1 || a[n-1] > a[*i1]) {
*i2 = *i1;
*i1 = n-1;
} else if (*i2 == -1 || a[n-1] > a[*i2]) {
*i2 = n-1;
}
get2(a, n-1, i1, i2);
}
To test:
#define NUM 10
int main()
{
int a[NUM];
int i, i1, i2;
srand(time(NULL));
for (i=0;i<NUM;i++) {
a[i] = rand() & 0xFFFF;
fprintf(stderr,"%d ",a[i]);
}
fprintf(stderr,"\n");
i1 = i2 = -1;
get2(a,NUM,&i1,&i2);
fprintf(stderr,"i1=%d, i2=%d\n", i1, i2);
fprintf(stderr,"a[i1]=%d, a[i2]=%d\n", a[i1], a[i2]);
}
Just another try on your function prototype,
void get2(int a[], int n, int *i1, int *i2)
{
if(n <= 0)
return;
if(*i1 == -1 && n < 2){//initial a[] is null or with only one element
*i1 = n-1;
return;
}
if(*i1 == -1 && n >=2){
if(a[n-1] > a[n-2]){
*i1 = n-1;
*i2 = n-2;
}else{
*i1 = n-2;
*i2 = n-1;
}
return get2(a, n-2, i1, i2);
}
int max= a[*i1], less = a[*i2];
if(a[n-1] > max){
*i2 = *i1;
*i1 = n-1;
}else if (a[n-1] > less){
*i2 = n-1;
}
get2(a, n-1, i1, i2);
}
Test as follows,
int main()
{
int a[] = { 1, 2, 3, 4, 7, 8, 6, 5, 0};
int maxIndex = -1, lessIndex= -1;
get2(a,sizeof(a)/sizeof(int),&maxIndex,&lessIndex);
printf("maxIndex=%d(value:%d), lessIndex=%d(value:%d)\n",
maxIndex,a[maxIndex],lessIndex, a[lessIndex]);
}
Output,
maxIndex=5(value:8), lessIndex=4(value:7)

Modify any element of the array

Given an array of integers , you can modify any of a number of arbitrary positive integer , and ultimately makes the entire array is strictly increasing and are positive integers , and asked at least need to change a few numbers
input: 5 1 2 2 3 4
output: 3
and there is what i have tried ,Each number in order to reduce more a ( first number minus one , then the second number minus two ,the third number minus three)
#include <stdio.h>
int Modify_the_array(int B[],int n);
int max(int a,int b);
int main(int argc,char *argv) {
int before_array[]={1,2,3,4,1,2,3,4,5};
int len=sizeof(before_array[0])/sizeof(before_array);
int b;
b=Modify_the_array(before_array,len);
printf("%d\n",b);
return 0;
}
int max(int a,int b){
return a>b?a:b;
}
int Modify_the_array(int B[],int len) {
int i,b=0,n=1;
int maxsofar,tmp,j;
for (i=0;i<len;i++){
B[i]=B[i]-n;
n++;
}
maxsofar=0;
tmp=0;
for(i=0;i<len;i++) {
for (j=i+1;j<len;j++) {
if (B[j]==B[i]&&B[i]>1) {
maxsofar=max(maxsofar,++tmp);
b=len-maxsofar;
}
}
}
return b;
}
somebody recommend there is another solution for this question,more efficently ,can anyone give me some advice,thank in advance
I came across the same problem recently. To make clear:
Problem Statement
You are given a sequence of integers a1,a2,a3.....an. You are free to replace any integer with any other positive integer. How many integers must be replaced to make the resulting sequence strictly increasing?
Input Format
The first line of the test case contains an integer N - the number of entries in the sequence.
The next line contains N space separated integers where the ith integer is ai.
Output Format
Output the minimal number of integers that should be replaced to make the sequence strictly increasing.
Given your input, len = 5, arr = [1 2 2 3 4], after minus index+1, get [0 0 -1 -1 -1].
Ignoring negative elements(these must be changed), compute Longest Increasing Subsequence(nondecreasing for this problem), which is a classic Dynamic Programming problem.
Denote the length of LIS = n(these elements will not be changed). So the final answer(the part doesn't belong to the increasing subsequence and the ignored negative part) is len-n(5-2=3).
We can compute LIS in O(nlogn) time with O(n) space.
int solve(vector<int> &arr) {
int len = arr.size();
for(int i = 0; i < len; i++) {
arr[i] -= i+1;
}
vector<int> lis(len,0);
int n = 0;
for(int i = 0; i < len; i++) {
if(arr[i] >= 0) {
int pos = binarysearchPos(lis,n,arr[i]);
lis[pos] = arr[i];
if(n == pos)
n++;
}
}
return len-n;
}
int binarysearchPos(vector<int> &arr, int n, int target) {
if(n == 0)
return 0;
if(arr[n-1] <= target)
return n;
int low = 0, high = n-1;
while(low < high) {
int mid = (low+high)/2;
if(arr[mid] > target) {
high = mid;
} else {
low = mid+1;
}
}
return low;
}

Rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space

The task is to rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space.
Example:
2 1 3 5 4 0
becomes:
3 1 5 0 4 2
I can think of an O(n²) solution. An O(n) solution was presented here:
Increase every array element arr[i] by (arr[arr[i]] % n)*n.
Divide every element by n.
But this is very limited as it will cause buffer overflow.
Can anyone come up with an improvement upon this?
If the values in the array are all positive (or all negative), one way to avoid overflow could be to run the permutation cycles and use the integer sign to mark visited indexes. (Alternatively, if the array length is smaller than 2^(number of bits for one array element - 1), rather than use the sign, we could shift all the values one bit to the left and use the first bit to mark visited indexes.) This algorithm results in both less iterations and less modifications of the original array values during run-time than the algorithm you are asking to improve.
JSFiddle: http://jsfiddle.net/alhambra1/ar6X6/
JavaScript code:
function rearrange(arr){
var visited = 0,tmp,indexes,zeroTo
function cycle(startIx){
tmp = {start: startIx, value: arr[startIx]}
indexes = {from: arr[startIx], to: startIx}
while (indexes.from != tmp.start){
if (arr[indexes.from] == 0)
zeroTo = indexes.to
if (indexes.to == visited){
visited++
arr[indexes.to] = arr[indexes.from]
} else {
arr[indexes.to] = -arr[indexes.from]
}
indexes.to = indexes.from
if (indexes.from != tmp.start)
indexes.from = arr[indexes.from]
}
if (indexes.to == visited){
visited++
arr[indexes.to] = tmp.value
} else {
arr[indexes.to] = -tmp.value
}
}
while (visited < arr.length - 1){
cycle(visited)
while (arr[visited] < 0 || visited == zeroTo){
arr[visited] = -arr[visited]
visited++
}
}
return arr
}
//Traverse the array till the end.
//For every index increment the element by array[array[index] % n]. To get //the ith element find the modulo with n, i.e array[index]%n.
//Again traverse to end
//Print the ith element after dividing the ith element by n, i.e. array[i]/n
class Rearrange
{
void rearrange(int arr[], int n)
{
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
for (int i = 0; i < n; i++)
arr[i] /= n;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println("");
}
public static void main(String[] args)
{
Rearrange rearrange = new Rearrange();
int arr[] = {6, 4, 9, 2, 5, 7};
int n = arr.length;
System.out.println("Given Array is :");
rearrange.printArr(arr, n);
rearrange.rearrange(arr, n);
System.out.println("Modified Array is :");
rearrange.printArr(arr, n);
}
}

Resources