띠오니 개발자 성장일지
article thumbnail
반응형

인프런의 "자바(Java) 알고리즘 문제풀이 : 코딩테스트 대비" 강좌를 수강했습니다.

 


 

Q1-05. 특정 문자 뒤집기

영어 알파벳과 특수문자가 섞인 문자열이 주어진다.
영어 알파벳만 뒤집고, 특수문자는 그 자리에 그대로 있는 문자열을 만들어 출력하기

예시입력과 출력은 아래와 같다.

//입력
a#b!GE*T@S

//출력
S#T!EG*b@a

 

 

✏️ 내가 쓴 답

내가 쓴 첫 번째 답 - 오답 😅

 

처음 생각한 과정은 

1. 문자와 기호가 섞인 문자열을 입력받는다.
2. solution(str)로 넘겨준다.
3. str 문자열을 toCharArray() 로 문자 배열화
4. 문자열 양끝 lt, rt 자리를 할당시킨 후, while() 문 실행
5. if (앞뒤 대칭 자리에 위치하는 문자 2개 각각 소문자, 대문자인가?) true면 바꾸고, false면 그대로 두기

 

1~4번까지는 잘 했는데 5번 과정에서 if문 폭주해버렸다...

저번에 배웠던 문자를 ASCII Code로 알아내는 방법이 생각나, 앞뒤로 대칭되는 알파벳들이 97~122(소문자), 65~90(대문자) 값 사이라면 문자이므로 서로 자리를 바꾸면 될 것같았다.

import java.util.Scanner;

public class Main {

    public String solution(String str){
        String answer = "";

        // 3. 문자열 toCharArray() 로 문자배열화
        char[] cArr = str.toCharArray();

         // 4. while lt, rt 로 양 자리 할당
        int lt = 0, rt = cArr.length-1;

        
       // 5. if cArr[lt] && cArr[rt] 값이 65-90 97-122 사이인지 확인
       // 자리를 바꾸려면 양쪽 자리 다 문자여야 할 것 같음
        while(lt < rt){

            if((cArr[lt] >= 65 && cArr[lt] <=90) && (cArr[rt] >= 65 && cArr[rt] <= 90)       // 소&&소
               || (cArr[lt] >= 97 && cArr[lt] <=122) && (cArr[rt] >= 97 && cArr[rt] <= 122)  // 대&&대
               || (cArr[lt] >= 97 && cArr[lt] <=122) && (cArr[rt] >= 65 && cArr[rt] <= 90)   // 대&&소
               || (cArr[lt] >= 65 && cArr[lt] <=90) && (cArr[rt] >= 97 && cArr[rt] <= 122)){ // 소&&대
                    char tmp = cArr[lt];
                    cArr[lt] = cArr[rt];
                    cArr[rt] = tmp;    
            }

                lt++;
                rt--;

        }

        String tmp = String.valueOf(cArr);
        answer = tmp;

        return answer;
    }

    public static void main(String[] args){
        Main main = new Main();

        Scanner sc = new Scanner(System.in);

        // 1. 문자 기호 섞인 단어 입력 받는다
        String str = sc.next();

        // 2. solution(str) 넘겨주어 결과 출력한다.
        System.out.println(main.solution(str));

    }
}

 

 

두번째 코드 - 역시 오답..

위 방식처럼 풀다가 생각난 Character 객체! 바로 활용하려고 했는데, 알파벳 값인지 아닌지를 확인하는 메소드는 모르겠어서 이것저것 찾아보다가, 가장 그럴듯(?)하게 생긴 Character.isLetter() 메소드를 활용해봤다. 하지만 오답 ㅠㅠ 

public String solution(String str) {
	String answer = "";
    
    char[] cArr = str.toCharArray();
    int lt=0, rt=cArr.length-1;

    while(lt < rt){
        if(Character.isLetter(cArr[lt]) && Character.isLetter(cArr[rt])){
            char tmp = cArr[lt];
            cArr[lt] = cArr[rt];
            cArr[rt] = tmp; 
            lt++;
            rt--;
        }
    }
    	
    String tmp = String.valueOf(cArr);
    answer = tmp;
    
    return answer;
}

 

 

