수 찾기

2025. 5. 10. 17:40·CS/알고리즘 & 자료구조
728x90
반응형

문제

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^31 보다 크거나 같고 2^31보다 작다.

  • N 개의 정수 배열
  • M 개의 정수 배열
  • M 배열의 정수가 N 배열에 있는지 판단하여 1,0 출력
  • 정수 범위 -2^31 <= 정수 < 2^31

 

출력

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

 


해결방법

1. 절차적

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }
        int m = sc.nextInt();
        int[] queries = new int[m];
        for (int i = 0; i < m; i++) {
            queries[i] = sc.nextInt();
        }

        Arrays.sort(arr);  // O(n log n)
        
        // 바이너리 서치, O(log n)
        for (int q : queries) {
            // 내장 기능 사용, 반환값 ≥ 0 이면 찾음, 음수면 없음
            System.out.println(Arrays.binarySearch(arr, q) >= 0 ? 1 : 0);
            // 로직 구현
            if(binarySearch(arr, q){
            	System.out.println(1);
            } else {
            	System.out.println(0);
            }
        }
        
        private static boolean binarySearch(int[] arr, int target) {
            int left = 0, right = arr.length - 1;

            // 이진 탐색이 계속 실행될 조건
            while (left <= right) {
                int mid = (left + right) / 2;
                // 이진 탐색에서 타켓을 찾았는지 확인
                if (arr[mid] == target) {
                    return true;
                }
                // 타겟 값이 중간 값보다 큰 경우의 조건
                else if (arr[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return false;
        }
    }

 

2. 객체

  • 재사용성과 확장성이 용이
  • 검색 방식을 바꿀 때, NumberFinder를 수정하면 된다.
  • 테스트 용이
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) arr[i] = sc.nextInt();

        NumberFinder finder = new NumberFinder(arr);

        int m = sc.nextInt();
        while (m-- > 0) {
            int q = sc.nextInt();
            System.out.println(finder.contains(q) ? 1 : 0);
        }
    }
}

public class NumberFinder {
    private final int[] data;

    public NumberFinder(int[] data) {
        Arrays.sort(data);
        this.data = data;
    }

    public boolean contains(int target) {
        return Arrays.binarySearch(data, target) >= 0;
    }
}

 

 

3. 알고리즘

문제: 정렬 O(n log n) + 매번 이진탐색 O(log n) → 전체 O(n log n + m log n)
해결: 해시나 비트마스크를 이용해 O(n + m)으로 줄이기

3.1 HashSet

  • 시간 복잡도: O(n + m) (평균)
  • 단점: 해시 충돌 드물지만, 최악 O(n) 가능 / 메모리 사용량이 다소 증가
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class FindWithHash {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Set<Integer> set = new HashSet<>(n * 2);
        for (int i = 0; i < n; i++) {
            set.add(sc.nextInt());
        }

        int m = sc.nextInt();
        for (int i = 0; i < m; i++) {
            System.out.println(set.contains(sc.nextInt()) ? 1 : 0);
        }
    }
}

  

3.2 BitSet 

  • 시간 복잡도: O(n + m), 공간: 약 2 000 001 bool (≈2 MB)
  • 장점: 가장 빠른 상수 시간 조회
import java.util.Scanner;

public class FindWithBitset {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        final int OFFSET = 1_000_000;
        boolean[] present = new boolean[2 * OFFSET + 1];

        int n = sc.nextInt();
        for (int i = 0; i < n; i++) {
            present[sc.nextInt() + OFFSET] = true;
        }

        int m = sc.nextInt();
        for (int i = 0; i < m; i++) {
            int q = sc.nextInt() + OFFSET;
            System.out.println((q >= 0 && q < present.length && present[q]) ? 1 : 0);
        }
    }
}

 

결론

  • 간단히 한두 번만 돌려볼 때는 절차적
    • 장점: 코드 흐름이 직관적이라 로직을 파악하기 쉽고, 한 번만 실행하거나 간단한 스크립트 형태로 처리할 때 빠르게 구현할 수 있습니다.
    • 단점: 기능이 늘어날수록 함수나 전역 변수가 여기저기 얽히기 쉬워 유지보수가 어려워지고, 재사용성도 떨어집니다.
  • 앞으로 기능이 추가되거나 테스트·재사용을 염두에 뒀다면 객체지향
    • 장점: 데이터와 동작을 클래스로 묶어 역할을 명확히 분리하므로 확장성·재사용성이 높고, 단위 테스트도 용이합니다.
    • 단점: 구조 설계·추상화에 드는 초기 작업량이 늘어나고, 작은 문제에 과도하게 복잡해질 수 있습니다.
  • 수백만 건 이상의 빈번한 조회가 필요하다면 해시셋/비트셋 기반 알고리즘
    • 장점: 해시셋이나 비트셋 같은 자료구조를 이용하면 검색을 O(1)에 가깝게 처리할 수 있어 대량 데이터·반복 질의에 최적화됩니다.
    • 단점: 해시셋은 객체 오버헤드가 크고, 비트셋은 범위 전체 메모리를 선점하므로 메모리 트레이드오프가 있습니다.
728x90
반응형
저작자표시 비영리 (새창열림)

'CS > 알고리즘 & 자료구조' 카테고리의 다른 글

동적계획법(DP, Dynamic Programming)  (0) 2025.05.13
자료구조 선택 (HashSet vs BitSet)  (0) 2025.05.10
덱(Deque) 보다 큐(Queue)와 스택(Stack)이 더 좋은 경우?  (0) 2025.03.11
Deque?  (1) 2025.03.11
스택? 큐?  (0) 2025.03.11
'CS/알고리즘 & 자료구조' 카테고리의 다른 글
  • 동적계획법(DP, Dynamic Programming)
  • 자료구조 선택 (HashSet vs BitSet)
  • 덱(Deque) 보다 큐(Queue)와 스택(Stack)이 더 좋은 경우?
  • Deque?
크크크크
크크크크
공뷰를 합시다.
    반응형
  • 크크크크
    Tom's Note
    크크크크
  • 전체
    오늘
    어제
    • 분류 전체보기 (124)
      • IT 지식 (4)
      • CS (65)
        • 알고리즘 & 자료구조 (19)
        • 운영체제 (40)
        • 네트워크 (1)
        • 데이터베이스 (5)
      • 보안 (3)
      • SW 공학 & 프로그래밍 언어 (46)
        • Java (28)
        • 디자인 패턴 (1)
        • 형상관리 (2)
        • 톰캣(WAS) (2)
        • SW 방법론 (3)
        • 스프링부트 (5)
      • 시스템 설계 (4)
        • Docker (2)
      • 자격증 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      su
      man
      불변
      REST API
      DI
      문제해결
      chmod
      passwd
      단반향
      1급
      암호설정
      whereis
      /etc/passwd
      java
      whatis
      docker
      스프링부트
      cifs
      분석기법
      ADsP
      자바
      2차
      DTO
      비트연산
      Chage
      알고리즘
      apropos
      usermod
      which
      리눅스
    • 최근 댓글

    • 최근 글

    • 250x250
    • hELLO· Designed By정상우.v4.10.3
    크크크크
    수 찾기
    상단으로

    티스토리툴바