(C) 获取矩阵中一行最小的 3 个元素,并随机选择一个

Posted

技术标签:

【中文标题】(C) 获取矩阵中一行最小的 3 个元素,并随机选择一个【英文标题】:(C) Getting the 3 minimum elements of an row in a matrix, and choose one randomly 【发布时间】:2013-05-07 06:28:20 【问题描述】:

我有一个 8x8 矩阵,在选择我想要的行之后,我想得到它的三个最小元素,并随机选择这三个中的一个。问题是我不知道如何处理这三个元素。我只知道如何获取最小元素,就是下面的代码。

int piezas[8][8] = 
0, 2, 2, 5, 3, 2, 1, 1,
0, 4, 5, 2, 4, 3, 0, 0,
0, 4, 2, 2, 1, 2, 3, 2,
0, 3, 1, 5, 1, 2, 3, 4,
2, 5, 6, 5, 3, 1, 2, 7,
8, 2, 0, 0, 0, 2, 1, 1,
1, 2, 2, 1, 1, 6, 3, 4,
;

int myrow = 3; // the row I want to analyze
int index;
int min=0;

for (index=0;index<8;index++) 
    printf("%d", piezas[myrow][index] );
    if(piezas[myrow][index]<min)
        min=piezas[myrow][index];
    printf("\t\t");

printf("min: %d", min);

我想要的输出是,如果初始矩阵是:

int piezas[8][8] = 
0, 2, 2, 5, 3, 2, 1, 1,
0, 4, 5, 2, 4, 3, 0, 0,
0, 4, 2, 2, 1, 2, 3, 2,
0, 3, 1, 5, 1, 2, 3, 4,
2, 5, 6, 5, 3, 1, 2, 7,
8, 2, 0, 0, 0, 2, 1, 1,
1, 2, 2, 1, 1, 6, 3, 4,
;

我选择第 3 行:

0, 3, 1, 5, 1, 2, 3, 4,

算法必须选择

0, 1, 1

并从这三个中随机选择一个。

有人可以告诉我我该怎么做吗?从今天早上开始,我就一直坚持这个。谢谢

【问题讨论】:

【参考方案1】:

我会尝试对该行进行排序,然后随机选择前三个元素中的一个。

// integer comparator
int compare(int * a, int * b) return *a - *b;

// allocate memory to hold the copy
int rowCopy[sizeof(piezas[myrow])/sizeof(int)];
// copy the row
memcpy(rowCopy, piezas[myrow], sizeof(piezas[myrow]));
// sort it
qsort(rowCopy, sizeof(piezas[myrow])/sizeof(int), sizeof(rowCopy[0]), compare);
// initialize the random number generator
srand(time(NULL));
// return randomly one of the first 3 elements
return rowCopy[rand() % 3]

【讨论】:

一切似乎都很好,但我遇到了 qsort 行的问题。这是它显示的错误:main.cpp:64: error: invalid conversion from 'int (*)(int*, int*)' to 'int (*)(const void*, const void*)' main.cpp:64: error: initializing argument 4 of 'void qsort(void*, size_t, size_t, int (*)(const void*, const void*))' 是的,这是一个警告,我将比较器定义为不是真正的原型。除非您正在开发一些奇怪的嵌入式系统,否则将其类型转换为int (*)(const void*, const void*) 是安全的。否则将其定义为int compare(void * a, void * b) return *(int*)a - *(int*)b;。我通常在开发代码中将其设置为警告,并在发布代码中使用函数指针类型转换。在 x84 上它可以正常工作,在某些嵌入式架构上,使用双 void* 定义函数并在其中对参数进行类型转换会更安全。 调用你的第二个解决方案线性时间是......误导。它只是线性的,因为请求的数字是一个固定常数。如果您想去那里,可以说由于行的大小也是固定的,因此整个解决方案在恒定时间内运行。它更像是一个 O(N*M),它可能比您在 nlogn 时间内的排序解决方案更糟糕。 @xaxxon 是的,你说得对。起初我想将3 硬编码到函数中,但后来决定不这样做。最终,它变成了一种或多或少受元素限制的廉价插入排序。 第二次通过输入 2、1 的第二个解决方案 j 循环,它将 2 移到位置 [1],在 [0] 处插入 1 并将 j 增加到 j =1 不小于 numfound==1。然后它将命中 numfound = numfound。基本上是告诉你是否在 j-loop 中添加了任何内容。或者只是使用一个标志。或者也许只是在之前插入前 3 个【参考方案2】:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SIZE_ROW 8
#define N_MIN 3


