循环移动数组元素

参考

link

问题描述

设计一个算法,将数组A[1:n]中的元素循环右移k位,要求只使用一个元素的附加空间,元素移动或交换次数为O(n).
然后这样是不行的。
转而去网上求助。

假如原数组: 1 2 3 4 5 6 7 需要右移4次,那么我们想要的结果是: 5 6 7 1 2 3 4。
1.将1234逆置 变成 4321
2.将567逆置 变成 765
3.将两个逆置数组拼接: 4321765
4.将这个已拼接的数组逆置: 5671234 就成了我们想要的结果了。
————————————————
版权声明:本文为CSDN博主「chomol」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mayh554024289/article/details/47914237

如果把部分逆置的话,确实只需要一个元素的附加空间,而且时间复杂度为O(n)
其实这就是把字符串看做两个整体来移动。1234567–>1234|567–>567|1234

分析

从第一个元素开始,在移动k位之前,将他要移动到的位置的元素先存储起来。然后将其移动到那个位置,再将其存储的元素移动k位。依次类推。循环到把所有元素都移动完的时候结束。(总共移动次数等于元素个数)
但是有个问题就是,比如有9个元素,

code

void move(char str[], int k)
{
	int len, i = 0, goal = 0;//数组长度,要移动的元素的位置,目标移动位置 
	char tem;
	len = strlen(str);
	while(len--)
	{
		goal = (i + k) % len;//实现循环移动的操作 
		tem = str[goal];//赋值
		str[goal] = str[i];//存储下来要即将移动到的位置的元素
		i = goal; 
	}
} 

最初写出来的程序。我觉得没毛病啊,但是什么都输出不了。
呸,一堆错误。谁让你len--了?len不是就变了吗???而且这个算法是错误的根本不能移动每一位元素。

#include<stdio.h>  
#include<string.h>  
#include<iostream>  
using namespace std;  
void move(char str[], int k);//将str数组中的元素循环移动k位   
void inverse(char str[], int start, int end);//将字符串的[start, end]部分逆置   
int main()  
{  
    char str[100];  
    int k;//要移动的位置   
    cout<<"请输入字符串"<<endl;   
    cin>>str;  
    cout<<"请输入移动位置"<<endl;  
    cin>>k;  
    move(str, k);  
    cout<<"结果:"<<endl;  
    cout<<str;  
    return 0;  
}   
void move(char str[], int k)  
{  
    int len = strlen(str);//字符串长度   
    inverse(str, len - k % len, len - 1);//逆置右半边字符串  
    inverse(str, 0, len - k - 1);//逆置左半边字符串   
    inverse(str, 0, len - 1);//逆置所有字符串   
}   
void inverse(char str[], int start, int end)  
{  
    int i, j;  
    char tem;  
    for(i = start, j = end; i <= (start + end) / 2; i++, j--)  
    {  
        tem = str[i];  
        str[i] = str[j];  
        str[j] = tem;  
    }  
}  
   

输出正确

总结

1.每次不要只举了一个例子就以为能找到规律。要多找几个例子,还要想到特殊情况。
2.注意分开测试,每写出一个函数就做一下测试。

发布了74 篇原创文章 · 获赞 4 · 访问量 1426

猜你喜欢

转载自blog.csdn.net/weixin_44814121/article/details/102604641
今日推荐