[문제 링크]

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

 

[난이도]

- Silver 4

 

[알고리즘]

- 이분 탐색

 

[코드]

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

public class Main {
    static long n, answer = 0;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        n = Long.parseLong(br.readLine());
        binarySearch(n);
        System.out.println(answer);
    }

    static void binarySearch(long key) {
        long left = 0;
        long right = key;
        while (left <= right) {
            long mid = (left + right) / 2;
            if (key <= Math.pow(mid, 2)){
                answer = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
    }
}

[풀이]

이분탐색 알고리즘 보다 타입맞추는게 더 까다로웠다.

(mid * mid) 로 계산하면 long의 범위를 넘어가 버려 정답을 맞출 수 없다.

Math.pow(mid, 2) 는 반환값이 double 이기때문에 이를 사용해야한다.

[문제 링크]

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

[난이도]

- Silver 2

 

[알고리즘]

- 파라메트릭 서치

 

[코드]

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

public class Main {
    static int K, N;
    static long left = 1, right = Integer.MIN_VALUE;
    static int[] arr;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        K = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());
        arr = new int[K];

        for (int i = 0; i < K; i++) {
            arr[i] = Integer.parseInt(br.readLine());
            right = Math.max(right, arr[i]);
        }

        parametricSearch();

        br.close();
    }
    static void parametricSearch() {
        while (left <= right) {
            long mid = (left + right) / 2;
            long LAN = 0;
            for (int i = 0; i < arr.length; i++) {
                LAN += (arr[i] / mid);
            }
            if (LAN>=N){
                left = mid + 1;
            } else if (LAN < N) {
                right = mid - 1;
            }
        }
        System.out.println(right);
    }
}

[풀이]

- left, right, mid 를 long으로 설정해주어야 한다.

- left의 최소값이 1이어야 한다. 그렇지 않으면 divide by zero 오류가 발생한다. 예를들어 모든 가지고있는 랜선의 길이가 1이고 left가 0일 경우 mid가 0이 된다.

API를 쓸모 있게 하려면 잘 작성된 문서도 곁들여야 한다. API를 올바로 문서화하려면 공개된 모든 클래스, 인터페이스, 메서드, 필드 선언에 문서화 주석을 달아야 한다.

 

  • 메서드용 문서화 주석에는 해당 메서드와 클라이언트 사이의 규약을 명료하게 기술해야 한다.

 

  • 제네릭 타입이나 제네릭 메서드를 문서화할 때는 모든 타입 매개변수에 주석을 달아야 한다.
/**
 * 제네릭 스택 클래스.
 *
 * @param <E> 스택에 저장할 요소의 타입
 */
public class GenericStack<E> {
    private List<E> elements = new ArrayList<>();

    /**
     * 스택에 요소를 추가합니다.
     *
     * @param element 추가할 요소
     */
    public void push(E element) {
        elements.add(element);
    }

    /**
     * 스택에서 요소를 제거하고 반환합니다.
     *
     * @return 제거된 요소
     * @throws EmptyStackException 스택이 비어 있는 경우
     */
    public E pop() {
        if (elements.isEmpty()) {
            throw new EmptyStackException();
        }
        return elements.remove(elements.size() - 1);
    }
}

 

  • 열거 타입을 문서화할 때는 상수들에도 주석을 달아야 한다.

 

  • 애너테이션 타입을 문서화할 때는 멤버들에도 모든 주석을 달아야 한다.

 

  • 클래스 혹은 정적 메서드가 스레드 안전하든 그렇지 않든, 스레드 안전 수준을 반드시 API 설명에 포함해야 한다.

 

 

핵심 정리 : 문서화 주석은 여러분 API를 문서화하는 가장 훌륭하고 효과적인 방법이다. 공개 API라면 빠짐없이 설명을 달아야 한다. 표준 규약을 일관되게 지키자. 문서화 주석에 임의의 HTML태그를 사용할 수 있음을 기억하라. 단, HTML 메타문자는 특별하게 취급해야 한다.

  • Opional을 반환하는 메서드에서는 절대 null을 반환하지 말자.
  • 컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안 된다.
  • 옵셔널을 반환값이 아닌 필드나 다른 용도로 사용하지 말자.

 

 

메서드 반환 타입을 T 대신 Optional<T>로 선언해야 하는 기본 규칙 : 

  • 결과가 없을 수 있으며, 클라이언트가 이 상황을 특별하게 처리해야 한다면 Optional<T>를 반환한다.

 

핵심 정리 : 값을 반환하지 못할 가능성이 있고, 호출할 때마다 반환값이 없을 가능성을 염두에 둬야하는 메서드라면 옵셔널을 반환해야 할 상황일 수 있다. 하지만 옵셔널 반환에는 성능 저하가 뒤따르니, 성능에 민감한 메서드라면 null을 반환하거나 예외를 던지는 편이 나을 수 있다. 그리고 옵셔널을 반환값 이외의 용도로 쓰는 경우는 매우 드물다.

메서드에서 컬렉션이나 배열을 반환할 때, null이 아닌 빈 컬렉션이나 빈 배열을 반환해야 하는데 그 이유는

 

  1. 호출자 코드 단순화 : 호출자가 null을 처리할 필요 없이 바로 컬렉션이나 배열을 사용할 수 있다.
  2. 널 포인터 예외 방지 : null을 반환할 경우 이를 처리하지 않아 발생할 수 있는 NullPointerException을 방지할 수 있다.
  3. 일관성 유지 : 항상 같은 타입의 객체를 반환하므로 메서드 사용이 일관되고 예측가능해진다.

 

핵심 정리 : null이 아닌, 빈 배열이나 컬렉션을 반환하라. null을 반환하는 api는 사용하기 어렵고 오류 처리 코드도 늘어난다. 그렇다고 성능이 좋은 것도 아니다.

+ Recent posts