I am new to merge sorts and am trying to create one. My merge sort is not sorting the array I am sending it and I can't figure out why. here is a link to all of the code http://pastebin.com/M4RUzhUa
Here is my mergesort function
void merge_sort(int array[], int low, int high) {
int middle = (low + high) / 2;
if(low < high) {
merge_sort(array, low, middle);
merge_sort(array, middle+1, high);
merge(array, low, middle, high);
}
}
Here is my (updated) merge function
void merge(int array[], int low, int middle, int high) {
int size,left,right,i, j;
size = high - low + 1;
int array1[high];
left = low;
right = middle + 1;
i = low;
while ((left<=middle) && (right<=high)) {
if(array[left] < array[right]) {
array1[i] = array[left];
left++;
i++;
}
else {
array1[i] = array[right];
right++;
i++;
}
}
while (left <= middle) {
array1[i] = array[left];
left++;
i++;
}
while (right <= high) {
array1[i] = array[right];
right++;
i++;
}
for (j = low; j < i; j++) {
array[j] = array1[j];
}
}
In my program the input array is
9
3
2
1
5
and the output is
0
1
2
3
5
something is happening with the first element that i can't figure out
New comments for updated code:
It looks like you are waltzing past the end of your array. A way to test that would be to add some guard variables around your array, like this:
#define NUM_OF_INTS 5
#define DEBUG 1
int main()
{
int frontguard=-500;
int numbers[NUM_OF_INTS];
int backguard=-600;
int i;
srand(0);
//Fill the array
for( i = 0; i < NUM_OF_INTS; i++ )
{
//Use random numbers
//numbers[i] = rand()%10000;
//Use reverse sorted list
numbers[i] = NUM_OF_INTS-i;
//Use sorted list
//numbers[i] = i;
}
if (DEBUG == 1) printf( "Unsorted list\n" );
if (DEBUG == 1) printarray( numbers, 0, NUM_OF_INTS/2, NUM_OF_INTS );
if (DEBUG == 1) printf( "frontguard=%04d, backguard=%04d\n", frontguard, backguard);
merge_sort( numbers, 0, NUM_OF_INTS );
if (DEBUG == 1 ) printf( "\nSorted list\n");
if (DEBUG == 1) printarray( numbers, 0, NUM_OF_INTS/2, NUM_OF_INTS );
if (DEBUG == 1) printf( "frontguard=%04d, backguard=%04d\n", frontguard, backguard);
return 0;
}
printarray is a helper function I wrote to prettyprint what is happening in an array
void printarray( const int arr[], const int low, const int middle, const int high )
{
int i;
for (i = low; i < high; i++ )
{
if( i == low )
printf( " L%04d", i );
else if( i == middle )
printf( " M%04d", i );
else if( i == (high-1) )
printf( " H%04d", i );
else
printf( " *%04d", i );
}
printf( "\n" );
for( i = low; i < high; i++ )
printf( " %04d", arr[i] );
printf( "\n" );
}
It is common to have to create some helper debug functions such as this to get your code working if you do not have/want a debugger. Do not be afraid to write some throw-away code to understand what your code is doing! In this case, I didn't need the line of L/M/H, but it is still worthwhile to spend the time. I recommend leaving these types of functions in your code, commented out (using a #define such as DEBUG), in case a future maintainer needs them.
Here is the output of your function as-is:
Unsorted list
L0000 *0001 M0002 *0003 H0004
0005 0004 0003 0002 0001
frontguard=-500, backguard=-600
Sorted list
L0000 *0001 M0002 *0003 H0004
-600 0001 0002 0003 0004
frontguard=-500, backguard=0005
You can see that the backguard got overwritten and "stolen" into your output. (This behavior can differ on different CPU architectures, C implementations, and run specifics, btw.) The problem is that you call merge_sort from main() with high as the size of the array (5 in this case), however merge_sort expects high to be the last valid index in the array (numbers[4] is the last array item). Modify main() to
merge_sort( numbers, 0, NUM_OF_INTS-1 );
and test it against a sorted, reverse sorted, and random array of numbers.
Original comments:
Well, first off, you should be receiving a segementation fault, not just incorrectly sorted data.
size = high - low + 1;
//create a helper array and set it equal to the input array
int array1[size];
for (i = low; i <= high; i++) {
array1[i] = array[i];
}
Think about what happens here when low is not zero. Let's say l=6, m=6, h=7. You are setting the size of your helper array to 2, but you are accessing it with i=6, so you are trashing the stack.
The easiest fix for this is to declare int array1[high];. It's memory inefficient but it keeps the rest of the code simple, which is really more valuable.
Second, your for loop is indexing past the end of array, you need to use i < high. In C, arrays start at 0, so an array of size 5 has valid locations at 0,1,2,3,4. Your code as-is would try to read from array[5] (probably not fatal), and write to array1[5] (very possibly fatal). I'll bet this why you have a +1 in the size statement, since you were advancing past the end of array1 otherwise.
for (i = low; i < high; i++) {
These will fix your segmentation fault. With that fixed, you are still getting garbage data in your output.
Your middle else-if statement is never going to be executed - any equivalent data is going to be covered by the first if statement.
Your while loop does not properly handle the degenerate cases. It needs to detect if one of the two lists has been completely consumed, and if so, just copy the rest of the other list.
Also, the while loop needs separate tracker variables for low, mid, and the output array. You cannot use currentLow for both low and the output array.
Finally, when testing sorting, random data is not sufficient (esp. with a size of 5), you should always test the totally degenerate cases of a sorted and reverse-sorted lists.
Related
I was doing selection sort yesterday. I wondered if I could replace the min and max values to begining and end of the unsorted array every time I iterated. I am just a beginner at programming, so its obvious that this wouldn't work. However, suprisingly, the code below does sort a larger array (~ 30k - 40k) in size. I experimented by generating random values from rand()%2000 and the function sorted the array successfully 28 times in 30 experiments.
But it can't sort something as simple as {4,2,3}
I think there's a bug somewhere, I couldn't figure it out so I've come here.
I'm also curious about the fact that it sorted such large arrays successfully. How?
int *zigzag_sort(int arr[])
{
// loop through array
// find min and max
// replace min at begining and max at end
// keep doing until sorted
int f_idx = 0, l_idx = n-1;
int min_pos, max_pos;
while( f_idx < l_idx ) {
min_pos = f_idx;
max_pos = l_idx;
for(int i = f_idx+1; i <= l_idx; i++)
{
if(arr[i] < arr[min_pos])
min_pos = i;
else if(arr[i] > arr[max_pos])
max_pos = i;
}
swap(&arr[f_idx], &arr[min_pos]);
swap(&arr[l_idx], &arr[max_pos]);
f_idx++;
l_idx--;
}
return arr;
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
Your swaps are not as simple as you think, and there is a hole in your position starting points going in to the inner loop iterations.
First, there are there situations that must be accounted after completing a segment enumeration and finding the segment min-index and max-index locations. They all deal with where you're reading data from, and where you'r'e trying to write it to. There can be partial, or in one case, full, overlap.
After each inner iteration, one of several conditions can transpire...
(min_pos == l_idx) && (max_pos == f_idx) . In other words, the minimum and maximum values are each in the places where the other wants to be. If that is the case ONE swap is needed (each other) and you're done for that iteration.
One of (min_pos == l_idx) or (max_pos == f_idx) is true, but not both. The order of the impending two swaps is important, depending on which of those conditions is true. In short, don't swap something into a slot that is about to be swapped again with the second swap. Ex: If the maximum value resides at the low target position, you need to swap it out to the maximum target position before the minimum value is swapped to the low target position. Otherwise you will dislocate something right after you put it home.
Neither of the above are true, in which case two swaps are still required, but order is irrelevant.
The probability of the special cases in (1) and (2) above increase significantly as you squeeze the iteration window down further and further during the outer loop iteration. For a random ordering, sooner or later it is going to happen.
Secondly, both the min_pos and max_pos starting points should be the same location in the segment, f_idx. It may not seem important, but it is so because the inner loop starts a f_idx+1. that means if the maximum value of the iteration was originally at f_idx you never accounted for it, will not discover it, etc.
The fixed routine is below, with notes where appropriate.
int *zigzag_sort(int arr[], int n)
{
int f_idx = 0, l_idx = n - 1;
while (f_idx < l_idx)
{
// both should start at the same location
int min_pos = f_idx;
int max_pos = f_idx;
for (int i = f_idx + 1; i <= l_idx; i++)
{
if (arr[i] < arr[min_pos])
min_pos = i;
else if (arr[i] > arr[max_pos])
max_pos = i;
}
if (max_pos == f_idx)
{
if (min_pos == l_idx)
{
// swap each other
swap(&arr[max_pos], &arr[min_pos]);
}
else
{ // swap the max out before overwritine with min
swap(&arr[l_idx], &arr[max_pos]);
swap(&arr[f_idx], &arr[min_pos]);
}
}
else
{ // also handle the case of l_idx == min_pos
swap(&arr[f_idx], &arr[min_pos]);
swap(&arr[l_idx], &arr[max_pos]);
}
f_idx++;
l_idx--;
}
return arr;
}
Why doesn't it work for { 4, 2, 3 }?
... // f_idx = 0; l_idx = 2; min_pos = 1; max_pos = 0;
swap(&arr[f_idx], &arr[min_pos]); // swap(&arr[0], &arr[1]) ==> { 2, 4, 3 }
// ===> max_pos is "wrong" now <===
swap(&arr[l_idx], &arr[max_pos]); // swap(&arr[2], &arr[0]) ==> { 3, 4, 2 }
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...
I am new to programming and C is the only language I know. Read a few answers for the same question written in other programming languages. I have written some code for the same but I only get a few test cases correct (4 to be precise). How do I edit my code to get accepted?
I have tried comparing one element of the array with the rest and then I remove the element (which is being compared with the initial) if their sum is divisible by k and then this continues until there are two elements in the array where their sum is divisible by k. Here is the link to the question:
https://www.hackerrank.com/challenges/non-divisible-subset/problem
#include<stdio.h>
#include<stdlib.h>
void remove_element(int array[],int position,long int *n){
int i;
for(i=position;i<=(*n)-1;i++){
array[i]=array[i+1];
}
*n=*n-1;
}
int main(){
int k;
long int n;
scanf("%ld",&n);
scanf("%d",&k);
int *array=malloc(n*sizeof(int));
int i,j;
for(i=0;i<n;i++)
scanf("%d",&array[i]);
for(i=n-1;i>=0;i--){
int counter=0;
for(j=n-1;j>=0;j--){
if((i!=j)&&(array[i]+array[j])%k==0)
{
remove_element(array,j,&n);
j--;
continue;
}
else if((i!=j)&&(array[i]+array[j])%k!=0){
counter++;
}
}
if(counter==n-1){
printf("%ld",n);
break;
}
}
return 0;
}
I only get about 4 test cases right from 20 test cases.
What Gerhardh in his comment hinted at is that
for(i=position;i<=(*n)-1;i++){
array[i]=array[i+1];
}
reads from array[*n] when i = *n-1, overrunning the array. Change that to
for (i=position; i<*n-1; i++)
array[i]=array[i+1];
Additionally, you have
remove_element(array,j,&n);
j--;
- but j will be decremented when continuing the for loop, so decrementing it here is one time too many, while adjustment of i is necessary, since remove_element() shifted array[i] one position to the left, so change j-- to i--.
Furthermore, the condition
if(counter==n-1){
printf("%ld",n);
break;
}
makes just no sense; remove that block and place printf("%ld\n", n); before the return 0;.
To solve this efficiently, you have to realize several things:
Two positive integer numbers a and b are divisible by k (also positive integer number) if ((a%k) + (b%k))%k = 0. That means, that either ((a%k) + (b%k)) = 0 (1) or ((a%k) + (b%k)) = k (2).
Case (1) ((a%k) + (b%k)) = 0 is possible only if both a and b are multiples of k or a%k=0 and b%k=0. For case (2) , there are at most k/2 possible pairs. So, our task is to pick elements that don't fall in case 1 or 2.
To do this, map each number in your array to its corresponding remainder by modulo k. For this, create a new array remainders in which an index stands for a remainder, and a value stands for numbers having such remainder.
Go over the new array remainders and handle 3 cases.
4.1 If remainders[0] > 0, then we can still pick only one element from the original (if we pick more, then sum of their remainders 0, so they are divisible by k!!!).
4.2 if k is even and remainders[k/2] > 0, then we can also pick only one element (otherwise their sum is k!!!).
4.3 What about the other numbers? Well, for any remainder rem > 0 make sure to pick max(remainders[rem], remainders[k - rem]). You can't pick both since rem + k - rem = k, so numbers from such groups can be divisible by k.
Now, the code:
int nonDivisibleSubset(int k, int s_count, int* s) {
static int remainders[101];
for (int i = 0; i < s_count; i++) {
int rem = s[i] % k;
remainders[rem]++;
}
int maxSize = 0;
bool isKOdd = k & 1;
int halfK = k / 2;
for (int rem = 0; rem <= halfK; rem++) {
if (rem == 0) {
maxSize += remainders[rem] > 0;
continue;
}
if (!isKOdd && (rem == halfK)) {
maxSize++;
continue;
}
int otherRem = k - rem;
if (remainders[rem] > remainders[otherRem]) {
maxSize += remainders[rem];
} else {
maxSize += remainders[otherRem];
}
}
return maxSize;
}
I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.
Today, an interviewer asked me this question. My immediate response was that we could simply do a linear search, comparing the current element with the previous element in the array. He then asked me how the problem could be solved in less-than-linear time.
Assumptions
The array is sorted
There is only one duplicate
The array is only populated with numbers [0, n], where n is the length of the array.
Example array: [0,1,2,3,4,5,6,7,8,8,9]
I attempted to come up with a divide-and-conquer algorithm to solve this, but I'm not confident that it was the right answer. Does anyone have any ideas?
Can be done in O(log N) with a modified binary search:
Start in the middle of the array: If array[idx] < idx the duplicate is to the left, otherwise to the right. Rinse and repeat.
If no number is missing from the array, as in the example, it's doable in O(log n) with a binary search. If a[i] < i, the duplicate is before i, otherwise it's after i.
If there is one number absent and one duplicate, we still know that if a[i] < i the duplicate must be before i and if a[i] > i, the absent number must be before i and the duplicate after. However, if a[i] == i, we don't know if missing number and duplicate are both before i or both after i. I don't see a way for a sublinear algorithm in that case.
I attempted to come up with a divide-and-conquer algorithm to solve this, but I'm not confident that it was the right answer.
Sure, you could do a binary search.
If arr[i/2] >= i/2 then the duplicate is located in the upper half of the array, otherwise it is located in the lower half.
while (lower != upper)
mid = (lower + upper) / 2
if (arr[mid] >= mid)
lower = mid
else
upper = mid-1
Since the array between lower and upper is halved in each iteration, the algorithm runs in O(log n).
ideone.com demo in Java
Difference between sum of given array elements and sum of 0 to n-1 natural numbers gives you the duplicated element.
Sum of 0 to n-1 elements is (N * N-1)/2
example array is [0,1,2,3,4,5,6,7,8,8,9]
sum of 0 to 9 natural numbers is : 45
sum of given array elements : 53
53-45 = 8 Which is the duplicated element
#include <bits/stdc++.h>
using namespace std;
int find_only_repeating_element(int arr[] , int n){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + (high - low)/2;
if(arr[mid] == arr[mid + 1] || arr[mid] == arr[mid - 1]){
return arr[mid];
}
if(arr[mid] < mid + 1){
high = mid - 2;
}else{
low = mid + 1;
}
}
return -1;
}
int main(int argc, char const *argv[])
{
int n , *arr;
cin >> n;
arr = new int[n];
for(int i = 0 ; i < n ; i++){
cin >> arr[i];
}
cout << find_only_repeating_element(arr , n) << endl;
return 0;
}
How about that? (recursion style)
public static int DuplicateBinaryFind(int[] arr, int left, int right)
{
int dup =0;
if(left==right)
{
dup = left;
}
else
{
int middle = (left+right)\2;
if(arr[middle]<middle)
{
dup = DuplicateBinaryFind(arr,left, middle-1);
}
else
{
dup = DuplicateBinaryFind(arr, middle+1, right);
}
}
return dup;
}
The example array is a little bit different from your question. Since n is the length of array and there are one and only duplicate in array, the value of each element in array should be in [0,n-1].
If that is true, then this question is the same one with How to find a duplicate element in an array of shuffled consecutive integers?
The following code should find the duplicate in O(n) time and O(1) space.
public static int findOnlyDuplicateFromArray(int[] a, boolean startWithZero){
int xor = 0;
int offset = 1;
for(int i=0; i < a.length; i++){
if(startWithZero)
xor = xor ^ (a[i] + offset) ^ i;
else
xor = xor ^ a[i] ^ i;
}
if(startWithZero)
xor = xor - offset;
return xor;
}