[알고리즘] 체육복
탐욕법 Greedy 문제
풀이 접근
- 해시맵을 이용해준다.
- n 만큼의 키 값에 기본으로 1을 넣어준다.
- lost에 있는 키 값이 있으면 다시 값을 -1 해준다.
- 이렇게 하는 이유는 여벌의 체육복을 가져왔는데 도난당했을 때의 로직을 단순화 해주기 위해서다.
- reverse에 있는 키 값으로 다시 + 1을 해준다.
- lost 반복문을 돌면서 벨류 값이 0인 키 값에 앞 뒤로 베류가 2이상일 경우 앞에 는 -1 본인은 +1 을 해준다.
구현 코드
import java.util.HashMap;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 1; i <= n ; i++) {
map.put(i,map.getOrDefault(i, 1));
}
for (int s : lost){
if(map.containsKey(s)){
map.put(s, 0);
}
}
for (int s : reserve){
if(map.containsKey(s)){
map.put(s, map.get(s) + 1);
}
}
for (int s : lost){
if(map.get(s) == 0){
if(map.get(s-1) >= 2){
map.put(s-1, 1);
map.put(s, 1);
} else if (map.get(s+1) >=2) {
map.put(s+1, 1);
map.put(s, 0);
}else {
map.remove(s);
}
}
}
return map.size();
}
}
런타임 에러…
불필요한 부분을 지우고 다시 해봤다.
import java.util.HashMap;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 1; i <= n ; i++) {
map.put(i, 1);
}
for (int s : lost){
map.put(s, 0);
}
for (int s : reserve){
if(map.get(s) == 1){
map.put(s,2);
}else {
map.put(s,1);
}
}
for (int s : lost){
if(map.get(s) == 0){
if(map.get(s-1) >= 2){
map.put(s-1, 1);
map.put(s, 1);
} else if (map.get(s+1) >=2) {
map.put(s+1, 1);
map.put(s, 0);
}else {
map.remove(s);
}
}
}
return map.size();
}
}
- 추측으로는 시간복잡도 문제는 아닌거 같은데 아마 인덱스 부분에서 문제가 있는 것 같았다.
import java.util.Arrays;
import java.util.HashMap;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 1; i <= n ; i++) {
map.put(i, 1);
}
for (int s : lost){
map.put(s, 0);
}
for (int s : reserve){
if(map.get(s) == 1){
map.put(s,2);
}else {
map.put(s,1);
}
}
for (int s : lost){
if(map.get(s) == 0){
if(s-1 >= 1 && map.get(s-1) >= 2){
map.put(s-1, 1);
map.put(s, 1);
} else if (s+1 <= n && map.get(s+1) >=2) {
map.put(s+1, 1);
map.put(s, 1);
}else {
map.remove(s);
}
}
}
return map.size();
}
}
- 예외케이스를 살펴 봤을 때 해시맵에서 최소값이나 최대값의 키 값이 넘어가는 문제를 잡지 못해서 문제가 발생했었다. 하지만 여전히 오류는 잡지 못하고 있었는데 문제는 내가 해시맵을 지우는거에 있었다.
- 키 값을 삭제할 경우 에러가 나는거였다. 그래서 그냥 내비두고 벨류값이 0 이상일 때만 체크를 해줬다.
import java.util.HashMap;
import java.util.Map;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 1; i <= n; i++) {
map.put(i, 1);
}
for (int s : lost) {
map.put(s, 0);
}
for (int s : reserve) {
if (map.get(s) == 1) {
map.put(s, 2);
} else {
map.put(s, 1);
}
}
for (int s : lost) {
if (map.get(s) == 0) {
if (s - 1 >= 1 && map.get(s - 1) >= 2) {
map.put(s - 1, 1);
map.put(s, 1);
} else if (s + 1 <= n && map.get(s + 1) >= 2) {
map.put(s + 1, 1);
map.put(s, 1);
}
}
}
int count = 0;
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if (entry.getValue() > 0){
count ++;
}
}
return count;
}
}
다른 사람의 코드를 보고 내가 틀린점을 바로 잡아야겠다고 생각했다.
import java.util.Arrays;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = 0;
Arrays.sort(reserve);
Arrays.sort(lost);
// 도난 당하지 않은 학생 수
answer = n - lost.length;
// 여벌 체육복을 가져왔지만 도난당한 학생 수
// 다른 학생에게 체육복을 빌려줄 수 없음
for (int i = 0; i < lost.length; i++) {
for (int j = 0; j < reserve.length; j++) {
if (lost[i] == reserve[j]) {
answer++;
lost[i] = -1;
reserve[j] = -1;
break;
}
}
}
// 도난당했지만 체육복을 빌릴 수 있는 학생 수
for (int i = 0; i < lost.length; i++) {
for (int j = 0; j < reserve.length; j++) {
if (lost[i] - 1 == reserve[j] || lost[i] + 1 == reserve[j]) {
answer++;
reserve[j] = -1;
break;
}
}
}
return answer;
}
}
정렬이 보장되어 있지 않아서가 틀린 이유였다..
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
HashMap<Integer, Integer> map = new HashMap<>();
Arrays.sort(lost);
for (int i = 1; i <= n; i++) {
map.put(i, 1);
}
for (int s : lost) {
map.put(s, 0);
}
for (int s : reserve) {
if (map.get(s) == 1) {
map.put(s, 2);
} else {
map.put(s, 1);
}
}
for (int s : lost) {
if (map.get(s) == 0) {
if (s - 1 >= 1 && map.get(s - 1) >= 2) {
map.put(s - 1, 1);
map.put(s, 1);
} else if (s + 1 <= n && map.get(s + 1) >= 2) {
map.put(s + 1, 1);
map.put(s, 1);
}
}
}
int count = 0;
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if (entry.getValue() > 0){
count ++;
}
}
return count;
}
}
정리
- 정렬되어 있다고 따로 나오지 않았다면 정말 정렬이 안되어 있다고 생각해야한다.
- 해시맵으로 문제를 풀어서 정렬이 필요 없겠다고 생각했는데 정작 마지막 부분은 정렬이 보장되어있지 않았을 경우 당연히 틀린 답이 나올 수 밖에 없다.
댓글남기기