- 使用言語
C言語
- タイトル説明
文字列内の左利きのk文字を処理できる関数を実装します。
例:ABCDは1文字を左に回転してBCDAを取得します
ABCDは2文字を左に回転してCDABを取得します
- アイデア分析+コード実装(複数のアイデア)
アイデア1:
従来のアイデアは非常にシンプルで思いつくのが簡単です。例として左利きの文字を取り上げ、変数tmpを作成し、文字列の最初の文字をtmpに割り当ててから、文字列内のすべての文字を移動します。たとえば、1ビット進むと、ABCDになる前に移動し、移動した後はBCDDになります。これは、最後の文字が前方に移動してカバーされないため、変更されないままであるため、最後の文字にtmpを割り当てて、の左回転を完了します。キャラクター。左利きでn文字が必要な場合は、ループを設定し、左利きの1文字の操作を繰り返します。ただし、文字列の長さがlenの場合、左利きの文字数が文字列の長さよりも大きいと、多くの無駄な操作が実行されるため、ステートメントn%= lenを追加してください。 (nは左利きの数値が必要な文字数、lenは文字列の長さです)。
このアイデアの時間計算量はO(N ^ 2)です。以下のコード実装を見てください。
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<assert.h>
void leftmove(char str[],int n,int sz)
{
int i = 0;
assert(str);
n %= sz;
while(n--)
{
char tmp = str[0];
for(i=0; i<sz-1; i++)
{
str[i] = str[i+1];
}
str[sz-1] = tmp;
}
}
int main()
{
int n = 0;
char str[] = "ABCD";
int len = strlen(str);
printf("请输入要旋转几个字符:>");
scanf("%d",&n);
leftmove(str,n,len);
printf("%s\n",str);
return 0;
}
アイデア2:
このアイデアを少し最適化します。左利きのn文字は、左利きの文字をn回繰り返すことを意味します。これは少し非効率的です。左利きが必要な文字を格納するための文字配列tempを作成し、次に、元の文字列を置き換えます。文字は2桁前に移動します。たとえば、ABCD、移動後はCDCDであり、temp []の文字を元の文字列の最後の2桁に順番に割り当てます。ループの数が多いほど、セットをループする必要はありません。ループ、時間の複雑さはO(N)です。
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<assert.h>
void leftmove(char arr[], int n, int len)
{
assert(arr);
int i = 0;
char temp[] = "";
n %= len;
for (i = 0; i < n; i++)
{
temp[i] = arr[i];
}
for (i = 0; i < len - n; i++)
{
arr[i] = arr[i + n];
}
for (i = 0; i < n; i++)
{
arr[i + len - n-1] = temp[i];
}
}
int main()
{
int n = 0;
char str[] = "ABCD";
int len = strlen(str);
printf("请输入要旋转几个字符:>");
scanf("%d",&n);
leftmove(arr, n, len);
printf("%s", arr);
return 0;
}
アイデア3:
この種の考え方は最初から考えるのが難しく、時間計算量はO(N)であり、上記の2つのアイデアよりもはるかに優れています。
コード
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<assert.h>
void Reverse(char *start, char *end)
{
while (start < end){
*start ^= *end;
*end ^= *start;
*start ^= *end;
start++, end--;
}
}
void leftmove(char *str, int len, int num)
{
assert(str);
assert(len > 0);
assert(num > 0);
num %= len;
char *mid = str + num - 1;
Reverse(str, mid);
Reverse(mid + 1, str + len - 1);
Reverse(str, str + len - 1);
}
int main()
{
int n = 0;
char str[] = "ABCD";
int len = strlen(str);
printf("请输入要旋转几个字符:>");
scanf("%d",&n);
leftmove(arr, n, len);
printf("%s", arr);
return 0;
}
アイデア4:
上記の3つのアイデアは、時間計算量をO(N)に徐々に最適化しましたが、最適化は継続でき、理論的には、時間計算量はO(1)に達する可能性があります。アイデアは次のとおりです。
コードの実装:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
void leftmove(char *str, int len, int num)
{
assert(str);
assert(len > 0);
assert(num > 0);
num %= len;
char *buf = (char*)malloc(2 * len + 1);
strcpy(buf, str);
strcat(buf, str);
strncpy(str, buf+num, len);
free(buf);
buf = NULL;
}
int main()
{
int n = 0;
char str[] = "ABCD";
int len = strlen(str);
printf("请输入要旋转几个字符:>");
scanf("%d",&n);
leftmove(arr, n, len);
printf("%s", arr);
return 0;
}
4つのアイデアのうち最初の2つは、考えやすい従来のアイデアです。後の2つは、しばらくは考えにくいです。個人的には3つ目のアイデアをお勧めしますが、このアイデアは他のトピックでも使用できます。