1. Lv.1
1) x만큼 간격이 있는 n개의 숫자
- long 자료형 사용하기!
- Why? 유효 범위 때문에 이러한 문제가 발생했다.
class Solution {
public long[] solution(int x, int n) {
long[] answer = new long[n];
long y = (long) x;
for(int i=0; i<n; i++){
answer[i] += y;
y += (long) x;
}
return answer;
}
}
- try_2: 좀 더 코드 수를 줄임, 정리된 느낌은 아니다.
class Solution {
public long[] solution(int x, int n) {
long[] answer = new long[n];
for(int i = 0; i < n; i++){
answer[i] += (long)x + (long)x*i;
}
return answer;
}
}
2) 서울에서 김서방 찾기
- String 객체에서 문자열 더하기에서 무조건 String 형만 더하기 할 수 있다. 그렇지 않고는 printf를 이용해야 한다.
class Solution {
public String solution(String[] seoul) {
String answer = "";
for(int i = 0; i<seoul.length; i++)
if(seoul[i].equals("Kim"))
answer = "김서방은 " +i+"에 있다";
return answer;
}
}
- try_2: IntStream를 이용하려고 했으나 테케 1개 남기고 틀림, chatGPT에 물어보니 마지막 i의 범위를 변경하란다. i가 0인 경우도 있어서 ‘i > 0’로 변경하기!!
import java.util.*;
import java.util.stream.*;
class Solution {
public String solution(String[] seoul) {
String answer = "";
for(int i = 0; i < seoul.length; i++){
if(seoul[i].equals("Kim"))
answer = "김서방은 " + i + "에 있다";
}
// int[] index = IntStream.range(0, seoul.length)
// .filter(i -> seoul[i].equals("Kim"))
// .toArray();
// for(int i : index){
// System.out.println(i);
// if(i > 0) // -> if(i > 0)
// answer = "김서방은 " + i + "에 있다";
// }
return answer;
}
}
3) 하샤드 수
-
각 자리수마다 나누는 방법 어렵다 : Math.log10() 이용!
-
나머지 연산을 이용하기 나머지 값 계산이 즉시 가능하다!(빠르다.)
-
나누기 숫자가 0인 것도 체크해서 넘겨야 한다.(범위 중요!)
class Solution {
public boolean solution(int x) {
boolean answer = false;
int div = 0;
int sum = 0;
int firstx = x;
for(int i = (int) Math.log10(x); i>=0; i--){
div = (int) Math.pow(10, i);
sum += x / div;
x %= div; // 그냥 '나머지 연산'으로 전체에서 빼는 로직을 해결!!
if(div <= 0)
break;
}
answer = ((firstx >= 1) && (firstx <= 10000)) && (firstx % sum == 0);
return answer;
}
}
- try_2: 앞에서 푼 문제보다 더 코드 수를 늘려서 풀었다. 반복되는 부분은 항상 순회문 이용할 것!!
import java.util.*;
class Solution {
public boolean solution(int x) {
boolean answer = true;
int number = 0;
int xNumber = x;
for(int i = 0; i < (int)(Math.log10(x)+1); i++){
if(x / 10000 > 0) {
number += xNumber / 10000;
xNumber -= xNumber/10000*10000;
}
if(x / 1000 > 0) {
number += xNumber / 1000;
xNumber -= xNumber/1000*1000;
}
if(x / 100 > 0) {
number += xNumber / 100;
xNumber -= xNumber/100*100;
}
if(x / 10 > 0) {
number += xNumber / 10;
xNumber -= xNumber / 10*10;
}
if(x / 1 > 0) {
number += xNumber / 1;
xNumber -= xNumber / 1*1;
}
}
if(x % number == 0){
answer = true;
}
else if(x % number != 0){
answer = false;
}
return answer;
}
}
4) 음양 더하기
- 문제를 빠르게 이해하기!
class Solution {
public int solution(int[] absolutes, boolean[] signs) {
int answer = 0;
for(int i = 0; i<absolutes.length; i++){
if(signs[i] == true){
absolutes[i] = 1 * absolutes[i];
}
else{
absolutes[i] = (-1) * absolutes[i];
}
answer += absolutes[i];
}
return answer;
}
}
5) 부족한 금액 계산하기
- long 자료형 사용하기!
- Why? 유효 범위 때문에 이러한 문제가 발생했다.
class Solution {
public long solution(int price, int money, int count) {
long answer = -1;
long result = 0;
long y = 0;
long sum = 0;
for(int i = 0; i<count; i++){
y += (long) price;
sum += y;
System.out.println(y);
}
result = money - sum;
if(result >= 0){
answer = 0;
}
else{
answer = ((long) result) * (-1);
}
return answer;
}
}
- try_2: 기존 방식보단 정돈된 느낌이다. 코드 수를 줄이려는 노력!
class Solution {
public long solution(int price, int money, int count) {
long sum = 0;
long answer = -1;
for(int i = 1; i <= count; i++) {
sum += (long) price * i;
}
if(sum - money < 0)
answer = 0;
else
answer = (long) sum - (long) money;
return answer;
}
}
6) 같은 숫자는 싫어
-
Stack 자료 구조를 사용해야하며, Stack 콜렉션 클래스를 사용하는 방법 복습하기!
-
Push(). Pop(). Peek(), inEmpty() 사용 주의!
import java.util.*;
public class Solution {
public int[] solution(int []arr) {
Stack<Integer> stack = new Stack<>();
for(int num : arr){
if(stack.isEmpty() || stack.peek() != num){
stack.push(num);
}
}
int[] answer = new int[stack.size()];
for(int i = answer.length-1; i >= 0 ; i--){
answer[i] = (int) stack.pop();
}
return answer;
}
}
- try_2: 앞에서는 Stack 자료구조를 이용하였지만 이번엔 Queue 자료구조를 이용함으로써 데이터의 순서 고려하지 않음!
- pop vs poll 같은 기본 메서드 공부 다시하기!!
import java.util.*;
public class Solution {
public int[] solution(int[] arr) {
Queue<Integer> queue = new LinkedList<>();
Queue<Integer> queue2 = new LinkedList<>();
for(int num : arr) {
if(queue.isEmpty()) {
queue.offer(num);
queue2.offer(num);
} else if ((queue2.peek() != num)) {
queue.offer(num);
queue2.poll();
queue2.offer(num);
}
}
int[] answer = new int[queue.size()];
int i = 0;
while(!queue.isEmpty()){
answer[i] = queue.poll();
i++;
}
return answer;
}
}
7) 이상한 문자 만들기
-
StringBuilder를 사용하여 append를 이용해서 더하면, 아직도 StringBuilder 타입이라서 결과를 도출할 땐, toString()으로 String로 변환하여 결과 출력하기!!
-
자리수가 홀수인지 짝수인지에 따라 바뀌는 것이 아니라 공백인 “ ”에 의해 값이 결정되어야 한다.
-
String 타입의 데이터를 비교할 때는
==
가 아니라 무조건equals()
를 이용할 것!- String은 자료형이 아니라 클래스이므로 객체이다. 그래서 객체 비교를 해줘야 한다.
class Solution {
public String solution(String s) {
StringBuilder st = new StringBuilder();
String[] trims = s.split("");
boolean check = true;
for(String c : trims){
if(check){
st.append(c.toUpperCase());
}
else{
st.append(c.toLowerCase());
}
check = !check;
if(c.equals(" ")){
check = true;
}
}
return st.toString();
}
}
- 효율성의 제약이 없어서 for문을 2번 써서 간단하게 풀어봤다. 하지만, 기존 방식은 문자열 전체를 split해서 “ “로 구분지어서 for문을 최대한 줄여풀었다.
import java.util.*;
class Solution {
public String solution(String s) {
String[] strs = s.split(" ");
char c = ' ';
String xString = "";
String answer = "";
for(String str : strs) {
for(int i = 0; i < str.length(); i++){
if(i % 2 == 0) {
c = str.charAt(i);
xString += Character.toUpperCase(c);
} else {
c = str.charAt(i);
xString += Character.toLowerCase(c);
}
}
answer += xString;
if(s.length() != answer.length())
answer += ' ';
xString = "";
}
return answer;
}
}
8) 예산
- 처음 푼 방식 : 테케 2개 중 1개만 통과
import java.util.*;
class Solution {
public int solution(int[] d, int budget) {
// 정렬 후 작은 수부터 더하기
int sum = 0;
int count =0;
int answer = 0;
Arrays.sort(d);
for(int i = 1; i < d.length-1; i++){
if(d[i-1] <= d[i]){
sum += d[i-1] + d[i];
count++;
}
if(sum >= budget){
answer = count;
return answer;
}
}
return answer;
}
}
- 수정 된 방식 : 빼는 방향으로
import java.util.*;
class Solution {
public int solution(int[] d, int budget) {
// 정렬 후 작은 수부터 더하기
int answer = 0;
Arrays.sort(d);
for(int i = 0; i < d.length; i++){
if(d[i] <= budget){
budget -= d[i];
answer++;
}
else{
break;
}
}
return answer;
}
}
- try_2: 우선순위 큐를 이용했더니 테스트는 통과 했는데 실행시간 초과되어서 정렬을 이용해서 문제 품…
import java.util.*;
class Solution {
public int solution(int[] d, int budget) {
int answer = 0;
int sum = 0;
// PriorityQueue<Integer> pq = new PriorityQueue<>();
// for(int num : d)
// pq.offer(num);
// while(!pq.isEmpty()){
// if(sum < budget){
// sum += pq.poll();
// answer++;
// }
// }
Arrays.sort(d);
for(int num : d){
sum += num;
if(sum <= budget){
answer++;
}
}
return answer;
}
}
9) 시저암호
-
Java에서 아스키코드 이용하는 방법 익혀두기
-
toCharArray(), String.valueOf(), matches(), equals() 사용법!
- ‘Z’에서 ‘A’로 넘기는 방식 구현에서 까다로웠다.
- 첫 번째 풀이 방법 :
- 이 방식은 아스키코드를 알아야지 풀 수 있다.
import java.util.*;
class Solution {
public String solution(String s, int n) {
char[] trims = s.toCharArray(); // 배열에 바로 담기
String Up = "^[A-Z]*$";
String Low = "^[a-z]*$";
StringBuilder sb = new StringBuilder();
for(int i = 0; i<trims.length; i++){
int ascii = (int) trims[i];
if(String.valueOf(trims[i]).equals(" ")){
sb.append(String.valueOf(trims[i]));
continue;
}
if(String.valueOf(trims[i]).matches(Up)){
if(ascii + n > 90){
trims[i] = (char)(ascii+n-90+64);
}
else{
trims[i] = (char) (ascii + n);
}
sb.append(trims[i]);
}
else if(String.valueOf(trims[i]).matches(Low)){
if(ascii + n > 122){
trims[i] = (char)(ascii+n-122+96);
}
else{
trims[i] = (char) (ascii + n);
}
sb.append(trims[i]);
}
}
String answer = "";
return sb.toString();
}
}
- 두 번째 풀이 방법 :
- 나름의 직관적인 풀이!
import java.util.*;
class Solution {
public String solution(String s, int n) {
char[] trims = s.toCharArray(); // 배열에 바로 담기
String Up = "^[A-Z]*$";
String Low = "^[a-z]*$";
StringBuilder sb = new StringBuilder();
for(int i = 0; i<trims.length; i++){
int ascii = (int) trims[i];
if(String.valueOf(trims[i]).equals(" ")){
sb.append(String.valueOf(trims[i]));
continue;
}
if(String.valueOf(trims[i]).matches(Up)){
if(ascii + n > 'Z'){
trims[i] = (char) ('A' + (ascii + n - 'Z' - 1) % 26);
}
else{
trims[i] = (char) (ascii + n);
}
sb.append(trims[i]);
}
else if(String.valueOf(trims[i]).matches(Low)){
if(ascii + n > 'z'){
trims[i] = (char) ('a' + (ascii + n - 'z' - 1) % 26);
}
else{
trims[i] = (char) (ascii + n);
}
sb.append(trims[i]);
}
}
String answer = "";
return sb.toString();
}
}
- try_2: StringBuilder, isLowerCase, isUpperCase 이용하기
- StringBuilder를 사용하여 문자열을 효율적으로 구성
- char인 상태에서 int인 n값을 더해서 아스키코드로 계산이 되어서 다음 문자로 변환된다.
- 첫 번째 시도한 방법은 테케 맞지 않는게 있어서 다른 방법으로 전환
import java.util.*;
class Solution {
public String solution(String s, int n) {
StringBuilder answer = new StringBuilder();
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(c == ' '){
answer.append(' ');
} else if(Character.isLowerCase(c)){
char newChar = (char) (c + n);
if(newChar > 'z') {
newChar -= 26;
}
answer.append(newChar);
} else if(Character.isUpperCase(c)){
char newChar = (char) (c + n);
if(newChar > 'Z') {
newChar -= 26;
}
answer.append(newChar);
}
}
// int[] nums = new int[s.length()];
// for(int i = 0; i < s.length(); i++){
// nums[i] = s.charAt(i) + n;
// System.out.println(nums[i]);
// }
// for(int i = 0; i < s.length(); i++) {
// if(s.charAt(i) != ' '){
// if(nums[i] >= 65 && nums[i] <= 90)
// answer += (char) nums[i];
// else if(nums[i] < 97 && nums[i] > 90)
// answer += (char) (nums[i] - 26);
// else if(nums[i] >= 97 && nums[i] <= 122)
// answer += (char) nums[i];
// else if(nums[i] > 122)
// answer += (char) (nums[i] - 26);
// } else {
// answer += " ";
// }
// }
return answer.toString();
}
}
10) 비밀지도K
- 주의 할 사항 :
String.format("%0"+n+"d", data)
: %0은 자리수에 n자리 수만큼 숫자가 안채워지면 ‘0’이 채워진다. 원래 채워지는 숫자는 d이며 자세한 내용은 ‘,’뒤에 나열된다.- ‘String.format()’에서 원래는 %d에서 ‘%0d’가 되었고 ‘%03d’ 이런 식이지만 몇자리 수까지 채워질지 모르기 때문에
%0 + n + d
로 정해졌다. - 유효범위 때문에 int가 아니라 Long으로 형변환(실제로도 런타임 에러가 발생한다!)
- 핵심 내용** :
- String 문자열을 각각 비교할 때는 제발 equals()를 쓰자!
-
2진수라서 ‘+’ 대신해서 비트연산자인 ‘ ‘를 사용하자!
- 코드 :
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
String[] arr3 = new String[n];
for(int i = 0; i < n; i++){
arr3[i] = String.format("%0"+n+"d", Long.parseLong(Long.toBinaryString(arr1[i]|arr2[i])));
}
for(int i = 0; i < n; i++){
String[] result = arr3[i].split("");
String res = "";
for(int j = 0; j < result.length; j++){
if(result[j].equals("1")){
res += '#';
}
else if(result[j].equals("0")){
res += ' ';
}
}
answer[i] = res;
}
return answer;
}
}
- 다른 사람들의 풀이 :
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
for(int i = 0; i < n; i++) {
String binary1 = Integer.toBinaryString(arr1[i]);
String binary2 = Integer.toBinaryString(arr2[i]);
binary1 = "0".repeat(n - binary1.length()) + binary1;
binary2 = "0".repeat(n - binary2.length()) + binary2;;
String[] biArr1 = binary1.split("");
String[] biArr2 = binary2.split("");
StringBuilder sb = new StringBuilder();
for(int j = 0; j < n; j++) {
if(biArr1[j].equals("1") || biArr2[j].equals("1")) {
sb.append("#");
} else {
sb.append(" ");
}
}
answer[i] = sb.toString();
}
return answer;
}
}
- try_2_1 : (k / 5) 이 부분에서 행에 대해 고정된 크기인 5를 가정한다. 5가 아니면 범위를 벗어난 ArrayIndexOutOfBoundsException 오류가 발생할 수 있다.
import java.util.*;
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
int[][] numbers = new int[n][n];
ArrayList<Integer> list = new ArrayList<>();
int count = 0;
numbers = createArray(arr1, arr2, n);
String[] answer = new String[n];
for(int j = 0; j < n; j++){
for(int i = 0; i < n; i++){
list.add(numbers[j][i]);
}
}
for(int k = 0; k < list.size(); k++){
if(!list.isEmpty()){
if(list.get(k) == 1)
answer[(k / 5)] += '#';
else if(list.get(k) == 0)
answer[(k / 5)] += ' ';
else
answer[(k / 5)] += ' ';
}
}
return answer;
}
public int[][] createArray(int[] arr1, int[] arr2, int n){
int[][] numbers1 = new int[n][n];
int[][] numbers2 = new int[n][n];
int[][] numbers = new int[n][n];
for(int j = 0; j < n; j++){
for(int i = 0; i < n; i++){
if(arr1[j] > 0) {
numbers1[j][i] = arr1[j] % 2;
arr1[j] = arr1[j] / 2;
}
}
}
for(int j = 0; j < n; j++){
for(int i = 0; i < n; i++){
if(arr2[j] > 0) {
numbers2[j][i] = arr2[j] % 2;
arr2[j] = arr2[j] / 2;
}
}
}
for(int j = 0; j < n; j++){
for(int i = 0; i < n; i++){
numbers[j][i] = numbers1[j][i] + numbers2[j][i];
if(numbers[j][i] > 1)
numbers[j][i] = 1;
}
}
return numbers;
}
}
- try_2_2 : ArrayIndexOutOfBoundsException의 해결 방법은 StringBuilder를 이용해서 Row의 길이를 제한하지 않는 것이다.
import java.util.*;
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
int[][] numbers = createArray(arr1, arr2, n);
String[] answer = new String[n];
for (int j = 0; j < n; j++) {
StringBuilder row = new StringBuilder();
for (int i = 0; i < n; i++) {
if (numbers[j][i] == 1) {
row.append('#');
} else {
row.append(' ');
}
}
answer[j] = row.toString();
}
return answer;
}
public int[][] createArray(int[] arr1, int[] arr2, int n) {
int[][] numbers = new int[n][n];
for (int j = 0; j < n; j++) {
for (int i = n - 1; i >= 0; i--) {
if (arr1[j] > 0) {
numbers[j][i] += arr1[j] % 2;
arr1[j] = arr1[j] / 2;
}
if (arr2[j] > 0) {
numbers[j][i] += arr2[j] % 2;
arr2[j] = arr2[j] / 2;
}
if (numbers[j][i] > 1) {
numbers[j][i] = 1;
}
}
}
return numbers;
}
}
11) 숫자 문자열과 영단어K
-
패턴이 같다… String 객체는 값 비교시, 무조건 equals로 비교!
-
내가 쓴 풀이 :
class Solution {
public int solution(String s) {
String[] number = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
char[] arr1 = new char[s.length()];
int answer = 0;
String result = "";
for(int i = 0; i < s.length(); i++){
arr1 = s.toCharArray();
}
String st1 = "";
for(int i = 0; i < arr1.length; i++){
if((int) arr1[i] > 58){
st1 += arr1[i];
}
else{
result += arr1[i];
}
for(int j = 0; j < number.length; j++){
if(st1.equals(number[j])){
result += String.valueOf(j);
st1 = "";
}
}
}
System.out.println(result);
System.out.println(st1);
answer = Integer.parseInt(result);
// 패턴이 같다... String 객체는 값 비교시, 무조건 equals로 비교!
return Integer.parseInt(result);
}
}
- 더 간단한 풀이 :
class Solution {
public int solution(String s) {
int answer = 0;
String[] num = {"zero","one","two","three","four","five","six","seven","eight","nine"};
for(int i=0;i<10;i++){
s=s.replace(num[i],Integer.toString(i));
}
answer = Integer.parseInt(s);
return answer;
}
}
- try_2 : 두번째 풀었는데 위의 간단한 풀이와 같은 방식으로 풀게 되었다.
replace
,contain
을 주로 쓴다!!
class Solution {
public int solution(String s) {
int answer = 0;
String[] numbers = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
for(int i = 0; i<numbers.length; i++){
if(s.contains(numbers[i])){
s = s.replace(numbers[i], String.valueOf(i));
}
}
answer = Integer.parseInt(s);
return answer;
}
}
12) 문자열 내 마음대로 정렬하기
-
String 객체처럼, 객체 정렬에는 Comparator 사용!
-
문제 11) 처럼 String 값 비교는 equals 이용!
import java.util.*;
class Solution {
public String[] solution(String[] strings, int n) {
// String 객체처럼, 객체 정렬에는 Comparator 사용!
Arrays.sort(strings, new Comparator<String>(){
@Override
public int compare(String o1, String o2){
if(o1.charAt(n) > o2.charAt(n)){
return 50; // 정방향 정렬(양수)
}
else if(o1.charAt(n) < o2.charAt(n)){
return -50; // 역방향 정렬(음수)
}
else if(o1.charAt(n) == o2.charAt(n)){
return o1.compareTo(o2);
// 'o1'라는 기준값에 'o2'값이 포함되었는지 차이로 비교하여 정렬
}
return 0; // 종료
}
});
String[] answer = {};
return strings;
}
}
- try_2 : 위와 같은 방법이 아니면 생각이 나질 않는다. 그 이유는 리스트 크기를 비교할 때, 단순히 크기를 비교해주는 값으로 index를 구할 수 있지만 정확하게 index를 지정해서 가져올 수 없기 때문에 다른방법이 필요했다. 그것이 Comparator 클래스의 compare 메서드를 재정의해서 크기 비교 값을 갖고 정렬하는 방식이다.
13) K번째수
- 2차원 배열의 데이터 구조라서 시작 값과 끝 값 그리고 이들의 값에 대한 새로운 임시 배열로 생성하기!
import java.util.*;
class Solution {
public int[] solution(int[] array, int[][] commands) {
int[] answer = new int[commands.length];
// 시작, 끝 값 그리고 이들의 값에 대한 새로운 임시 배열로 생성하기!
for(int i = 0; i< commands.length; i++){
int s = commands[0][i];
int e = commands[1][i];
int[] temp = new int[e - s + 1];
for(int j = 0; j <= e - s; j++){
temp[j] = array[j + s - 1];
}
Arrays.sort(temp);
answer[i] = temp[commands[2][i]-1];
}
return answer;
}
}
- try_2 : 기본적인 개념으로는 copyOfRange를 이용해서 해당 범위에서 배열을 잘라내서 가져오고 정렬해서 끝낸다.
- 처음에는 2중 for문으로 해결하려고 했으나 타임에러로 for문을 줄이고자 2차배열의 개념을 이용하고자 했다.
import java.util.*;
class Solution {
public int[] solution(int[] array, int[][] commands) {
int[] answer = new int[commands.length];
for(int j = 0; j < commands.length; j++){
int[] mid = new int[commands[j][1] - commands[j][0] + 1];
mid = Arrays.copyOfRange(array, commands[j][0]-1, commands[j][1]);
Arrays.sort(mid);
answer[j] = mid[commands[j][2] - 1];
}
return answer;
}
}
14) K두 개 뽑아서 더하기*
-
이 문제 중요!! : 예전에 로또 문제와 비슷하지만 로또에서는 HashSet을 이용하지 않고 기본 코드로 작성!!
-
예전에 풀었던 로또 코드* :
import java.util.Random;
public class Lotto {
int[] lottoNums = new int[7];
public Lotto() {
}
public void generateNumbers() {
Random rand = new Random();
for(int i=0; i<6; i++) {
lottoNums[i] = rand.nextInt(49) + 1;
// 로또 번호가 같으면 for문 다시 실행하도록 i를 하나 내린다.
for(int j=0; j<i; j++) {
if(lottoNums[i] == lottoNums[j]){
i--;
}
}
}
for(int i=0; i<6; i++) {
System.out.printf("%d, ", lottoNums[i]);
}
}
}
-
ArrayList(배열 크기 생각 x), HashSet(중복 제거), HashSet에는 정렬이 없어서 Arrays.sort() 정렬 이용!
-
java에서 forEach 구문 주의!
-
참고하기 : 완전 탐색 페이지의 문제 다 풀기!
a. ‘K두 개 뽑아서 더하기’의 구현 코드* :
import java.util.*;
class Solution {
public int[] solution(int[] numbers) {
// ArrayList(배열 크기 생각 x), HashSet(중복 제거), HashSet에는 정렬이 없어서 Arrays.sort() 정렬 이용!
// java에서 forEach 구문 주의!
ArrayList<Integer> numList = new ArrayList<Integer>();
for(int i = 0; i < numbers.length; i++){
for(int j = 0; j < numbers.length; j++){
if(i != j){
numList.add(numbers[i] + numbers[j]);
// System.out.println(numList);
}
}
}
HashSet<Integer> hashSet= new HashSet<>();
for(int num : numList){
hashSet.add(num);
}
int[] answer = new int[hashSet.size()];
int idx = 0;
for(int setNum : hashSet){
answer[idx] = setNum;
idx++;
}
Arrays.sort(answer);
return answer;
}
}
- try_2 : PriorityQueue를 이용해서 2중 for문을 줄이려고 했지만 딱히 의미는 없었던 것 같다.
- 여기서, Arrays.sort()가 핵심이었고 Set 사용시, forEach문을 사용하는 것이 무난하고 여기에 while문에서 배열에 값 넣어주기 위해서
i++
이용하기! 처음에는i++
이용할 것을 생각 못했다.
- 여기서, Arrays.sort()가 핵심이었고 Set 사용시, forEach문을 사용하는 것이 무난하고 여기에 while문에서 배열에 값 넣어주기 위해서
import java.util.*;
class Solution {
public int[] solution(int[] numbers) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
Arrays.sort(numbers);
List<Integer> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
for(int num : numbers){
pq.offer(num);
list.add(num);
}
int num1 = 0;
while(!pq.isEmpty()){
num1 = pq.poll();
for(int i = 1; i < list.size(); i++){
if(num1 != list.get(i-1))
set.add(list.get(i-1) + num1);
if(list.get(i-1) == list.get(i))
set.add(list.get(i-1) + list.get(i));
}
}
int[] answer = new int[set.size()];
int i = 0;
for(int num : set){
answer[i] = num;
i++;
}
Arrays.sort(answer);
return answer;
}
}
15) 2016년
- a값에 따라서 b값이 달라지게 노가다!
- 다시 한번 더 풀기!
- 64점까지만 풀음.
- 코드 :
class Solution {
public String solution(int a, int b) {
String[] weeks = {"SUN","MON","TUE","WED","THU","FRI","SAT"};
// 2. 두 번째 풀이: 참고한 것 응용(로직 이용) : 64점
int[] days = {31,29,31,30,31,30,31,31,30,31,30,31};
String answer = "";
int daySum = 0;
int day = 0;
for(int i = 0; i < a; i++){
daySum += days[i];
}
if(daySum > 0){
daySum = daySum + b;
day = (daySum + 1) % 7;
}
return weeks[day];
// 1. 첫번째 풀이: 내 풀이(35점)
// a 값에 따라서 b 값이 달라지게 노가다!
// if(a == 1){
// return weeks[(b+4) % 7];
// }
// else if(a == 2){
// return weeks[b % 7];
// }
// else if(a < 8 && a > 2){
// return weeks[(b-1) % 7];
// }
// else{
// return weeks[(b+4) % 7];
// }
}
}
- try_2 : 월별 일 수를 일반적인 범위로 분기 처리할 수 없기에 배열에 지정해놓고 사용하자!!
- 더해지는 순서 주의!!
class Solution {
public String solution(int a, int b) {
String answer = "";
String[] dd = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
int[] days = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int sum = 0;
int num = 0;
for(int i = 0; i < a - 1; i++){
sum += days[i];
}
sum += b - 1;
num = sum % 7;
answer = dd[(num + 5) % 7];
return answer;
}
}
16) 폰켓몬
-
HashSet 사용 방법!
-
이부분 주의!
- count가 일치하지 않아서 nums.length 보다 클 값일 경우 처리하는 방법
if(hashSet.size() > (nums.length/2)){
count = nums.length/2;
}
- 코드 :
import java.util.*;
class Solution {
public int solution(int[] nums) {
int[] result = new int[nums.length];
int answer = 0;
HashSet<Integer> hashSet = new HashSet<>();
Random random = new Random();
for(int i = 0; i < nums.length; i++){
for(int j = 0; j < nums.length/2; j++){
hashSet.add(nums[random.nextInt(nums.length)]);
}
}
int count = 0;
for(int num: hashSet){
if(hashSet.size() > (nums.length/2)){
count = nums.length/2;
}
else {
count++;
}
}
answer = count;
return answer;
}
}
- try_2 : 단순히 객체 크기의 최소값이 중요하다고 판단해서 크기로 비교하여 결론을 냈다. 위의 방식보다 더 간단한 것 같다.
import java.util.*;
class Solution {
public int solution(int[] nums) {
int answer = 0;
int N = nums.length / 2;
Set<Integer> set = new HashSet<>();
for(int num : nums){
set.add(num);
}
if(set.size() > N)
answer = N;
else
answer = set.size();
return answer;
}
}
17) 모의고사
- 첫번째 풀이 : 테케 2개 중 2개 다 통과하지만 테스트 결과에서 (20점)이라서 다시 풀기!
import java.util.*;
class Solution {
public int[] solution(int[] answers) {
int[] person1 = {1, 2, 3, 4, 5};
int[] person2 = {2, 1, 2, 3, 2, 4, 2, 5};
int[] person3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int[] count = new int[3];
for(int i = 0; i < answers.length; i++){
if(answers[i] == person1[i % 4]){
count[0]++;
}
if(answers[i] == person2[i % 7]){
count[1]++;
}
if(answers[i] == person3[i % 9]){
count[2]++;
}
}
Arrays.sort(count);
int result_count = 0;
if(count[0] == Math.max(count[0], Math.max(count[1], count[2])))
result_count++;
if(count[1] == Math.max(count[0], Math.max(count[1], count[2])))
result_count++;
if(count[2] == Math.max(count[0], Math.max(count[1], count[2])))
result_count++;
int[] answer = new int[result_count];
for(int i = 0 ; i < result_count; i++){
answer[i] = i+1;
}
return answer;
}
}
- try_2 :
- 정리하자면, 문제 조건을 제대로 파악하기!! 최대값을 구하는 과정을 Math.max를 반복하여 구할 수도 있다.
-
두 번째 시도했던 코드에서 지금은 주석처리 된 부분을 보면 가장 중요한 부분이 정확하게 구현되지 않았다. 가장 많은 문제를 맞힌 사람을 찾는 로직에서, 현재
count
변수를 사용해 맞힌 문제의 수가 0보다 큰 경우를 카운팅하고 있다. 이 부분은 잘못된 접근이다. 여기서는 최대 점수를 받은 사람이 누구인지와 가장 높은 점수를 받은 사람이 여럿일 경우 그 사람들 모두를 반환해야 한다. 따라서, 최대 점수를 구한 뒤, 해당 최대 점수와 동일한 점수를 가진 수포자들을 결과 배열에 추가하는 과정을 재검토해야 한다. - 즉, 마지막에 결과 배열을 채우는 로직에서 현재
count
의 길이를 기준으로 배열을 채우고 있지만, 이 방법은 최대 점수를 가진 수포자의 인덱스를 정확히 파악하고 배열에 추가하는 일을 처리하지 못한다. 다시 말해서, 모든 수포자의 점수를 비교한 뒤, 최고 점수와 같은 점수를 가진 모든 수포자를 정확히 식별하고, 이들의 번호(1, 2, 3)을 오름차순으로 배열에 추가해야 한다. 이미 계산된maxNumber
를 사용하여check
배열을 다시 반복하면서maxNumber
와 같은 값을 가진 수포자들만 결과 배열에 추가하는 방식으로 로직을 수정해 볼 수 있겠다.
import java.util.*;
class Solution {
public int[] solution(int[] answers) {
int[] p1 = {1, 2, 3, 4, 5};
int[] p2 = {2, 1, 2, 3, 2, 4, 2, 5};
int[] p3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int[] check = new int[3];
int i = 0;
int j = 0;
int k = 0;
for(int ans : answers){
if(ans == p1[i % p1.length]){
check[0]++;
}
if(ans == p2[j % p2.length]){
check[1]++;
}
if(ans == p3[k % p3.length]){
check[2]++;
}
i++;
j++;
k++;
}
// 문제 방향이 max 값으로 비교하는 문제라서 이렇게 아래처럼 주석된 부분처럼 설계하면 안된다. 출제자의 의도!!
// int count = 0;
// for(int chk : check){
// if(chk > 0)
// count++;
// System.out.println(chk);
// }
// int[] answer = new int[count];
// for(int l = 0; l < count; l++){
// if(check[l] == maxNumber){
// answer[l] = l+1;
// }
// }
// Arrays.sort(answer);
int maxNumber = Math.max(check[0], Math.max(check[1], check[2]));
List<Integer> list = new ArrayList<>();
for(int l = 0; l < check.length; l++){
if(check[l] == maxNumber){
list.add(l+1);
}
}
int[] answer = new int[list.size()];
for(int n = 0; n < list.size(); n++){
answer[n] = list.get(n);
}
Arrays.sort(answer);
return answer;
}
}
18) 실패율K*
- 다시 풀기!!(어렵다.)
import java.util.*;
class Solution {
public int[] solution(int N, int[] stages) {
double[] per = new double[N];
double[] place = new double[N];
int[] answer = new int[N];
int count = 0;
for(int i = 0; i < stages.length; i++){
for(int j = 0; j < N; j++){
if(stages[i] == j+1){
if(j == 0) {
per[j] += (j+1) / (stages.length - count); // (2/7)
place[j] += (j+1) / (stages.length - count);
}
else {
per[j] += j+1 / (stages.length - count); // (2/7)
place[j] += j+1 / (stages.length - count);
}
count++;
System.out.println(per[j]);
}
}
}
Arrays.sort(per);
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
if(place[i] == per[j]) {
answer[N-j-1] = i+1;
}
}
}
return answer;
}
}
- try_2: 위의 다른 문제들처럼 최대값 같이 값을 하나 고정해놓고 리스트들을 비교하면 단순히 List로 설계해서 값을 비교하면 되는데 2개의 값을 동시에 컨트롤 하는 경우는 객체를 하나 만들어서 개별로 정렬 해주는 것이 편하다!!(Collection.sort 이용하는 방법!!)
- 또한, 문제의 모든 조건을 추가해주기!! ‘0’을 처리하는 조건들!!
- 성능 측면:
- 효율성: 수만 건의 데이터에 대해서도 Timsort는 효율적으로 작동합니다. 일반적으로 Java의 기본 정렬 구현은 다양한 상황에서 잘 동작하도록 최적화되어 있습니다.
- 정렬 기준: 두 가지 기준(실패율과 스테이지 번호)에 따라 정렬하므로 추가적인 비교가 필요합니다. 하지만 이는 정렬의 복잡도를 증가시키지 않으며, 일반적으로 성능에 큰 영향을 미치지 않습니다.
- 메모리 사용: 리스트를 사용하여 객체를 저장하고 정렬하기 때문에 추가적인 메모리 사용이 필요합니다. 수만 건의 데이터가 들어가더라도 Java의 메모리 관리가 효과적으로 작동합니다.
- 결론:
- 수만 건의 데이터 처리는 충분히 가능하며, 이 코드의 정렬 로직은 효율적입니다.
- 만약 데이터의 양이 100만 건 이상으로 증가할 경우 성능에 영향을 받을 수 있지만, 일반적인 사용에서는 문제가 되지 않습니다.
- 성능 최적화를 고려해야 하는 경우, 상황에 따라 데이터 구조나 정렬 알고리즘을 조정할 수 있습니다. 예를 들어, 데이터의 특정 성격(예: 이미 부분적으로 정렬됨)을 활용할 수도 있습니다.
import java.util.*;
class Solution {
public int[] solution(int N, int[] stages) {
List<failureStructure> failList = new ArrayList<>();
Double[] num = new Double[N];
int result = 0;
double bottom = stages.length - result;
for(int j = 0; j < N; j++){
int count = 0;
for(int i = 0; i < stages.length; i++){
if(stages[i] == j+1){
count++;
}
}
if(count != 0.0)
num[j] = (double) count / (double) (bottom);
else
num[j] = 0.0;
result = count;
bottom = bottom - result;
failList.add(new failureStructure(j, num[j]));
}
Collections.sort(failList, (o1,o2) -> {
if(Double.compare(o2.failure, o1.failure) != 0)
return Double.compare(o2.failure, o1.failure); // 기본적으로 실패율에서 내림차순으로 객체 정렬
else
return Integer.compare(o1.stage, o2.stage); // 실패율 값이 동일하면, stage 숫자가 적은 순으로 정렬
});
int[] answer = new int[N];
for(int k = 0; k < N; k++){
answer[k] = failList.get(k).stage + 1;
}
return answer;
}
// 객체 사용하기!!
static class failureStructure{
int stage;
double failure;
failureStructure(int stage, double failure){
this.stage = stage;
this.failure = failure;
}
}
}
19) 다트 게임K
- 첫번 째 풀이 :
- 테케 3개만 성공
- 이렇게 풀면 ‘#’이 해결이 안된다.
import java.util.*;
class Solution {
public int solution(String dartResult) {
String[] arr1 = dartResult.split("");
int answer = 0;
int buffer = 0;
for(int i = 0; i < arr1.length; i++){
if((arr1[i].charAt(0) - '0') <= 9 && (arr1[i].charAt(0) - '0') >= 0){
if((arr1[i].charAt(0) - '0') == 1 && (arr1[i+1].charAt(0) - '0') == 0){
buffer = 10;
i++;
}
else{
buffer = arr1[i].charAt(0) - '0';
}
System.out.println(buffer);
}
else if(((int) arr1[i].charAt(0)) >= 20){
if(arr1[i].charAt(0) == 'S') {
answer += (int) Math.pow(buffer, 1);
}
else if(arr1[i].charAt(0) == 'D') {
answer += (int) Math.pow(buffer, 2);
}
else if(arr1[i].charAt(0) == 'T') {
answer += (int) Math.pow(buffer, 3);
}
else if(arr1[i].charAt(0) == '*'){
answer = answer * 2;
}
if(arr1[i].charAt(0) == '#'){
answer += buffer * (-1);
}
}
}
return answer;
}
}
- 두번째 풀이 :
- 다트 3회 기회에 대해 따로 처리해야 된다.
- 결과 값이 ‘10’을 처리하는 방법 유의!
- 결과 값 2배 연속 처리되는 ‘*’ 처리 방법 유의!
import java.util.*;
class Solution {
public int solution(String dartResult) {
String[] arr1 = dartResult.split("");
int answer = 0;
int[] buffer = new int[3];
int count = 0;
for(int i = 0; i < arr1.length; i++){
if((arr1[i].charAt(0) - '0') <= 9 && (arr1[i].charAt(0) - '0') >= 0){
if((arr1[i].charAt(0) - '0') == 1 && (arr1[i+1].charAt(0) - '0') == 0){
buffer[count] = 10;
count++;
i++;
}
else{
buffer[count] = arr1[i].charAt(0) - '0';
count++;
}
System.out.println(buffer[count-1]);
}
else if(((int) arr1[i].charAt(0)) >= 20){
if(arr1[i].charAt(0) == 'S') {
buffer[count-1] = (int) Math.pow(buffer[count-1], 1);
}
else if(arr1[i].charAt(0) == 'D') {
buffer[count-1] = (int) Math.pow(buffer[count-1], 2);
}
else if(arr1[i].charAt(0) == 'T') {
buffer[count-1] = (int) Math.pow(buffer[count-1], 3);
}
else if(arr1[i].charAt(0) == '*'){
if(count == 1)
buffer[count-1] = buffer[count-1] * 2;
else{
buffer[count-2] = buffer[count-2] * 2;
buffer[count-1] = buffer[count-1] * 2;
}
}
if(arr1[i].charAt(0) == '#'){
buffer[count-1] = buffer[count-1] * (-1);
}
}
}
answer = buffer[0] + buffer[1] + buffer[2];
return answer;
}
}
- try_2 : 이게 더 간단한 느낌이지만, 다트의 순서가 반복되면서 행해지는 일련의 과정들을 일일이 생각해야 한다!!
- 내가 문제를 잘 못 읽었었다.
7. 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
이부분!! - 숫자 10 때문에 StringBuilder를 사용할 수 밖에 없다.
- 내가 문제를 잘 못 읽었었다.
import java.util.*;
class Solution {
public int solution(String dartResult) {
int answer = 0;
String[] arrayDart = dartResult.split("");
int count = 0;
int[] dartSplit = new int[3];
StringBuilder sb = new StringBuilder();
for(int i = 0; i < dartResult.length(); i++){
char c = dartResult.charAt(i);
if(Character.isDigit(c)){
sb.append(c);
}
if(c == 'S' || c == 'D' || c == 'T'){
int score = Integer.parseInt(sb.toString());
if(c == 'S') {
dartSplit[count] = score;
sb.setLength(0);
} else if(c == 'D'){
dartSplit[count] = score * score;
sb.setLength(0);
} else if(c == 'T'){
dartSplit[count] = score * score * score;
sb.setLength(0);
}
count++;
} else if(c == '#' || c == '*'){
if(c == '#') {
dartSplit[count - 1] *= (-1);
} else if(c == '*'){
dartSplit[count - 1] *= 2;
if(count > 1)
dartSplit[count - 2] *= 2;
}
}
}
for(int sc : dartSplit){
answer += sc;
}
return answer;
}
}
20) 체육복
- 정렬 하는 이유 주의! : 반례
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = 0;
answer = n - lost.length;
Arrays.sort(lost);
Arrays.sort(reserve);
for(int i = 0; i < reserve.length; i++){
for(int j = 0; j < lost.length; j++){
// lost와 reserve가 같다면,
// (n - lost.length)에 의해 빠졌기 때문에 더 해준다.
if(reserve[i] == lost[j]) {
answer++;
lost[j] = -1;
reserve[i] = -1;
}
}
}
for(int i = 0; i < reserve.length; i++){
for(int j = 0; j < lost.length; j++){
if( (reserve[i] == lost[j] - 1) || (reserve[i] == lost[j] + 1)) {
answer++;
lost[j] = -1;
reserve[i] = -1;
}
}
}
return answer;
}
}
- try_2 : 이 방식이 더 직관적이다. 위의 방식에서는
lost[j] = -1, reserve[i] = -1
가 이해가 안간다..- 체육복을 앞사람이나 뒷사람에만 주는 것에 관한 조건을 인지하기!!
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = 0;
int[] students = new int[n+1];
for(int l : lost){
students[l]--;
}
for(int r : reserve){
students[r]++;
}
for(int i = 1; i <= n; i++){
if(students[i] == -1){
if(i > 1 && students[i - 1] == 1){
students[i]++;
students[i - 1]--;
}
else if(i < n && students[i + 1] == 1){
students[i]++;
students[i + 1]--;
}
}
}
for(int i = 1; i <= n; i++){
if(students[i] >= 0){
answer++;
}
}
return answer;
}
}
21) 완주하지 못한 선수*
- 첫번째 풀이 : 효율성 때문에 ArrayList 정렬 이용하기!
- 100,000명 이하라서 for문 2번을 사용하면 시간초과된다.(Big-O)
import java.util.*;
class Solution {
public String solution(String[] participant, String[] completion) {
String answer = "";
boolean[] isChecked = new boolean[participant.length];
// Arrays.sort 정렬가 효율성 증대 시킴!
// 이보다 더 효율이 좋은 것이 해시이다.
Arrays.sort(participant);
Arrays.sort(completion);
int i= 0;
for(i = 0; i < completion.length; i++){
if(!participant[i].equals(completion[i]))
break;
}
return participant[i]; // 예외처리 때문에 필요!
// 마지막 선수가 도착하지도 않았는데 조회가 끝나는 경우(for문 동작 방식)
}
}
- 두번째 풀이 : 해시 이용하기! key-value라서 검색 시, 빠르다!
import java.util.*;
class Solution {
public String solution(String[] participant, String[] completion) {
String answer = "";
// https://coding-grandpa.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%99%84%EC%A3%BC%ED%95%98%EC%A7%80-%EB%AA%BB%ED%95%9C-%EC%84%A0%EC%88%98-%ED%95%B4%EC%8B%9C-Lv-1
// https://dos-soles.tistory.com/23
Map<String, Integer> hashMap = new HashMap<>();
// count하는 것과 같다. 대신 hashMap에서 count하는 방법!
for(String p : participant) {
hashMap.put(p, hashMap.getOrDefault(p,0)+1);
}
for(String c : completion) {
hashMap.put(c, hashMap.getOrDefault(c,0)-1);
}
for(String k : hashMap.keySet()){
if(hashMap.get(k) != 0){
answer = k;
}
}
return answer;
}
}
- try_2 : List, PriorityQueue를 이용해서 풀고자 함.
- 입력값이 크기 때문에 시간복잡도가 중요해서 정렬을 사용해야 했고 같은 이름의 선수가 달리는 경우를 처리해주는 예외처리가 중요하다.
import java.util.*;
class Solution {
public String solution(String[] participant, String[] completion) {
// String answer = "";
// // 1번째 풀이
// List<String> plist = new ArrayList<>();
// List<String> clist = new ArrayList<>();
// for(String p : participant){
// plist.add(p);
// }
// for(String c : completion){
// clist.add(c);
// }
// Collections.sort(plist, (o1,o2) -> o1.compareTo(o2));
// Collections.sort(clist, (o1,o2) -> o1.compareTo(o2));
// for(int i = 0; i< clist.size(); i++){
// if(!(plist.get(i)).equals(clist.get(i))){
// return plist.get(i);
// }
// }
// answer = plist.get(plist.size()-1);
// return answer;
// 2번째 풀이:
String answer = "";
PriorityQueue<String> pq = new PriorityQueue<>();
PriorityQueue<String> cq = new PriorityQueue<>();
for(String p : participant){
pq.offer(p);
}
for(String c : completion){
cq.offer(c);
}
System.out.printf("pq: %s\n", pq);
System.out.printf("cq: %s\n", cq);
while(!pq.isEmpty()){
String p1 = pq.poll();
String c1 = cq.poll();
if(!p1.equals(c1)){
return p1;
}
}
answer = cq.poll().toString();
return answer;
}
}
-
로그 분석 1
-
파싱하는거 다시 암기하기!!(중요!!)**
- 예측 실행 결과
192.168.0.1 (2)
192.168.0.2 (3)
192.168.0.3 (1)
- 코드 :
package com.wogjs0911.codetest.acro;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class Java1 {
public static void main(String[] args) {
String[] input = new String[]{
"1622025201 REQUEST 10001 192.168.0.1",
"1622025202 REQUEST 10002 192.168.0.2",
"1622025203 REQUEST 10003 192.168.0.1",
"1622025211 RESPONSE 10003",
"1622025212 RESPONSE 10002",
"1622025213 RESPONSE 10001",
"1622025221 REQUEST 10004 192.168.0.2",
"1622025223 REQUEST 10005 192.168.0.2",
"1622025230 RESPONSE 10004",
"1622025231 REQUEST 10006 192.168.0.3",
"1622025236 RESPONSE 10006"
};
String[] logType = new String[4];
String ip = "";
List<String> arr = new ArrayList<>();
HashSet<String> hashSet = new HashSet<>();
for(int i = 0; i < input.length; i++) {
logType = input[i].split(" ");
if(logType[1].equals("REQUEST")) {
ip = logType[3];
arr.add(ip);
hashSet.add(ip);
}
}
int[] cntHash = new int[hashSet.size()];
int cnt = 0;
for(String hs : hashSet) {
for(int i = 0; i < arr.size(); i++) {
if(hs.equals(arr.get(i))) {
cntHash[cnt]++;
}
}
cnt++;
}
String[] answer = new String[hashSet.size()];
int idx = 0;
for(String hs : hashSet) {
answer[idx] = hs;
idx++;
}
Map<String, Integer> hm = new HashMap<>();
for(int i = 0; i < cnt; i++) {
// System.out.printf("%s (%d)\n", answer[i], cntHash[i]);
hm.put(answer[i], cntHash[i]);
}
Arrays.sort(answer);
for(String ans : answer) {
System.out.printf("%s (%d)\n", ans, hm.get(ans));
}
}
}
- 로그 분석 2
- 예측 실행 결과
10001 1622025201 12sec
10002 1622025202 10sec
10003 1622025203 8sec
10004 1622025221 9sec
10005 1622025223 FAIL
10006 1622025231 5sec
- 실습 코드 :
- TreeMap 사용 주의!! or getOrDefault
package com.wogjs0911.codetest.acro;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Java2 {
public static void main(String[] args) {
String[] input = new String[]{
"1622025201 REQUEST 10001 192.168.0.1",
"1622025202 REQUEST 10002 192.168.0.2",
"1622025203 REQUEST 10003 192.168.0.1",
"1622025211 RESPONSE 10003",
"1622025212 RESPONSE 10002",
"1622025213 RESPONSE 10001",
"1622025221 REQUEST 10004 192.168.0.2",
"1622025223 REQUEST 10005 192.168.0.2",
"1622025230 RESPONSE 10004",
"1622025231 REQUEST 10006 192.168.0.3",
"1622025236 RESPONSE 10006"
};
String[] logType = new String[4];
String id = "";
Integer time = 0;
Map<String,Integer> hm1 = new HashMap<>();
Map<String,Integer> hm2 = new HashMap<>();
for(int i = 0; i < input.length; i++) {
logType = input[i].split(" ");
if(logType[1].equals("REQUEST")) {
id = logType[2];
time = Integer.parseInt(logType[0]);
hm1.put(id, time);
}
}
for(int i = 0; i < input.length; i++) {
logType = input[i].split(" ");
if(logType[1].equals("RESPONSE")) {
id = logType[2];
time = Integer.parseInt(logType[0]);
hm2.put(id, time);
}
}
// TreeMap 기본은 문자열 오름차순 정렬이고
// TreeMap에 new Comparator<T>()로 재정의해서 사용하면 문자열 내림차순 정렬도 가능하다.
Map<String, Integer> treeMap1 = new TreeMap<>(hm1);
Map<String, Integer> treeMap2 = new TreeMap<>(hm2);
for(String rId : treeMap1.keySet()) {
int checkTime = treeMap2.getOrDefault(rId,0) - treeMap1.getOrDefault(rId,0);
// String result = "";
if(checkTime < 0) {
String result = "";
result = "FAIL";
System.out.printf("%s %d %s\n", rId , treeMap1.get(rId), result);
}
else {
System.out.printf("%s %d %s\n", rId , treeMap1.get(rId), checkTime);
}
}
}
}
22) 완크레인 인형뽑기 게임K
- 첫 번째 풀이 방법 : 다시 풀기
- 에러 발생!
import java.util.*;
class Solution {
public int solution(int[][] board, int[] moves) {
int answer = 0;
List<Integer> buffer = new ArrayList<>();
// moves의 인자가 board의 인자 중 x 값을 의미한다.
for(int k = 0; k < moves.length; k++){
for(int j = 0; j < board.length; j++){
if(board[j][moves[k]-1] > 0){
buffer.add(board[moves[k]-1][j]);
break;
}
}
System.out.println(buffer.get(k));
}
for(int i = 1; i < buffer.size(); i++){
if(buffer.get(i-1) == buffer.get(i)){
answer += 2;
buffer.remove(i-1);
buffer.remove(i);
}
}
return answer;
}
}
- 두 번째 풀이 방법 :
- 1번 테스트에서만 에러, 나머지는 통과 : 두번째 for문 인덱스 문제?
- ArrayList에서 remove 메서드 이용 시, 인덱스 주의하기! remove되면 사라지므로 ‘i–‘로 줄여야 한다.
- 해결방법 : i가 리스트의 remove 메서드와 ‘i–‘에 의해서 음수가 되면 인덱스 에러가 발생하므로 음수가 될 경우, ‘i++’을 해준다.
- 즉, 리스트 원소 제거 시, 인덱스 더욱 주의하기!!
import java.util.*;
class Solution {
public int solution(int[][] board, int[] moves) {
// sqld 기출 : https://yunamom.tistory.com/265#answer1
List<Integer> buffer = new ArrayList<>();
// moves의 인자가 board의 인자 중 x값을 의미한다.
for(int k = 0; k < moves.length; k++){
for(int j = 0; j < board[0].length; j++){
if((board[j][moves[k]-1]) > 0){
buffer.add(board[j][moves[k]-1]);
board[j][moves[k]-1] = 0;
break;
}
}
}
int answer = 0;
for(int i = 1; i < buffer.size(); i++){
if((buffer.size() >= 2) && (buffer.get(i-1) == buffer.get(i)) ){
int r1 = buffer.remove(i--);
int r2 = buffer.remove(i--);
// i가 리스트의 remove 메서드와 i--에 의해서 음수가 되면
// 인덱스 에러가 발생하므로 음수가 될 경우, i++을 해준다.
// 리스트 원소 제거 시, 인덱스 더욱 주의하기!!
if(i < 0){
i++;
}
answer += 2;
}
}
return answer;
}
}
- try_2 : 재귀함수를 이용하여 풀고자함.. isChecked를 쓰는 이유는 더 명확하게 재귀함수를 쓰기 위해서이다. 리스트의 원소가 삭제되면 리스트의 인덱스가 변경되기 때문에 인덱스를 확신할 수 없어서
list.remove(k);
와list.remove(k - 1);
의 순서가 중요한 이유 : 리스트의 인덱스가 변경되기 때문[1,2,3,4]
배열에서[2,3]
을 k-1, k번째 index로 지우게 되는 방식을 순서 바꿔가면서 생각해보기!! 지워지면서 전체 인덱스가 지워지게 되어서 뒤에서 부터 지우는게 맞다!!
import java.util.*;
class Solution {
public int solution(int[][] board, int[] moves) {
int answer = 0;
List<Integer> list = new ArrayList<>();
for(int i = 0; i < moves.length; i++){
for(int j = 0; j < board.length; j++){
if(board[j][moves[i] - 1] > 0){
list.add(board[j][moves[i] - 1]);
board[j][moves[i] - 1] = 0;
break;
}
}
}
int firstSize = list.size();
answer = firstSize - checkReturn(list);
return answer;
}
private int checkReturn(List<Integer> list){
boolean isChecked = false;
for(int k = 1; k < list.size(); k++){
if(list.get(k-1) == list.get(k)){
list.remove(k);
list.remove(k-1);
isChecked = true;
}
}
if(isChecked)
return checkReturn(list);
return list.size();
}
}
23) 신규 아이디 추천K
- 첫 번째 풀이 방법 :
- 복잡하게 풀었다. 수정하기!
- 기본 제공 메서드를 이용하면 훨씬 쉬워진다!
import java.util.*;
class Solution {
public String solution(String new_id) {
String[] spl = new_id.split("");
List<String> testTxt = new ArrayList<>();
// ** 1
for(int i = 0; i < spl.length; i++){
testTxt.add(spl[i].toLowerCase());
// System.out.println(testTxt.get(i));
}
// ** 2
for(int i = 0; i < spl.length; i++){
if(!((testTxt.get(i)).matches(".*[a-z].*")) && !((testTxt.get(i)).matches(".*[0-9].*")) && !((testTxt.get(i)).equals("-")) && !((testTxt.get(i)).equals("_")) && !((testTxt.get(i)).equals(".")) ){
testTxt.remove(i--);
if(i < 0){
i++;
}
}
// System.out.println(testTxt.get(i));
}
// ** 3
for(int i = 1; i < spl.length+1; i++){
if(testTxt.get(i-1).equals(".") && testTxt.get(i-1).equals(testTxt.get(i))){
testTxt.remove(i--);
if(i<0)
i++;
}
}
// ** 4
if((testTxt.get(0)).equals(".")){
testTxt.remove(0);
if((testTxt.get(testTxt.size()-1).equals(".")))
testTxt.remove(testTxt.size()-1);
}
// ** 5
for(int i = 0; i< testTxt.size(); i++){
if(testTxt.isEmpty() || (!(testTxt.get(i)).equals("^[a-z]*$"))){
testTxt.remove(i--);
if(i < 0)
i++;
testTxt.add("a");
}
}
// ** 6
for(int i = 0; i< testTxt.size(); i++){
if(testTxt.size() > 15)
testTxt.remove(testTxt.size()-i-1);
if((testTxt.get(testTxt.size()-1).equals(".")))
testTxt.remove(testTxt.size()-1);
}
// ** 7
if(testTxt.size() <= 2 ){
for(int i = 0; i < 3; i++){
testTxt.add(testTxt.get(testTxt.size()-1));
}
}
String answer = "";
for(int i = 0; i< testTxt.size(); i++){
answer += testTxt.get(i);
}
return answer;
}
}
- 두 번째 풀이 방법 :
- 기본 제공 메서드를 이용하면 훨씬 쉬워진다!
- 정규식 눈에 익혀두기
- 말 그대로 replace는 첫번째 인자값을 보시면 문자열이 들어갑니다. 문자열만 변환가능한데 반해서
- replaceAll은 첫번째 인자값에 정규식이 들어갑니다
- String 메서드 공부 : replace, repalceAll, substring, split 구별하기!
- 더불어 : chartAt, indexOf, trim, toUpperCase, toLowerCase, isEmpty, concat, getBytes(byte 배열로 반환하는 메서드)
import java.util.*;
class Solution {
public String solution(String new_id) {
String answer = "";
// ** 1
answer = new_id.toLowerCase();
// ** 2
answer = answer.replaceAll("[^a-z0-9-_.]","");
// ** 3
answer = answer.replaceAll("\\.{2,}",".");
// ** 4
answer = answer.replaceAll("^[.]|[.]$","");
// ** 5
answer = answer.equals("") ? "a" : answer;
// ** 6-1
answer = answer.length() >= 16? answer.substring(0,15) : answer;
// ** 6-2
answer = answer.replaceAll("[.]$", "");
// ** 7
// char last = answer.charAt(answer.length()-1);
String last = answer.substring(answer.length()-1,answer.length());
if(answer.length() <= 2){
while(answer.length() < 3){
answer += last;
}
}
return answer;
}
}
- try_2 : replaceAll, substring 문법 주의!!
- charAt으로 하면 index가 마이너스일 경우가 있어서 에러 발생 확률이 높다.
- 앞에 값이나 마지막 값을 표현하기 위해서 replaceAll 대신에 substring을 이용해도 된다.
import java.util.*;
class Solution {
public String solution(String new_id) {
String answer = "";
System.out.println(new_id.length());
if(new_id.length() > 0){
new_id = new_id.toLowerCase();
String match = "[^a-z0-9-_.]";
new_id = new_id.replaceAll(match, "");
new_id = new_id.replaceAll("\\.{2,}", ".");
if(new_id != null && new_id.length() > 0 && new_id.startsWith(".")){
new_id = new_id.substring(1);
}
if(new_id != null && new_id.length() > 0 && new_id.endsWith(".")){
new_id = new_id.substring(0, new_id.length()-1);
}
if(new_id.length() >= 16){
new_id = new_id.substring(0, 15);
if(new_id.endsWith("."))
new_id = new_id.substring(0, new_id.length()-1);
}
if (new_id.isEmpty()) {
new_id = "a";
}
while(new_id.length() < 3)
new_id += new_id.substring(new_id.length() - 1, new_id.length());
}
answer = new_id;
return answer;
}
}
24) 성격 유형 검사하기K*
- 첫 번째 풀이 : 그냥 노가다로 풀어서 테케는 통과하지만 10점
- 다시 풀기
class Solution {
public String solution(String[] survey, int[] choices) {
// choices가 4보다 작으면, survey는 왼쪽 알파벳 초이스
// 4보다 크면, survey는 오른쪽 알파벳 초이스
String[][] buffer = new String[4][2];
int[][] score = new int[4][2];
System.out.println(choices.length);
for(int i = 0; i < choices.length; i++){
if(survey[i].equals("RT") || survey[i].equals("TR")){
if(choices[i] > 4){
buffer[0][1] = survey[i].substring(1,2);
score[0][1] = choices[i];
}
else{
buffer[0][0] = survey[i].substring(0,1);
score[0][0] = choices[i];
}
}
else{
continue;
}
}
for(int i = 0; i < choices.length; i++){
if(survey[i].equals("CF") || survey[i].equals("FC")){
if(choices[i] > 4){
buffer[1][1] = survey[i].substring(1,2);
score[1][1] = choices[i];
}
else{
buffer[1][0] = survey[i].substring(0,1);
score[1][0] = choices[i];
}
}
else{
continue;
}
}
for(int i = 0; i < choices.length; i++){
if(survey[i].equals("JM") || survey[i].equals("MJ")){
if(choices[i] > 4){
buffer[2][1] = survey[i].substring(1,2);
score[2][1] = choices[i];
}
else{
buffer[2][0] = survey[i].substring(0,1);
score[2][0] = choices[i];
}
}
else{
continue;
}
}
for(int i = 0; i < choices.length; i++){
if(survey[i].equals("AN") || survey[i].equals("NA")){
if(choices[i] > 4){
buffer[3][1] = survey[i].substring(1,2);
score[3][1] = choices[i];
}
else{
buffer[3][0] = survey[i].substring(0,1);
score[3][0] = choices[i];
}
}
else{
continue;
}
}
String answer = "";
for(int i = 0; i < 4; i++){
if(score[i][1] > 4){
if(score[i][1] == 0){
if(i == 0){
answer += "R";
}
else if(i == 1){
answer += "C";
}
else if(i == 2){
answer += "J";
}
else if(i == 3){
answer += "A";
}
}
else{
answer += buffer[i][1];
}
}
else{
if(score[i][0] == 0){
if(i == 0){
answer += "R";
}
else if(i == 1){
answer += "C";
}
else if(i == 2){
answer += "J";
}
else if(i == 3){
answer += "A";
}
}
else{
answer += buffer[i][0];
}
}
}
return answer;
}
}
- 두 번째 풀이 :
- 정리된 풀이
- 어렵다.. 반복해서 볼 것
import java.util.*;
class Solution {
public String solution(String[] survey, int[] choices) {
Map<Character, Integer> hm = new HashMap<>();
// choices가 4보다 작으면, survey는 왼쪽 알파벳 초이스
// 4보다 크면, survey는 오른쪽 알파벳 초이스
for(int i = 0; i< survey.length; i++) {
int val = choices[i];
if(val > 0 && val < 4){ // 4보다 작으면 4만큼 더해주고
char c = survey[i].charAt(0);
hm.put(c, hm.getOrDefault(c,0) + 4 - val);
// hm.getOrDefault(c,0)는 중복 체크 때문에 필요하다!
}
else if(val > 4){ // 4보다 크면 4만큼 빼주고
char c = survey[i].charAt(1);
hm.put(c, hm.getOrDefault(c,0) + val - 4);
}
}
StringBuilder sb = new StringBuilder();
sb.append(hm.getOrDefault('R',0) >= hm.getOrDefault('T',0) ? 'R' : 'T');
sb.append(hm.getOrDefault('C',0) >= hm.getOrDefault('F',0) ? 'C' : 'F');
sb.append(hm.getOrDefault('J',0) >= hm.getOrDefault('M',0) ? 'J' : 'M');
sb.append(hm.getOrDefault('A',0) >= hm.getOrDefault('N',0) ? 'A' : 'N');
return sb.toString();
}
}
- try_2 : 위의 두번째 방식으로 풀어봤는데 아직 어렵다..
- 더 쉬운 방법이 있을까?
25) 신고 결과 받기K
- 다시 풀기!! : 테케 2개 중에서 1개만 통과
import java.util.*;
class Solution {
public int[] solution(String[] id_list, String[] report, int k) {
Map<String, Object> hm = new HashMap<>();
int[] answer = new int[id_list.length];
for(int i = 0; i < report.length; i++){
List<String> buffer = new ArrayList<>();
String[] rPeople = report[i].split(" ");
buffer.add(rPeople[1]);
hm.put(rPeople[0], buffer);
System.out.println(hm.get(rPeople[0]));
}
for(int i = 0; i < id_list.length; i++){
List<Object> buf = new ArrayList<>();
if(hm.getOrDefault(id_list[i],"") != ""){
buf.add(hm.get(id_list[i]));
if(k <= buf.size())
answer[i] = buf.size();
else{
answer[i] = 0;
}
}
}
return answer;
}
}
- try_2 : 중복 제거하는 추가해서 다시 풀기!!(Map, Set 이용해보기!!)
import java.util.*;
class Solution {
public int[] solution(String[] id_list, String[] report, int k) {
int[] answer = new int[id_list.length];
Map<String, Set<String>> reportMap = new HashMap<>();
Map<String, Integer> countMap = new HashMap<>();
for(String str1 : report){
String[] sp1 = str1.split(" ");
String reportUser = sp1[0];
String reportedUser = sp1[1];
reportMap.putIfAbsent(reportUser, new HashSet<>());
reportMap.get(reportUser).add(reportedUser);
countMap.put(reportedUser, countMap.getOrDefault(reportedUser, 0) + 1);
}
Set<String> set1 = new HashSet<>();
for(Map.Entry<String, Integer> entry : countMap.entrySet()){
if(entry.getValue() >= k){
set1.add(entry.getKey());
}
}
for(int i = 0; i < id_list.length; i++){
String userId = id_list[i];
if(reportMap.containsKey(userId)){
for(String reportUser : reportMap.get(userId)){
if(set1.contains(reportUser))
answer[i]++;
}
}
}
return answer;
}
}
26) 파일명 출력하기*
-
문자열들 중에서 파일명만 추출하기!
-
실행 결과 :
post abcd test.file cd
- 코드 :
package com.wogjs0911.codetest.byeol;
import java.util.*;
public class Java1 {
public static void main(String[] args) {
String[] files = new String[]{
"post.txt",
"c:\\test\\abcd.txt",
"home/src/test.file.txt",
"file/bro/cd.txt"
};
List<String> arr = new ArrayList<>();
for(int i = 0; i < files.length; i++) {
int idxs = files[i].lastIndexOf(".");
String file = files[i].substring(0, idxs);
files[i] = file;
}
for(int i = 0; i < files.length; i++) {
String[] file = files[i].split("\\\\");
files[i] = (file[file.length-1]);
}
for(int i = 0; i < files.length; i++) {
String[] file = files[i].split("/");
arr.add(file[file.length-1]);
}
for(int i = 0; i < arr.size(); i++) {
System.out.print(arr.get(i) + " ");
}
}
}
- 추가 문제 :
- 마지막에 변수명 추가하여 출력하기
- 리플렉션 이용하거나 다른 클래스 추가해서 사용하기