hasNext() : 입력이 들어올 때까지 기다렸다가 입력 시 true 반환, 강제 종료 시 false 반환
hasNextLine() : 다음 입력받을 Line이 있는지 확인
Scanner sc = new Scanner(System.in);
byte a = sc.nextByte(); short b = sc.nextShort(); int c = sc.nextInt(); long d = sc.nextLong(); float e = sc.nextFloat(); double f = sc.nextDouble(); boolean g = sc.nextBoolean(); String h = sc.next(); String i = sc.nextLine();
어떤 숫자에서 k개의 수를 제거했을 때 얻을 수 있는 가장 큰 숫자를 구하려 한다. 예를 들어, 숫자 1924에서 수 두 개를 제거하면 [19, 12, 14, 92, 94, 24] 를 만들 수 있으며, 이 중 가장 큰 숫자는 94이다. 문자열 형식으로 숫자 number와 제거할 수의 개수 k가 solution 함수의 매개변수로 주어진다. number에서 k 개의 수를 제거했을 때 만들 수 있는 수 중 가장 큰 숫자를 문자열 형태로 return 하도록 solution 함수를 완성하라.
나의 답안(오답)
내가 생각한 구조는 다음과 같다.
가장 큰 수가 되기 위해, 주어진 수의 맨 앞에서 k+1번째까지 숫자 중 가장 큰 수가 가장 앞에 놓여야 한다.
가장 앞에 놓일 수가 정해지고 나면, 그 뒤부턴 그 다음 자리의 숫자와 비교하여 더 작을 경우 하나씩 제거한다.
k개만큼 제거되면 남은 숫자가 답이 된다!
이를 코딩으로 짜보았으나, 테스트케이스는 통과됐으나 오답으로 처리되었다.
다시 확인해보니 예외가 많았다.
다른 풀이법을 찾아보니, 굳이 k+1번째 자리에서 가장 큰 수를 찾을 필요 없이, 맨 앞자리부터 다음 숫자와 비교하여 더 작을 경우, 하나씩 제거해나가면 되는 문제였다..
<오답입니다>
class Solution { public String solution(String number, int k) { char[] num_char = number.toCharArray(); char[] answer = new char[number.length()-k]; int count = 0; answer[0] = num_char[0];
for (int i=1; i<=k; i++) { if (answer[0] <num_char[i]) { answer[0] = num_char[i]; count++; } }
int j = 1; for (int i=count+1; i<num_char.length; i++) { if (count < k) { if (i != num_char.length-1 && num_char[i] < num_char[i+1]) { count++; } else { answer[j] = num_char[i]; j++; } } else { answer[j] = num_char[i]; j++; } }
return String.valueOf(answer); } }
모범 답안
스택 타입의 변수 생성
다음 자리의 수와 비교하며 현재 숫자가 더 작을 경우 stack에서 제거 후 k값 1 감소
k가 0이 되면 result값을 문자열로 변환하여 반환
import java.util.Stack;
class Solution { public String solution(String number, int k) { char[] result = new char[number.length() - k]; Stack<Character> stack = new Stack<>();
for (int i=0; i<number.length(); i++) { char c = number.charAt(i); while (!stack.isEmpty() && stack.peek() < c && k-- > 0) { stack.pop(); } stack.push(c); } for (int i=0; i<result.length; i++) { result[i] = stack.get(i); } return new String(result); } }
<테스트10 통과 X> class Solution { public String solution(String number, int k) { StringBuilder sb = new StringBuilder(number); for (int i = 0; i+1 < sb.length() && k>0; i++) { if(sb.charAt(i) < sb.charAt(i+1)) { sb.deleteCharAt(i); i=-1; k--; } } if(k!=0) sb.delete(sb.length()-k, sb.length()); return sb.toString(); } }
사람들을 구명보트를 이용하여 구출하려고 한다. 구명보트는 한 번에 최대 2명까지만 탈 수 있고, 무게 제한도 있다. 예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없다.
구명보트를 최대한 적게 사용하여 모든 사람을 구출하려 하며, 사람들의 몸무게를 담은 배열 people과 구명보트의 무게 제한 limit가 매개변수로 주어질 때, 모든 사람을 구출하기 위해 필요한 구명보트 개수의 최솟값을 return 하도록 solution 함수를 작성하라
나의 답안(오답)
문제를 풀 때 최대 인원 제한이 2명이라는 것을 미처 생각지 못했다...
최대한 limit에 딱 맞게 태우면 최소한으로 배를 사용할 수 있겠다는 생각에
각 인덱스값에 limit을 나눠보기도 하고, 더했을 때 limit에 딱 맞는 사람 먼저 태워 보내는 것 등
여러 알고리즘을 생각해 봤지만 딱 맞는 알고리즘을 생각해내지 못했다.
그래서 오름차순으로 정렬 후 가벼운 사람들 먼저 태우자는 생각을 하여
코드를 작성했지만 답이 계속 틀렸고,
뒤늦게 인원제한이 있다는 것을 깨닫고 코드를 다시 짰다 ㅠㅠ
오름차순으로 정렬
무게 제한에서 해당 인덱스 무게를 빼가며 무게제한을 초과하지 않을 때까지 연산
무게제한 초과 시 count변수에 1을 더함
마지막 인원까지 태워 count+1을 return
<오답입니다>
import java.util.Arrays;
class Solution { public int solution(int[] people, int limit) { int count = 0; int limitcheck = limit;
Arrays.sort(people);
for (int i=0; i<people.length; i++) { if (limitcheck - people[i] >= 0) { limitcheck -= people[i]; } else if (limitcheck - people[i] < 0) { count++; limitcheck = limit;
}
return count+1; } }
모범 답안
오름차순 정렬
좌우 동시 비교를 위한 인덱스 변수(i, j) 생성
가장 무거운 사람과 가벼운 사람의 합이 limit을 넘지 않으면 2명을 태우고(++i), 넘을 경우 무거운 사람만 태움
import java.util.Arrays;
class Solution { public int solution(int[] people, int limit) { Arrays.sort(people);
int i = 0, j = people.length - 1; for (; i < j; --j) { if (people[i] + people[j] <= limit) ++i; } return people.length - i; } }
따로 count변수를 생성하지 않고 people.length-i로 값을 return한 것이 인상적이다. 전부 1명씩만 태우면 people.length만큼 태웠을 것이고, 2명을 태웠다면 그 수만큼 i값을 올려 굳이 변수를 선언하지 않아도 결과값을 리턴할 수가 있는 것이다.
복습
for문의 예외형식
1. 초기값 생략 가능
int i=0; for ( ; i<5; i++) { System.out.println(i); } // 출력: 0 1 2 3 4
2. 초기, 증감 생략 가능
int i=0; for ( ; i<5; ) { System.out.println(i); i++; } // 출력: 0 1 2 3 4
도난당한 학생 및 여벌 옷 있는 학생 번호에 해당하는 people 인덱스 값에 각각 -1, +1 해줌 (위 과정에서 여벌옷이 있으면서 도난당한 학생은 자동으로 처리됨)
1번 학생(people[0])부터, 앞 뒤 번호에 여벌옷이 있는 경우 즉, +1값인 경우 옷을 빌림
해당하지 않으면 answer -1
class Solution { public int solution(int n, int[] lost, int[] reserve) { int[] people = new int[n]; //크기가 n인 people변수 생성 (인덱스 0부터 학생 1번에 해당)
int answer = n;
for (int l : lost) people[l-1]--; //도난당한 학생 위치의 값 -1 for (int r : reserve) people[r-1]++; //여벌 옷 있는 학생 위치의 값 +1
for (int i = 0; i < people.length; i++) { if(people[i] == -1) { if(i-1>=0 && people[i-1] == 1) { people[i]++; people[i-1]--; }else if(i+1< people.length && people[i+1] == 1) { people[i]++; people[i+1]--; // 앞 뒤 학생 중 여벌 옷이 있을 경우 빌림 }else answer--; // 없을 경우 수업을 들을 수 없으므로 answer -1 } } return answer; } }
변수를 새로 생성해줌으로써 도난당한 학생 중 여벌 옷이 있는 학생을 거를 수 있음
그에 더하여 for문을 간소화하고 이중 for문 사용을 하지 않아 훨씬 효율적이다.
복습
★크기를 지정하여 정수 배열을 선언할 경우, 기본 값은 0
int[] arr = new int[5]; for (int a : arr) System.out.print(a); // 출력 : 00000