解题思路:

时间复杂度和空间复杂度降到最低,并且不需要任何的辅助空间。

使用双指针,进行数组元素原地后移

假设我们使用 1 2 3 4 5 6 7 8 9 10 作为测试数据,我们需要将其变成9 10 1 2 3 4 5 6 7 8


首先我们需要两个指针i和j
原始数据:   1 2 3 4 5 6 7 8 9 10 , 这个时候指针i指向0的位置,j指向n-m也就是8这个位置,接下来我们对前m个数和后m个数对应的一一交换,1和9交换,2和10交换。

第一次交换后:指针i指向了2这个位置,而j指向索引为10的地方,由于指针j超过了数组的索引范围,我们将其重置为n-m也就是8,数组变为 9 10 3 4 5 6 7 8 1 2

第二次交换后:指针i指向了4这个位置,而j指向索引为10的地方,由于指针j超过了数组的索引范围,我们将其重置为n-m也就是8,数组变为 9 10 1 2 5 6 7 8 3 4

第三次交换后:指针i指向了6这个位置,而j指向索引为10的地方,由于指针j超过了数组的索引范围,我们将其重置为n-m也就是8,数组变为 9 10 1 2 3 4 7 8 5 6

第四次交换后:指针i指向了8这个位置,而j指向索引为10的地方,由于指针j超过了数组的索引范围,我们将其重置为n-m也就是8,数组变为 9 10 1 2 3 4 5 6 7 8,这个时候由于 i==j 指针i与j相遇,退出循环,数组后移完成。


参考代码:

#include <stdio.h>
#include <stdlib.h>

#define SWAP(a, b)((a)^=(b),(b)^=(a),(a)^=(b))

#define mal(n, t)((t *) malloc(sizeof(t) * n))

int main() {
    // 输入
    int n, m, *arr, i, j, k;
    scanf("%d", &n);
    arr = mal(n, int);

    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    scanf("%d", &m);

    // 数组原地后移
    i = 0;
    j = n - m;
    while (i < j) {
        for (k = 0; k < m && i < j; k++) {
            SWAP(arr[i], arr[j]);
            i++;    // i,j 指针后移
            j++;
            if (j == n) {
                j = n - 1;
            }
        }
    }

    // 输出
    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    free(arr);
    return 0;
}


点赞(0)
 

0.0分

9 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 8 条评论

喵呜王 2周前 回复TA
请问这个k有什么用呢,我把for (k = 0; k < m && i < j; k++)这行删了也能提交成功啊? 
keheia 1年前 回复TA
@keheia n) {                 j = n - 2;             }         }     }       // 输出     for (i = 0; i < n; i++) {         printf("%d ", arr[i]);     }     free(arr);     return 0; }
keheia 1年前 回复TA
改成j=n-2;
#include <stdio.h>
#include <stdlib.h>
 
#define SWAP(a, b)((a)^=(b),(b)^=(a),(a)^=(b))
 
#define mal(n, t)((t *) malloc(sizeof(t) * n))
 
int main() {
    // 输入
    int n, m, *arr, i, j, k,x[10]={1,2,3,4,5,6,7,8,9,10};
//    scanf("%d", &n);
    n=10;
    arr = mal(n, int);
 	
 	arr=x;
//    for (i = 0; i < n; i++) {
//        scanf("%d", &arr[i]);
//    }
//    scanf("%d", &m);
 m=2;
 // 数组原地后移
    i = 0;
    j = n - m;
    while (i < j) {
        for (k = 0; k < m && i < j; k++) {
            SWAP(arr[i], arr[j]);
            i++;    // i,j 指针后移
            j++;
            if (j==
Noob 2年前 回复TA
@清心珏 改过之后可以了,谢谢大佬
Noob 2年前 回复TA
@新城已无旧少年 嗯,这种方法简单一点,三次reverse即可
Noob 2年前 回复TA
@清心珏 感谢,确实有问题,后面三个数的顺序错了
新城已无旧少年 3年前 回复TA
三部先先交换所有的数,然后交换前m个数,在交换后n-m个数就好了。
清心珏 3年前 回复TA
算法有问题 当例如n=10,m=7时是错的