[프로그래머스] x 사이의 개수

사당동씩씩이·2024년 5월 2일
post-thumbnail

문제

  • 난이도 : lv.0

  • 간단하게 x를 기준으로 문자를 나누는 문제다.
  • 또, x가 아닌 문자를 세는 문제라고 이해할 수 있다.
  • oxooxoxxox -> ["o","oo","o","","o",""] 로 나누어져야 한다.
  • xabcxdefxghi -> ["","abc","def","ghi"] 가 되어야 한다.
  • myString에 x가 5개 있다면 result는 5보다 같거나 크다.
  • x가 myString에서 처음과 끝에 존제할 때 result의 갯수는 커진다.
  • xxx가 주어진다면, [0,0,0,0]이 되야할 것이다.

풀이

  • 첫 시행착오에 split("x")를 사용했었는데 oxooxoxxox -> ["o","oo","o","","o"] 로 리턴됨을 확인했다. 문자 끝에 "x"가 있는 경우 원하는 결과가 도출되지 않았다.
  • split의 패턴이 반복되는 횟수를 조정하거나, 직접 문자열을 순회하도록 하여 해결할 수 있다.

case1 - String.split()

class Solution {
    public int[] solution(String myString) {
        String[] pwd = myString.split("x", -1);
        int[] answer = new int[pwd.length];
        
        int index = 0;
        for (String a : pwd) {
            answer[index] = a.length();
            index++;
        }
        return answer;
    }
}

case2 - char[]로 순회해보기

import java.util.ArrayList;
class Solution {
    public int[] solution(String myString) {
        ArrayList<Integer> answer = new ArrayList();
        char[] pwd = myString.toCharArray();
        
        int count = 0;
        for (int i = 0; i < pwd.length; i++) {
            if (pwd[i]!='x') {
                count++;
            } else {
                answer.add(count);
                count=0;
            }
            if ((i==pwd.length-1)) {
                answer.add(count);
            }
        }
        return answer.stream().mapToInt(Integer::intValue).toArray();
    }
}

split() 메소드 보고 가기

  • 결국 아주 가벼운 문제였으나 java에서 split이 어떻게 작동하는지 보고 가려한다.
  • java Stirng의 split()은 2가지로 오버로딩 되는데
    split(String regex) 그리고 split(String regex, int limit)이다.
  • 당연히 regex로 주어진 string을 기점으로 분리해주는건 알고 있으나 limit는 뭘까??

split()의 작동구조 - java 17

  1. 내가 평소 사용하던 split(Sting regex)는 split(String reget, int limit)를 호출하고 있다.

  2. split의 작동원리

  • regex가 정규식이 아닌경우 Patten 클래스의 split을 호출 하게 되는데, 내부 작동원리와 순서는 같음으로 정규식 표현을 기준으로 포스팅 해보려 한다.
  • 가장 궁금했던건 limit를 어떻게 전달해야하고, 각각 어떻게 처리되는가 이다.
			int off = 0;
            int next = 0;
            boolean limited = limit > 0;
            ArrayList<String> list = new ArrayList<>();
            while ((next = indexOf(ch, off)) != -1) {
                if (!limited || list.size() < limit - 1) {
                    list.add(substring(off, next));
                    off = next + 1;
                } else {    // last one
                    //assert (list.size() == limit - 1);
                    int last = length();
                    list.add(substring(off, last));
                    off = last;
                    break;
                }
            }
            // If no match was found, return this
            if (off == 0)
                return new String[]{this};

            // Add remaining segment
            if (!limited || list.size() < limit)
                list.add(substring(off, length()));
  • while문을 통해 ch(String regex로 주어진 정규식 표현)의 위치를 찾는다.
  • substring을 통해 찾은 index의 앞까지 자른 string을 저장한다.
  • limit가 0보다 큰 양수로 주어진다면, 주어진 limit n의 -1 개로 list가 생성된다.
  • indexOf로 문자열의 위치를 찾고 있기 때문에 만약 "x"를 찾는데 "xxx"라면 빈문자열이 생성된다.
			int resultSize = list.size();
            if (limit == 0) {
                while (resultSize > 0 && list.get(resultSize - 1).isEmpty()) {
                    resultSize--;
                }
            }
            String[] result = new String[resultSize];
            return list.subList(0, resultSize).toArray(result);
  • 결과를 리턴하는 과정에서 limit이 0이라면 get을 통해 뒤에서부터 빈문자열을 제외한 size를 구하여 리턴하게된다.
  1. limit가 음수, 0, 양수인 경우를 구분할 수 있다.
  • 0인 경우 : 뒤에온 빈문자열을 제외함으로 주어진 문제를 해결하는데 맞지 않다.
  • 양수인 경우 : "x"를 indexOf로 탐색하는 횟수가 제한된다.
  • 음수인 경우 : 모든 "x"를 기준으로 빈문자열이 있더라도 포함하여 리턴한다.

결론

  • java에서 제공되는 메서드 작동을 보다보면 문자열을 다룰 때 찾고하자하는 문자열의 시작위치를 찾는다. 예를 들어 "Hello"를 "Hello World"에서 찾을 때, 먼저 "H"를 찾은 후 뒤를 검사하여 불필요한 비교수를 줄인것이 많이 보인다. 그 과정에서 indexOf가 자주 사용되는데 이번 split에서도 indexOf를 사용한 것을 볼수 있었다.
  • 과거 연산우선자를 암기하던 때가 있었는데, while의 조건에서 대입과 비교를 동시에 사용하여 처리된 부분이 인상적이었다.

stream 사용해서 풀기

  • stream은 반복적인 작업을 직관적으로 보여줄 수 있어 연습해보고자 작성해본다.
import java.util.Arrays;
class Solution {
    public int[] solution(String myString) {
        return Arrays.stream(myString.split("x", -1))
            .mapToInt(i -> i.length())
            .toArray();
    }
}
profile
N잡러 대충 이것저것 해보며 대충 사는 중

0개의 댓글