본문 바로가기

Java/코딩테스트

[코드트리/NL] 중복되지 않는 정수 중 최대 (w. HashMap, Math.max)

✏️ 문제 설명

N개의 정수가 주어졌을 때, 중복하여 등장하지 않는 정수 중 최댓값을 구하는 프로그램을 작성해보세요.


✏️ code

💻 HashMap

  • 정의
    • key-value 쌍을 저장하는 컬렉션 클래스
    • Hash Table을 기반으로 데이터 저장 및 검색을 제공합니다.
    • java.util.HashMap 클래스는 Map 인터페이스를 구현하며, 중복 키를 허용하지 않고, 하나의 키에 하나의 값만 매핑됩니다.
    • key-value 쌍을 저장할 때 내부적으로 배열과 연결리스트(또는 트리) 구조를 사용합니다. 이 구조를 버킷이라고 부릅니다.
  • 주요 특징
    • 동기화 되지 않음: 동시성 제어가 필요한 경우 ConcurrentHashMap이나 Collections.synchronizedMap()을 사용해야 합니다.
    • 순서 보장 없음: 입력 순서나 정렬 순서를 보장하지 않습니다.
      (입력 순서 보장 희망 시, LinkedHashMap / 정렬 순서 보장 희망 시, TreeMap 사용할 것)
    • Null 키와 값 허용: 하나의 null 키와 여러 개의 null 값을 허용합니다.
    • 시간 복잡도: 키에 대한 해싱과 버킷 조회 덕분에 평균 O(1)입니다.
      단, 해시 충돌 발생 시 성능이 저하될 수 있으며 충돌 처리는 내부적으로 연결 리스트(Java 8 이전) 혹은 균형이진트리(Java 8 이후, 버킷의 엔트리 수가 특정 임계값을 초과하는 경우)를 사용합니다.
  • 자주 사용되는 메서드
종류 내용 설명
추가 및 수정 V put(K key, V value) key-value 쌍을 추가하거나, 기존 키에 대해 값을 업데이트 합니다.
반환값: 기존 값(없으면 null)
  V putIfAbsent(K key, V value) 지정된 키가 없을 경우에만 값을 추가합니다.
  boolean replace(K key, V oldValue, V newValue) 지정된 키의 값이 예상 값과 일치할 때만 새 값으로 대체합니다.
조회 V get(Object key) 지정된 키에 해당하는 값을 반환합니다.
키가 없으면 null을 반환합니다.
  Set<K> keySet() 모든 키를 가져옵니다.
  Collection<V> values() 모든 값을 가져옵니다.
  boolean containsKey(Object key) 지정된 키가 맵에 존재하는지 확인합니다.
  boolean containsValue(Object value) 지정된 값이 맵에 존재하는지 확인합니다.
  V getOrDefault(Object key, V defaultValue) 지정된 키가 해당하는 값을 반환하며, 키가 없을 경우 지정된 기본값을 반환합니다.
삭제 V remove(Object key) 지정된 key-value 쌍을 제거합니다.
반환값: 삭제된 값(없으면 null)
크기 확인 int size() 맵에 저장된 key-value 쌍의 개수를 반환합니다.
  boolean isEmpty() 맵이 비어 있는지 확인합니다.
전체 데이터 처리 Set<K> keySet() 맵의 모든 키를 Set으로 반환합니다.
  Collection<V> values() 맵의 모든 값을 Collections로 반환합니다.
  Set<Map.Entry<K, V>> entrySet() 모든 키-값 쌍을 Set으로 반환합니다.
  void forEach(BiConsumer<? super K, ? super V> action) 모든 key-value 쌍에 대한 지정된 작업을 수행합니다.

 

 

import java.util.HashMap;
import java.util.Map;

public class HashMapExample {
    public static void main(String[] args) {
        // HashMap 생성
        HashMap<String, Integer> map = new HashMap<>();

        // put(): 키-값 쌍 추가
        map.put("사과", 5);
        map.put("바나나", 3);
        map.put("오렌지", 2);

        // get(): 키로 값 조회
        System.out.println("사과의 개수: " + map.get("사과"));

        // containsKey(): 키 존재 여부 확인
        System.out.println("키 '바나나' 존재 여부: " + map.containsKey("바나나"));

        // containsValue(): 값 존재 여부 확인
        System.out.println("값 '4' 존재 여부: " + map.containsValue(4));

        // size(): 맵의 크기 확인
        System.out.println("맵의 크기: " + map.size());

        // remove(): 키-값 쌍 제거
        map.remove("오렌지");
        System.out.println("오렌지 제거 후 맵: " + map);

        // putIfAbsent(): 키가 없을 때만 값 추가
        map.putIfAbsent("포도", 4);
        System.out.println("putIfAbsent 후 맵: " + map);

        // replace(): 키의 값 교체
        map.replace("사과", 6);
        System.out.println("사과 값 교체 후: " + map.get("사과"));

        // forEach(): 모든 키-값 쌍에 대해 작업 수행
        map.forEach((key, value) -> System.out.println(key + ": " + value));

        // keySet(): 모든 키 가져오기
        System.out.println("모든 키: " + map.keySet());

        // values(): 모든 값 가져오기
        System.out.println("모든 값: " + map.values());

        // entrySet(): 모든 엔트리 가져오기
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }

        // getOrDefault(): 키가 없을 때 기본값 반환
        System.out.println("키워드의 개수: " + map.getOrDefault("키위", 0));

        // clear(): 맵 비우기
        map.clear();
        System.out.println("맵 비운 후 크기: " + map.size());
    }
}

 

📌 고민했던 부분

  • 각 입력별 중복여부 체크
    • countMap.put(num, contMap.getOrDefault(num, 0)+1)
      • countMap: 숫자(key)와 출현 횟수(value)를 저장하는 HashMap
      • num: 현재 처리 중인 숫자
      • countMap.getOrDefault(num, 0): num이 countMap에 이미 존재하면 그 값(출현 횟수)를 반환, 존재하지 않는다면 기본값 0을 반환
      • countMap.getOrDefault(num, 0) + 1: 현재 숫자의 기존 출현 횟수에 +1을 더함
      • countMap.put(num, ~): num을 키로, 새로 계산된 출현 횟수를 값으로 하여 countMap에 저장
  • 최대값 판별
    • 기존 방식: for문을 사용하여 최댓값을 구함
    • 이번에 사용한 방식: max = Math.max(max, num)
      • Math.max(max, num): max와 num 중 더 큰 값을 max에 저장
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine().trim());
        int arr[] = new int[n];
        StringTokenizer st = new StringTokenizer(br.readLine().trim());
        for (int i = 0; i < n; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        System.out.print(maxResult(arr));
        br.close();
    }

    private static int maxResult(int arr[]) {
        HashMap<Integer, Integer> countMap = new HashMap<>();
        for (int num : arr) {
            countMap.put(num, countMap.getOrDefault(num, 0)+1);
        }
        int max = Integer.MIN_VALUE;
        boolean found = false;
        for (int num : countMap.keySet()) {
            if (countMap.get(num) == 1) {
                max = Math.max(max, num);
                found = true;
            }
        }
        return found ? max : -1;
    }
}

 

 

 

 

반응형