티스토리 뷰

1️⃣ 최소직사각형

 

문제 설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호  가로 길이  세로 길이
1 60 50
2 30 70
3 60 30
4 80 40

 

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

 

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • sizes의 길이는 1 이상 10,000 이하입니다.
    • sizes의 원소는 [w, h] 형식입니다.
    • w는 명함의 가로 길이를 나타냅니다.
    • h는 명함의 세로 길이를 나타냅니다.
    • w와 h는 1 이상 1,000 이하인 자연수입니다.

 

입출력 예

sizes result
[[60, 50], [30, 70], [60, 30], [80, 40]] 4000
[[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]] 120
[[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]] 133

 

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

 

입출력 예 #2
명함들을 적절히 회전시켜 겹쳤을 때, 3번째 명함(가로: 8, 세로: 15)이 다른 모든 명함보다 크기가 큽니다. 따라서 지갑의 크기는 3번째 명함의 크기와 같으며, 120(=8 x 15)을 return 합니다.

 

입출력 예 #3
명함들을 적절히 회전시켜 겹쳤을 때, 모든 명함을 포함하는 가장 작은 지갑의 크기는 133(=19 x 7)입니다.

 

 

💻 나의 풀이

class Solution {
    public int solution(int[][] sizes) {
        int max_w = 0;    // 가로의 최대 길이
        int max_h = 0;    // 세로의 최대 길이
        
        for (int i = 0; i < sizes.length; i++) {
            max_w = Math.max(max_w, Math.max(sizes[i][0], sizes[i][1]));
            max_h = Math.max(max_h, Math.min(sizes[i][0], sizes[i][1]));
        }
        
        return max_w * max_h;
    }
}

 

문제가 이해가 안 가서 몇 번을 다시 읽어봤습니다.

하나하나 다 비교하자니 말도 안되는 것 같아 어떤 규칙이 있을지 고민해봤습니다.

배열의 원소 중 큰 값을 가로 길이, 작은 값을 세로 길이로 설정해서 가로 길이와 세로 길이 중 가장 큰 값을 각각 구하여 곱한 값을 반환하면 된다고 생각했어요. 

그리고 Math.max() 메소드를 쉽게 떠올려서 해결했습니다!

 

Math.max(a, b) : 두 개의 값 ab 중에서 더 큰 값을 반환하는 Java의 Math 클래스의 정적 메소드

 

 

 

🔍 다른 사람의 풀이

class Solution {
    public int solution(int[][] sizes) {
        
        int max_row = 0; //가로의 최대 길이
        int max_col = 0; // 세로의 최대 길이
        
        for(int i=0;i<sizes.length;i++){ //긴 부분을 가로로 재배치
            if(sizes[i][0]<sizes[i][1]){
                int tmp = sizes[i][0];
                sizes[i][0] = sizes[i][1];
                sizes[i][1] = tmp;
            }
            if(max_row<sizes[i][0]) max_row = sizes[i][0]; // 최대값
            if(max_col<sizes[i][1]) max_col = sizes[i][1]; // 최대값
        }
        
        return max_col*max_row; //결과
    
    
}}

 

주어진 가로, 세로 길이 모두 포함하여 제일 긴 길이는 가로, 세로 어디에 놓아도 제일 긴 쪽이라는 것이 핵심.

그래서 가장 긴 길이를 가진 명함을 찾아 고정시켜보면, 우리가 구하는 것은 명함 넓이의 최소값이기 때문에 각 명함마다 가로, 세로 중 긴 부분을 제일 긴 길이를 가진 명함에 대치시킨다면 -> 나머지 짧은 부분들은 각 명함에서 짧은 부분이기 때문에 -> 이 짧은 부분들의 최대값을 구한다면 -> 제일 긴 길이와 곱하면 최소값이 나오게 됩니다.

 

  1. 가장 긴 길이를 가진 명함을 구하고 고정시킨 후
  2. 나머지 명함들을 긴 부분은 가장 긴 길이를 가진 명함에 대치시키고 (회전)
  3. 각 명함들 중 짧은 부분들을 모아 최대값을 산출

    그런데 생각해보니 가로, 세로라는 기준점이 있었기 때문에 각 명함들은 긴 부분은 가로로 짧은 부분은 세로로 만든다면 1,2는 한꺼번에 해결됩니다.

