-
[Java] - 푸드 파이트 대회 (134240) (String / StringBuffer & StringBuilder)알고리즘/프로그래머스 2024. 2. 29. 11:23
📚 문제 - 134240
수웅이는 매달 주어진 음식을 빨리 먹는 푸드 파이트 대회를 개최합니다. 이 대회에서 선수들은 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" - 입출력 예 #1
문제 예시와 같습니다. - 입출력 예 #2
두 선수는 1번 음식 3개, 3번 음식 1개를 먹게 되므로 음식의 배치는 "111303111"입니다.
⌨️ 작성한 코드
class Solution { public String solution(int[] food) { StringBuilder answerBuilder = new StringBuilder("0"); // 배열을 끝에서부터 순회 for (int i = food.length - 1; i >= 1; i--) { // 음식의 양이 2로 나눌 수 있는 경우 if (food[i] / 2 > 0) { // 음식의 종류를 문자열로 변환 String eatable = String.valueOf(i); // 음식의 양을 반으로 나눈 만큼 반복하여 StringBuilder에 추가 for (int j = 0; j < food[i] / 2; j++) { // 결과 문자열의 앞에 음식의 종류를 추가하고, 뒤에도 추가 answerBuilder.insert(0, eatable).append(eatable); } } } return answerBuilder.toString(); } }
✅ 배운 점
[ String 과 StringBuffer & StringBuilder ]
String, StringBuffer, 그리고 StringBuilder는 모두 문자열을 다루는 Java 클래스 이다.
- String: String 클래스는 불변(immutable)이므로, 한 번 생성된 문자열은 변경할 수 없다. 예를 들어, 문자열을 수정한다면 실제로는 새로운 문자열 객체가 생성되는 것이다. 이는 문자열의 안정성을 보장하지만, 문자열을 변경할 때마다 새로운 객체를 생성하기 때문에 메모리 낭비와 속도가 느려진다는 단점이 있다.
String str = "Hello"; str += " World"; // 새로운 문자열(hello world)을 생성하여 str에 할당 System.out.println(str); // hello world, 즉 기존의 str이던 Hello는 GC로서 남아있다
- StringBuffer: StringBuffer 클래스는 String 클래스와 달리 가변(mutable)이라서, 문자열을 변경할 수 있다. 또한 StringBuffer는 동기화되어 있어 멀티스레드 환경에서 안전하게 사용할 수 있다. 그러나 성능 면에서는 StringBuilder보다 느리다.
StringBuffer buffer = new StringBuffer("Hello"); buffer.append(" World"); // 기존 문자열을 변경함
- StringBuilder: StringBuffer와 마찬가지로 가변(mutable)이라, 문자열을 변경할 수 있다. 그러나 StringBuilder는 동기화되어 있지 않기 때문에 멀티스레드 환경에서 안전하지 않다. 하지만 단일 스레드 환경이라면 StringBuffer보다 더 빠르다.
StringBuffer buffer = new StringBuffer("Hello"); buffer.append(" World"); // 기존 문자열을 변경함
- StringBuilder & StringBuffer 클래스의 사용 문법
StringBuilder sb = new StringBuilder("Hello"); // append(): 지정된 값을 현재 문자열에 추가 sb.append(" World"); // "Hello World" // insert(): 지정된 위치에 값을 삽입 sb.insert(5, " Inserted"); // "Hello Inserted World" // delete(): 지정된 범위의 문자열을 삭제 sb.delete(5, 15); // "Hello World" // deleteCharAt(): 지정된 위치의 문자를 삭제 sb.deleteCharAt(5); // "Hell World" // replace(): 지정된 범위의 문자열을 다른 문자열로 대체 sb.replace(4, 9, "Replaced"); // "HellReplaced World" // reverse(): 문자열을 뒤집기 sb.reverse(); // "dlroW detalpeRlleH" // substring(): 문자열의 일부분을 반환 String sub = sb.substring(5); // " detalpeRlleH" // length(): 문자열의 길이를 반환 int len = sb.length(); // 17 // charAt(): 지정된 위치의 문자를 반환 char ch = sb.charAt(7); // 'e' // indexOf(): 지정된 문자열 또는 문자의 첫 번째 등장 위치를 반환 int index = sb.indexOf("Replaced"); // 4 // lastIndexOf(): 지정된 문자열 또는 문자의 마지막 등장 위치를 반환 int lastIndex = sb.lastIndexOf("l"); // 15
- 성능 비교 (위의 동일한 코드 사용)
- String의 평균 실행 시간: 15.06ms
- StringBuffer의 평균 실행 시간: 0.778 ms
- StringBuilder의 평균 실행 시간: 0.65ms
StringBuilder가 String에 비해 약 23배 빠르며, 평균적으로 약 5.86MB 더 적은 메모리를 사용했다. 또한 StringBuilder가 StringBuffer에 비해 평균적으로 0.543 ms로 더 빠르며( 약 30.1%), 약 0.855 MB 더 적은 메모리를 사용했다.
문자열 자료형 비교 String StringBuffer StringBuilder 가변 여부 불변 가변 가변 스레드 세이프 O O X 연산 속도 느림 빠름 빠름 사용 시점 문자열 추가 연산이 적고, 스레드 세이프 환경에서 문자열 추가 연산이 많고, 스레드 세이프 환경에서 문자열 추가 연산이 많고, 빠른 연산이 필요한 경우
따라서 싱글 쓰레드 환경에서나 비동기를 사용할 일이 없으면, StringBuilder를 쓰는 것이 이상적이라 할 수 있다.
하지만 현업에서는 자바 어플리케이션을 대부분 멀티 스레드 이상의 환경에서 돌아가기 때문에 웬만하면 안정적인 StringBuffer로 통일하여 코딩하는것이 좋다고 한다.
'알고리즘 > 프로그래머스' 카테고리의 다른 글
[Java] - 두 개 뽑아서 더하기 (68644) (Set/ TreeSet) (0) 2024.03.04 [Java] - K번째수 (42748) (0) 2024.02.29 [Java] - 숫자 문자열과 영단어 (81301: 2021 카카오 채용연계형 인턴십) (0) 2024.02.28 [Java] - 가장 가까운 같은 글자 (142086) (HashMap) (0) 2024.02.28 [Java] - 시저암호 (12926) (0) 2024.02.28