交换数组的部分

Posted

技术标签:

【中文标题】交换数组的部分【英文标题】:Swapping sections of an array 【发布时间】:2021-12-18 00:02:04 【问题描述】:

我被要求制作一个交换数组中两个部分的函数。

类似的,

array[] = 1 , 2, 5, 7, 8, a , b, c
           |               |
sections:  First           Second

签名是void reverse_reg(int *arr, int s, int k, int j),其中arr是数组,s是第一节的第一个索引,k是第一节的最后一个索引,j表示第二节的结尾部分,开始是k(因为C中的索引从0开始)

到目前为止,我有类似的东西,

void reverse_reg(int *arr, int s, int k, int j)

    for (int i = s; i < j; i++)
    
        if (i > k / 2) /* swap the rest */
        
            swap(&arr[i], &arr[j - i + 1]); /* this is wrong */
        
        else
        
            swap(&arr[i], &arr[k + i + 1]);
        
    

我已经测试了else 块,到目前为止它成功地交换了第二部分,生成,

result:
a b c 7 8 1 2 5

尽管如此,我还没有找到交换第二部分的方法,因为 if 块产生了完全错误的东西(这是有道理的),这让我认为最初的逻辑是错误的。有什么提示吗?

如果有帮助,我调用函数的方式是,reverse_reg(arr, 0, 4, 8);

结果数组应该是:

result:
a b c 1 2 5 7 8

【问题讨论】:

请说明想要的结果是什么。 @500-InternalServerError 是的,我刚刚添加了那个。对不起 1) 反转整个数组 2) 反转每个部分。或以相反的顺序 - 更方便。 难题。 ╔ 【参考方案1】:
"12578abc"
"abc12578"

假设array 被声明为unsigned char array[8];,这可以是对 64 位整数的循环操作。使用旋转函数,我们可以将"abc" 向左移动,"12578" 向右移动,然后组合它们的结果:

uint64_t rot_left_64(uint64_t num, int n) 

    return (num << n) | (num >> (64 - n));


uint64_t num = 0x01020507080a0b0c;
num = rot_left_64(num , 8 * 5);
printf("%016llX\n", n); //output 0x0A0B0C0102050708

【讨论】:

【参考方案2】:

正如@EugeneSh 所指出的,一种简单的方法是反转每个部分,然后反转整个数组。可以这么简单:

void swap(int* i, int* j) 
    int k = *i;
    *i = *j;
    *j = k;


void reverse(int arr[], int len) 
    for (int i = 0; i < len / 2; i++) 
        swap(arr + i, arr + len - i - 1);
    


void reverse_reg(int* arr, int s, int k, int j) 
    // you use last index of initial section while I need index of second one
    ++k;
    reverse(arr + s, k - s);
    reverse(arr + k, j - k);
    reverse(arr + s, j - s);

【讨论】:

以上是关于交换数组的部分的主要内容,如果未能解决你的问题,请参考以下文章

CF 540E, 树状数组

常用算法Java实现之快速排序

Java数组元素位置交换?

交换数组两个数位置方法

计算机网路电路交换分组交换

输入一个一维数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。