Hello Kitty Eyes Shut
λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

πŸ’» μ½”ν…Œ/πŸ“Œ JAVA

[ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€/JAVA] λŒ€μΆ© λ§Œλ“  자판

λ°˜μ‘ν˜•

 

 

 

πŸ”— 문제 λ°”λ‘œκ°€κΈ°

 

https://school.programmers.co.kr/learn/courses/30/lessons/160586

 

ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€

SW개발자λ₯Ό μœ„ν•œ 평가, ꡐ윑의 Total Solution을 μ œκ³΅ν•˜λŠ” 개발자 μ„±μž₯을 μœ„ν•œ λ² μ΄μŠ€μΊ ν”„

programmers.co.kr

 


πŸ“Œ 문제 μš”μ•½

 

πŸ“„ 문제 상황

μ˜›λ‚  νœ΄λŒ€ν° μžνŒμ€ ν•œ 킀에 μ—¬λŸ¬ λ¬Έμžκ°€ ν• λ‹Ήλ˜μ–΄ μžˆμ—ˆλ˜ 것과 λΉ„μŠ·ν•œ 상황이닀.

 

예λ₯Ό λ“€μ–΄ 1번 킀에 "A", "B", "C" 순으둜 λ“€μ–΄ μžˆλ‹€λ©΄,

1번 ν‚€λ₯Ό ν•œ 번 λˆ„λ₯΄λ©΄ A, 두 번 λˆ„λ₯΄λ©΄ B, μ„Έ 번 λˆ„λ₯΄λ©΄ C 이런 μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€.

 

그런데 이 문제의 μžνŒμ€ μ˜›λ‚  νœ΄λŒ€ν° 보닀 훨씬 μžμœ λΆ„λ°©(?)ν•˜λ‹€.

  • ν‚€μ˜ κ°œμˆ˜λŠ” 1~100개 사이이고
  • 각 킀에 μ–΄λ–€ λ¬Έμžκ°€ λ“€μ–΄κ°ˆμ§€λŠ” λ¬΄μž‘μœ„λ‹€.
  • κ²Œλ‹€κ°€ 쀑볡도 ν—ˆμš©ν•΄μ„œ, 같은 λ¬Έμžκ°€ μ—¬λŸ¬ 킀에 μžˆκ±°λ‚˜, ν•œ 킀에 μ—¬λŸ¬ 번 μžˆμ„ μˆ˜λ„ μžˆλ‹€.
  • 심지어 μ–΄λ–€ λ¬ΈμžλŠ” μ•„μ˜ˆ 없을 μˆ˜λ„ μžˆλ‹€. (μž…λ ₯ λΆˆκ°€λŠ₯)

 

🎯 λͺ©ν‘œ

우리의 λͺ©ν‘œλŠ” μ£Όμ–΄μ§„ 자판(keyamp)을 μ΄μš©ν•΄μ„œ νƒ€κ²Ÿ λ¬Έμžμ—΄(targets)을 μž‘μ„±ν•  λ•Œ

μ΅œμ†Œ λͺ‡ 번 ν‚€λ₯Ό λˆŒλŸ¬μ•Ό ν•˜λŠ”μ§€λ₯Ό κ΅¬ν•˜λŠ” 것이닀.

(λ§Œμ•½ λ§Œλ“€ 수 μ—†λŠ” λ¬Έμžμ—΄μ΄λΌλ©΄ -1을 λ°˜ν™˜ν•˜λ©΄ λœλ‹€.)

 

 

πŸ”Ž μ˜ˆμ‹œ

keymap = ["ABACD", "BCEFD"]
targets = ["ABCD"]

 

μœ„μ™€ 같은 μ˜ˆμ‹œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, "ABCD"λ₯Ό μž…λ ₯ν•˜λŠ” 상황을 μ•Œμ•„λ³΄μž.

