문제 링크
1. 아이디어
입력이 알파벳으로만 이루어지므로 문자열을 한 글자씩 보며 대소문자를 뒤집어 출력하면 된다. 길이가 최대 20으로 짧아 방식에 따른 성능 차이는 없고, 한 글자의 대소문자를 어떻게 뒤집느냐만 남는다.
ASCII에서 대문자 A부터 Z는 10진수로 65부터 90, 소문자 a부터 z는 97부터 122에 놓인다. 같은 알파벳의 대문자와 소문자는 항상 32만큼 차이 나므로, 문자가 대문자 구간에 있는지 직접 비교해 판별한 뒤 32를 더하거나 빼면 반대쪽 글자로 옮겨진다. 이 판별과 변환은 표준 라이브러리의 대소문자 함수에 맡길 수도 있다.
32는 $2^5$이라서 대문자와 소문자의 이진 표현은 여섯 번째 비트 하나만 다르다.(비트 자리올림 X) 그 비트를 XOR로 뒤집으면(c ^ 32) 대문자는 소문자로, 소문자는 대문자로 분기 없이 바뀐다. 입력이 알파벳으로 한정되어 있어 구간 판별 없이 모든 문자에 적용해도 안전하다.
2. 복잡도
| 접근 | 시간 | 공간 |
|---|
| ASCII 오프셋 | $O(N)$ | $O(1)$ |
| 문자별 표준 함수 | $O(N)$ | $O(1)$ |
| 비트 토글 | $O(N)$ | $O(1)$ |
| swapcase 메서드 | $O(N)$ | $O(N)$ |
($N$ = 입력 문자열의 길이. 문자별 표준 함수 풀이의 Python은 변환한 문자를 join으로 이어붙여 출력하므로 공간 $O(N)$, swapcase 메서드 풀이는 새 문자열을 만들어 공간 $O(N)$)
3. 코드
풀이 1: ASCII 오프셋 [Java][C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| import java.io.*;
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (char c : br.readLine().toCharArray()) {
if ('A' <= c && c <= 'Z') {
System.out.print((char) (c - 'A' + 'a'));
} else {
System.out.print((char) (c - 'a' + 'A'));
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| #include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
string s;
cin >> s;
for (char c : s) {
if ('A' <= c && c <= 'Z') {
cout << (char)(c - 'A' + 'a');
} else {
cout << (char)(c - 'a' + 'A');
}
}
}
|
풀이 2: 문자별 표준 함수 [Java][C++][Python]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| import java.io.*;
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (char c : br.readLine().toCharArray()) {
if (Character.isUpperCase(c)) {
System.out.print(Character.toLowerCase(c));
} else {
System.out.print(Character.toUpperCase(c));
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| #include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
string s;
cin >> s;
for (char c : s) {
if (isupper(c)) {
cout << (char)tolower(c);
} else {
cout << (char)toupper(c);
}
}
}
|
1
2
3
4
5
6
| import sys
input = sys.stdin.readline
s = input()
print("".join(c.lower() if c.isupper() else c.upper() for c in s))
|
풀이 3: 비트 토글 [Java][C++]
1
2
3
4
5
6
7
8
9
10
11
| import java.io.*;
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (char c : br.readLine().toCharArray()) {
System.out.print((char) (c ^ 32));
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| #include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
string s;
cin >> s;
for (char c : s) {
cout << (char)(c ^ 32);
}
}
|
풀이 4: swapcase 메서드 [Python]
1
2
3
4
5
| import sys
input = sys.stdin.readline
print(input().swapcase())
|
Python은 문자열 전체의 대소문자를 한 번에 뒤집는 swapcase 메서드를 쓰면 직접 순회할 필요도 없다.