따라서 이 방법을 사용하여 구현하고 최소값을 구하면 됩니다.

 

 

class Solution {
    public int solution(int[][] sizes) {
        int max_w  = 0;
        int max_h = 0;
        
        for(int i=0; i<sizes.length; i++){
            int w = Math.max(sizes[i][0], sizes[i][1]);     //긴 부분
            int h = Math.min(sizes[i][0], sizes[i][1]);     //짧은 부분
            
            max_w = Math.max(max_w, w);
            max_h = Math.max(max_h, h);
        }
        return max_w*max_h;
    }
}

 

마찬가지로 원리는 비슷합니다.

가로와 세로로 구분짓지 않고 두 길이 중 긴 부분과 짧은 부분으로 구분합니다. ( 가로: 긴 부분, 세로: 짧은 부분 )

가로, 세로에서 각각 Max값을 산출합니다.

 

 


 

2️⃣ 시저 암호

 

문제 설명

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한사항

  • 공백은 아무리 밀어도 공백입니다.
  • s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
  • s의 길이는 8000이하입니다.
  • n은 1 이상, 25이하인 자연수입니다.

 

입출력 예

s n answer
"AB" 1 "BC"
"z" 1 "a"
"a B z" 4 "e F d"

 

 

💻 나의 풀이 - 첫번째 코드

class Solution {
    public String solution(String s, int n) {
        String answer = "";
        
        for(int i=0; i<s.length(); i++) {
        	char ch = s.charAt(i);
            
            if(ch == ' ') {    // 공백이라면
            	answer += ch;
            }
            
            if(ch >= 'a' && ch<='z') {   // 소문자라면
            	if(ch+n > 'z') {   
                	answer += (char)(ch - 26 + n);   // z를 넘어가면 -26을 해준다.
                } else {
                	answer += (char)(ch + n);    // z를 넘어가지 않으면 그냥 n만큼 더해줌
                }
                
            } else if(ch >= 'A' && ch <='Z') {   // 대문자라면
                if(ch+n > 'Z'){
                    answer += (char)(ch - 26 + n);   // Z를 넘어가면 -26을 해준다.
                }else{
                    answer += (char)(ch + n);   // Z를 넘어가지 않으면 그냥 n만큼 더해줌
                }
            }
        }
            
        return answer;
    }
}

 

먼저 문자열을 문자 단위로 보고 조작해야 하므로 toCharArray() 메소드를 떠올렸고, n만큼 움직여서 글자를 바꿔주어야 하는데 어떻게 움직일까에 대한 고민을 해보았습니다.🙄

 

첫 번째 코드는 통과는 됐으나...길고, 조건문 파티라 뭔가 보기가 싫더라구요.

다시 생각해봤더니 

바로, 아스키코드로 해결할 수 있었습니다.

 

먼저 아스키코드에 대해 정리해봅시다.

💡 ASCII 코드

컴퓨터에서 문자를 숫자로 나타내기 위한 표준 인코딩 체계입니다. 아스키 코드는 7비트(0부터 127까지)로 이루어져 있으며, 총 128개의 다양한 문자를 나타냅니다.

숫자: 0부터 9까지의 숫자는 48부터 57까지의 아스키 코드에 해당합니다.
대문자 알파벳: A부터 Z까지의 대문자는 65부터 90까지의 아스키 코드에 해당합니다.
소문자 알파벳: a부터 z까지의 소문자는 97부터 122까지의 아스키 코드에 해당합니다.

 

 

 

💻 나의 풀이 - 두 번째 코드

class Solution {
    public String solution(String s, int n) {
        String answer = "";
        
        char[] ch = s.toCharArray();
        
        for(char c : ch) {
            if(c == 32) answer += " ";   // 아스키코드 32는 공백
            else {
                if(c <= 90) {
                    c += n;
                    if(c > 90) c -= 26;   // 90(Z)를 넘어간다면 -26
                } else {
                    c += n;
                    if(c > 122) c -= 26;   // 122(z)를 넘어간다면 -26
                }
                answer += c;
            }
        }
        
        return answer;
    }
}

 

 

 

 