💪🏻 보완하고 싶은 점

 문제를 잘못 이해해서, 알파벳이 앞 뒤로 대칭해서 뒤집혀지는 줄 알았다. 대칭된 자리에 있는 두 문자가 알파벳 - 문자 이런 관계였다면 그대로 두고, 알파벳-알파벳 위치일 때만 바꾼다고 생각했었다. 그래서 lt와 rt를 계속 동시에 비교하고, 동시에 증감하려고 했다.

영상의 질문 커뮤니티를 보니 나처럼 생각한 사람이 한둘이 아니었다 ㅋㅋ 문제 오답률도 높았고.. 조금만 더 생각해봤으면 나... 풀 수 있었을지도?? (응 못풀어)

 

 

👨🏻‍🏫 풀이 코드

강의를 참고하여 아래와 같이 수정했다.

이 문제는 대칭된 문자끼리 뒤집는 게 아닌, 문제 그대로 특수문자는 건너뛰고 앞의 알파벳과 뒤의 알파벳의 자리를 뒤집는 것이다. lt와 rt가 동시에  비교 되는게 아니라, lt별개로 비교되고, rt는 또 별개로 비교되는 것이었고, lt와 rt가 꼭 대칭인 위치일 필요가 없었던 것!

public String solution(String str){
        String answer = "";

        char[] cArr = str.toCharArray();
        int lt=0, rt=cArr.length-1;

        while(lt < rt){
            if(!Character.isAlphabetic(cArr[lt])) lt++;     // 왼쪽 문자가 특수문자일 경우 스킵
            else if(!Character.isAlphabetic(cArr[rt])) rt++;    // 오른쪽 문자가 특수문자일 경우 스킵
            else {
                char tmp = cArr[lt];
                cArr[lt] = cArr[rt];
                cArr[rt] = tmp;
                lt++;
                rt--;
            }
        }
		answer = String.valueOf(cArr);
        
        return answer;
    }
반응형

 

8번줄 왼쪽, 오른쪽 문자가 동시에 비교되는 게 아니라, 왼쪽 문자가 특수문자일 경우 lt++된 후 다음 while()문으로 진행되어 계속 왼쪽 문자를 검사하게 된다.

9번줄 왼쪽 문자가 알파벳일 경우, 그제서야 오른쪽 문자가 특수문자 여부가 체크되는 것이다.

10번줄 왼쪽 문자, 오른쪽 문자 둘다 알파벳일 경우 자리를 바꿔준 후, 자리수 증감 시켜준다.

대칭하는 자리의 문자끼리 비교하려는 생각에 lt, rt 동시에 비교했던 건데 그렇게 푸는 문제가 아니었다.

대칭과 동시성은 상관 없이 그냥 특수문자는 건너뛰고 다른 알파벳이 나오면 자리를 바꾸는 것.

 

또한 쌤이 주신 팁! cArr[lt] 의 값이 문자일 경우를 생각하는 것 보다, cArr[lt] 의 값이 `특수문자일 경우`로 생각하는 것이 더 수월하다.

특수문자일 경우 즉, 문자가 아닐 경우(!)를 조건식으로 두고 풀어보자. 

 

잠깐 ✅ isLetter() 과 isAlphabetic() 의 차이점

https://www.baeldung.com/java-character-isletter-isalphabetic

 

 

🤓 정리

  • 문제가 쉬워보이고 익숙해보여도 잘 읽어보고 생각을 해볼 것! 
  • 같은 조건을 만드는 데에도, 여러 방식이 있을 수 있다. 문자일 경우, 문자가 아닐경우, 특수문자일 경우, 특수문자가 아닐 경우 등 조건 표현 방식이 다양하니 문제를 많이 풀어보자!
  • 해당 문자가 알파벳인지 확인하는 방법은  Character.isAlphabetic()을 사용한다.

 

 


요즘 몸 컨디션이 안좋아서 너무 피곤한데 ... 귀찮지만 그래도 꾸준히 하려한다.

화이팅 ! 

 

 

반응형
profile

띠오니 개발자 성장일지

@띠오니

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!