문제

Given an object or an array, return if it is empty.

  • An empty object contains no key-value pairs.
  • An empty array contains no elements.

You may assume the object or array is the output of JSON.parse.

https://leetcode.com/problems/is-object-empty/

 

예시

 

코드

/**
 * @param {Object|Array} obj
 * @return {boolean}
 */
var isEmpty = function(obj) {
    return JSON.stringify(obj).length == 2;
};

인자로 들어오는 obj의 형식이 Object이거나 Array이기 때문에 이를 JSON.stringify를 이용해 JSON 문자열로 변환하였다. 그렇다면 비어있는 array의 경우 `'[]'` 로 변환이 되고, 비어있는 Object의 경우 `'{}'`로 변환이 되기 때문에 비어있을 경우 length가 2가 된다. 따라서 길이가 2인지 여부를 판단하여 리턴해주었다.

728x90

문제

https://www.acmicpc.net/problem/2178

N×M크기의 배열로 표현되는 미로가 있다.

1 0 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 1
1 1 1 0 1 1

미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.

위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.

 

입력

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

 

출력

첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.


코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
    static class Node {
        int x;
        int y;
        int cnt; // 현재까지 이동한 칸 수

        public Node(int x, int y, int cnt){
            this.x =  x;
            this.y = y;
            this.cnt = cnt;
        }
    }

    static int[][] maze;
    static boolean[][] visited;
    static int N;
    static int M;
    static int moveCnt;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        maze = new int[N+1][M+1];
        visited = new boolean[N+1][M+1];

        for(int i = 0; i < N; i++){
            String str = br.readLine();

            for(int j = 0; j < M; j++){
                maze[i+1][j+1] = str.charAt(j) - '0';
            }
        }

        bfs();

        System.out.println(moveCnt);

    }


    static void bfs(){
        // 상 하 좌 우
        int[] dx = new int[]{0,0,-1,1};
        int[] dy = new int[]{-1,1,0,0};

        Queue<Node> queue = new LinkedList<>();
        queue.add(new Node(1,1,1));
        visited[1][1] = true;

        while(!queue.isEmpty()){
            Node node = queue.poll();

            for(int i = 0; i < 4; i++){
                int nx = node.x + dx[i];
                int ny = node.y + dy[i];

                if(checkBoundary(nx, ny)){
                    if(nx == N && ny == M) {
                        moveCnt = node.cnt + 1;
                        return;
                    }
                    visited[nx][ny] = true;
                    queue.add(new Node(nx, ny, node.cnt + 1));
                }
            }
        }
    }

    static boolean checkBoundary(int nx, int ny){
        return nx >= 1 && nx <= N && ny >= 1 && ny <= M && maze[nx][ny] == 1 && !visited[nx][ny];
    }
}

BFS를 이용해서 풀었다. visited 배열을 이용해서 방문 여부를 저장하고, queue에 출발하는 칸인 (1,1)을 넣었다. 이때, Node class를 생성하여 넣어주었는데, x좌표, y좌표, 현재까지 이동한 총 cnt를 저장하고 있는 객체이다. queue가 빌 때까지 queue에서 객체를 하나 뽑고, 해당 객체의 상, 하, 좌, 우에 있는 값을 큐에 넣어준다. 이동할 때는 미로의 경계값을 넘지 않는지와 처음 방문하는 곳인지를 확인하고, 큐에 Node를 넣을 때는 cnt를 하나씩 올려서 넣어준다. 원하는 값은 x가 N이고, y가 M일 때이기 때문에, 다음에 방문할 x와 y인 nx, ny 값을 확인하여 nx가 N이고 ny가 M일 때 최소 이동 칸 수를 저장하는 moveCnt에 값을 저장해주고 return 한다.

728x90

'Algorithm > 백준' 카테고리의 다른 글

[백준][Java] 2493. 탑  (0) 2024.08.13
[백준][Java] 1021. 회전하는 큐  (0) 2024.08.10
[백준][Java] 1920. 수 찾기  (0) 2024.02.11
[백준][Java] 2630. 색종이 만들기  (0) 2024.02.06
[백준][Java] 14888. 연산자 끼워넣기  (0) 2024.02.05

문제

https://www.acmicpc.net/problem/1920

N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.

 

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -2³¹보다 크거나 같고 2³¹보다 작다.

 

출력

M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.


코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

    static int N;
    static int[] arr;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        N = Integer.parseInt(br.readLine());

        arr = new int[N];
        StringTokenizer st = new StringTokenizer(br.readLine());

        for(int i = 0 ; i < N; i++){
            arr[i] = Integer.parseInt(st.nextToken());
        }
        Arrays.sort(arr);

        int M = Integer.parseInt(br.readLine());

        int[] targets = new int[M];
        st = new StringTokenizer(br.readLine());

        for(int i = 0; i < M; i++){
            targets[i] = Integer.parseInt(st.nextToken());
        }

        for(int i = 0; i < M; i++){
            int result = binarySearch(targets[i]);

            sb.append(result == -1 ? 0 : 1);
            sb.append("\n");
        }

        System.out.println(sb.toString());


    }

    static int binarySearch(int target){
        int left = 0;
        int right = N - 1;
        int mid;

        while(left <= right){

            mid = (left + right) / 2;
            
            if(arr[mid] == target){
                return mid; // 탐색 완
            }

            if(arr[mid] > target){
                right = mid - 1;
            }else {
                left = mid + 1;
            }

        }
    
        return -1; // 탐색 실패
       
    }
}

