✏️ 문제 설명
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에 저장
- countMap.put(num, contMap.getOrDefault(num, 0)+1)
- 최대값 판별
- 기존 방식: 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;
}
}
반응형
'Java > 코딩테스트' 카테고리의 다른 글
[프로그래머스/181903] qr code (배열과 String 클래스의 문자 접근 방식이 다른 이유, .charAt()) (0) | 2025.01.03 |
---|---|
[프로그래머스/181847] 0 떼기 (w. 정규표현식, String.replaceFirst()) (0) | 2024.12.30 |
[코드트리/NL] 연속부분수열일까 (w. 슬라이딩 윈도우 알고리즘) (1) | 2024.12.27 |
[코드트리/NL] 나눗셈의 나머지 (1) | 2024.12.25 |
[코드트리/NL] 특정 규칙에 따른 숫자 출력 (0) | 2024.12.22 |