🔍 다른 사람의 풀이

class Caesar {
    String caesar(String s, int n) {
        String result = "";
    	n = n % 26;   // 나머지를 사용해서 26을 넘어갈 떄도 답 얻기 가능
        
        for (int i = 0; i < s.length(); i++) {   // 문자열 s를 문자 단위로 순회
          char ch = s.charAt(i);   // 현재 순회 중인 위치의 문자
          
          // ch - 'a': 주어진 소문자 ch가 'a'로부터 얼마나 떨어져 있는지
          // (ch - 'a' + n): 시저 시프트 횟수 n을 더해준다 -> 알파벳이 몇 칸씩 이동할지
          // ((ch - 'a' + n) % 26): 26으로 나눈 나머지를 계산- > 알파벳을 한 바퀴 돌게끔
          // ((ch - 'a' + n) % 26 + 'a'): 나머지에 'a'를 더해 'a'부터 시작하는 알파벳으로 다시 매핑
          
          if (Character.isLowerCase(ch)) {   // 소문자인 경우
            ch = (char) ((ch - 'a' + n) % 26 + 'a');   
          } else if (Character.isUpperCase(ch)) {   // 대문자인 경우
            ch = (char) ((ch - 'A' + n) % 26 + 'A');
          }
          
      result += ch;
    }
        return result;
    }
}

 

포인트1 : 26으로 나눈 나머지를 이용해 알파벳의 처음으로 되돌아 가게 됩니다.

  1. ch - 'a' : 주어진 소문자 ch가 'a'로부터 얼마나 떨어져 있는지를 계산합니다. 이 값은 0부터 25까지의 범위를 갖습니다.
  2. (ch - 'a' + n) : 시저 시프트 횟수 n을 더해줍니다. 이로써 알파벳이 몇 칸씩 이동할지를 나타냅니다.
  3. ((ch - 'a' + n) % 26) : 26으로 나눈 나머지를 계산합니다. 이렇게 함으로써 알파벳을 한 바퀴 돌게 됩니다. 예를 들어, 'z'에서 1만큼 더 이동하면 'a'가 되도록 만들어주는 역할을 합니다.
  4. ((ch - 'a' + n) % 26 + 'a') : 나머지에 'a'를 더해줍니다. 이로써 원래의 'a'부터 시작하는 알파벳으로 다시 매핑됩니다.

포인트2 : 굳이 아스키코드를 안써도 Character.isLowerCase(ch)와 Character.isUpperCase(ch) 으로 소문자인지 대문자인지 판별할 수 있습니다!

 


 

3️⃣ 숫자 문자열과 영단어

 

문제 설명

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

  • 1478 → "one4seveneight"
  • 234567 → "23four5six7"
  • 10203 → "1zerotwozero3"

이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.

제한사항

  • 1 ≤ s의 길이 ≤ 50
  • s가 "zero" 또는 "0"으로 시작하는 경우는 주어지지 않습니다.
  • return 값이 1 이상 2,000,000,000 이하의 정수가 되는 올바른 입력만 s로 주어집니다.

 

입출력 예

입출력 예 #1

  • 문제 예시와 같습니다.

입출력 예 #2

  • 문제 예시와 같습니다.

입출력 예 #3

  • "three"는 3, "six"는 6, "seven"은 7에 대응되기 때문에 정답은 입출력 예 #2와 같은 234567이 됩니다.
  • 입출력 예 #2와 #3과 같이 같은 정답을 가리키는 문자열이 여러 가지가 나올 수 있습니다.

입출력 예 #4

  • s에는 영단어로 바뀐 부분이 없습니다.

 

 

💻 나의 풀이

import java.util.HashMap;
import java.util.Map;

