C:仅打印 2 个数组中的不常见元素
C: Print only not common elements in 2 arrays
我有一些 C 代码,我想修改非常简单。
假设我有两个像这样的数组
int v1[5] = {1, 3, 7, 13, 10};
int v2[2] = {1, 10};
我想打印不常见的元素(差异),如:
3, 7, 13
这是我的尝试,但还不够:
#include <stdio.h>
int main()
{
int v1[5] = { 1, 3, 7, 13, 10 };
int v2[2] = { 1, 10 };
for (int i = 0; i < sizeof(v1) / (sizeof * v1); i++) {
for (int j = 0; j < sizeof(v2) / (sizeof * v2); j++) {
if (v1[i] != v2[j]) {
printf("%d ", v1[i]);
break;
} else {
break;
}
}
}
return 0;
}
这两个数组总是很短(最多 6 个元素)。它们没有被订购,我不应该修改它们。它们每个中的元素都是唯一的,即每个数字在每个数组中只能出现 1 次。 v2 将只包含 v1 中元素的一个子集。
实现此目标的最有效方法是什么?
您可以首先获取任何数组并逐个元素地迭代它,然后通过嵌套的 for 循环查找该元素是否也在第二个数组中,然后将 if 条件放在内部 for 循环中,并将公共元素存储在另一个数组中数组,然后将两个数组与该数组一一比较,并将不常见的元素放入另一个数组。
喜欢:
int a[min(l1,l2)], b[l], x = 0, k = 0, flag = 1;
for(int i=0; i<l1; i++){
for(int j=0; j<l2; j++){
if(v1[i]==v2[j]){
a[k] = v1[i];
k++;
}
}
}
for(int i=0; i<l1; i++){
flag = 1;
for(int j=0; j<k; j++){
if(v1[i] == a[j]){
flag = 0;
break;
}
}
if(flag==1){
b[x] = v1[i];
x++;
}
}
for(int i=0; i<l2; i++){
flag = 1;
for(int j=0; j<k; j++){
if(v2[i] == a[j]){
flag = 0;
break;
}
}
if(flag==1){
b[x] = v2[i];
x++;
}
}
之后就可以打印数组了。
一种在内存方面贪婪,但在 CPU 周期(线性时间)方面快速的方法是直方图,因为平凡意义上的列表比较通常使用二次执行复杂度 :(
.
代码清单
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
/* Allocate. */
int numElements1 = 0;
int numElements2 = 0;
const int maxHistVal = UINT8_MAX + 1;
const int maxElements = 10;
const int minElements = 1;
uint8_t *arr1 = NULL, *arr2 = NULL;
uint8_t *histogram = NULL;
/* Init random seed. */
srand(time(NULL));
/* Determine number of elements for each array. */
numElements1 = (rand() % (maxElements - minElements)) + minElements;
numElements2 = (rand() % (maxElements - minElements)) + minElements;
/* Generate two random arrays with non-duplicated values. */
if (NULL == (arr1 = calloc(numElements1, sizeof(uint8_t)))) {
return ENOMEM;
} else if (NULL == (arr2 = calloc(numElements2, sizeof(uint8_t)))) {
free(arr1);
return ENOMEM;
} else if (NULL == (histogram = calloc(maxHistVal, sizeof(uint8_t)))) {
free(arr2);
free(arr1);
return ENOMEM;
} else {
/* Have our sample arrays and histogram. Populate them and print them
* out.
*/
printf("ARR1: ");
uint8_t j = 0;
for (int i = 0, j = 0; i < numElements1; i++) {
/* Populate array. */
j += (rand() % 2) + 1;
arr1[i] = j;
printf("%-3d ", arr1[i]);
/* Update histogram. */
histogram[arr1[i]]++;
}
printf("\n");
printf("ARR2: ");
for (int i = 0, j = 0; i < numElements2; i++) {
/* Populate array. */
j += (rand() % 2) + 1;
arr2[i] = j;
printf("%-3d ", arr2[i]);
/* Update histogram. */
histogram[arr2[i]]++;
}
printf("\n");
/* Print out only values that appear exactly once in the histogram. */
printf("HISTOGRAM: UNIQUE VALUES: ");
for (int i = 0, j = 0; i < maxHistVal; i++) {
/* Print histogram. */
if (1 == histogram[i]) {
printf("%-3d ", i);
}
}
printf("\n");
/* For fun, identify the duplicates. */
printf("HISTOGRAM: DUPLICATE VALUES: ");
for (int i = 0, j = 0; i < maxHistVal; i++) {
/* Print histogram. */
if (1 < histogram[i]) {
printf("%-3d ", i);
}
}
}
/* Cleanup..*/
free(histogram);
free(arr2);
free(arr1);
return 0;
}
样本运行
ARR1: 2 3 4 6 8 9 10
ARR2: 1 2 3 4
HISTOGRAM: UNIQUE VALUES: 1 6 8 9 10
HISTOGRAM: DUPLICATE VALUES: 2 3 4
What would be the most efficient way to achieve this?
如果 a[], b[]
中的值范围限制在 0 到 63 之间,代码可以使用 unsigned long long
掩码。
这通过每个数组 l1 + l2
操作迭代一次,而不是使用 l1 * l2
操作的双重 for()
循环。
#include <assert.h>
#include <stdio.h>
int main(void) {
const int v1[5] = { 1, 3, 7, 13, 10 };
const int v2[2] = { 1, 10 };
unsigned long long mask = 0;
for (size_t i = 0; i < sizeof(v2) / (sizeof *v2); i++) {
assert(v2[i] >= 0 && v2[i] < 64);
mask |= 1ull << v2[i];
}
mask = ~mask;
for (size_t i = 0; i < sizeof(v1) / (sizeof *v1); i++) {
assert(v1[i] >= 0 && v2[i] < 64);
if ((1ull << v1[i]) & mask) {
printf(" %d", v1[i]);
}
}
puts("");
return 0;
}
输出
3 7 13
#include<stdio.h>
#define MAX_OLD 4
#define MAX_NEW 2
int main()
{
int old[] = {3, 4, 5, 6};
int new[] = {4, 5};
int temp[] = {0, 0, 0, 0, 0, 0, 0, 0};
int j = 0,z=0,i=0;
for(i = 0; i < MAX_NEW; i++)
{
for(; j < MAX_OLD; j++)
{
if(old[j] <= new[i])
{
if(old[j]!=new[i])
temp[z++] = old[j];
}
else
{
break;
}
}
}
while(j<MAX_OLD)
temp[z++]=old[j++];
printf("Temp[0] : %d %d %d %d %d %d %d %d\n",temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7]);
return 0;
}
我有一些 C 代码,我想修改非常简单。
假设我有两个像这样的数组
int v1[5] = {1, 3, 7, 13, 10};
int v2[2] = {1, 10};
我想打印不常见的元素(差异),如:
3, 7, 13
这是我的尝试,但还不够:
#include <stdio.h>
int main()
{
int v1[5] = { 1, 3, 7, 13, 10 };
int v2[2] = { 1, 10 };
for (int i = 0; i < sizeof(v1) / (sizeof * v1); i++) {
for (int j = 0; j < sizeof(v2) / (sizeof * v2); j++) {
if (v1[i] != v2[j]) {
printf("%d ", v1[i]);
break;
} else {
break;
}
}
}
return 0;
}
这两个数组总是很短(最多 6 个元素)。它们没有被订购,我不应该修改它们。它们每个中的元素都是唯一的,即每个数字在每个数组中只能出现 1 次。 v2 将只包含 v1 中元素的一个子集。 实现此目标的最有效方法是什么?
您可以首先获取任何数组并逐个元素地迭代它,然后通过嵌套的 for 循环查找该元素是否也在第二个数组中,然后将 if 条件放在内部 for 循环中,并将公共元素存储在另一个数组中数组,然后将两个数组与该数组一一比较,并将不常见的元素放入另一个数组。
喜欢:
int a[min(l1,l2)], b[l], x = 0, k = 0, flag = 1;
for(int i=0; i<l1; i++){
for(int j=0; j<l2; j++){
if(v1[i]==v2[j]){
a[k] = v1[i];
k++;
}
}
}
for(int i=0; i<l1; i++){
flag = 1;
for(int j=0; j<k; j++){
if(v1[i] == a[j]){
flag = 0;
break;
}
}
if(flag==1){
b[x] = v1[i];
x++;
}
}
for(int i=0; i<l2; i++){
flag = 1;
for(int j=0; j<k; j++){
if(v2[i] == a[j]){
flag = 0;
break;
}
}
if(flag==1){
b[x] = v2[i];
x++;
}
}
之后就可以打印数组了。
一种在内存方面贪婪,但在 CPU 周期(线性时间)方面快速的方法是直方图,因为平凡意义上的列表比较通常使用二次执行复杂度 :(
.
代码清单
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
/* Allocate. */
int numElements1 = 0;
int numElements2 = 0;
const int maxHistVal = UINT8_MAX + 1;
const int maxElements = 10;
const int minElements = 1;
uint8_t *arr1 = NULL, *arr2 = NULL;
uint8_t *histogram = NULL;
/* Init random seed. */
srand(time(NULL));
/* Determine number of elements for each array. */
numElements1 = (rand() % (maxElements - minElements)) + minElements;
numElements2 = (rand() % (maxElements - minElements)) + minElements;
/* Generate two random arrays with non-duplicated values. */
if (NULL == (arr1 = calloc(numElements1, sizeof(uint8_t)))) {
return ENOMEM;
} else if (NULL == (arr2 = calloc(numElements2, sizeof(uint8_t)))) {
free(arr1);
return ENOMEM;
} else if (NULL == (histogram = calloc(maxHistVal, sizeof(uint8_t)))) {
free(arr2);
free(arr1);
return ENOMEM;
} else {
/* Have our sample arrays and histogram. Populate them and print them
* out.
*/
printf("ARR1: ");
uint8_t j = 0;
for (int i = 0, j = 0; i < numElements1; i++) {
/* Populate array. */
j += (rand() % 2) + 1;
arr1[i] = j;
printf("%-3d ", arr1[i]);
/* Update histogram. */
histogram[arr1[i]]++;
}
printf("\n");
printf("ARR2: ");
for (int i = 0, j = 0; i < numElements2; i++) {
/* Populate array. */
j += (rand() % 2) + 1;
arr2[i] = j;
printf("%-3d ", arr2[i]);
/* Update histogram. */
histogram[arr2[i]]++;
}
printf("\n");
/* Print out only values that appear exactly once in the histogram. */
printf("HISTOGRAM: UNIQUE VALUES: ");
for (int i = 0, j = 0; i < maxHistVal; i++) {
/* Print histogram. */
if (1 == histogram[i]) {
printf("%-3d ", i);
}
}
printf("\n");
/* For fun, identify the duplicates. */
printf("HISTOGRAM: DUPLICATE VALUES: ");
for (int i = 0, j = 0; i < maxHistVal; i++) {
/* Print histogram. */
if (1 < histogram[i]) {
printf("%-3d ", i);
}
}
}
/* Cleanup..*/
free(histogram);
free(arr2);
free(arr1);
return 0;
}
样本运行
ARR1: 2 3 4 6 8 9 10
ARR2: 1 2 3 4
HISTOGRAM: UNIQUE VALUES: 1 6 8 9 10
HISTOGRAM: DUPLICATE VALUES: 2 3 4
What would be the most efficient way to achieve this?
如果 a[], b[]
中的值范围限制在 0 到 63 之间,代码可以使用 unsigned long long
掩码。
这通过每个数组 l1 + l2
操作迭代一次,而不是使用 l1 * l2
操作的双重 for()
循环。
#include <assert.h>
#include <stdio.h>
int main(void) {
const int v1[5] = { 1, 3, 7, 13, 10 };
const int v2[2] = { 1, 10 };
unsigned long long mask = 0;
for (size_t i = 0; i < sizeof(v2) / (sizeof *v2); i++) {
assert(v2[i] >= 0 && v2[i] < 64);
mask |= 1ull << v2[i];
}
mask = ~mask;
for (size_t i = 0; i < sizeof(v1) / (sizeof *v1); i++) {
assert(v1[i] >= 0 && v2[i] < 64);
if ((1ull << v1[i]) & mask) {
printf(" %d", v1[i]);
}
}
puts("");
return 0;
}
输出
3 7 13
#include<stdio.h>
#define MAX_OLD 4
#define MAX_NEW 2
int main()
{
int old[] = {3, 4, 5, 6};
int new[] = {4, 5};
int temp[] = {0, 0, 0, 0, 0, 0, 0, 0};
int j = 0,z=0,i=0;
for(i = 0; i < MAX_NEW; i++)
{
for(; j < MAX_OLD; j++)
{
if(old[j] <= new[i])
{
if(old[j]!=new[i])
temp[z++] = old[j];
}
else
{
break;
}
}
}
while(j<MAX_OLD)
temp[z++]=old[j++];
printf("Temp[0] : %d %d %d %d %d %d %d %d\n",temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7]);
return 0;
}