이 문제를 푸는 여러 방법이 있겠지만, 이분 탐색을 공부하는 김에 사용해보았다. left, right, mid는 A의 index를 의미하고, left와 right을 이용해 mid의 값을 갱신해나가며 값을 찾는다. A배열의 left부터 right까지 확인하여 target이 있는지 찾으면 된다. 이때, A 배열은 정렬이 되어 있어야 한다. left <= right 일 때까지 돌면서 반복하고, 만약 target 값과 A[mid]의 값이 같다면 target이 A 안에 있다는 의미이기 때문에 mid 값을 리턴한다. 만약 A[mid]가 target 보다 크다면, mid보다 왼쪽에 target이 있다는 의미이기 때문에 right을 `mid - 1`로 변경하여 A[left] ~ A[mid - 1] 까지의 배열만 탐색하도록 한다. 만약 A[mid] 가 target 보다 작다면 target이 mid 보다 오른쪽에 있다는 의미이기 때문에, 그 후에 탐색할 때는 A[mid + 1]부터 A[right]까지만 보면 된다. 따라서 left를 `mid + 1`로 변경하면 된다. 만약 while 문을 통과했는데 리턴하지 못했을 때는 A 배열에 target이 존재하지 않는 것이기 때문에 -1을 리턴한다.

728x90

문제

Design a Calculator class. The class should provide the mathematical operations of addition, subtraction, multiplication, division, and exponentiation. It should also allow consecutive operations to be performed using method chaining. The Calculator class constructor should accept a number which serves as the initial value of result.

  • add - This method adds the given number value to the result and returns the updated Calculator.
  • subtract - This method subtracts the given number value from the result and returns the updated Calculator.
  • multiply - This method multiplies the result  by the given number value and returns the updated Calculator.
  • divide - This method divides the result by the given number value and returns the updated Calculator. If the passed value is 0, an error "Division by zero is not allowed" should be thrown.
  • power - This method raises the result to the power of the given number value and returns the updated Calculator.
  • getResult - This method returns the result.

Solutions within 10-5 of the actual result are considered correct.

  • Your Calculator class should have the following methods:

https://leetcode.com/problems/calculator-with-method-chaining/

 

예시

 

코드

const DIVISION_ZERO_ERROR = "Division by zero is not allowed";

class Calculator {
    
    /** 
     * @param {number} value
     */
    constructor(value) {
        this.value = value;
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    add(value){
        this.value += value;
        console.log(this);
        return this;
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    subtract(value){
        this.value -= value;
        return this;
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */  
    multiply(value) {
        this.value *= value;
        return this;
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    divide(value) {
        if(value === 0) throw new Error(DIVISION_ZERO_ERROR);
        this.value /= value;
        return this;
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    power(value) {
        this.value = this.value ** value;
        return this;
    }
    
    /** 
     * @return {number}
     */
    getResult() {
        return this.value;
    
    }
}

 

메소드 체이닝을 위해서는 각 메소드에서 this를 반환하여 Calculator 클래스 자체를 반환해주어야 한다. 따라서 생성자 함수인 constructor()와 연산 결과를 리턴할 getResult() 메소드를 제외한 나머지 메소드에서 this를 리턴해주었다.

728x90

문제

Given a function fn, an array of arguments args, and an interval time t, return a cancel function cancelFn.

After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.

setTimeout(cancelFn, cancelTimeMs)

The function fn should be called with args immediately and then called again every t milliseconds until cancelFn is called at cancelTimeMs ms.

https://leetcode.com/problems/interval-cancellation/

 

예시

 

코드

/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    fn(...args);
    const timerId = setInterval(() => {fn(...args)}, t);
    
    return function(){
       clearInterval(timerId);
    }
};

/**
 *  const result = [];
 *
 *  const fn = (x) => x * 2;
 *  const args = [4], t = 35, cancelTimeMs = 190;
 *
 *  const start = performance.now();
 *
 *  const log = (...argsArr) => {
 *      const diff = Math.floor(performance.now() - start);
 *      result.push({"time": diff, "returned": fn(...argsArr)});
 *  }
 *       
 *  const cancel = cancellable(log, args, t);
 *
 *  setTimeout(cancel, cancelTimeMs);
 *   
 *  setTimeout(() => {
 *      console.log(result); // [
 *                           //     {"time":0,"returned":8},
 *                           //     {"time":35,"returned":8},
 *                           //     {"time":70,"returned":8},
 *                           //     {"time":105,"returned":8},
 *                           //     {"time":140,"returned":8},
 *                           //     {"time":175,"returned":8}
 *                           // ]
 *  }, cancelTimeMs + t + 15)    
 */

cancellable 함수는 function을 리턴해야 하며, 호출하였을 때 특정 함수의 호출을 cancel 하는 역할을 한다. log 함수는 계속 t(ms) 마다 실행이 되어야 하고, cancelTimeMs(ms) 후에 cancel 이 호출되고, 그때 log 함수가 멈춰야 한다. 따라서 cancellable 함수 내부에서 setInterval 을 이용해서 t(ms) 마다 fn을 호출하였고, 원하는 output에서 0초부터 로그가 찍히는 것을 원했기 때문에 setInterval 호출 전 따로 fn을 호출해주었다. 그리고 setInterval에서 반환된 timerId를 이용해서 interval을 취소시키는 행동을 하는 함수를 리턴한다.

728x90

+ Recent posts