Among Us - Crewmates
 

[Baekjoon] C++ 백준 25501 - 재귀의귀재

728x90

시간 제한 : 2초 (추가 시간 없음)

메모리 제한 : 1024MB (추가 메모리 없음)

 

문제

정휘는 후배들이 재귀 함수를 잘 다루는 재귀의 귀재인지 알아보기 위해 재귀 함수와 관련된 문제를 출제하기로 했다.

팰린드롬이란, 앞에서부터 읽었을 때와 뒤에서부터 읽었을 때가 같은 문자열을 말한다.

팰린드롬의 예시로 AAA, ABBA, ABABA 등이 있고, 팰린드롬이 아닌 문자열의 예시로 ABCA, PALINDROME 등이 있다.

어떤 문자열이 팰린드롬인지 판별하는 문제는 재귀 함수를 이용해 쉽게 해결할 수 있다.

아래 코드의 isPalindrome 함수는 주어진 문자열이 팰린드롬이면 1, 팰린드롬이 아니면 0을 반환하는 함수다.

#include <stdio.h>
#include <string.h>

int recursion(const char *s, int l, int r){
    if(l >= r) return 1;
    else if(s[l] != s[r]) return 0;
    else return recursion(s, l+1, r-1);
}

int isPalindrome(const char *s){
    return recursion(s, 0, strlen(s)-1);
}

int main(){
    printf("ABBA: %d\n", isPalindrome("ABBA")); // 1
    printf("ABC: %d\n", isPalindrome("ABC"));   // 0
}

 

정휘는 위에 작성된 isPalindrome 함수를 이용하여 어떤 문자열이 팰린드롬인지 여부를 판단하려고 한다.

구체적으로는, 문자열 S 를 isPalindrome 함수의 인자로 전달하여 팰린드롬 여부를 반환값으로 알아낼 것이다.

더불어 판별하는 과정에서 recursion 함수를 몇 번 호출하는지 셀 것이다.

 

정휘를 따라 여러분도 함수의 반환값과 recursion 함수의 호출 횟수를 구해보자.

 

 

입력

첫째 줄에 테스트케이스의 개수 T가 주어진다. (1 <= T <= 1000)
둘째 줄부터 T개의 줄에 알파벳 대문자로 구성된 문자열 S가 주어진다. (1 <= |S| <= 1000)

 

출력

각 테스트케이스마다, isPalindrome 함수의 반환값과 recursion 함수의 호출 횟수를 한 줄에 공백으로 구분하여 출력한다.

 

예제

입력 출력
5
AAA
ABABA
ABCA
PALINDROME
1 2
1 3
1 3
0 2
0 1

 

힌트

Python 3

def recursion(s, l, r):
    if l >= r: return 1
    elif s[l] != s[r]: return 0
    else: return recursion(s, l+1, r-1)

def isPalindrome(s):
    return recursion(s, 0, len(s)-1)

print('ABBA:', isPalindrome('ABBA'))
print('ABC:', isPalindrome('ABC'))

Java 15

public class Main{
    public static int recursion(String s, int l, int r){
        if(l >= r) return 1;
        else if(s.charAt(l) != s.charAt(r)) return 0;
        else return recursion(s, l+1, r-1);
    }
    public static int isPalindrome(String s){
        return recursion(s, 0, s.length()-1);
    }
    public static void main(String[] args){
        System.out.println("ABBA: " + isPalindrome("ABBA"));
        System.out.println("ABC: " + isPalindrome("ABC"));
    }
}

 


풀이 (시간초과)

#include <iostream>
#include <string>

using namespace std;

int cnt = 0;

int recursion(string str, int l, int r) {
  cnt++;
  if(l >= r) return 1;
  else if(str[l] != str[r]) return 0;
  else return recursion(str, l+1, r-1);
}
int isPalindrome(string str) {
  return recursion(str, 0, str.length()-1);
}
int main() {
  int T;
  cin >> T;
  for(int i = 0; i < T; i++) {
    cnt = 0;
    string S;
    cin >> S;
    cout << isPalindrome(S) << " " << cnt << endl;
  }
  return 0;
}

 

문제에서 정휘가 작성한 함수의 매개변수처럼 const char *s 방식이 아닌

string str 매개변수를 택해서 풀이했다.

결과는 시간 초과..

도대체 왜 안될까 하고 검색을 여러 번 시도했는데 정휘가 쓴 함수처럼이 아닌 반복문을 사용하라는 게시글을 발견했다.

 

하지만 이 문제의 의도는 정휘의 함수를 이용해야하는 것 같았고,

나와 같은 고민을 하고 있는 분의 질문글을 발견하게 되었다.

 

https://www.acmicpc.net/board/view/101970

 

글 읽기 - C++ 시간초과 이유가 궁금합니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

새롭게 알게 된 점..!

char * 를 인자로 사용했을 때 시간이 훨씬 단축된다는 점이다.

이유는 문자열의 시작 주소만 넘겨주기 때문...

 

 

풀이 (정답)

#include <iostream>
#include <cstring>

using namespace std;

int cnt = 0;

int recursion(const char * s, int l, int r) {
  cnt++;
  if(l >= r) return 1;
  else if(s[l] != s[r]) return 0;
  else return recursion(s, l+1, r-1);
}
int isPalindrome(const char * s) {
  return recursion(s, 0, strlen(s) - 1);
}
int main() {
  int T;
  string S;
  cin >> T;
  for(int i = 0; i < T; i++) {
    cnt = 0;
    cin >> S;
    cout << isPalindrome(S.c_str()) << " " << cnt << endl;
  }
  return 0;
}

 

따라서 새롭게 작성한 정답풀이이다.

  • #include <string>을 #include <cstring>으로 바꿔주었고
  • string S를 S.c_str() 를 이용해 const char 형태로 변환해주었다.

 

 

 

 

728x90
반응형