class Solution {
    public int solution(String s) {
        
        Map<String, Integer> map = new HashMap<>();
        map.put("zero", 0);
        map.put("one", 1);
        map.put("two", 2);
        map.put("three", 3);
        map.put("four", 4);
        map.put("five", 5);
        map.put("six", 6);
        map.put("seven", 7);
        map.put("eight", 8);
        map.put("nine", 9);
        
        String answer = "";   // 최종 반환값 변수
        String tmp = "";   // 현재까지 처리 중인 알파벳 문자열을 저장할 변수
        
        for(int i=0; i<s.length(); i++) {   // 문자열 s를 한 글자씩 순회
            char c = s.charAt(i);   // 현재 순회 중인 문자를 c에 가져오기
            if(Character.isDigit(c)) {   // c가 숫자라면
                answer += c;   // answer에 그대로 추가
                tmp = "";   // tmp를 초기화
            } else {
                tmp += c;   // c가 숫자가 아니고 알파벳이라면
                if(map.get(tmp) != null) {   // 만약 tmp가 map의 key로 존재한다면
                    answer += map.get(tmp);   // key값에 맞는 value를 꺼내서 answer에 추가
                    tmp = "";   // tmp를 초기화
                }
            }     
        }
        
        return Integer.parseInt(answer);   // 문자열을 정수로 변환해서 반환
    }
}

 

HashMap을 사용해 key-value 값을 전부 넣어줬습니다.

그리고 문자열 s의 문자들을 하나씩 보면서

숫자라면 -> 결과값에 바로 추가

숫자가 아니라면 -> key에 매칭되는 value값 숫자를 결과값에 추가하기

이런 로직으로 풀어봤습니다.

Character.isDigit(char ch)는 주어진 문자 ch가 10진수(0부터 9까지) 숫자인지 여부를 판단하는 메소드입니다.

 

 

 

🔍 다른 사람의 풀이

class Solution {
    public int solution(String s) {
        String[] strArr = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
        for(int i = 0; i < strArr.length; i++) {
            s = s.replaceAll(strArr[i], Integer.toString(i));
        }
        return Integer.parseInt(s);
    }
}

 

문자열 배열 하나만 만들고 replaceAll() 메소드를 통해 간단히 구현할 수 있네요!

각 영어 단어를 숫자로 변환하기 위해 문자열 배열 strArr을 사용하고, replaceAll 메소드를 통해 각 영어 단어를 해당하는 숫자로 치환한 후, 최종적으로 정수로 변환하여 반환하는 방식입니다.

  1. String[] strArr : 영어 단어를 숫자로 변환하기 위한 문자열 배열입니다.
  2. for(int i = 0; i < strArr.length; i++) : strArr 배열을 순회하면서 각 영어 단어를 숫자로 치환합니다.
  3. s = s.replaceAll(strArr[i], Integer.toString(i)); : 문자열 s에서 현재 순회 중인 영어 단어를 해당하는 숫자로 모두 치환합니다.
  4. return Integer.parseInt(s); : 최종적으로 변환된 문자열 s를 정수로 변환하여 반환합니다.

 


 

 

4️⃣ 가장 가까운 같은 글자

 

문제 설명

문자열 s가 주어졌을 때, s의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알고 싶습니다.
예를 들어, s="banana"라고 할 때,  각 글자들을 왼쪽부터 오른쪽으로 읽어 나가면서 다음과 같이 진행할 수 있습니다.

  • b는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
  • a는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
  • n은 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
  • a는 자신보다 두 칸 앞에 a가 있습니다. 이는 2로 표현합니다.
  • n도 자신보다 두 칸 앞에 n이 있습니다. 이는 2로 표현합니다.
  • a는 자신보다 두 칸, 네 칸 앞에 a가 있습니다. 이 중 가까운 것은 두 칸 앞이고, 이는 2로 표현합니다.

따라서 최종 결과물은 [-1, -1, -1, 2, 2, 2]가 됩니다.

문자열 s이 주어질 때, 위와 같이 정의된 연산을 수행하는 함수 solution을 완성해주세요.

제한사항

  • 1 ≤ s의 길이 ≤ 10,000
    • s은 영어 소문자로만 이루어져 있습니다.

입출력 예

s result
"banana" [-1, -1, -1, 2, 2, 2]
"foobar" [-1, -1, 1, -1, -1, -1]

 

 

💻 나의 풀이

import java.util.*;

