-1

I hope i made my self clear enough in the title but if not i am here to explain my self i got an array from an input ( like Arr = {, ).

we can use only 1 additional array (1 original 1 additional)

this is what i made so far : I made a new array named newArr and assigned it all the values Arr contains. i sorted it (because its requires time complexity of nlogn) and then moved duplicates to the end.

now what i can't figure out :

now i need to move the original digits to their place according to the main (all the values in the arrays are positive and they can be bigger then
n-which is the size of the array and ofc they can be also smaller then n)
i also need to return the number of original digits in the array the original number should stay in the same position and the duplicates in the end of the array their order doesn't matter.

from here we can't use another additional array only the current arrays that we have ( which are 2) i have been thinking about doing some kind of binary search but all of them went wrong.(like bin_search_first) and original binary and still couldn't manage it. can some one give me an hint?

here is the code at where i am


#define _CRT_SECURE_NO_WARNINGS

/*Libraries*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

int* input_array(int);
int moveDuplicatesV2(int*, int);
void merge(int* a, int p, int q, int r);
void merge_sort(int* a, int first, int last); 
void swap(int* v, int* u);
int bin_search_first(int , int* , int );


int main()
{
    int arr[10] =  { };
    int n = 12; 
    int k = 0;
    int first = 0;
    int last = n - 1;
    int mid = (first + last) / 2;
    int l = n - 1;
    int* D = arr + 1;
    int j = 0;
    size_t dupes_found = 0;
    int* newArr = (int*)malloc(12 * sizeof(int));
    assert(newArr);
    for (int i = 0; i < n; i++)
    {
        newArr[i] = arr[i];
    }
    merge_sort(newArr, first, last);
    for (size_t i = 0; i < n - 1 - dupes_found;) 
    {
        if (newArr[i] == newArr[i + 1])
        {
            dupes_found++;
            int temp = newArr[i];
            memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
            newArr[n - 1] = temp;
        }
        else {
            i++;
        }
    }
    j = 0;
    int key = 0;
    first = 0;
    for (int i = 0; i < n - dupes_found; i++)
    {
        key = newArr[i];
        first = bin_search_first(key, arr,n);
        swap(&newArr[i], &newArr[first]);
        newArr[first] = newArr[i];


    }

    for (int i = 0; i < n; i++)
    {
        arr[i] = newArr[i];
    }

    
    for (int i = 0; i < n; i++)
    {
        printf("%d", arr[i]);
    }
    return n - dupes_found;
}
void merge(int* a, int p, int q, int r)
{
    int i = p, j = q + 1, k = 0;
    int* temp = (int*)malloc((r - p + 1) * sizeof(int));
    assert(temp);
    while ((i <= q) && (j <= r))
        if (a[i] < a[j])
            temp[k++] = a[i++];
        else
            temp[k++] = a[j++];
    while (j <= r)
        temp[k++] = a[j++];
    while (i <= q)
        temp[k++] = a[i++];
    /* copy temp[] to a[]   */
    for (i = p, k = 0; i <= r; i++, k++)
        a[i] = temp[k];
    free(temp);
}
void merge_sort(int* a, int first, int last)
{
    int middle;
    if (first < last) {
        middle = (first + last) / 2;
        merge_sort(a, first, middle);
        merge_sort(a, middle + 1, last);
        merge(a, first, middle, last);
    }
}

