완벽한 햄버거 만들기 (Java)
제출한 답 :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class day4 {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// n 입력 받기
int n = Integer.parseInt(reader.readLine());
// ki 배열 입력 받기
String[] kiInput = reader.readLine().split(" ");
int[] ki = new int[n];
for (int i = 0; i < n; i++) {
ki[i] = Integer.parseInt(kiInput[i]);
}
// 최대값과 인덱스 찾기
int best = Arrays.stream(ki).max().getAsInt();
int bestIdx = 0;
for (int i = 0; i < n; i++) {
if (ki[i] == best) {
bestIdx = i;
break;
}
}
// 왼쪽 부분과 오른쪽 부분 나누기
int[] left = Arrays.copyOfRange(ki, 0, bestIdx + 1);
int[] right = Arrays.copyOfRange(ki, bestIdx, n);
// 제대로 된 햄버거인지 검증
if (isSorted(left) && isSortedDescending(right)) {
// 제대로 된 햄버거라면 맛 구하기
int sum = Arrays.stream(ki).sum();
System.out.println(sum);
} else {
System.out.println(0);
}
reader.close();
}
// 배열이 정렬되어 있는지 확인하는 메서드
private static boolean isSorted(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
if (arr[i] < arr[i - 1]) {
return false;
}
}
return true;
}
// 배열이 내림차순으로 정렬되어 있는지 확인하는 메서드
private static boolean isSortedDescending(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
return false;
}
}
return true;
}
}
다른 언어는 되게 간단하게 나오던데.. 자바는 왜 이렇게 긴거죠?ㅎㅎㅎ
최대값을 찾고, 배열을 정렬하는 문제로 간단하게 풀어야 하는게 정상이겠지만.. 정말 시간이 오래걸렸다.
진짜 공부 빡세게 해야 할 듯?
문제 풀이가 기대된다.
드디어 문제 풀이보고 다시 정리하는 시간!!
내가 이해한 개념을 글로 풀어서 적혀 있으니까 진짜 훨씬 더 이해가 잘 되는 것 같다.
1. 가장 큰 값의 위치를 찾기
2. 큰 값을 기준으로 앞은 오름차순 / 큰 값을 기준으로 뒤는 내림차순으로 배열되었는지 확인
3. 확인한 값이 문제가 없다면 완벽한 햄버거, 아니면 0
array를 사용할 때와 arraylist를 사용할 때 차이점
자바 collections을 잘 쓰면 쉽게 할 수 있다더니.. 진짜 개발 공부는 끝이 없는듯..
근데 이렇게 코드가 길어질 때면 파이썬을 쓰고 싶은 생각이...
문제 풀이
필요한 개념
- ArrayList
- sort
분석
햄버거를 구성하는 N개의 재료가 순서대로 주어졌을 때, 조건대로 정렬되어 있는지 확인하는 문제입니다. 이때 정렬의 조건은 가장 높은 정수를 기준으로, 왼쪽이나 오른쪽으로 갈 수록 정수의 값이 같거나 감소되어야 합니다.
그리고 문제에서는 주어지는 정수들이 그러한 상태인지 확인을 요구하는 문제입니다.
문제 풀이
문제를 해결하기 위해서는 주어진 값 중 가장 큰 값의 위치를 찾아야 합니다.
그 다음에는 큰 값의 위치를 기준으로 앞의 값들은 오름차순으로 배열되어 있는지, 뒤의 값들은 내림차순으로 배열되어 있는지 확인하면 됩니다. 이 값이 문제가 없다면 완벽한 햄버거이고, 아니라면 완벽한 햄버거가 아닙니다.
ArrayList
데이터 입력을 받은 뒤, 아래와 같이 변수를 정리했습니다.
이번 문제부터는 다양한 메소드 활용을 위해서 ArrayList로 배열을 관리하려고 해요.
ArrayList는 인덱스 기반의 데이터를 관리하고 있으며, 순서가 존재하고 있어요.
동적으로 크기가 변경될 수 있기 때문에 이 문제와 같이 데이터를 나누고,
정렬하고 합치는 문제에서는 적합한 자료형입니다.
- ArrayList는 아래처럼 선언할 수 있고, 다음과 같은 메소드를 제공하고 있어요.
ArrayList<Integer> list = new ArrayList<Integer>();
- add(E e): 리스트의 마지막에 원소를 추가합니다.
- add(int index, E element): 지정한 인덱스에 원소를 추가합니다.
- remove(int index): 지정한 인덱스의 원소를 삭제합니다.
- get(int index): 지정한 인덱스의 원소를 반환합니다.
- set(int index, E element): 지정한 인덱스의 원소를 새 원소로 대체합니다.
- size(): 리스트의 크기(원소의 수)를 반환합니다.
다음과 같이 ArrayList에 요소를 할당해 줄 수 있습니다.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 입력을 받기 위해 Scanner 객체 생성
// N 입력 받기
int n = Integer.parseInt(sc.nextLine());
// 배열 입력 받기
String[] arrStr = sc.nextLine().split(" ");
//ArrayList 선언하기
ArrayList<Integer> arr = new ArrayList<>();
for (String s : arrStr) {
arr.add(Integer.parseInt(s));
}
}
배열 나누기
배열을 나누는 기준은 주어진 수 중에서 가장 큰 정수 입니다. 가장 큰 정수가 여러 개라고 해도, 대부분 언어에서 특정한 값을 찾을 때는 맨 처음 등장하는 정수의 인덱스를 반환합니다.
그리고 가장 큰 값의 위치를 maxIndex 라고 한다면, 이 값을 기준으로 배열을 분리합니다.
이는 이후에 분리된 배열끼리 정렬을 하기 위함입니다.
- Collections.max(arr) : arr 배열 중에서 가장 큰 값을 반환합니다.
- arr.indexOf(target) : arr 배열 중에서 target의 위치를 반환합니다.
- Array.copyOfRange(array, start, end) : arr 배열을 arr[A]부터 arr[B] 전까지 분리합니다.
// 최대값과 그 인덱스 찾기
int maxIndex = arr.indexOf(Collections.max(arr));
// 좌측 리스트와 우측 리스트 생성
ArrayList<Integer> left = new ArrayList<>(arr.subList(0, maxIndex));
ArrayList<Integer> right = new ArrayList<>(arr.subList(maxIndex, n));
정렬
maxIndex 를 기준으로 나누어진 left 와 rignt 변수는 각각 오름, 내림차순으로 정렬해야 합니다.
자바에서는 sort() 를 활용해서 쉽게 정렬할 수 있고, 내림차순은 Collections.reverseOrder() 를 활용해서 쉽게 정렬할 수 있습니다.
// 좌측 리스트는 오름차순, 우측 리스트는 내림차순으로 정렬
Collections.sort(left);
Collections.sort(right, Collections.reverseOrder());
배열 합치기
이제 나눈 배열을 다시 합쳐야 합니다. 배열을 합칠 때는 새로운 ArrayList 를 선언한 뒤, addAll 메소드를 사용해서 추가할 수 있습니다.
// 좌측 리스트와 우측 리스트 합치기
ArrayList<Integer> sortedArr = new ArrayList<>();
sortedArr.addAll(left);
sortedArr.addAll(right);
배열 비교하고, 모든 요소 합치기
저희가 만든 sortedArr 과 원래의 배열인 arr 을 비교했을 때 동일하다면, 완벽한 햄버거이고, 아니라면 0을 출력하면 됩니다.
배열을 서로 비교하는 방법은 arrA.equals(arrB) 로 2개의 배열을 비교할 수 있습니다.
이때 ArrayList의 모든 요소를 합하는 방법은 반복문을 활용하거나, Java8 이상에서 Stream API 를 활용하는 방법이 있습니다.
- for-each Loop : ArrayList의 모든 요소를 순회하면서 각 요소를 합계에 더합니다.
int sum = 0;
for (int num : list) {
sum += num;
}
- Stream API : ArrayList를 스트림으로 변환하고, mapToInt 메소드로 각 요소를 Integer에서 기본형 int로 변환한 다음, sum 메소드로 모든 요소를 더합니다.
int sum = list.stream().mapToInt(Integer::intValue).sum();
답 :
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 입력을 받기 위해 Scanner 객체 생성
// N 입력 받기
int n = Integer.parseInt(sc.nextLine());
// 배열 입력 받기
String[] arrStr = sc.nextLine().split(" ");
ArrayList<Integer> arr = new ArrayList<>();
for (String s : arrStr) {
arr.add(Integer.parseInt(s));
}
// 최대값과 그 인덱스 찾기
int maxIndex = arr.indexOf(Collections.max(arr));
// 좌측 리스트와 우측 리스트 생성
ArrayList<Integer> left = new ArrayList<>(arr.subList(0, maxIndex));
ArrayList<Integer> right = new ArrayList<>(arr.subList(maxIndex, n));
// 좌측 리스트는 오름차순, 우측 리스트는 내림차순으로 정렬
Collections.sort(left);
Collections.sort(right, Collections.reverseOrder());
// 좌측 리스트와 우측 리스트 합치기
ArrayList<Integer> sortedArr = new ArrayList<>();
sortedArr.addAll(left);
sortedArr.addAll(right);
// 리스트 비교 후 결과 출력
if (sortedArr.equals(arr)) {
int sum = sortedArr.stream().mapToInt(Integer::intValue).sum();
System.out.println(sum);
} else {
System.out.println(0);
}
}
}
'문제풀기 > 구름톤 챌린지' 카테고리의 다른 글
구름톤 챌린지 2주 Day1 - 이진수 정렬 (0) | 2023.08.22 |
---|---|
구름톤 챌린지 1주 Day5 - 이진수 정렬 (0) | 2023.08.20 |
구름톤 챌린지 1주 Day3 - 합 계산기 (0) | 2023.08.18 |
구름톤 챌린지 1주 Day2 - 프로젝트 매니징 (1) | 2023.08.17 |
구름톤 챌린지 1주 Day1 - 운동 중독 플레이어 (0) | 2023.08.16 |