int piezas[SIZE_ROW][SIZE_ROW] = 
0, 2, 2, 5, 3, 2, 1, 1,
0, 4, 5, 2, 4, 3, 0, 0,
0, 4, 2, 2, 1, 2, 3, 2,
0, 3, 1, 5, 1, 2, 3, 4,
2, 5, 6, 5, 3, 1, 2, 7,
8, 2, 0, 0, 0, 2, 1, 1,
1, 2, 2, 1, 1, 6, 3, 4,
;

int sort(const void *x, const void *y) 
  return (*(int*)x - *(int*)y);


int* sort_array(int* row, int size_row)
    int* output = (int*) calloc(size_row, sizeof(int) );
    memcpy(output, row, size_row*sizeof(int) ); // copy array
    qsort (output, size_row, sizeof (int), sort);

    return output;



int random_pick(int* array, int size_row)
    return array[ rand() % size_row ]; // possible buffer overflow if size_row too big.


int main(void)
    srand(time(NULL));

    int myrow = 3; // the row I want to analyze
    int* sorted_row = NULL;


    int i,j;


    sorted_row = sort_array(piezas[myrow],SIZE_ROW );

    printf("N mins : \n");
    for(i=0;i<N_MIN;i++)
        printf(" %d ", sorted_row[i] );
    
    printf("\n");

    printf("Random Pick : %d \n", random_pick(sorted_row, N_MIN) );



【讨论】:

【参考方案3】:

在 tmp_array(8 个元素)中创建一行的副本,然后是 qsort(tmp_array),最后使用 rand() % 3 作为您的答案元素编号。

【讨论】:

【参考方案4】:

简单的解决方案是你有三个变量 min1、min2、min3 来保存三个最小变量。

【讨论】:

【参考方案5】:

取一个数组 numbers[3] 并将这三个值保存在其中。现在

int length = sizeof(numbers) / sizeof(int);
int randomNumber = numbers[rand() % length];

【讨论】:

找到最小的 3 比随机选择一个要困难得多。正如他的评论所述,他在找到 3 时遇到了问题。【参考方案6】:

一般来说,你可以使用堆排序来获取数组中的N个最小元素,比如你选择的行,你不需要对所有元素进行排序。但记住不要将排序结果保存在行本身中。 并使用 rand() 来选择其中之一。

【讨论】:

【参考方案7】:
#include <stdio.h>

int main(void)
    int piezas[8][8] = 
        0, 2, 2, 5, 3, 2, 1, 1,
        0, 4, 5, 2, 4, 3, 0, 0,
        0, 4, 2, 2, 1, 2, 3, 2,
        0, 3, 1, 5, 1, 2, 3, 4,
        2, 5, 6, 5, 3, 1, 2, 7,
        8, 2, 0, 0, 0, 2, 1, 1,
        1, 2, 2, 1, 1, 6, 3, 4,
    ;

    int myrow = 3; // the row I want to analyze
    int index;
    int min[3]=99,99,99;//or INT_MAX at <limits.h>
    for (index=0;index<8;index++) 
        printf("%d", piezas[myrow][index] );
        int i, temp = piezas[myrow][index];
        for(i=0;i<3;++i)
            if(temp<=min[i])
                int wk = min[i];
                min[i]=temp;
                temp = wk;
            
        
        printf(" ");
    
    printf("min:");
    for(index=0;index<3;++index)
        printf(" %d", min[index]);
    return 0;

【讨论】:

以上是关于(C) 获取矩阵中一行最小的 3 个元素,并随机选择一个的主要内容,如果未能解决你的问题,请参考以下文章

matlab中已知一矩阵,如何将其中的已知的元素打乱顺序进行随机排列得到新的矩阵,如:

R获取矩阵中每一行的最小值,并返回行名和列名

矩阵列的最小元素

如何计算矩阵的乘法?

用lingo导入excel数据生成矩阵并对元素进行累加怎么敲代码

matlab中矩阵随机取几个元素赋值