「演習」は、文字列内の左利きのk文字を使用できる関数を実装します

  • 使用言語

C言語

  • タイトル説明

文字列内の左利きのk文字を処理できる関数を実装します。
例:ABCDは1文字を左に回転してBCDAを取得します
ABCD2文字を左に回転して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つ目のアイデアをお勧めしますが、このアイデアは他のトピックでも使用できます。

おすすめ

転載: blog.csdn.net/NanlinW/article/details/103103634