본문 바로가기

알고리즘

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

반응형

출처 : programmers.co.kr/learn/courses/30/lessons/42577

 

코딩테스트 연습 - 전화번호 목록

전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다. 전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다. 구조

programmers.co.kr

문제 설명

전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다.
전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다.

  • 구조대 : 119
  • 박준영 : 97 674 223
  • 지영석 : 11 9552 4421

전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • phone_book의 길이는 1 이상 1,000,000 이하입니다.
  • 각 전화번호의 길이는 1 이상 20 이하입니다.

입출력 예제

phone_book                                                                  return

[119, 97674223, 1195524421] false
[123,456,789] true
[12,123,1235,567,88] false

입출력 예 설명

입출력 예 #1
앞에서 설명한 예와 같습니다.

입출력 예 #2
한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.

입출력 예 #3
첫 번째 전화번호, “12”가 두 번째 전화번호 “123”의 접두사입니다. 따라서 답은 false입니다.

풀이방법 & 사용 메소드

  • 1. Hash를 사용한 풀이 & (  [ containsKey - get ] & [ substring ] )
     * contains 메소드는 포함하면 true , 아니면 false 반환
  • 2. indexOf 메소드를 사용한 풀이 

indexOf 코드

public static boolean solution(String[] phone_book) {
		boolean answer = true;
		
		// 1. 이거 처음에 정렬한번 하거나
		Arrays.sort(phone_book);
		for( int i=0; i<phone_book.length-1; i++) {
			// 2. j를 매번 0 부터 시작하거나
			for( int j=i+1; j<phone_book.length; j++) {
				
				// N^2 의 
				if ( phone_book[j].indexOf(phone_book[i]) == 0 ) {
					return false;
				}
			}
		}		
		return answer ;
	}

코멘트

 - 직관적으로O( N^2 ) 방법으로 하나씩 모두 검사하는 방법
 - indexOf 메소드를 통해 반환되는 값이 0 이라면 가장 앞부분에 매칭되는 prefix 조건을 충족함을 활용

  • 주의사항
    - 주석의 1) 또는 2) 와 같이 해줘야 모든 경우의 수를 탐색 할 수 있다.

Hash 코드 - 탐색시간을 조금 줄일 수 있지 않을까?

import java.util.*;


class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;
       HashMap<String, String> hm = new HashMap<>();
		
		// 중복을 제거해서 해시 맵에 모두 저장
		for( String input : phone_book ) {
			hm.put(input, input);
		}
		
		// 다른 관점이다. : input 데이터를 분해해서 input의 prefix를 다른 string에서 찾는 것이다.
		for ( String target : phone_book) {
			// target을 분해하며 다른 곳에서 prefix 있는지 찾기 
			for( int i=0; i< target.length(); i++) {
				// 이거랑 
				if( hm.containsKey(target.substring(0,i)) ) {
					return false;
				}
				// 이거랑 같은 말이야.
				else if ( hm.get(target.substring(0,i)) != null) {
					return false;
				}
			}
			
		}
        return answer;
    }
}

코멘트 - 해시를 통해 중복해서 저장되어있는 input 값을 중복을 제거해주기.
 - containsKey 메소드를 통해 target을 분해하며 prefix로 하는 다른 접두어가 있는지 조사한다.
 - 해시의 키를 통해 찾으므로 위 방법보다 탐색속도가 조금은 빠르지 않을까 생각한다.

  • 주의사항
    - prefix를 찾는 관점을 바꿔야 이해할 수 있었다.
    - target이라 생각하고 앞에서부터 분해하며, 분해된 target을 prefix로하는 "다른" phone_book을 찾는다.
반응형