[프로그래머스] 전화번호 목록

🚨문제 설명

💡푼 방법

import java.util.*;

class Solution {

    public boolean solution(String[] phone_book) {

        boolean answer = true;
        String[] list = new String[phone_book.length];

        for(int n = 1; n < phone_book.length; n++){

            list[n] = phone_book[n].substring(0, phone_book[0].length());

        }

        for(int i = 1; i < phone_book.length; i++){

            if(phone_book[0].equals(list[i])){
            	answer = false;
                break;
            }
        }
        
        return answer;
    }
}

일단 내가 문제를 잘못 이해해서 정답도 나왔지만 런타임에러와 실패도 나왔다.

효율도 실패하였었다.

 

  • 내가 이해한 문제

인덱스 0번에 있는 수가 접두어로 간 전화번호가 존재할 때 answer를 false로 변경

 

  • 내가 푼 방법

인덱스 0번을 제외하고 나머지 인덱스에 들어있는 전화번호의 앞부분을 인덱스 0번의 길이만큼 잘라서 리스트에 넣어 0번과 비교해주었다.

 

🚧오답 노트

내가 생각했던 것과 일단 문제 이해를 잘못했었다.

 

실제 문제
전화번호가 여러개 존재하면 어느 인덱스에 있던 한 인덱스가 다른 인덱스의 접두어일 경우 false를 반환 아니면 true를 반환

 

런타임 오류가 난 이유

내가 인덱스 0번으로 모든 것을 비교하려해서 만약 다른 인덱스에 있는 글의 길이가 인덱스 0번보다 작은경우 런타임 오류가 발생하는 것이었다. 

그래서 테스트 때는 잘 돌아가고 실제로 제출했을 때는 런타임에러가 발생했던 것이다.

 

효율

문제에 대한 이해 자체를 잘못해서 효율이 안나온 것도 있지만 더욱 효율적이게 코드를 구성할 수 있는 로직은 

1. Sort

2. HashSet

이 두가지 방법을 이용하는 것이다.

 

1. Sort(정렬)

import java.util.*;

class Solution {
    public boolean solution(String[] phone_book) {
        // 1. 정렬: 사전순으로 정렬하면 "12", "123", "1234" 순서가 됩니다.
        Arrays.sort(phone_book);
        
        // 2. 인접한 것끼리만 비교
        for (int i = 0; i < phone_book.length - 1; i++) {
            
            if (phone_book[i+1].startsWith(phone_book[i])) {
                return false;
            }
        }
        return true;
    }
}

 

Arrays.sort(배열): 배열을 오름차순으로 정렬하여 배열에 바로 적용

.startsWith() 메서드: 문자열이 특정 문자열로 시작하는지 판단할 수 있는 도구

*substring으로 잘라 비교하는 것보다 코드의 가독성이 좋다.

 

2. HashSet

import java.util.*;

class Solution {
    public boolean solution(String[] phone_book) {
    	
        //배열을 리스트로 변환해 해시셋에 넣는다.
        HashSet<String> set = new HashSet<>(Arrays.asList(phone_book));
        
        for (String phone : phone_book) {
	        //배열을 돌면서 인덱스에 있는 단어의 길이만큼 확인
			for (int i = 1; i < phone.length(); i++) {
                // 번호를 한 글자씩 잘라가며 접두어인지 확인
                //set에 그 글자가 포함되어있는지 확인 -> 있으면 false
                if (set.contains(phone.substring(0, i))) return false;
            }
        }
        return true;
    }
}

Arrays.asList(배열): 배열을 리스트처럼 사용하고 싶을 때 사용

*데이터 추가(add)/삭제(remove)가 불가능한 읽기전용 리스트가 됨 

그 말은 리스트의 크기가 고정되어있다는 뜻이고 만약 데이터를 자유롭게 추가/삭제하고 싶다면

new ArrayList<>(new ArrayList<>(Arrays.asList(배열)))처럼 새로운 리스트 객체를 생성하는 것이 좋다.