上部下部
Bibi还想挑战Jojo和Lili。她的字符串S的长度为N。字符串可以包含 大写和小写字符。然后,她将从字符串的开头开始迭代,如果第K个 字符是大写字符,那么她将更改其后的所有字符,例如大写 字符将变为小写,小写字符将变为大写。结束后 迭代,她会问Jojo和Lili字符串是什么。
格式输入
1。输入的第一行将包含一个整数T,即测试用例的数量。
2。每个测试用例都将包含一个字符串S和一个整数N作为长度。
格式化输出
对于每个测试用例,打印“案例#X:”(X以1开头)。然后在同一行上,在 迭代。
约束
1 <= T <= 10
1 <= N <= 100000
该字符串仅包含大写和小写字符。
这是我的解决方案。但它一直在获得TLE。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(){
int room,len;
scanf("%d",&room);
char words[100000];
for(int i = 0; i<room; i++){
scanf("%s %d",words,&len);
char next[100000];
int j = 0;
printf("Case #%d: ",i+1);
while(j<len){
int k = j+1;
if(isupper(words[j])){
while(k<len){
if(isupper(words[k])){
words[k] = tolower(words[k]);
}else{
words[k] = toupper(words[k]);
}
k++;
}
}
//printf("%c",words[j]);
j++;
}
printf("%s",words);
printf("\n");
}
return 0;
}
需要帮助以寻求更好的解决方案。
我认为TLE来自嵌套循环,但是如果没有嵌套循环,我将无法解决。
答案 0 :(得分:2)
在“新算法”部门-您已按照规定实施了算法。但是,这意味着您要花费大量时间(我猜大部分时间都是在字符串中),从而可能多次更改字符的大小写。您实际上不需要这样做。保留您发现的大写字符数的计数器,该字符最初设置为零。检查字符时,请检查计数器。如果计数器为奇数(即if (counter & 1)...
),请反转当前正在查看的字符的大小写(从上到下,从下到上)。完成此操作后,测试一下您当前正在查看的字符是否为大写(可能刚刚更改为大写)。如果是这样,请增加计数器。然后继续下一个字符。
这可以就地完成并一次性完成,没有任何嵌套循环。
所以您在字符串上的循环看起来像
for (i = 0, counter = 0 ; i < strlen(string) ; ++i)
{
if (counter & 1) /* if counter is odd */
if (isupper(string[i])) /* if character [i] is upper case */
string[i] = tolower(string[i]); /* convert character [i] to lower case */
else
string[i] = toupper(string[i]); /* convert character [i] to upper case */
if(isupper(string[i])) /* if character [i] is now upper case */
counter += 1; /* increment the counter */
}
好运。
答案 1 :(得分:0)
您可以尝试使用一些指针魔术来尝试此操作。另外,请尝试将程序分成功能,以便代码的每个部分都有明确的用途。最后,scanf
并不是获得用户输入的很好解决方案:如果用户输入的字符比预期的多,它将破坏您的程序(如果使用Windows,则可能会破坏您的系统)。我只是以这个scan_str
为例。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Helper function to swap a character case */
char swap_case(char c) {
if(isupper(c))
return tolower(c);
return toupper(c);
}
/* Our iteration test case */
char*test_iterate(char*str) {
char *p, *p0;
/* Don't swap until first upper char is found */
int swap = 0;
/*
* - Initialize both pointers to beginning of string
* - Iterate until a 0 is found (end of string)
* - Each iteration, "advance" pointer by one
*/
for(p0 = p = str; *p != 0; p++) {
/* If is upper, begin to swap case */
if(isupper(*p))
swap = 1;
*p = swap ? swap_case(*p) : *p;
}
/* Return pointer to begining of word */
return p0;
}
/*
* `scanf("%s", &word)` is not good if you are serious and want to avoid memory overflow
*/
char*scan_str() {
/* Lets begin with 10 bytes allocated */
size_t buf_size = 10;
char c, *word = (char*) malloc(buf_size);
int length = 0;
/* Iterate reading characters from `stdin` until ENTER is found */
while( (c = getc(stdin)) != '\n' && c != EOF ) {
/* If we need more than already allocated, allocate more (10 bytes more) */
if((length + 1) >= buf_size) {
buf_size += 10;
word = realloc(word, buf_size);
if(word == NULL)
return "Some weird error.";
}
/* Save read char to our word/buffer */
word[length] = c;
length++;
}
/* Add word ending character */
word[length] = 0;
return word;
}
int main(void) {
int room;
/* Two dimensional array: list of string pointers */
char**tests;
/*
* Use `scanf` to read an integer
* It's still not good enough, as you need this weird `%*c` to discard ENTER inputs
*/
printf("Insert number of tests to do:\n");
scanf("%d%*c", &room);
/* Allocate memory for `tests`: array of pointers to strings */
tests = (char**) malloc(sizeof(char*) * room);
/* Get input from user */
for(int i = 0; i < room; i++) {
printf("Insert test case #%d:\n", i + 1);
tests[i] = scan_str();
}
/* Print results and free each test memory */
for(int i = 0; i < room; i++) {
printf("Case #%d: %s\n", i + 1, test_iterate(tests[i]) );
free(tests[i]);
}
/* Free `tests` array */
free(tests);
return 0;
}