Home > Mobile >  reverse array in range in C
reverse array in range in C

Time:10-12

I have to solve it in C language. I have arrays with n integers. L and U are lower and upper bound. I have to reverse numbers in array which is in [L,U]. I tried it by this way, but in some cases the answer is wrong. What mist be changed in the code? Or is there any other logic to complete the task?

#include <stdio.h>
int main() {
  int x, arr[100], n, l, u, a, temp, temp1;
  scanf("%d%d%d", &n, &l, &u);
  for (int i = 0; i < n; i  ) {
    scanf("%d", &x); // read elements of an array
    arr[i] = x;
  }
  a = n / 2;
  for (int i = 0; i < a; i  ) {
    for (int j = a; j < n; j  ) {
      if (arr[i] >= l && arr[i] <= u) {
        if (arr[j] >=l && arr[j] < u) {
          temp = arr[j];
          temp1 = arr[i];
          arr[i] = temp;
          arr[j] = temp1;
        }
      }
    }
  }

  for (int i = 0; i < n; i  ) {
    printf("%d ", arr[i]);
  }
}

sample input: 10(number of integers) -7(lower bound) 5(upper bound) -10 -9 5 -2 -3 7 10 6 -8 -5

sample output: -10 -9 -5 -3 -2 7 10 6 -8 5

my output: -10 -9 -5 -2 -3 7 10 6 -8 5

CodePudding user response:

There is an O(N) solution that does not require nesting of loops.

First, with the code as you as you have it, declare an additional array and some other helper variables that keeps track of what indices need to be swapped.

  int left, right;
  int swaplist[100] = {0};
  int swapcount = 0;

Your can keep your initial intake loop exactly as you have it, but amended to append the index of the newly scanned value to the swaplist array if the value is between the lower and upper bounds.

  for (int i = 0; i < n; i  ) {
    scanf("%d", &x); // read elements of an array
    arr[i] = x;

    if ((x >= l) && (x <= u)) {
        swaplist[swapcount  ] = i;
    }
  }

Then a single loop to iterate over "swaplist" and do the swaps against the original array.

  left = 0;
  right = swapcount-1;
  while (left < right) {
      int leftindex = table[left];
      int rightindex = table[right];

      int tmp = arr[leftindex];
      arr[leftindex] = arr[rightindex];
      arr[rightindex] = tmp;
      left  ; right--;
  }

CodePudding user response:

If I have understood the assignment correctly you need to reverse elements of an array that satisfy some condition.

If so then these nested for loops

  for (int i = 0; i < a; i  ) {
    for (int j = a; j < n; j  ) {
      if (arr[i] >= l && arr[i] <= u) {
        if (arr[j] >=l && arr[j] < u) {
          temp = arr[j];
          temp1 = arr[i];
          arr[i] = temp;
          arr[j] = temp1;
        }
      }
    }
  }

do not make sense.

It is enough to use only one for loop as shown in the demonstration program below.

#include <stdio.h>

int main( void )
{
    int a[] = { 1, 10, 2, 3, 20, 4, 30, 5, 40, 6, 7, 50, 9 };
    const size_t N = sizeof( a ) / sizeof( *a );

    for (size_t i = 0; i < N; i  )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    int l = 10, u = 50;

    for (size_t i = 0, j = N; i < j; i   )
    {
        while (i < j && !( l <= a[i] && a[i] <= u ))   i;

        if (i < j)
        {
            while (i < --j && !( l <= a[j] && a[j] <= u ));

            if (i < j)
            {
                int tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }

    for (size_t i = 0; i < N; i  )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );
}

The program output is

1 10 2 3 20 4 30 5 40 6 7 50 9
1 50 2 3 40 4 30 5 20 6 7 10 9

You could write a separate function as for example

#include <stdio.h>

void reverse_in_range( int a[], size_t n, int low, int upper )
{
    for (size_t i = 0, j = n; i < j; )
    {
        while (i < j && !( low <= a[i] && a[i] <= upper ))   i;

        if (i < j)
        {
            while (i < --j && !( low <= a[j] && a[j] <= upper ));

            if (i < j)
            {
                int tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;

                  i;
            }
        }
    }
}

int main( void )
{
    int a[] = { 1, 10, 2, 3, 20, 4, 30, 5, 40, 6, 7, 50, 9 };
    const size_t N = sizeof( a ) / sizeof( *a );

    for (size_t i = 0; i < N; i  )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    reverse_in_range( a, N, 10,50 );

    for (size_t i = 0; i < N; i  )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );
}

CodePudding user response:

My best guess is that scanf is very annoying, on top of that, your format is ambiguous.

How will %d%d%d read 1234? Will it give you 12 3 and 4? 1 23 and 4? ...

try to do

scanf("%d %d %d" ...); // or
scanf("%d, %d, %d" ...); 

something like that. Note that scanf is not recommended to be used, getc is a neat alternative, though also annoying when you want to read numbers with more than one digit, but you could create a function read_number, which, based on getc, will read a number as a string and return the int value with stoi.

  • Related