알고리즘 풀이 방법입니다.
문제(Problem) -> 생각(Think) -> 해결책(Solution) -> 리뷰(Review) 를 통해서 정리해서 작성합니다.
Problem📄

https://level.goorm.io/exam/43111/%ED%99%80%EC%A7%9D-%ED%8C%90%EB%B3%84/quiz/1

 

구름LEVEL

코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입니다. 기업에서 선호하는 C, C++, 파이썬(Python), 자바(Java), 자바스크립트(Javascript) 이

level.goorm.io


Think🤔

홀짝 판별하는 문제이다 홀수면 odd 짝수면 even을 출력하면 된다.

먼저 버퍼리더를 생성하고 값을 받아주는 input이 String 형태로 나와있다.

 

일단 먼저 input 값을 나누기 위해서는 숫자형으로 바꿔줄 필요가 있다.

int형으로 바꿔준 후 계산한다


Solution✍
import java.io.*;
class Main {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String input = br.readLine();
		
		int numberInput = Integer.parseInt(input);
		
		/*
		if(numberInput % 2 == 0){
			System.out.print("even");
		}else{
			System.out.print("odd");
		}
		*/
		
		 numberInput % 2 == 0 ? System.out.print("even") : System.out.print("odd");
	}
}

첫번째 if else를 이용해서 성공적으로 제출했다.

그리고 다른 삼항 연산자를 이용해서 풀었는데 정답이 나오지 않았다.

? 부분에서 에러가 났기 때문

 

왜 에러가났을까?

 

중간에 : 문을 빼먹었기 때문... 근데 돌아가지 않는다 이클립스로 확인해본다.

 

그리고 readLine을 사용할때 throw Exception 해주지 않거나 try-catch로 예외를 처리하지 않으면 readLine() 메서드에 에러가 나는 이유를 확인해보았다.

import java.io.*;
import java.lang.*;

class Main {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String input = br.readLine();
		
		int numberInput = Integer.parseInt(input);
		String answer = (numberInput % 2) == 0 ? "even" : "odd";
		
		System.out.print(answer);
		br.close(); // 버퍼리더 닫아주기
	}
}

 

작성했을때 in == null 이면 IOException을 던지는 구조이다.

아무것도 입력하지 않았을때 Reader가 프로그램에 인식하지 않고, 그러므로 예외처리를 던지기 때문이다.

 

그리고 리더로 작성하고 마지막에 닫을때는 close를 써주면 좋다.

close() 메소드를 명시 안해줘도 GC에 의해 내부객체들이 자동으로 정리된다.

하지만 GC에 의해서 자원이 정리되기 전에 연속/반복적으로 Buffereade가 close 되지 않고 사용되면

정상적으로 reading이 되지 않는다.


Review🤩

구름에서는 왜 처음에 BufferedReader를 사용할까? 

일단 Scanner를 사용하면 띄어쓰기와 개행문자를 경계하여 입력 값을 인식하고 따로 가공할 필요가 없다.

그리고 더 많은 메소드를 지원해주고 , 사용하기가 버퍼리더보다 쉽지만 버퍼 사이즈가 1024char 이기 때문에

많은 입력이 필요하지 않는 경우에는 성능상 좋지 못한 결과를 불러온다.

import java.io.*;
import java.util.Scanner;

class Main {
	public static void main(String[] args)  {
		
		Scanner sc = new Scanner(System.in);
		
		int num = sc.nextInt();
		
		if(num % 2 == 0){
			System.out.print("even");
		}else{
			System.out.print("odd");
		}
		
		sc.close();
		
	}
}

스캐너를 이용한 방법

스캐너에 필요한 메서드들을 불러오기 위해서 import 했음.


 

알고리즘 풀이 방법입니다.
문제(Problem) -> 생각(Think) -> 해결책(Solution) -> 리뷰(Review) 를 통해서 정리해서 작성합니다.
Problem📄

https://programmers.co.kr/learn/courses/30/lessons/12919

 

코딩테스트 연습 - 서울에서 김서방 찾기

String형 배열 seoul의 element중 "Kim"의 위치 x를 찾아, "김서방은 x에 있다"는 String을 반환하는 함수, solution을 완성하세요. seoul에 "Kim"은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니

programmers.co.kr


Think🤔

"Kim" 이라는 단어를 String의 서울 배열에서 찾으면 된다.

처음에는 ==로 찾으려고 했지만 if문을 안타서 왜 안타나 고민한 결과

문자열의 비교는 equals가 맞다 생각하여 equals를 사용해서 정답을 찾을 수 있었다.


