문제 설명

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

  • 구조대 : 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입니다.

주어진 String 배열들 중 접두사인 경우가 존재하는지 찾는 문제이다.

 

1. 코드

풀이방법 1 :

이중 for문을 통한 완전탐색으로 코드를 작성했다.

startsWith로 접두어인지 검사한다.

(※startsWith는 타겟단어로 시작하는 말인지 검사, contain은 타겟단어를 포함하는 문자인지 검사)

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;
        
        for(int i=0;i<phone_book.length;i++){
            for(int j=i+1;j<phone_book.length;j++){
                String now = phone_book[i];
                String now2 = phone_book[j];
                
                if(now.startsWith(now2)||now2.startsWith(now)){
                    return false;
                } 
            }
        }
        
        return answer;
    }
}

 

효율성 테스트 3,4를 통과하지 못했다.

 

풀이방법 2:

Arrays.Sort()로 String 배열을 정렬한다.

배열의 앞뒤 인덱스끼리 비교한다.

 

ex ) [123, 88, 888, 12, 12345]

Sort 정렬 : [12, 123, 12345, 88, 888]

import java.util.Arrays;

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;
        Arrays.sort(phone_book);
        
       for(int i=0; i<phone_book.length -1 ; i++){
           if(phone_book[i+1].startsWith(phone_book[i]))
               return false;
       }
        
       return true;
    }
}

이 코드로 효율성검사까지 통과하였다.

문제 설명

 

당신은 폰켓몬을 잡기 위한 오랜 여행 끝에, 홍 박사님의 연구실에 도착했습니다. 홍 박사님은 당신에게 자신의 연구실에 있는 총 N 마리의 폰켓몬 중에서 N/2마리를 가져가도 좋다고 했습니다.
홍 박사님 연구실의 폰켓몬은 종류에 따라 번호를 붙여 구분합니다. 따라서 같은 종류의 폰켓몬은 같은 번호를 가지고 있습니다. 예를 들어 연구실에 총 4마리의 폰켓몬이 있고, 각 폰켓몬의 종류 번호가 [3번, 1번, 2번, 3번]이라면 이는 3번 폰켓몬 두 마리, 1번 폰켓몬 한 마리, 2번 폰켓몬 한 마리가 있음을 나타냅니다. 이때, 4마리의 폰켓몬 중 2마리를 고르는 방법은 다음과 같이 6가지가 있습니다.

  1. 첫 번째(3번), 두 번째(1번) 폰켓몬을 선택
  2. 첫 번째(3번), 세 번째(2번) 폰켓몬을 선택
  3. 첫 번째(3번), 네 번째(3번) 폰켓몬을 선택
  4. 두 번째(1번), 세 번째(2번) 폰켓몬을 선택
  5. 두 번째(1번), 네 번째(3번) 폰켓몬을 선택
  6. 세 번째(2번), 네 번째(3번) 폰켓몬을 선택

이때, 첫 번째(3번) 폰켓몬과 네 번째(3번) 폰켓몬을 선택하는 방법은 한 종류(3번 폰켓몬 두 마리)의 폰켓몬만 가질 수 있지만, 다른 방법들은 모두 두 종류의 폰켓몬을 가질 수 있습니다. 따라서 위 예시에서 가질 수 있는 폰켓몬 종류 수의 최댓값은 2가 됩니다.
당신은 최대한 다양한 종류의 폰켓몬을 가지길 원하기 때문에, 최대한 많은 종류의 폰켓몬을 포함해서 N/2마리를 선택하려 합니다. N마리 폰켓몬의 종류 번호가 담긴 배열 nums가 매개변수로 주어질 때, N/2마리의 폰켓몬을 선택하는 방법 중, 가장 많은 종류의 폰켓몬을 선택하는 방법을 찾아, 그때의 폰켓몬 종류 번호의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • nums는 폰켓몬의 종류 번호가 담긴 1차원 배열입니다.
  • nums의 길이(N)는 1 이상 10,000 이하의 자연수이며, 항상 짝수로 주어집니다.
  • 폰켓몬의 종류 번호는 1 이상 200,000 이하의 자연수로 나타냅니다.
  • 가장 많은 종류의 폰켓몬을 선택하는 방법이 여러 가지인 경우에도, 선택할 수 있는 폰켓몬 종류 개수의 최댓값 하나만 return 하면 됩니다.

입출력 예

nums result
[3,1,2,3] 2
[3,3,3,2,2,4] 3
[3,3,3,2,2,2] 2
입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

입출력 예 #2
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리, 2번 폰켓몬 한 마리, 4번 폰켓몬 한 마리를 고르면 되며, 따라서 3을 return 합니다.

입출력 예 #3
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리와 2번 폰켓몬 두 마리를 고르거나, 혹은 3번 폰켓몬 두 마리와 2번 폰켓몬 한 마리를 고르면 됩니다. 따라서 최대 고를 수 있는 폰켓몬 종류의 수는 2입니다.

 

주어진 int 배열(nums)의 중복을 제거하는 문제이다.

중복값을 담지 않는 HashSet이용하여 문제를 풀었다.

 

1. 문제해설

배열의 길이의 1/2만큼 폰켓몬을 가져가기 때문에 최대 가져갈수 있는 값을 maxCnt로 선언한다.

HashSet에 배열의 종류를 담고, 담긴 Set의 길이와 maxCnt를 비교하여 리턴한다.

 

2. 코드