class Solution {
    public int[] solution(String s) {
        String[] arr = s.split("");   // s를 한 글자씩 잘라서 배열 arr에 담는다.
        int[] answer = new int[arr.length];   // answer 배열의 길이는 arr 길이로 설정
        answer[0] = -1;   // 초기값을 -1로 지정 (첫 번째 글자는 처음 나온거니까 무조건 -1)

        for (int i = 1; i <arr.length; i++) {   // 두 번째 글자부터 시작
            answer[i] = -1;   // 아직 동일한 글자가 없을 경우 -1
            for (int j = i - 1; j >= 0; j--) {   // 현재 위치 이전의 문자에 대한 거리만 계산하기 위해 i-1부터 시작
                if (arr[j].equals(arr[i])) {  // 만약 글자가 동일하다면
                    answer[i] = i - j;   // 현재 값에서 가장 가까운 거리
                    break;
                }
            }
        }

        return answer;
    }
}

 

중복된 글자를 어떻게 알아낼까 고민했고 map과 이중for문이 떠올랐습니다.

결국 이중 for문으로 풀어봤습니다.

 

포인트는

1. answer[0] = -1 : 첫 번째 글자는 처음 나온거니까 무조건 -1이 되니 -1로 초기화 시켜줍니다.

2. for (int i = 1;   i <arr.length;   i++) : 첫 번째 for문은 두 번째 글자부터 시작합니다.

3. for (int j = i - 1;   j >= 0;   j--) : ji - 1부터 시작하는 이유는 현재 위치 이전의 문자들에 대해서만 거리를 계산하려는 것입니다. 만약 j가 0부터 시작하게 된다면, 현재 위치의 문자까지 거리를 계산하게 되므로 현재 위치 이전의 문자에 대한 거리만을 계산하려면 i - 1부터 시작해야 합니다. 즉, 현재 위치 i에서부터 시작하여 0까지 거꾸로 이전 위치를 확인하는 루프를 나타냅니다.

4. answer[i] = i - j : 현재 값에서 가장 가까운 거리를 구합니다.

 

 

 

🔍 다른 사람의 풀이

import java.util.*;

class Solution {
    public int[] solution(String s) {
        int[] answer = new int[s.length()];
        HashMap<Character,Integer> map = new HashMap<>();
        for(int i=0; i<s.length();i++){
            char ch = s.charAt(i);
            answer[i] = i-map.getOrDefault(ch,i+1);
            map.put(ch,i);
        }
        return answer;
    }
}

 

  1. HashMap<Character,Integer> map = new HashMap<>(); : 문자와 해당 문자의 마지막 등장 위치를 저장하기 위한 HashMap을 생성합니다.
  2. for(int i=0; i<s.length(); i++) : 문자열 s를 처음부터 끝까지 순회합니다.
  3. char ch = s.charAt(i); : 현재 위치의 문자를 가져옵니다.
  4. answer[i] = i - map.getOrDefault(ch, i + 1); : 현재 위치에서 가장 가까운 동일한 문자까지의 거리를 계산하여 answer 배열에 저장합니다. map.getOrDefault(ch, i + 1)는 현재 문자 ch가 이전에 등장한 적이 없을 경우 기본값으로 현재 위치 i + 1을 사용합니다.
    ✔ i+1 인 이유?
    문자열에서의 인덱스는 0부터 시작하므로, 만약 i + 1을 사용하지 않고 i로만 설정한다면, 처음 등장한 문자의 거리가 0으로 나타나게 됩니다. 그러나 실제로는 처음 등장한 문자까지의 거리는 1이어야 합니다.
  5. map.put(ch, i); : 현재 문자의 위치를 map에 저장합니다.
  6. 최종적으로 계산된 거리가 저장된 answer 배열이 반환됩니다.

이중 for문을  쓰는 것보다 훨씬 효율적입니다!

앞으론 고민하지말고 map을 쓰는 걸로..^^

 


 

 

5️⃣ 푸드 파이트 대회

 

문제 설명