Solution✍
class Solution {
    public String solution(String[] seoul) {
        String answer = "";
        int num = 0;
        
        for(int i=0; i<seoul.length; i++){
            if(seoul[i].equals("Kim")){
                num = i;
                break;
            }
        }
        answer = "김서방은 " + String.valueOf(num) + "에 있다";
        
        return answer;
    }
}

Review🤩

처음에 asList를 이용해서 contains로 찾으려고 했다.

하지만 contains는 true 나 false를 알려주는 거지 그럼 몇 번째 인지 알수는 없다.

다른 사람의 풀이를 본 결과 indexOf를 이용해서 몇 번째 인지 확인하는 코드를 확인하고 직접 작성해보았다.

import java.util.Arrays;

class Solution {
    public String solution(String[] seoul) {
        int x = Arrays.asList(seoul).indexOf("Kim");
        
        return "김서방은 " + x + "에 있다";
    }
}

 

알고리즘 풀이 방법입니다.
문제(Problem) -> 생각(Think) -> 해결책(Solution) -> 리뷰(Review) 를 통해서 정리해서 작성합니다.
Problem📄

https://programmers.co.kr/learn/courses/30/lessons/17681

 

코딩테스트 연습 - [1차] 비밀지도

비밀지도 네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다

programmers.co.kr


Think🤔

int n이 주어지는데 한변의 길이가 n의 정사각형이 만들어짐

각 칸 공백 또는 # 두 종류로 이루어져 있음

 

전체 지도는 두 장의 지도를 겹쳐서 모두 공백인 부분은 공백

 

n승의 값이 중요하다.(n은 0승 까지 있음)

n이 5이면 맨 처음에 #이 들어갈 경우는 2의4승인 16, 그 다음은 8 그 다음은 4이다

만약 8보다 큰 값이 나오면 그걸로 나눠서 그 값의 나머지를 넣어준다.

 

제곱은 Math.pow(double형, double형)을 이용해서 푼다.

class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        StringBuilder sb = new StringBuilder();
        
        for(int i=0; i<n; i++){
            while(arr1[i] != 0 && arr2[i] != 0){
                if(arr1[i] >= Math.pow(2,i)){
                    sb.append("#");
                    arr1[i] %= Math.pow(2,i);
                }else if(arr2[i] >= Math.pow(2,i)){
                    sb.append("#");
                    arr2[i] %= Math.pow(2,i);
                }else{
                    sb.append(" ");
                }
            }
            answer[i] = sb.toString();
        }
        
        return answer;
    }
}

실행시간이 길어서 실행이 중단된 코드

그리고 같은 숫자값이 나오면 if else if문 하나만 타게되고 하나는 16을 나눌 수 없게돼서 맞지 않는 코드가 된다.

 

문제를 보면 중복된 값인 "#"은 한번만 출력하게 하면 된다.

 

모르겠어서 다른 사람의 코드를 확인했다.

 

일단 풀면서 진법 변환 메소드를 사용해야 한다는 것은 알고 있었지만, 그 메소드를 어떻게 사용할지 몰라서 다른 방법으로 풀었었다.

 

1. 진법 변환 메소드 사용

String temp1 = Integer.toBinaryString(arr1[i]); 처럼

temp1에 만약 9가 들어온 값이 있으면 이것을 2진법으로 바꿔서 String형으로 표현할 수 있다.

 

이렇게 진법 변환을 이용하면 n이 5일때 앞에 0을 출력해야 하는 부분이 필요하다.

 

그리고 반복문을 이용해서 charAt값을 '0'의 값으로 뺴주면서 0은 아마 아스키코드에서 48일 것이다.

-48을 빼주거나 -'0'을 해서 문자에 담아서 answer의 번지에 추가 시키는 방법이 있다.

 

또 비슷한 방법은 2진법의 연산을 이용한다.

 

비트 연산!

AND(&)

- AND로 각 자리 수 1이 같으면 1로 변환

OR(|)

- OR로 둘 중 하나라도 1이면 1로 변환

XOR(^)

- 두수 각자리가 다르면 1로 변환

NOT(~)

- 각 자리수를 반대로 변환

 

비트 연산을 이용하면 위에 코드를 리팩토링 해서 풀 수 있다.