import java.util.*;

class Solution {
    public int solution(int[] nums) {
        int answer = 0;
        HashSet<Integer> hs =new HashSet<Integer>();
        int maxCnt = nums.length/2;
        
        //HashSet에 배열값을 담음(중복제거)
        for(int a : nums){
            hs.add(a);
        }
        
        //Set사이즈가 더 클경우 maxCnt를 리턴한다.
        if(hs.size() > maxCnt){
            answer = maxCnt;  
        }else{
            answer = hs.size();
        }
        
        
        return answer;
    }
}

정확성: 100.0&nbsp; 합계: 100.0 / 100.0

 

문제 설명

어떤 숫자에서 k개의 수를 제거했을 때 얻을 수 있는 가장 큰 숫자를 구하려 합니다.

예를 들어, 숫자 1924에서 수 두 개를 제거하면 [19, 12, 14, 92, 94, 24] 를 만들 수 있습니다. 이 중 가장 큰 숫자는 94 입니다.

문자열 형식으로 숫자 number와 제거할 수의 개수 k가 solution 함수의 매개변수로 주어집니다. number에서 k 개의 수를 제거했을 때 만들 수 있는 수 중 가장 큰 숫자를 문자열 형태로 return 하도록 solution 함수를 완성하세요.

제한 조건

  • number는 2자리 이상, 1,000,000자리 이하인 숫자입니다.
  • k는 1 이상 number의 자릿수 미만인 자연수입니다.

입출력 예

numbrt k return
"1924" 2 "94"
"1231234" 3 "3234"
"4177252841" 4 "775841"

 

임의의 수에 대해 k만큼의 갯수의 수를 제거하고 그 중에서 가장 큰 수를 찾는 문제이다.

나는 Greedy(탐욕법) 탐색을 통해 문제를 풀었다.

 

1. 문제 해설

이중 for문을 사용하여

number = "1234123"

k = 3 일때

첫번째 for문의 조건은 반환해야하는 숫자의 자릿수만큼 loop를 돌려준다.

따라서 i는 0부터 number.length()-k  전 까지 돌려준다. ( 예시로 치면 0~3까지 )

이중 for문의 안쪽 for문은 기준 인덱스부터 뒤에 붙여야하는 자릿수의 전 인덱스까지 loop를 돌려준다.

따라서 j는 index부터 i+k까지 돌려준다. (예시로 치면 0~3, 4~4...)   

또한 String을 이어붙이는 것이 아니라 Stringbuilder를 사용하면 좀 더 효율적으로 String을 이어붙여 리턴 할 수 있다.

 

2. 코드

class Solution {
    public String solution(String number, int k) {
        int index=0;
        int max=0;
        //StringBuilder를 사용하면 효율성 증가
        StringBuilder sb = new StringBuilder();
        
        for(int i=0; i<number.length()-k; i++){
            max =0;
            for(int j=index; j<=i+k; j++){
                if(max < number.charAt(j) -'0'){
                    max = number.charAt(j) - '0';
                    index = j+1; //다음 인덱스부터 검사하도록
                }
            }
            sb.append(max);
        }
        
        return sb.toString();
    }
}

정확성: 100.0 합계: 100.0 / 100.0

number.charAt(j)를 int값과 비교를 하기위해서는

number.charAt(j)값이 아스키코드값을 반환하기때문에 '0'(아스키코드값 48)을 빼줌으로 써

int값과 비교가 가능해진다.

문제 설명

피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다.

예를들어

  • F(2) = F(0) + F(1) = 0 + 1 = 1
  • F(3) = F(1) + F(2) = 1 + 1 = 2
  • F(4) = F(2) + F(3) = 1 + 2 = 3
  • F(5) = F(3) + F(4) = 2 + 3 = 5

와 같이 이어집니다.

2 이상의 n이 입력되었을 때, n번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수, solution을 완성해 주세요.

제한 사항

  • n은 2 이상 100,000 이하인 자연수입니다.

 

임의의 값이 주어지면 피보나치 수를 구해 그 값을 1234567로 나누는 문제이다.

나는 재귀적 함수 호출 방법으로 첫번째 답변을 작성했다.

 

1. 재귀적 방법

class Solution {
    public int solution(int n) {
        int answer = 0;
        int a = fibo(n);
        answer = a % 1234567;     
        return answer;
    }
    
    //재귀함수
    public int fibo(int n){
        if(n<=1){
            return n;
        }else{
            return fibo(n-1)+fibo(n-2);
        }
    }
}

 

위와 같은 방법으로 답변을 제출하니 몇가지 케이스에 대해 시간초과가 발생하였다.

 

정확성: 42.9&nbsp; 합계: 42.9 / 100.0

 

2. 반복문 사용

class Solution {
    public int solution(int n) {
        int answer = 0;
        int fn1 = 0;
        int fn2 = 1;
        
        for(int i=2;i<=n;i++){
            answer = (fn1 + fn2) % 1234567;
            fn1 = fn2;
            fn2 = answer;
        }      
        return answer;
    }
}

 

정확성: 100.0&nbsp; 합계: 100.0 / 100.0

 

위와 같이 반복문을 사용하니 효율성면에서 통과되었다.

재귀적방법이 직관적이나, 연산이 많이 필요하여 효율성이 떨어진다.

따라서 이 피보나치 수의 경우에는 반복문으로 통한 풀이가 효율성 측면에서 더 낫다.

+ Recent posts