νŽΈμ˜μƒ "ABACD"λ₯Ό 1번 ν‚€λ§΅, "BCEFD"λ₯Ό 2번 킀맡이라고 λΆ€λ₯΄κΈ°λ‘œ ν•˜μž.

  • 1번 킀맡에 Aκ°€ μ‘΄μž¬ν•˜λŠ”λ°, ν‚€λ₯Ό 1번 λˆŒλŸ¬μ„œ Aλ₯Ό λ§Œλ“€ μˆ˜λ„ 있고, 3번 λˆŒλŸ¬μ„œ Aλ₯Ό λ§Œλ“€ μˆ˜λ„ μžˆλ‹€.
  • μ΅œμ†Œ νšŸμˆ˜λŠ” 1번 λˆŒλŸ¬μ„œ Aλ₯Ό λ§Œλ“œλŠ” κ²ƒμ΄λ―€λ‘œ, 1번 킀맡을 1회 λˆ„λ₯Έλ‹€.
  • BλŠ” 1번 ν‚€λ§΅κ³Ό 2번 킀맡에 λͺ¨λ‘ μ‘΄μž¬ν•œλ‹€.
  • κ·ΈλŸ¬λ‚˜ 1번 ν‚€λ§΅μ—μ„œλŠ” 2회 λˆŒλŸ¬μ•Ό ν•˜μ§€λ§Œ, 2번 ν‚€λ§΅μ—μ„œλŠ” 1회만 λˆ„λ₯΄λ©΄ λœλ‹€.
  • λ”°λΌμ„œ 2번 킀맡을 1회 λˆŒλŸ¬μ„œ Bλ₯Ό λ§Œλ“ λ‹€.
  • C도 1번 ν‚€λ§΅κ³Ό 2번 킀맡에 λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ”λ°, 2번 킀맡이 λˆ„λ₯΄λŠ” νšŸμˆ˜κ°€ 더 적닀.
  • λ”°λΌμ„œ 2번 킀맡을 2회 λˆŒλŸ¬μ„œ Cλ₯Ό λ§Œλ“ λ‹€.
  • D도 1번 ν‚€λ§΅κ³Ό 2번 킀맡에 λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ”λ°, λ‘˜ λ‹€ 5회 λˆŒλŸ¬μ•Ό Dλ₯Ό μž…λ ₯ν•  수 μžˆλ‹€.
  • λ”°λΌμ„œ μ•„λ¬΄κ±°λ‚˜ 5회 λˆŒλŸ¬μ„œ Dλ₯Ό λ§Œλ“ λ‹€.

πŸ‘‰πŸ» 즉, "ABCD"λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” ν‚€λ₯Ό μ΅œμ†Œ 1 + 1 + 2 + 5 = 9회 λˆŒλŸ¬μ•Ό ν•œλ‹€.

 


πŸ’‘ 아이디어

🧠 핡심 μ „λž΅

1️⃣ μ „μ²˜λ¦¬λ₯Ό μœ„ν•œ λ§΅ λ§Œλ“€κΈ°

Map<Character, Integer> map = new HashMap<>();
for (String key : keymap) {
  for (int i = 0; i < key.length(); i++) {
    char c = key.charAt(i);
    int press = i + 1; // iλŠ” 0-based, λˆ„λ₯Έ νšŸμˆ˜λŠ” 1λΆ€ν„° 카운트 ν•˜λ―€λ‘œ +1 ν•΄μ£ΌκΈ°
    
    // κΈ°μ‘΄ κ°’κ³Ό μƒˆ 후보 μ€‘μ—μ„œ 더 μž‘μ€ 값을 μ €μž₯ν•˜κΈ°
    map.put(c, Math.min(map.getOrDefault(c, Integer.MAX_VALUE), press));
  }
}

 

같은 λ¬Έμžκ°€ μ—¬λŸ¬ ν‚€ & μ—¬λŸ¬ μœ„μΉ˜μ— μžˆμ–΄λ„ κ°€μž₯ μž‘μ€ λˆ„λ¦„ 횟수만 μ €μž₯ν•˜κΈ° μœ„ν•΄μ„œ μœ„μ™€ 같이 μ„€κ³„ν•˜μ˜€λ‹€.

 

 

2️⃣ νƒ€κ²Ÿλ³„ ν•©μ‚°ν•˜κΈ°