Solution✍
class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        int[] map = new int[n];
        
        // or 비트 연산
        for(int i=0; i<n; i++){
            map[i] = arr1[i] | arr2[i];
        }
        
        for(int i=0; i<map.length; i++){
            String tmp = Integer.toBinaryString(map[i]); // 이진법 변환
            //1001 > 01001 로 출력되게 해야함 n까지 앞에 "0"대입
            while(tmp.length() < n){
                tmp = "0"+tmp;
            }
            tmp = tmp.replaceAll("0"," "); //0은 공백으로
            tmp = tmp.replaceAll("1","#"); //1은 #으로 변환
            answer[i] = tmp;
        }
        
        return answer;
    }
}

Review🤩

replaceAll 그리고 Integer.toBinaryString을 통해서 2진법으로 바꾸는 방법과 비트 연산에 대해서 알게되었다.


 

알고리즘 풀이 방법입니다.
문제(Problem) -> 생각(Think) -> 해결책(Solution) -> 리뷰(Review) 를 통해서 정리해서 작성합니다.
Problem📄

https://programmers.co.kr/learn/courses/30/lessons/12918

 

코딩테스트 연습 - 문자열 다루기 기본

문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다. 제한 사항 s는 길이 1

programmers.co.kr


Think🤔

모든 문자가 숫자면 true를 리턴해준다.

charAt으로 하나하나 비교해서 각 자리의 값이 1~9사이면 true를 반환 하나라도 틀리면 false를 반환하게 한다.


Solution✍
class Solution {
    public boolean solution(String s) {
        boolean answer = true;
        if(s.length() != 4 && s.length() != 6){
            return false;
        }
        
        for(int i=0; i<s.length(); i++){
            if(s.charAt(i) < 48 || s.charAt(i) > 57){
                return false;
            }
        }
        
        return answer;
    }
}

문제를 보면 문자열의 길이가 4 또는 6이므로 길이가 1,2,3 같은 조건에 맞지 않으면 false를 반환시켜 줘야한다.

아스키 코드를 이용해서 48~57까지가 숫자 0~9를 나타내므로 그 사잇값이 아닌 값이 나오면 false를 리턴하면 된다.


Review🤩

엄청난 코드를 두 가지 봤다.

하나는 try catch문을 이용해서 NumberFormatException의 예외가 발생하면 false를 리턴하는 방식이고,

다른 하나는 매치스를 이용한 방법이다.

class Solution {
    public boolean solution(String s) {
        if(s.length() == 4 || s.length() == 6){
            try{
                int x = Integer.parseInt(s);
                return true;
            } catch(NumberFormatException e){
                return false;
            }
        }
        
        return false;
    }
}

직접 작성해 보았고, int x라는 변수를 하나 만들어서 형 변환이 불가능 하면 NumberFormatException이 발생해서 false를 반환 시킨다. 하지만 예외는 실제 예외 상황일때만 사용하는거라 적절하지는 않은 것 같다.

class Solution {
    public boolean solution(String s) {
        if(s.length() == 4 || s.length() == 6){
            return s.matches("(^[0-9]*$)");
        }
        
        return false;
    }
}

matches를 살펴보면

 

^ : 문자열 시작

$ : 문자열 종료

* : 앞 문자가 없을 수도 무한정 많을 수도

[] : 문자의 집합이나 범위를 나타내면 - 기호로 범위를 나타냄

 

여기서 좀 더 나아가서 길이 검사도 정규식으로 표현할 수 있다고 한다.

class Solution {
    public boolean solution(String s) {
        return s.matches("(^[0-9]{4}|{6}$)");
    }
}

단 한줄로 길이까지 검사했다. 

{} : 횟수 또는 범위를 나타낸다고 한다. 총 4번 나오거나 6번 나오면 범위에 맞음


 

알고리즘 풀이 방법입니다.
문제(Problem) -> 생각(Think) -> 해결책(Solution) -> 리뷰(Review) 를 통해서 정리해서 작성합니다.
Problem📄

https://programmers.co.kr/learn/courses/30/lessons/12915

 

코딩테스트 연습 - 문자열 내 마음대로 정렬하기

문자열로 구성된 리스트 strings와, 정수 n이 주어졌을 때, 각 문자열의 인덱스 n번째 글자를 기준으로 오름차순 정렬하려 합니다. 예를 들어 strings가 ["sun", "bed", "car"]이고 n이 1이면 각 단어의 인덱

programmers.co.kr


Think🤔

문자배열 strings 리스트

n번째 글자를 기준으로 오름차순 해준다.

n번쨰 글자를 맨 앞에 추가 시키고 정렬을 시키면 나머지 부분도 정렬이 된다!

 

그리고 다른 방법으로 정확히 기억이 안나는데 comparable 과 comparator의 정렬 기준을

