본문 바로가기
에러 해결기록

문자열을 요소로 갖는 배열의 가장 긴 글자, 작은 글자 제거하기

by shyun00 2023. 3. 21.

문제 자체는 아주 간단했는데, 처음 풀이 방향을 잡을때 놓친 부분때문에 한참을 헤맨 문제이다.

 

String 타입의 요소를 갖는 배열에서 가장 길이가 짧은 문자열과 가장 길이가 긴 문자열을 제거한 배열을 리턴하는 메서드를 작성하는 문제였다. List를 사용한 방법과  arraycopy를 사용한 방법 두가지로 작성했는데, 동일한 부분을 놓쳐서 정답이 맞기도/틀리기도한 결과를 계속 냈다.

 

<초기 작성 코드>

public static String[] removeExtremes(String[] arr) {
    // --------------------------- 1안 ---------------------------
    if (arr.length == 0) return null;

    int[] lengths = new int[arr.length];
    for (int i = 0; i < arr.length; i++) {
        lengths[i] = arr[i].length();
    }

    int smallIndex = 0;
    int largeIndex = 0;

    for (int i = 0; i < lengths.length - 1; i++) {
        if (lengths[i] <= lengths[i + 1]) largeIndex = i + 1; // 이부분이 문제였다. 값의 앞뒤만 비교하는것이 아니라 기준점이 필요했음.
    }
    for (int i = 0; i < lengths.length - 1; i++) {
        if (lengths[i] >= lengths[i + 1]) smallIndex = i + 1;
    }

    List<String> answer = new ArrayList<String>(Arrays.asList(arr));
    if (largeIndex > smallIndex) {
        answer.remove(largeIndex);
        answer.remove(smallIndex);
    } else {
        answer.remove(smallIndex);
        answer.remove(largeIndex);
    }

    return answer.stream().toArray(String[]::new);

    // --------------------------- 2안 ---------------------------
    if (arr.length == 0) return null;

    int longIndex = 0;
    for (int i = 0; i < arr.length - 1; i++) {
        if (arr[i + 1].length() >= arr[i].length()) longIndex = i + 1; // 위와 동일한 문제.
    }
    String[] result1 = new String[arr.length - 1];
    System.arraycopy(arr, 0, result1, 0, longIndex);
    System.arraycopy(arr, longIndex + 1, result1, longIndex, arr.length - longIndex - 1);

    int shortIndex = 0;
    for (int i = 0; i < result1.length - 1; i++) {
        if (result1[i].length() >= result1[i + 1].length()) shortIndex = i + 1;
    }
    String[] result2 = new String[result1.length - 1];
    System.arraycopy(result1, 0, result2, 0, shortIndex);
    System.arraycopy(result1, shortIndex + 1, result2, shortIndex, result1.length - shortIndex - 1);

    return result2;
}

배열에서 최대 길이, 최소 길이를 가지는 요소를 찾고 해당 인덱스 요소를 삭제하는 문제였는데

길이 비교를 연속된 요소 두개 사이에서 진행한 것이 문제였다.

길이 비교를 위해 해당 시점에서의 최대/최소 길이의 크기를 구하고 그 크기와 각 요소를 비교해야했다.

해당 시점 가장 작은/큰 요소의 크기를 변수로 선언해두고 값을 할당하면서 풀어나가면 정상적으로 답이 출력되었다.

 

<수정 코드>

public static String[] removeExtremes(String[] arr) {
    // ---------------------------- 1안  ----------------------------
    if (arr.length == 0) return null;

    int[] lengths = new int[arr.length];
    for (int i = 0; i < arr.length; i++) {
        lengths[i] = arr[i].length();
    }

    int smallIndex = 0;
    int largeIndex = 0;
    int smallValue = 20;  // 해당시점에서 비교할 값 선언 및 초기화. 반복문 돌면서 변경될 예정
    int largeValue = 0;   // 해당시점에서 비교할 값 선언 및 초기화. 반복문 돌면서 변경될 예정

    for (int i = 0; i < lengths.length; i++) {
        if (largeValue <= lengths[i]) {
            largeIndex = i;
            largeValue = lengths[i];
        }
    }
    for (int i = 0; i < lengths.length; i++) {
        if (smallValue >= lengths[i]) {
            smallIndex = i;
            smallValue = lengths[i];
        }
    }

    List<String> answer = new ArrayList<String>(Arrays.asList(arr));

    if (largeIndex > smallIndex) {
        answer.remove(largeIndex);
        answer.remove(smallIndex);
    } else {
        answer.remove(smallIndex);
        answer.remove(largeIndex);
    }

    return answer.stream().toArray(String[]::new);

    // ---------------------------- 2안  ----------------------------
    if (arr.length == 0) return null;

    int longIndex = 0;
    int longValue = 0;   // 해당시점에서 비교할 값 선언 및 초기화. 반복문 돌면서 변경될 예정
    for (int i = 0; i < arr.length; i++) {
        if (arr[i].length() >= longValue) {
            longIndex = i;
            longValue = arr[i].length();
        }
    }
    String[] result1 = new String[arr.length - 1];
    System.arraycopy(arr, 0, result1, 0, longIndex);
    System.arraycopy(arr, longIndex + 1, result1, longIndex, arr.length - longIndex - 1);

    int smallIndex = 0;
    int smallValue = 20;   // 해당시점에서 비교할 값 선언 및 초기화. 반복문 돌면서 변경될 예정
    for (int i = 0; i < result1.length; i++) {
        if (smallValue >= result1[i].length()) {
            smallIndex = i;
            smallValue = result1[i].length();
        }
    }
    String[] result2 = new String[result1.length - 1];
    System.arraycopy(result1, 0, result2, 0, smallIndex);
    System.arraycopy(result1, smallIndex + 1, result2, smallIndex, result1.length - smallIndex - 1);

    return result2;
}

<추가내용>

최대, 최소 크기를 가지는 요소의 인덱스를 구하고나면 전체 배열을 복사할 필요 없이, 아래 코드와 같이 새로운 배열을 만들어서 간단하게 값을 할당할 수 있다.

String[] result = new String[arr.length - 2];
        int curIndex = 0;
        //배열을 순회하며 결과를 넣어준 후
        for (int i = 0; i < arr.length; i++) {
            if (i != largeIndex && i != smallIndex) {
                result[curIndex] = arr[i];
                curIndex++;
            }
        }
        return result;

여러 문제들을 풀면서 어렵게 느껴졌던 부분 중 하나는 '어떤 변수를 사용해야하는가' 였다.

과연 여기서 새로운 변수를 선언하는게 맞는건지, 아니면 기존에 있던것들로 충분히 해결이 가능한것인지 아직은 판단하기가 어려웠다.

계속 여러가지 코드를 접하다보면 익숙해질거라고 믿고 반복해봐야겠다.