void swap(int* v, int* u)
{
    int temp;
    temp = *v;
    *v = *u;
    *u = temp;
}
int bin_search_first(int key, int* a, int n)
{
    int low, high, mid;
    low = 0;
    high = n - 1;
    while (low <= high)
    {
        mid = (low + high) / 2; // low + (high - low) / 2
        if (key > a[mid])
            low = mid + 1;
        else
            if (key < a[mid])
                high = mid - 1;
            else //key==a[mid]
                if ((low == high) || (a[mid - 1] < key))
                    return mid;
                else
                    high = mid - 1;
    }
    return -1;
}
EraoS
  • 31
  • 9
  • i am confused on where i should edit it ? when i am calling mege in merge sort or inside merge function its self. I have edit the code to see all my used functions – EraoS Jan 04 '23 at 21:15
  • Your title isn't clear (it has one more `[` than `]` so the 'code' in it won't compile). I'm also not clear what you're after. I think I understand the first paragraph; I don't understand the rest. – Jonathan Leffler Jan 04 '23 at 21:30
  • after i have my sorted arrey wit dups at the ends i need to change their position according to the first array ( the one that was inputed ) but excluding dups ( which are still stay at the end ) – EraoS Jan 04 '23 at 21:34
  • if you still didnt understand let me know exactly what – EraoS Jan 04 '23 at 21:35
  • well then i guess i am missing it because i cant find it since its merging between small or bigger its just assigning values by order (i am a bit tired so i might be wrong here) – EraoS Jan 04 '23 at 21:47
  • but it is because after i am sorting it ( with duplicates ) i have a an if statement that memmove the duplicates to the end, "You also need to handle getting the same value twice in a row from the same array" this is the biggest issue – EraoS Jan 04 '23 at 21:51
  • The approach I suggested doesn't work (because of the recursive nature.) – ikegami Jan 04 '23 at 21:54
  • 1
    Are the integer values gated to be within a certain range? (i.e. are they <= the size of the array?) That would open up to certain optimizations. – selbie Jan 04 '23 at 22:37
  • What selbie asked. – ikegami Jan 05 '23 at 02:32
  • 1
    "I hope i made my self clear enough in the title" It is very, very far from being clear. – n. m. could be an AI Jan 05 '23 at 07:11
  • I said already that all the values are positive (so they can’t be negetive ) and they can be bigger then the size of the arr it’s self . Make sense? – EraoS Jan 05 '23 at 07:16
  • This is a tricky homework. Have you been studying sorting algorithms? Counting sort? Maybe [my answer here](https://stackoverflow.com/a/75038351/2706707) can help. (Or, I could be way off. Let me know if y’all are _required_ to use merge sort.) – Dúthomhas Jan 07 '23 at 05:57
  • @Duthomhas Yeah i required to use merge sort / quick sort. yeah i studied sorting algoriths but we usually use like a "smart" bin search after sorting but dam this is so annoying with those duplicates. – EraoS Jan 07 '23 at 11:09
  • @secret1 See [my answer here](https://stackoverflow.com/questions/75036301/how-to-sort-this-array-in-c/75039163#75039163). It requires not much more than a stable sorting algorithm (merge sort would be perfect). – nielsen Jan 07 '23 at 12:33
  • Secret1 If you are required to MergeSort or QuickSort then definitely check out @nielsen’s answer in the other thread. I was already pretty clear that this wasn’t a full-blown Algorithms class — you have been asked to do things in the worst possible way (copy/annotate indices, dual-array sort, reorder, dual-array sort)... _**but**_... knowing how to do stuff like filter duplicates out of an ordered set is a very important skill. – Dúthomhas Jan 07 '23 at 14:37
  • "Sort the pairs (A[i],B[i]) using A[i] as key and with a stable sorting algorithm of complexity O(n log n):" this got me confused a bit. we use recursive merge sort with with inputs (arr,first,last)- how can i sort both of the arrays as pairs? besides that i understood the logic behind the explanation – EraoS Jan 07 '23 at 18:10

2 Answers2

0

Here is my idea:

  1. Sort the array (nlogn)
  2. Loop over the array and for each value, save a pointer to its first occurence (n)
  3. Loop over the original array and insert the value into a result array if it is the values first occurrence. Whether or not it is the first occurrence can be checked using the sorted array: each element in this array has an additional flag that will be set if the value has already been seen. So, search for the element using bsearch, if seen append to back of result array (order does not matter), if not seen append to beginning of array and set seen value. (nlogn, since bsearch doesn't need to seek the first element because it was precomputed thus logn, over the array n)

Here is an example code (you can replace the qsort by mergesort to make the algorithm actually nlogn, I just used qsort because it is given):

#include <stdio.h>
#include <stdlib.h>

struct arr_value {
    int value;
    int seen;
    struct arr_value *first;
};

int compar(const void *p1,const void *p2) {
    struct arr_value *v1 = (struct arr_value *)p1;
    struct arr_value *v2 = (struct arr_value *)p2;
    if(v1->value < v2->value) {
        return -1;
    } else if(v1->value == v2->value) {
        return 0;
    }
    return 1;
}

int main()
{
#define NumCount (12)
    int arr[NumCount] =  { 7, 3, 1, 2, 7, 9, 3, 2, 5, 9, 6, 2 };
    int arrResult[NumCount];
    int resultCount = 0;
    int resultCountBack = 0;
    struct arr_value arrseen[NumCount];
    for(int i = 0; i < NumCount; ++i) {
        arrseen[i].value = arr[i];
        arrseen[i].seen = 0;
    }
    
    qsort(arrseen, NumCount, sizeof(struct arr_value), compar);
    
    struct arr_value *firstSame = arrseen;
    firstSame->first = firstSame;
    for(int i = 1; i < NumCount; ++i) {
        if(arrseen[i].value != firstSame->value) {
            firstSame = arrseen + i;
        }
        arrseen[i].first = firstSame;
    }
    
    struct arr_value key;
    for(int i = 0; i < NumCount; ++i) {
        key.value = arr[i];
        struct arr_value *found = (struct arr_value *)bsearch(&key, arrseen, NumCount, sizeof(struct arr_value), compar);
        struct arr_value *first = found->first;
        
        if(first->seen) {
            // value already seen, append to back
            arrResult[NumCount - 1 - resultCountBack] = first->value;
            ++resultCountBack;
        } else {
            // value is new, append
            arrResult[resultCount++] = first->value;
            first->seen = 1;
        }
    }
    
    for(int i = 0; i < NumCount; ++i) {
        printf("%d ", arrResult[i]);
    }

    return 0;
}

Output:

7 3 1 2 9 5 6 2 9 2 3 7
  • really thanks for the answer but i still didnt learn structs and this makes it really hard to understand and how many arrays do you use here? – EraoS Jan 04 '23 at 21:40
  • 1
    This answer violates the space constraints by creating O(N) extra storage. OP: "*we can't use another additional array only the current arrays that we have*" (And if your `qsort` performs a quicksort, your answer also violates the time constraints by using a O(N^2) sorting algorithm. Fixing that is just a question of substituting `merge_sort` for `qsort`.) – ikegami Jan 04 '23 at 21:52
  • It's 3 to 4 extra arrays of size n. I give up – Knufy Einundzwanzig Jan 04 '23 at 21:58
0
  1. To begin with, memmove doesn't run in a constant time, so the loop

     for (size_t i = 0; i < n - 1 - dupes_found;) 
     {
         if (newArr[i] == newArr[i + 1])
         {
             dupes_found++;
             int temp = newArr[i];
             memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
             newArr[n - 1] = temp;
         }
         else {
             i++;
         }
     }
    

    drives the time complexity quadratic. You have to rethink the approach.

  2. It seems that you are not using a crucial point:

    all the values in the arrays are positive

    It seriously hints that changing values to their negatives is a way to go.

    Specifically, as you iterate over the initial array, and bin-search its elements in temp, comparing the _ absolute values_. When an element is found in temp, and it is still positive there, flip all its dupes in temp to negative. Otherwise flip it in initial.

    So far, it is O(n log n).

    Then perform an algorithm known as stable_partition: all positives are moved in front of negatives, retaining the order. I must not spell it here - I don't want to deprive you of a joy figuring it out yourself (still O(n log n)

    And finally flip all negatives back to positives.

user58697
  • 7,808
  • 1
  • 14
  • 28
  • i am a bit confused about turning them negative. fix me if i am wrong but : when i iterate over the original array to bin search its elements in temp (second array?) and every first time i see an original digit i make it negative? and if its more then one time its remains always positive? – EraoS Jan 05 '23 at 08:42