수웅이는 매달 주어진 음식을 빨리 먹는 푸드 파이트 대회를 개최합니다. 이 대회에서 선수들은 1대 1로 대결하며, 매 대결마다 음식의 종류와 양이 바뀝니다. 대결은 준비된 음식들을 일렬로 배치한 뒤, 한 선수는 제일 왼쪽에 있는 음식부터 오른쪽으로, 다른 선수는 제일 오른쪽에 있는 음식부터 왼쪽으로 순서대로 먹는 방식으로 진행됩니다. 중앙에는 물을 배치하고, 물을 먼저 먹는 선수가 승리하게 됩니다.

이때, 대회의 공정성을 위해 두 선수가 먹는 음식의 종류와 양이 같아야 하며, 음식을 먹는 순서도 같아야 합니다. 또한, 이번 대회부터는 칼로리가 낮은 음식을 먼저 먹을 수 있게 배치하여 선수들이 음식을 더 잘 먹을 수 있게 하려고 합니다. 이번 대회를 위해 수웅이는 음식을 주문했는데, 대회의 조건을 고려하지 않고 음식을 주문하여 몇 개의 음식은 대회에 사용하지 못하게 되었습니다.

예를 들어, 3가지의 음식이 준비되어 있으며, 칼로리가 적은 순서대로 1번 음식을 3개, 2번 음식을 4개, 3번 음식을 6개 준비했으며, 물을 편의상 0번 음식이라고 칭한다면, 두 선수는 1번 음식 1개, 2번 음식 2개, 3번 음식 3개씩을 먹게 되므로 음식의 배치는 "1223330333221"이 됩니다. 따라서 1번 음식 1개는 대회에 사용하지 못합니다.

수웅이가 준비한 음식의 양을 칼로리가 적은 순서대로 나타내는 정수 배열 food가 주어졌을 때, 대회를 위한 음식의 배치를 나타내는 문자열을 return 하는 solution 함수를 완성해주세요.

제한사항

  • 2 ≤ food의 길이 ≤ 9
  • 1 ≤ food의 각 원소 ≤ 1,000
  • food에는 칼로리가 적은 순서대로 음식의 양이 담겨 있습니다.
  • food[i]는 i번 음식의 수입니다.
  • food[0]은 수웅이가 준비한 물의 양이며, 항상 1입니다.
  • 정답의 길이가 3 이상인 경우만 입력으로 주어집니다.

 

입출력 예

food result
[1, 3, 4, 6] "1223330333221"
[1, 7, 1, 2]  "111303111"

 

 

💻 나의 풀이

class Solution {
    public String solution(int[] food) {
        StringBuilder sb = new StringBuilder();   // 음식 배치를 담을 sb
        
        for(int i=1; i<food.length; i++) {
            int arr = food[i]/2;   // 첫 선수의 음식 배치
            sb.append(String.valueOf(i).repeat(arr));
        }
        
        String answer = sb + "0";    // 0 더하고
        answer += sb.reverse();     // 순서 뒤집은 = 두번째 선수가 먹을 음식 배치 더하기
        
        return answer;
    }
}

 

결국 두 사람이 두 당 1개 이상 씩 먹어야하니까 -> 주어진 숫자를 2로 나눈 몫이 음식의 배치가 된다는 것을 캐치해냈습니다. 그리고 그렇게 구한 배열의 순서를 뒤집어서 0(물) 다음에 붙여주면 될 것 같습니다.

 

이 생각으로 로직을 작성한 게 위와 같습니다.

StringBuilder를 사용해 효율적으로 코드를 작성했습니다.

append() : 추가

String.valueOf() : i 값을 문자열로 반환하고

repeat() : 그 문자열을 arr 만큼 반복한 결과

reverse() : 문자열을 역순으로 변경

 

 

 

🔍 다른 사람의 풀이

class Solution {
    public String solution(int[] food) {
        String answer = "0";

        for (int i = food.length - 1; i > 0; i--) {
            for (int j = 0; j < food[i] / 2; j++) {
                answer = i + answer + i; 
            }
        }

        return answer;
    }
}

 

이야..이렇게 깔끔하게...^^

repeat 대신 직접 반복해서 붙이는 방식입니다.

하지만 String 객체가 많이 생성되서 StringBuilder를 사용하는 게 더 빠르고 성능이 좋긴 할 것 같습니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함