题目内容
实现一个函数,可以左旋字符串中的k个字符
例如:
ABCD左旋一个字符得到BCDAABCD左旋两个字符得到CDAB
方法一:逐个字符左旋
解题思路:
将字符串中第一个字符保存下来,然后将之后的字符一个一个向前位移,在最后添加保存下来的第一个字符,以此循环。
首先,我们需要根据字符串的左旋次数(time)来确定左旋的次数(count)。无论字符串有多长,只要当左旋次数到达一定值时,字符串便会变回原本的序列。
由图可知,当字符串长度为4时,左旋次数达到4次时字符串变回了原本的序列,由此可得,字符串的左旋有效变化次数为time = time % len 。
接着,我们需要嵌套循环来完成每一次左旋变化中字符串内部字符的左移。
我们需要在对应下标位置赋值上下一个下标位置的值:
arr[j] = arr[j+1]
完成一个位置的数据交换后我们也同样需要对下一个位置进行操作,由此可知,j 是本次循环的变量,同时 j 的变化也影响着循环进程。
将 j 的值作为循环结束的条件,我们需要分析 j 需要在什么位置停止后移。由赋值代码分析可得,在循环中我们需要对每一个有效数据进行赋值,直到 j+1 超出边界。所以 j 将停留在倒数第二个有效数据,也就是len-1。
当 j 不满足条件退出循环时,我们需要在字符串结尾赋值保存下来的第一个字符,这样一次循环就完成了。
代码展示
以字符串"abcd"为例左旋3次
void leftround(char arr[], int key)
{
int len = strlen(arr);
int count = 0;
int j = 0;
key = key % len;
for (count = 0; count < key; count++)//左旋次数
{
char tmp = arr[0];
for (j = 0; j < len - 1; j++)
{
arr[j] = arr[j + 1];
}
arr[j] = tmp;//将保存好的第一个字符放在最后
}
}
int main()
{
char arr[100] = "abcd";
leftround(arr, 3);
printf("%s\n",arr);
return 0;
}
运行结果:
方法二: 拷贝+拼接
解题思路:
我们可以利用库函数strcpy和strncat,通过对指定位置拷贝和拼接来完成字符串左旋。
对于如何找到指定位置进行拷贝和拼接,我们需要使用 数组名+左旋次数 来完成对指定位置的拷贝。
代码展示
以字符串"abcdef"为例左旋4次
void leftround(char arr[], int time)
{
int len = strlen(arr);
time = time % len;
char tmp[100] = { 0 };
strcpy(tmp, arr + time);//往tmp中拷贝ef
strncat(tmp, arr, time);//在tmp中拼接arr中的前time个字符abcd
strcpy(arr, tmp);//将tmp中的字符串拷贝到arr中
}
int main()
{
char arr[100] = "abcdef";
leftround(arr, 4);
printf("%s\n", arr);
return 0;
}
运行结果:
方法三:利用数组下标进行逆置
解题思路:
将左旋次数前time个字符进行逆置,同时将之后的字符进行逆置,最后整体逆置。
本次左旋我们只用到了逆置的操作,所以我们可以单独设计一个逆置的函数来完成本次左旋。
我们可以以传递数组下标的方式确定每一次逆置的范围,而后对字符串中的字符进行左右交换。
void reverse(char arr[], int left, int right)
{
while (left < right)
{
char tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
对于下标的确定方式,我们需要使用字符串长度len和左旋次数time进行调整。
代码展示
以字符串"abcdef"为例左旋4次
void reverse(char arr[], int left, int right)//逆置函数
{
while (left < right)
{
char tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
void leftround(char arr[], int time)
{
int len = strlen(arr);
time %= len;
reverse(arr, 0, time - 1);//找到前time个字符进行逆置
reverse(arr, time, len - 1);//对之后的字符进行逆置
reverse(arr, 0, len - 1);//整体逆置
}
int main()
{
char arr[100] = "abcdef";
leftround(arr, 4);
printf("%s\n", arr);
return 0;
}
运行结果:
总结
完成字符串左旋的方法有很多种,可以对其逐个左旋,也可以利用库函数快速解决。通过发掘不同的解题思路去解决问题,有助于我们逻辑思维能力的提升。