Hỏi về bài toán xoá giá trị trong mảng gần giá trị x nhất

đề bài thế này ạ: yêu cầu người dùng nhập 1 mảng và 1 giá trị x , ta phải xóa đi 2 phần tử 1 là nhỏ hơn x và mang giá trị gần x nhất, 2 là 1 phần tử lớn hơn x và gần x nhất
VD: cho x = 5 và dãy số: 1 3 -9 0 4 6 7 8. Phần tử gần x = 5 nhất là: 4 và 6. Dãy số sau khi xóa sẽ là: 1 3 -9 0 7 8
mình làm thế này k biết sai ở đâu ạ. mong mn giúp cho.

#include <stdlib.h>
#include<math.h>


int main ()
{ int array[100],soGiatri=0,i=0,x=0;
do
{
printf("moi ban nhap so gia tri\n");
scanf("%d",&soGiatri);            // yêu cầu người dùng khai báo số giá trị của mảng mảng
} while (soGiatri<0||soGiatri>100);
for (i=0;i<=soGiatri-1;i++)             // yêu cầu người dùng khai báo mảng
{
    printf("moi ban nhap gia tri thu %d\n",i+1);
    scanf("%d",&array[i]);
}
printf("moi ban nhap gia tri x"); // yêu cầu người dùng nhập số X
scanf("%d",&x);
int *a=&soGiatri;
int *b=&x;
xoagiatri(array,a,b);
for (i=0;i<=soGiatri-1;i++) // in ra mảng sau khi xóa các số
    printf("%d ",array[i]);
}
void xoagiatri(int array[], int *soGiaTri,int *x)
{
int i=0,y=0,m=9999999999,n=9999999999,u=9999999999,k=9999999999; // ở đây mình khai báo 4 biến có giá trị đặp biệt 1 chút bên dưới sẽ có tác dụng
for(i=0;i<=*soGiaTri-1;i++) // tạo 1 vòng lặp để so sánh các giá trị của mảng với x
{

    if(array[i]<*x&&*x-array[i]<=m) // tìm ra giá trị trong mảng nhỏ hơn x và gần x nhất, vừa mình lấy m rất lớn để trường hợp array[i]<*x đầu tiên mình sẽ luôn lấy và so sánh với các trường hợp sau
    {
    m=*x-array[i];
    u=i;
    }

    if(array[i]>*x&&array[i]-*x<=n) // tìm ra giá trị trong mảng lớn hơn x và gần x nhất,vừa mình lấy n rất lớn để trường hợp  array[i]>*x đầu tiên ban đầu mình sẽ luôn  lấy và so sánh với các trường hợp sau
        {
        n=array[i]-*x;
        k=i;
        }
}
if(u!=9999999999) // nếu u khác cái giá trị lớn ban đầu mình đặt này chứng tỏ tồn tại trường hợp array[i]<*x
{   *soGiaTri--;
    for(i=u;i<=*soGiaTri-1;i++)
    {
    array[i]=array[i+1];
    }
}
if(k!=9999999999) // nếu k khác cái giá trị lớn ban đầu mình đặt này chứng tỏ tồn tại trường hợp array[i]>*x
{      *soGiaTri--;
    for(i=k;i<=*soGiaTri-1;i++)
    {
    array[i]=array[i+1];
    }
}
}

Hàm này bạn mới chỉ định nghĩa chứ chưa khai báo.

:point_right: Thêm Dòng này trước main()

void xoagiatri(int array[], int *soGiaTri,int *x);

Đến phần chính nè. :slight_smile:

Sau vòng for đầu tiên của hàm xoaGiaTri() thì bạn sẽ được như này.

                   u   k       soGiaTri
| 1 | 3 | -9 | 0 | 4 | 6 | 7 | 8 |

Sau khi xóa phần tử có index là u thì sẽ thành:

                   u   k   soGiaTri
| 1 | 3 | -9 | 0 | 6 | 7 | 8 | 8 |

Như bạn thấy đó, index của k nó chi bị lệch về sau một đơn vị sau khi xóa u. (khi và chỉ khi k > u, không có chuyện k = u) :slight_smile:

:point_right: Thêm dòng này ngay trong if thứ nhất (if ngay dưới for)

if (k > u) k--;

Còn nữa, bạn nên thay 999.. bằng INT_MAX trong thư viện limits.h.
Và thêm thư viện stdio.h, thư viện math.h không dùng đến có thể bỏ đi :slight_smile:

Code sau khi sửa
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

void xoagiatri(int array[], int* soGiaTri, int* x);

int main() {
    int array[100], soGiatri = 0, i = 0, x = 0;
    do {
        printf("moi ban nhap so gia tri\n");
        scanf("%d", &soGiatri);  // yêu cầu người dùng khai báo số giá trị của mảng mảng
    } while (soGiatri < 0 || soGiatri > 100);
    for (i = 0; i <= soGiatri - 1; i++)  // yêu cầu người dùng khai báo mảng
    {
        printf("moi ban nhap gia tri thu %d\n", i + 1);
        scanf("%d", &array[i]);
    }
    printf("moi ban nhap gia tri x");  // yêu cầu người dùng nhập số X
    scanf("%d", &x);
    int* a = &soGiatri;
    int* b = &x;
    xoagiatri(array, a, b);
    for (i = 0; i <= soGiatri - 1; i++)  // in ra mảng sau khi xóa các số
        printf("%d ", array[i]);
    return 0;
}
void xoagiatri(int array[], int* soGiaTri, int* x) {
    int i = 0, y = 0, m = INT_MAX, n = INT_MAX, u = INT_MAX,
        k = INT_MAX;  // ở đây mình khai báo 4 biến có giá trị đặp biệt 1 chút bên dưới sẽ có tác dụng
    for (i = 0; i <= *soGiaTri - 1; i++)  // tạo 1 vòng lặp để so sánh các giá trị của mảng với x
    {
        if (array[i] < *x &&
            *x - array[i] <= m)  // tìm ra giá trị trong mảng nhỏ hơn x và gần x nhất, vừa mình lấy m rất lớn để trường
                                 // hợp array[i]<*x đầu tiên mình sẽ luôn lấy và so sánh với các trường hợp sau
        {
            m = *x - array[i];
            u = i;
        }

        if (array[i] > *x &&
            array[i] - *x <= n) // tìm ra giá trị trong mảng lớn hơn x và gần x nhất,vừa mình lấy n rất lớn để trường hợp
                                // array[i]>*x đầu tiên ban đầu mình sẽ luôn  lấy và so sánh với các trường hợp sau
        {
            n = array[i] - *x;
            k = i;
        }
    }
    if (u != INT_MAX)  // nếu u khác cái giá trị lớn ban đầu mình đặt này chứng tỏ tồn tại trường hợp array[i]<*x
    {
        (*soGiaTri)--;
        if (k > u) k--;
        for (i = u; i <= *soGiaTri - 1; i++) {
            array[i] = array[i + 1];
        }
    }
    if (k != INT_MAX)  // nếu k khác cái giá trị lớn ban đầu mình đặt này chứng tỏ tồn tại trường hợp array[i]>*x
    {
        (*soGiaTri)--;
        for (i = k; i <= *soGiaTri - 1; i++) {
            array[i] = array[i + 1];
        }
    }
}
3 Likes
// pseudo :D
var comp = x0 => (m, x) => x < x0 ? (m < x ? x : m) : m;
var doThis = (a, x) => (t = a.reduce(comp(x), -2147483648) == -2147483648) ?
                            a : a.remove(t);
3 Likes

ok cảm ơn mn nha…

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?