will come true

[프로그래머스 / Level1] 이상한 문자 만들기 (Java) 본문

Algorithm

[프로그래머스 / Level1] 이상한 문자 만들기 (Java)

haehyun 2021. 10. 26. 02:00
728x90

문제

https://programmers.co.kr/learn/courses/30/lessons/12930

 

코딩테스트 연습 - 이상한 문자 만들기

문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을

programmers.co.kr

 

기존 코드 (성공)

class Solution {
    public String solution(String s) {
        char[] chArr = s.toCharArray();
        int cnt = 0;
        
        for(int i=0; i < chArr.length; i++){
            if(chArr[i] == ' '){
                cnt = 0;
            }else if(cnt % 2 == 0){     //0인 경우도 포함
                if('a' <= chArr[i] && chArr[i] <= 'z'){
                    chArr[i] = (char)(chArr[i] - 32);
                }
                cnt++;
            }else{
                if('A' <= chArr[i] && chArr[i] <= 'Z'){
                    chArr[i] = (char)(chArr[i] + 32);
                }
                cnt++;
            }
        }
        
        return String.valueOf(chArr);
    }
}

- 문자를 하나씩 접근해서 바꿔야 한다는 생각때문에 처음은 무조건 .toCharArray()를 사용해서 char[] 배열로 쪼개야 한다고 생각했다. 그러나, toUpperCase(), toLowerCase()등의 대/소문자 전화 메서드는 String타입에만 존재하기 때문에 char타입에는 사용할 수 없었다.

- 그러면 String[] 배열로 쪼개야 겠구나! 라고 생각하는 게 정상적인 흐름일텐데, 어째서진 계속 char[] 배열을 사용해야 한다고만 생각했다.... 아마 내 머리에서 '문자 하나는 char로!, 문자여러개는 String으로!' 라는 고정관념에 사로잡혔던듯. char타입으로 대/소문자를 전환하기 위해 1. 대/소문자 구별 2. 유니코드 차이값 증감 등의 번잡한 과정이 추가되었다.

- 그렇게 헤맬 문제가 아니었는데, 너무 삽질을 해버려서.. 진짜 아직도 머리가 멍하다.. 문제명이 이상한 문자 만들기인데, 단언컨데 이 중에서 가장 이상한 건 내 코드일거다.

 

학습 내용

0을 정수로 나누기/나머지

0은 어떤 수로 나누기/나머지 연산을 하든 결과가 0이다. 짝수/홀수 판별 조건식에서 주의

0 / 2 == 0	//true
0 % 2 == 0	//true
0 / 3 == 0 	//ture
0 % 3 == 0  	//true

 

String 인스턴스 메서드

메서드 설명
String toUpperCase() 대상 문자열을 모두 대문자로 변환하여 반환
String toLowerCase() 대상 문자열을 모두 소문자로 변환하여 반환
String str1 = "Hello World";
String str2 = "HELLO WORLD";
		
System.out.println(str1.toUpperCase());		//HELLO WORLD
System.out.println(str1.toLowerCase());		//hello world
System.out.println(str2.toUpperCase());		//HELLO WORLD
System.out.println(str2.toLowerCase());		//hello world

*전체가 대문자인 문자열에 toUpperCase()메서드를 사용하거나, 전체가 소문자인 문자열에 toLowerCase()를 사용해도 아무 문제 없음.

 

String 문자열을 String[] 배열로 변환

String str = "Hello World";
String[] strArr = str.split("");

for(String s : strArr) {
	System.out.print(s + "/");
}
H/e/l/l/o/ /W/o/r/l/d/

 

String 문자열을 공백을 기준으로 분리

공백이 여러 개 연속으로 있을 수 있으며, 개행문자\n, 탭문자 \t 등 모든 공백을 포함시켜야 할 경우

String str = "Hello    World\nI  Love\tJava";
String[] strArr = str.split("\\s+");

for(String s : strArr) {
	System.out.print(s + "/");
}
Hello/World/I/Love/Java/

 

String 공백 체크

public static void main(String[] args) {
	String str1 = null;
	String str2 = "";
	String str3 = " ";
	
	System.out.println(isNullOrEmpty(str1));		//true
	System.out.println(isNullOrEmpty(str2));		//true
	System.out.println(isNullOrEmpty(str3));		//false
	
	System.out.println(isNullOrWhiteSpace(str1));		//true
	System.out.println(isNullOrWhiteSpace(str2));		//true
	System.out.println(isNullOrWhiteSpace(str3));		//true
}

static boolean isNullOrEmpty(String str) {
	return str == null || str.isEmpty();
}

static boolean isNullOrWhiteSpace(String str) {
	return str == null || str.isEmpty() || str.contains(" ");
}

 

StringBuffer, StringBuilder

String타입은 불변이기 때문에 문자열 연산을 수행할 때 마다(값이 바뀔때 마다) 새로운 String객체를 생성하는 반면,
StringBuffer와 StringBuilder는 가변적이기 때문에 동일 객체 내에서 문자열 값을 변경할 수 있다.

  • String : 불변, thread-safe
  • StringBuffer : 가변, thread-safe
  • StringBuilder : 가변

 

개선 코드 (성공)

class Solution {
    public String solution(String s) {
        StringBuffer sb = new StringBuffer();
        String[] strArr = s.split("");
        int cnt = 0;
        
        for(String str : strArr){
            cnt = str.contains(" ") ? 0 : cnt + 1;
            sb.append(cnt % 2 == 0 ? str.toLowerCase() : str.toUpperCase());
        }     
        
        return sb.toString();
    }
}

- 문자열 추가가 잦기 때문에 추가 시 매번 새로운 객체를 생성하는 String보다는 StringBuffer를 사용
   대/소문자 전환한 문자열을 하나씩 StringBuffer에 추가해서 마지막에 .toString()
- 문자열 배열의 요소를 순차적으로 읽어내릴뿐 인덱스는 필요없기 때문에 forEach문으로 변경
- 문자열 배열에서 공백이 나오면 cnt 리셋
- 기본 char[] 타입에서 String[] 타입을 사용하는 걸로 변경해 toLowerCase(), toUpperCase()를 활용

728x90
Comments