for (int i = 0; i < targets.length; i++) {
  String t = targets[i];
  int sum = 0;       // 이 νƒ€κ²Ÿμ˜ 총 λˆ„λ¦„ 수 합계
  boolean ok = true; // λ§Œλ“€ 수 μžˆλŠ”μ§€ μ—¬λΆ€ (쀑간에 λΆˆκ°€λŠ₯ν•˜λ©΄ false둜 λ°”κΏ”μ£ΌκΈ°)

  for (int j = 0; j < t.length(); j++) { // νƒ€κ²Ÿμ˜ 문자λ₯Ό μ™Όμͺ½λΆ€ν„° ν•˜λ‚˜μ”© μ‚΄νŽ΄λ³΄κΈ°
    char c = t.charAt(j);                // ν˜„μž¬ 문자
    Integer p = map.get(c);              // mapμ—μ„œ μ΅œμ†Œ λˆ„λ¦„ 수 μ°ΎκΈ°
    
    // μ–΄λ–€ 킀에도 μ—†μŒ → λΆˆκ°€λŠ₯
    if (p == null) {
    	ok = false;
        break;
    }
    
    sum += p;
  }
  
  answer[i] = ok ? sum : -1; // λ§Œλ“€ 수 있으면 합계λ₯Ό, μ—†μœΌλ©΄ -1을 μ €μž₯
}
  • sum: ν˜„μž¬ νƒ€κ²Ÿ ν•˜λ‚˜μ— λŒ€ν•œ ν•©κ³„λ‘œ, λ§€ νƒ€κ²Ÿλ§ˆλ‹€ 0으둜 μ΄ˆκΈ°ν™”ν•΄μ€˜μ•Ό ν•œλ‹€.
  • ok: 이 νƒ€κ²Ÿμ„ λ§Œλ“€ 수 μžˆλŠ”κ°€λ₯Ό ν‘œμ‹œν•˜λŠ” ν”Œλž˜κ·Έμ΄λ‹€.
          ν•˜λ‚˜λΌλ„ λ§Œλ“€ 수 μ—†λŠ” λ¬Έμžκ°€ λ‚˜μ˜€λ©΄, λ°”λ‘œ false둜 λ°”κΏ”μ€˜μ•Ό ν•œλ‹€.
  • answer[ ]: i번째 νƒ€κ²Ÿμ˜ κ²°κ³Όλ₯Ό λ„£μ–΄μ€€λ‹€.

 


πŸ‘©πŸ»‍πŸ’» μ΅œμ’… μ½”λ“œ

import java.util.*;

class Solution {
    public int[] solution(String[] keymap, String[] targets) {
        
        int answer[] = new int[targets.length];
        
        Map<Character, Integer> map = new HashMap();
        for(String key : keymap){
            for(int i = 0; i < key.length(); i++){
                char c = key.charAt(i);
                int press = i + 1;
                map.put(c, Math.min(map.getOrDefault(c, Integer.MAX_VALUE), press));
            }
        }
        
        for(int i = 0; i < targets.length; i++){
            String t = targets[i];
            int sum = 0;
            boolean ok = true;
            
            for(int j = 0; j < t.length(); j++){
                char c = t.charAt(j);
                Integer p = map.get(c);
                
                if(p == null){
                    ok = false;
                    break;
                }
                
                sum+= p;
            }
            
            answer[i] = ok ? sum : -1;
        }
    
        return answer;
    }
}

 


πŸ•‘ μ‹œκ°„ λ³΅μž‘λ„

1️⃣ μ „μ²˜λ¦¬ κ³Όμ •

for (String key : keymap) {
  for (int i = 0; i < key.length(); i++) {
    ...
  }
}

 

λͺ¨λ“  λ¬Έμžλ“€μ„ μ •ν™•νžˆ ν•œ λ²ˆμ”© μŠ€μΊ”ν•΄μ•Ό ν•˜λ―€λ‘œ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(N)이닀.

(μ΄λ•Œ, N은 λͺ¨λ“  킀맡에 μžˆλŠ” 각 λ¬Έμžμ—΄ 길이의 합이닀.)

 

 

2️⃣ νƒ€κ²Ÿλ³„ ν•©μ‚°

for (int i = 0; i < targets.length; i++) {
  for (int j = 0; j < t.length(); j++) {
    ...
  }
}

 

각 νƒ€κ²Ÿμ˜ λͺ¨λ“  문자λ₯Ό ν•œ λ²ˆμ”© μ‘°νšŒν•΄μ•Ό ν•˜λ―€λ‘œ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(M)이닀.

(μ΄λ•Œ, M은 νƒ€κ²Ÿμ— μžˆλŠ” 각 λ¬Έμžμ—΄ 길이의 합이닀.)

 

 

πŸ‘‰πŸ» λ”°λΌμ„œ μ΅œμ’… μ‹œκ°„ λ³΅μž‘λ„λŠ” O(N + M)이닀.

λ°˜μ‘ν˜•