[Programmers] 문제 풀이
- Programmers 기초 문제 Day1, Day2 문제 풀이
대소문자 바꿔서 출력하기(level 0)
문제 설명 :영어 알파벳으로 이루어진 문자열 str이 주어집니다.
각 알파벳을 대문자는 소문자로 소문자는 대문자로 변환해서 출력하는 코드를 작성해 보세요.
제한사항 :1 ≤ str의 길이 ≤ 20str은 알파벳으로 이루어진 문자열입니다.
//처음 코드
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a = sc.next();
int aLen = a.length();
char aChar;
String answer="";
if(1<=aLen && aLen<=20){
for(int i=0; i<aLen; i++){
aChar = a.charAt(i);
if(65<=aChar && aChar<=90){
aChar+=32;
answer+=String.valueOf(aChar);
}
else if(97<=aChar && aChar<=122){
aChar-=32;
answer+=String.valueOf(aChar);
}
}
System.out.println(answer);
}
sc.close();
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//이후 코드
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a = sc.next();
int aLen = a.length();
StringBuilder answer = new StringBuilder();
if(1<=aLen && aLen<=20){
for(char aChar : a.toCharArray()){
if(Character.isUpperCase(aChar)){
answer.append(Character.toLowerCase(aChar));
} else {
answer.append(Character.toUpperCase(aChar));
}
}
System.out.println(answer);
}
sc.close();
}
}
- 코드 분석
- 너무 쉬운 기초 문제임에도 코테 문제를 오랜만에 풀다보니 기본기도 부족하고 간결하지도 못한 코드같다....
메소드들이 기억이 안나서 최대한 기억나는 메소드 위주로만 코드를 작성하다보니 개판이 났다. - 내 풀이 과정
- 주어진 문자열을 문자 하나씩 쪼개기
- 문자를 아스키 코드를 통해 대소문자 구분하기
- 아스키 코드 65~90까지의 값이 A~Z, 97~122까지의 값이 a~z이다.
- 아스키 코드 65~90까지의 값이 A~Z, 97~122까지의 값이 a~z이다.
- 대문자인 경우 해당 아스키 값 +32 => 소문자로 변환
소문자인 경우 해당 아스키 값 -32 => 대문자로 변환 - 대소문자 변환 후 문자/문자열로 변환 후 출력
- 아스키 코드로 연산했기에 바로 값을 출력하면 아스키 코드의 숫자 값이 나오기 때문
- 문자열끼리는 + 연산이 가능
- 풀이 과정 잘못된 점 & 개선 사항
- 문자열을 문자로 변환 시
- 반복문 안에서 charAt() -> toCharArray() 문자 배열로 변환 후 반복문을 사용해도 된다.
- 대소문자 구분 시
- 아스키 코드 숫자 값으로 비교
-> 문자 자체인 a <= str && str <= z 와 같이 비교
-> Character.isUpperCase(), Character.isLowerCase() 사용
- 아스키 코드 숫자 값으로 비교
- 대소문자 변환 시
- 아스키 코드 값만큼 값을 증감 -> Character.toUpperCase(), Character.toLowerCase() 사용
- 결과 출력 시
- 아스키 코드 값을 valueOf()를 통해 문자열로 변환 후 + 연산 후 출력
-> 아스키 코드 값을 (char)로 형 변환해서 문자로 변환 후 문자열에 + 연산 후 출력
-> 아스키 코드 값을 (char)로 형 변환해서 문자로 변환 후 StringBuilder.append()를 사용해서 문자를 합한 후 출력
- 아스키 코드 값을 valueOf()를 통해 문자열로 변환 후 + 연산 후 출력
- 문자열을 문자로 변환 시
- 너무 쉬운 기초 문제임에도 코테 문제를 오랜만에 풀다보니 기본기도 부족하고 간결하지도 못한 코드같다....
- length(): 문자열의 길이, length: 배열의 길이, size(): 컬렉션의 길이를 구할 때 사용된다.
문자열 돌리기(level 0)
문제 설명 :문자열 str이 주어집니다.
문자열을 시계방향으로 90도 돌려서 아래 입출력 예와 같이 출력하는 코드를 작성해 보세요.
제한사항 :1 ≤ str의 길이 ≤ 10
입력 값: abcde
출력 값:
a
b
c
d
e
//처음 코드
import java.util.Scanner;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a = sc.next();
int aLen = a.length();
if(1 <= aLen && aLen <= 10){
Queue<Character> q = new LinkedList<>();
for(char aChar : a.toCharArray()){
q.offer(aChar);
}
while(!q.isEmpty()){
System.out.println(q.poll());
}
}
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//이후 코드
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a = sc.next();
int aLen = a.length();
if(1 <= aLen && aLen <= 10){
for(char aChar : a.toCharArray()){
System.out.println(aChar);
}
}
}
}
- 코드 분석
- 처음 문제를 봤을 때 선입선출을 사용해야겠다고 생각해서 Queue를 사용해서 풀어야겠다고 생각하고 잘 알지도 못하는 Queue를 꾸역꾸역 사용하면서 풀었다.
Queue를 잘 알지도 못해서 처음 PriorityQueue를 사용했다가 틀리기까지 했다. 바보같이 너무 쉬운 문제였는데 너무 어렵게 풀려고 했던 것 같다...
오랜만에 Queue를 사용했다는 것에 만족하자 - 내 풀이 과정
- 입력받은 문자열을 문자로 변환
- 모든 문자들을 Queue인 LinkedList에 삽입
- Queue에 값이 없어질 때까지 값을 꺼내서 출력
- 풀이 과정 잘못된 점 & 개선 사항
- Queue 자체를 사용할 필요조차 없던 문제였다.
- 입력받은 문자열을 문자로 변환하는 toCharArray()를 통해 문자 배열을 얻어서 배열의 처음부터 끝까지 값을 출력하면 되는 간단한 문제였다.
- Queue를 사용할 때 알아야할 것
- 삽입: offer() / add(), 삭제/꺼내기: poll(), 확인: peek()
- 제네릭 타입을 사용해도 하지 않아도 되지만 사용하는 것이 데이터 안정성 면에서 더 좋다.
- PriorityQueue는 저장한 순서와 관계없이 우선순위에 따라 꺼내는 순서가 정해지는 큐
- Deque는 양쪽 끝에서 값을 저장하고 꺼낼 수 있는 스택과 큐가 합쳐진 형태
- 일반적인 Queue를 사용할 때는 LinkedList를 사용하는 것이 가장 대중적이다.
- 사용할 때 import java.util.* 선언해주기
- LinkedList Big O
- 인덱스 조회 O(n)
- 데이터 추가/삭제 O(1)
- 데이터 검색 O(n)
- 제네릭 타입을 사용하는 경우 int와 같은 Primitive 타입이 아니라 Integer와 같은 Wrapper 클래스를 써 주어야 한다.
- 제네릭은 컴파일러에 의해 타입소거 과정을 거치게 되며 이로 인해 기존 제네릭 타입은 모두 Object로 바뀐다. 이로 인해 제네릭 타입 파라미터에는 Object로 형 변환 될 수 있는 참조 타입만 올 수 있다.
- Queue 자체를 사용할 필요조차 없던 문제였다.
- 처음 문제를 봤을 때 선입선출을 사용해야겠다고 생각해서 Queue를 사용해서 풀어야겠다고 생각하고 잘 알지도 못하는 Queue를 꾸역꾸역 사용하면서 풀었다.
문자열 돌리기(level 0)
문제 설명
문자열 my_string, overwrite_string과 정수 s가 주어집니다.
문자열 my_string의 인덱스 s부터 overwrite_string의 길이만큼을 문자열 overwrite_string으로 바꾼 문자열을 return 하는 solution 함수를 작성해 주세요.
제한사항
my_string와 overwrite_string은 숫자와 알파벳으로 이루어져 있습니다.
1 ≤ overwrite_string의 길이 ≤ my_string의 길이 ≤ 1,000
0 ≤ s ≤ my_string의 길이 - overwrite_string의 길이
//처음 코드
class Solution {
public String solution(String my_string, String overwrite_string, int s) {
StringBuilder ans = new StringBuilder();
if(my_string.length() <= overwrite_string.length() + s){
ans.append(my_string.substring(0,s));
ans.append(overwrite_string);
} else {
ans.append(my_string.substring(0,s));
ans.append(overwrite_string);
ans.append(my_string.substring(ans.length(),my_string.length()));
}
String answer = ans.toString();
return answer;
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//이후 코드
class Solution {
public String solution(String my_string, String overwrite_string, int s) {
StringBuilder ans = new StringBuilder();
ans.append(my_string.substring(0,s))
.append(overwrite_string)
.append(my_string.substring(s + overwrite_string.length()));
String answer = ans.toString();
return answer;
}
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//StringBuilder.replace() 사용
class Solution {
public String solution(String my_string, String overwrite_string, int s) {
StringBuilder ans = new StringBuilder(my_string);
ans.replace(s, s + overwrite_string.length(), overwrite_string);
String answer = ans.toString();
return answer;
}
}
- 코드 분석
- 아래 사진에서 왼쪽이 String 문자열 + 연산 방식 결과, 오른쪽이 StringBuilder로 append() 연산 방식 결과로 속도 측면에서 보면 매우 간단한 문제면서 간단한 연산이지만 String보다 StringBuilder를 사용하는 것이 훨씬 빠른 것을 볼 수 있다.
또한 코드는 여전히 지저분한 것을 볼 수 있다. - 내 풀이 과정
- 문자열 my_string 길이 값과 overwrite_string 길이 + s 값을 비교
- my_string 길이 값이 작으면 기존 my_string 문자열을 s부터 overwrite_string의 길이만큼 잘라준 후 그 부분을 문자열 overwrite_string로 바꿔준다.
- my_string 길이 값이 크면 기존 my_string 문자열을 s부터 overwrite_string의 길이만큼 잘라준 후 그 부분을 문자열 overwrite_string로 바꿔주고 나머지 my_string 문자열을 추가로 붙여줘야 한다.
- 먼저 문자열 my_string을 s부터 overwrite_string의 길이만큼 잘라주기
- substring(begin, end)을 사용하면 begin 인덱스 위치부터 end 인덱스 이전까지 문자열을 잘라서 반환해준다.
- substring(begin)을 사용하면 begin 인덱스 위치부터 끝까지 문자열을 잘라서 반환
- 문자열 연산을 최적화하기 위해서 StringBuilder를 사용해서 문자열 연산을 한다.
- solution 함수는 반환 타입이 String이기 때문에 반환하기 전 StringBuilder를 toString()을 통해 String으로 변환해서 반환한다.
- 문자열 my_string 길이 값과 overwrite_string 길이 + s 값을 비교
- 풀이 과정 잘못된 점 & 개선 사항
- 불필요한 코드를 제거함으로 코드 간소화
- StringBuilder의 append()는 메소드 체이닝이 가능
-> append()를 메소드 체이닝함으로 간소화 - 제한 사항에서 (0 ≤ s ≤ my_string의 길이 - overwrite_string의 길이)으로 인해 overwrite_string의 길이 값 + s는 my_string의 길이 값보다 클 수 없기에
substring(begin)을 사용했을 때 begin 인덱스가 길이를 넘어가서 예외가 터질 수 없다.
-> 불필요한 if 조건문을 제거
- StringBuilder의 append()는 메소드 체이닝이 가능
- 문자열을 바꿀 시
- substring(begin, end) / substring(begin)
-> StringBuilder.replace(start, end, str)을 사용하면 훨씬 간소화된 코드를 작성할 수 있다. - StringBuilder.replace(start, end, str): StringBuilder 기존 문자열을 start 인덱스부터 end 인덱스 전까지 str 문자열로 바꾼다.
- substring(begin, end) / substring(begin)
- 불필요한 코드를 제거함으로 코드 간소화
- 아래 사진에서 왼쪽이 String 문자열 + 연산 방식 결과, 오른쪽이 StringBuilder로 append() 연산 방식 결과로 속도 측면에서 보면 매우 간단한 문제면서 간단한 연산이지만 String보다 StringBuilder를 사용하는 것이 훨씬 빠른 것을 볼 수 있다.
부족한 점
- 공식 문서 보는 습관 들이기
- 컴파일 에러 발생 시 꼼꼼하게 살펴보기
- 오타, import, 띄어쓰기 등
- 리소스 반환 코드를 작성하지 않는 습관 고치기!
- 기초 문제에서 주로 사용되는 Scanner 클래스 등을 사용 후 메모리 누수가 발생하지 않도록 close()로 리소스를 반환해줘야 한다.
- 문자열을 다룰 때는 String보다는 StringBuilder 사용할 것
- String은 Immutable 하기에 StringBuilder나 StringBuffer를 사용하는 것이 메모리적인 측면에서 좋다.
- StringBuffer는 멀티 쓰레드 환경에서 좋기에 StringBuilder보다 속도적인 측면에서는 느리기에 속도적인 측면 & 메모리적인 측면에서 가능하면 StringBuilder를 사용하는 것이 좋다. (상황에 따라서는 다를 수 있다.)
- 코딩 테스트에서 자주 사용하는 import 패키지 알아두기
- java.lang, java.util, java.io, java.util.stream 등
- 가독성, 효율성 좋은 코드 작성할 것
- 가독성을 위해 코드 간소화하기
- ex) append()와 같은 메소드 체이닝 활용
- 삼항 연산자는 간소화되지만 가독성은 좋지 않음
- 효율성을 위해 메모리, 속도 측면 생각해서 코드 작성하기
- ex) String 대신 StringBuilder 사용
- 가독성을 위해 코드 간소화하기
'Problem Solving > 코딩 테스트' 카테고리의 다른 글
코딩테스트 문제 풀이 (1) | 2025.02.26 |
---|---|
코딩테스트 문제 풀이 (0) | 2025.02.21 |
코딩 테스트 회고 (0) | 2025.02.12 |