이 문제를 풀 때 로직을 제대로 생각하지 못했다. 

아스키코드값을 이용, 함수로 구현, 연속된 문자인지 알기 위해 prev 변수 사용하는 것 까지 생각하지 못해 문제 푸는데 애를 먹었다.

 

 처음엔 문자열 인덱스로 접근해야하나 싶었는데 아무리 생각해도 적절한 로직이 떠오르지 않았고 자꾸 산으로 가는 느낌이었다.

 두 번째로는 함수로 처리할 생각을 못해서 반복문을 몇 개씩이나 계속 사용해야 되는 거 같아 시간복잡도가 너무 커져 적절하지 않다는 생각을 했다.

 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;



public class Main {

    static BufferedReader br;
    static int number;

    public static void main(String[] args) throws IOException {

          br = new BufferedReader(new InputStreamReader(System.in));
          number = Integer.parseInt(br.readLine());

          int count = 0;
          for(int i=0;i<number;i++) {
              if(check()) {
                 count++;
              }
          }

         System.out.println(count);

   }

   public static boolean check() throws IOException {

        boolean[] check = new boolean[26];
        String st = br.readLine();

        char prev = ' ';
        for(char c : st.toCharArray()) {
           if(check[c - 'a']){
             if(prev == c) {
                continue;
             }else {
                return false;
             }

           }else {
               check[c - 'a'] = true;
               prev = c;
          }
       }

       return true;
    }
}


문자열 문제를 많이 안풀었더니 확실히 많이 까먹은 거 같다는 생각이 들었다. 또 알고리즘 문제 풀 때는 뭐랄까. 머리가 좀 굳는 느낌이다. 알고리즘 문제를 푼다하면 일단 겁부터 먹어서 그런 거 같기도하다.. 그래서 생각이 잘 안난다.

 계속 꾸준히 풀어서 무서움을 좀 없애야겠다.

 

문자열 문제인 2941 문제를 풀어보았다. 

 

처음엔 문제를 읽고 출력인 '몇 개의 크로아티아 알파벳으로 이루어져 있는지' 이 부분을 '몇 가지 종류의 크로아티아 알파벳' 인지라고 이해하고 문제를 풀었던 것 같다. 그래서 중복인 경우를 제외해줘야 되겠다고 생각했고 HashMap을 이용해서 풀었다. 

 


Map<String, Integer> maps = new HashMap<>();

maps.put("c=", 0);
maps.put("c-", 0);
maps.put("dz=", 0);
maps.put("d-", 0);
maps.put("lj", 0);
maps.put("nj", 0);
maps.put("s=", 0);
maps.put("z=", 0);

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;

str = br.readLine();
for(String key : maps.keySet()) {

if(str.contains(key)) {
maps.put(key, maps.getOrDefault(key, 0) + 1);
str = str.replace(key, "");
}
}

int sum = 0;
for(String key : maps.keySet()) {
sum += maps.get(key);
}
sum += str.length();
System.out.println(sum);


이 생각이 잘못되서 예제 입력 4도 틀렸었고, 예제 입력 5도 틀려서 의문을 갖기 시작했다.

print로 일일이 찍어보니 예제 입력 5인 "dz=ak"에서 keySet()으로 key값 하나씩 비교하는데 순서가 가장 마지막인 z=, dz=, 이 순서대로 key가 뽑혀나와 비교할 때 dz=를 제외해야하는데 z=을 먼저 제외해버려서 결과 출력이 틀리게 나왔던 것이다. 

 

 여기서 다시한번 알게 된 개념이 Set은 List와 다르게 순서가 지켜지지 않기 때문에 keySet()이나 iterator()로 접근할 때도 순서가 저장 순서와 동일하지 않다는 것이다.

 그래서 두 개의 의문점이 생겼다. 첫 번째는 그럼 Hash의 접근 순서를 내가 지정할 수 없는 것인가, 순서를 출력해보았을 때 할 때마다 달라지는 것은 아니던데 그렇다면 랜덤으로 순서가 정해지는 것인가? 였다. 두 번째는 예제 입력 5에서 과연 dz= 이 알파벳을 d와 z=으로 볼 것인지, 하나의 dz=으로 볼 것인지 기준이 뭔가 라는 것이었다.

 

 두 번째 의문점은 내가 문제를 제대로 읽지 않아서 생겨난 의문점이었다. 역시 문제에 나온 내용은 괜히 나오는 내용, 조건이 아니다. 분명히 해결하는데 필요한 조건들이니 꼼꼼하게 읽을 필요가 있다는 깨달음을 주게 된 의문점이었다. 

 

 첫 번째 의문점은 아직도 완전하게 의문을 해소하지 못했다. key를 정렬해주면 원하는 순서대로 나올까 했는데 그것도 아닌거 같다. Hash에 대해 다시 자세하게 공부를 해야할 것 같다.

 

 그래서 결론은 다른 방법을 생각해내는 것이었다. 중복을 제외하는 것이 아니라 사용된 알파벳 개수를 구하면 되니까 Hash를 안쓰고 그냥 문자열 배열을 이용해 해결하면 될 것 같았다. 

 


String[] arr = {"c=","c-", "dz=", "d-", "lj", "nj", "s=", "z="};


BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;

str = br.readLine();

for(String s : arr) {
if(str.contains(s)) {
str = str.replaceAll(s, " ");

}
}

System.out.println(str.length());

 


  입력받은 문자열이 해당 배열 값을 포함하고 있으면 공백으로 바꿔준 뒤 문자열의 길이만 구하면 된다.

  ('공백으로 바꿔준다' : 되게 간단한 방법인데 은근 생각해내기 힘들다. 문제를 많이 풀다 보면 이런 센스가 생길려나?)

 

 이렇게 간단하게 해결할 수 있는 문제를 문제를 잘못 읽고 이해해서 한참을 돌아 헤맸다. 앞으론 문제를 꼼꼼하게 잘 읽어야겠다.

+ Recent posts