Codewars 문제풀기 (05/04)
Delete occurrences of an element if it occurs more than n times
-
int[] elements, int maxOccurrences를 인자로 받는다.
-
elements 배열의 elemtent들 중 maxOccurrences보다 더 많은 element들을 maxOccurrences만큼만 남기고 삭제한다.
deleteNth(new int[]{20,37,20,21},1) 👉 {20,37,21} deleteNth(new int[]{1,1,1,3,3,3,7,2,2,2,2},2) 👉 {1,1,3,3,7,2,2}
1. Test와 리팩토링
-
테스트 1 - 입력이 빈 배열일 때 maxOccurrences에 상관없이 빈 배열을 리턴한다.
-
테스트 코드
@Test public void testShouldEmptyArrayWhenInputArrayIsEmptyRegardlessOfMaxOccurrences() { // Given: Set empty array and maxOccurrences int[] givenArray = new int[]{}; int givenMaxOccurrences = 5; // Then: Should Return empty array regardless maxOccurrences assertArrayEquals(givenArray, EnoughIsEnough.deleteNth(givenArray, givenMaxOccurrences)); }
- When없이 Then으로 처리해도 괜찮다고 생각해서 없앴다.
-
실제 코드
public class EnoughIsEnough { public static int[] deleteNth(int[] elements, int maxOccurrences) { return elements.length==0 ? new int[]{} : null; } }
-
-
테스트 2 - {20,37,20,21}, 1가 인자일때 {20,37,20}을 리턴한다
-
테스트 코드
@Test @DisplayName("test should return {20, 37, 21} when input is {20, 37, 20, 21} and 1") public void test1() { // Given: Set array {20, 37, 20, 21} and maxOccurrences 1 int[] givenArray = new int[]{20, 37, 20, 21}; int givenMaxOccurrences = 1; // Then: Should Return {20, 37, 21} assertArrayEquals(new int[]{20, 37, 21}, EnoughIsEnough.deleteNth(givenArray, givenMaxOccurrences)); }
-
실제 코드
public class EnoughIsEnough { public static int[] deleteNth(int[] elements, int maxOccurrences) { if (elements.length == 0) { return new int[]{}; } Map<Integer, Integer> valueCount = new HashMap<>(); List<Integer> result = new ArrayList<>(); for (int i = 0; i < elements.length; i++) { valueCount.put(elements[i], 0); } for (int i = 0; i < elements.length; i++) { if (valueCount.get(elements[i]) < maxOccurrences) { result.add(elements[i]); valueCount.put(elements[i], valueCount.get(elements[i]) + 1); } } return result.stream().mapToInt(i -> i).toArray(); } }
- value와 value count를 Map을 이용해서 key value로 저장했다. 그래서 List에 element들을 maxOccurrences이하 만큼만 저장한 뒤 array로 변환해서 리턴했다.
- for문을 잘 보면 같은 for문이기 때문에 하나로 합칠 수 있지 않을까? 생각을 했는데 그러면 for문 돌 때마다 0으로 초기화 되어서 그냥 분리해서 구현했다.
-
2. 답 비교, 느낀점
Best Practice 가장 많이 받은 코드
import java.util.*;
public class EnoughIsEnough {
public static int[] deleteNth(int[] elements, int max) {
if (max < 1) return new int[0];
final HashMap<Integer,Integer> map = new HashMap<>();
final List<Integer> list = new ArrayList<>();
for (final Integer i : elements) {
final Integer v = map.put(i, map.getOrDefault(i, 0) + 1);
if (v == null || v < max) list.add(i);
}
return list.stream().mapToInt(i->i).toArray();
}
}
- 구현하는 방법 자체는 같은데 더 좋은방법을 썼다.
Map.put()
의 리턴값이 이전 value값인것도 몰랐고,map.getOrDefault()
으로 Key가 없으면 default값을 리턴하도록 할 수 있는 메서드가 있는것도 몰랐다. 애초에 map이 key value로 구성되어있다. 라고만 알고 있고 지원하는 메서드는 잘 몰랐다.- 전에 문제 몇개를 통해서 알게 된것이지만 List 👉 Array로 변환하는 방법이 은근 유용하다고 문제 풀때마다 느낀다.
댓글남기기