오버라이딩해서 적용하면 가능할 것 같다.

 

Comparator 와 Comparable

- 객체 정렬에 필요한 메서드 (정렬기준 제공)를 정의한 인터페이스

String클래스가 Comparable을 구현하고 있음.

 

Comparable은 기본 정렬을 기준을 설정하는 인터페이스

Comparator는 기본 정렬 기준과는 다르게 정렬하고 싶을 때 이용

 

Comparable의 compareTo(T o) 메소드는 파라미터가 한개

Comparator의 compare(T o1, T o2) 메소드는 파라미터가 두개

 

Comparable은 "자기 자신과 매개변수 객체를 비교"

Comparator는 "두 매개변수 객체를 비교"

 

또 다른 차이점이라면

Comparable은 lang 패키지에 있어서 import안해줘도 되지만,

Comparator는 util 패키지에 있어서 import 해야 한다.


Solution✍
import java.util.Arrays;

class Solution {
    public String[] solution(String[] strings, int n) {
        String[] answer = new String[strings.length];
        
        // n의 문자를 맨 앞에 저장
        for(int i=0; i<strings.length; i++){
            answer[i] = strings[i].charAt(n) + strings[i];
        }
        
        // 정렬 하면 맨 앞과 동시에 원래 string도 정렬이 됨
        Arrays.sort(answer);
        
        // 맨 앞에 substring1을 통해서 지워줌
        for(int i=0; i<strings.length; i++){
            answer[i] = answer[i].substring(1);
        }
        
        return answer;
    }
}
import java.util.Arrays;
import java.util.Comparator;

class Solution {
    public String[] solution(String[] strings, int n) {
        
        
        // 익명 클래스
        Arrays.sort(strings, new Comparator<String>(){
            public int compare(String s1, String s2){
                char c1 = s1.charAt(n);
                char c2 = s2.charAt(n);
                
                if(c1 == c2){
                    return s1.compareTo(s2);
                }else
                    return c1 - c2;
            }
        });
        
        return strings;
    }
}

익명 클래스를 이용해서 선언과 동시에 객체를 생성하고,

커스텀해서 소팅이 가능합니다, 먼저 같지 않으면 charAt에 있는 값을 비교해서 정렬하고,

그 다음 n 번쨰의 문자가 같으면 원래대로 정렬하게 s1.compareTo(s2)를 리턴해줍니다.


Review🤩

Comparable과 Comparator에 대해서 복습했고,

substring을 이용해서 하나의 파라미터가 들어가면 그 부분을 지워줄 수 있다는 것도 알게되었다.


 

알고리즘 풀이 방법입니다.
문제(Problem) -> 생각(Think) -> 해결책(Solution) -> 리뷰(Review) 를 통해서 정리해서 작성합니다.
Problem📄

https://programmers.co.kr/learn/courses/30/lessons/12925

 

코딩테스트 연습 - 문자열을 정수로 바꾸기

문자열 s를 숫자로 변환한 결과를 반환하는 함수, solution을 완성하세요. 제한 조건 s의 길이는 1 이상 5이하입니다. s의 맨앞에는 부호(+, -)가 올 수 있습니다. s는 부호와 숫자로만 이루어져있습니

programmers.co.kr

 


Think🤔

양수이면 String.ValueOf로 바로 반환이 가능하다.

하지만 양수에 +가 올수도 있음! 그러면 맨 앞의 부호가 +이고 -인 것을 판별하고,

그것이 아니면 양수이기 때문에 String.ValueOf로 출력하면 될 것 같다.

class Solution {
    public int solution(String s) {
        int answer = 0;
        if(s.charAt(0) == '-'){
            answer = Integer.parseInt(s) * -1;
        }else{
            answer = Integer.parseInt(s);
        }
        
        return answer;
    }
}

-1을 해주면 변환된 줄 알았는데 1234가 그대로 나온다.

 

뭐가 문제일까? 곱하기 -1을 하면 음수가 되는것이 아니였나?

 

parseInt가 부호까지 가지고 와서 변형시켜 줬다...


Solution✍
class Solution {
    public int solution(String s) {
        int answer = 0;
        
        answer = Integer.parseInt(s);
        
        return answer;
    }
}

한 줄로 완성이 됨...


Review🤩

음수 양수로 혹시 판단하는 메서드가 없나 하고 찾아봤는데.. 

Math.sign(x)

- x의 부호 값을 반환함.

 

이런 함수도 있다는 것을 알게 되었다!


 

+ Recent posts