• 카테고리

    질문 & 답변
  • 세부 분야

    알고리즘 · 자료구조

  • 해결 여부

    미해결

뒤집은 소수 / 런타임 에러 + 궁금증

23.02.11 02:06 작성 23.02.11 02:27 수정 조회수 502

0

안녕하세요 강사님

예시 문제는 합격하는데 다른 4개의 테스트 케이스는 통과하지 못하고 있습니다.

문제는 런타임에러가 뜨는데 왜 뜨는지 정확한 이유를 아무리 보아도 모르겠습니다...

많이 더러운 코드지만 무엇이 문제인지 확인 한번 부탁 드리겠습니다...

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {

    public String solution(String str) {
        String answer = "";
        String[] arr = new StringBuilder(str).reverse().toString().split(" ");
        List<Integer> list = new ArrayList<>();

        for (String s : arr) {
            int target = Integer.parseInt(s);

            if (target != 2 && target % 2 == 0) continue;

            if (target == 1) continue;
            boolean check = true;

            for (int j = 3; j <= Math.sqrt(target); j+=2) {
                if (target % j == 0) {
                    check = false;
                    break;
                }
            }
            if (check) list.add(target);
        }

        for (int i =list.size()-1; i >= 0; i--) {
            answer += list.get(i) + " ";
        }
        return answer;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int input1 = in.nextInt();
        in.nextLine();
        String str = in.nextLine();
        Main main = new Main();
        System.out.println(main.solution(str));
        return;
    }
}

알아낸점

스크린샷 2023-02-11 오전 2.09.23.png저와 비슷한 사례를 겪는 분들을 질문창에서 발견하고 강사님이 적어두신 2번 케이스의 문제를 복사해서 적어보았는데 통과하였습니다.

저는 split() 메서드를 이용해서 입력받은 문자열을 배열로 변경하는데 이때 문자열 맨 뒤에 공백이 존재하게 되면 런타임 에러가 발생 하는것을 확인했습니다. 아무래도 그부분 때문인것 같은데 맞다면 확인 한번 부탁드리겠습니다.

변경

코드를 수정하였습니다.

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {

    public String solution(String[] arr) {
        String answer = "";

        for (int i = 0; i < arr.length; i++) {
            String s = new StringBuilder(arr[i]).reverse().toString();

            int target = Integer.parseInt(s);

            if (target != 2 && target % 2 == 0) continue;

            if (target == 1) continue;

            boolean check = isPrime(target);

            if (check) answer += target + " ";
        }

        return answer;
    }

    private boolean isPrime(int target) {
        for (int j = 3; j <= Math.sqrt(target); j+=2) {
            if (target % j == 0) {
                return false;
            }
        }
        return true;
    }
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int input1 = in.nextInt();
        String[] arr = new String[input1];
        for (int i = 0; i < input1; i++) {
            arr[i] = in.next();
        }
        Main main = new Main();
        System.out.println(main.solution(arr));
        return;
    }
}

이렇게 하니 해결되었습니다.

궁금증

혹시 실제 코딩테스트 볼때도 split을 사용할때 요청값끝부분에 있는 공백의 존재 가능성도 염두해두고 사용을 해야하나요? 아니면 단순 이 사이트의 실수였을까요?

 

 

답변 2

·

답변을 작성해보세요.

0

ksk님의 프로필

ksk

2023.02.12

저 또한 수강생이지만, 의견을 드리자면,

코테에서 입력값의 맨 뒷값에 공백을 포함시키지 않는다는 제약을 반드시 가하는지는 모르겠습니다.

만일 이것이 고민될 경우, trim을 통해 맨앞 맨 뒤의 공백을 제거해서 사용할 수도 있을것 같습니다.

 

또한 split은 지정한 구분자를 사용해서 분리를 시키기에, 공백이 포함될 경우 생각했던 길이와 다른 길이의 배열이 생성될 수 있습니다.

예를 들어,

"1(공백)2(공백)3(공백)4(공백)5(공백)" 를 공백을 기준으로 split한다면,

["1", "2", "3", "4", "5"] 로 길이 5개의 배열이 만들어지나,

 

"(공백)1(공백)2(공백)3(공백)4(공백)5" 를 공백을 기준으로 split한다면,

["", "1", "2", "3", "4", "5"] 로 길이 6개를 가지는 배열이 생성됨을 확인하였습니다.

 

발생하신 문제 또한,

처음 입력한 값의 맨 뒤에 공백이 포함될 경우,

reverse 과정에서, 맨 뒤의 공백은 맨 앞의 공백을 가지는 문자열로 변환되고,

이 맨앞의 공백에 의해, 생각했던 길이의 배열보다 1이 더 큰 배열이 생성되기 때문이 아닐까 합니다. (0번째 인덱스 값 : "")

"" 와 같은 빈 문자열은, Integer.parse() 실행시 런타임 에러가 발생합니다. 해당 빈 문자열은 정수형 변환할 수 없기 때문입니다.

아마도 발생하신 예외 또한, NumberFormatException이 발생하시지 않았나 싶습니다.

tldhs05222님의 프로필

tldhs05222

질문자

2023.02.12

NumberFormatException 맞습니다! 좋은 답변 감사합니다. split을 조심히 사용해야 겠습니다.

0

저도 코딩테스트를 본적은 없지만 아마 마지막 입력값에 공백이 있을 것 같지는 않네요

코드에서 오류가 발생한 부분은 테스트 케이스의 입력값을 복사하여 맨뒤에 공백을 제거하여 입력하면 정상적으로 출력되는 것으로 보아 추측하신대로 입력값 끝에 공백 때문에 reverse().split(" ")에서 문제가 생긴 것 같네요

 

 String[] inArr = bf.readLine().split(" ");
 입력을 for문으로 하나하나 읽지 않고 라인으로 받은 다음 split을 으로  
 한번에 입력 할 수 있습니다.
tldhs05222님의 프로필

tldhs05222

질문자

2023.02.11

좋은 의견 감사합니다.