코테 문제를 풀다가 List에서 remove하다가 분명 문제가 없어 보이는데 IndexOutOfBoundsException이 발생했다!
Leetcode의 77번 Combinations인데,
코테 풀이가 글의 목적은 아니니까 넘어가겠다.
주석을 해놓은 코드가 예외가 발생한 부분이다.
private List<List<Integer>> combine(int n, int k) {
List<List<Integer>> result = new ArrayList<>();
dfs(result, new ArrayList<>(), n, k, 1);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> elements, int n, int k, int start) {
if (k == 0) {
result.add(new ArrayList<>(elements));
return;
}
for (int i = start; i <= n; i++) {
elements.add(i);
dfs(result, elements, n, k - 1, i + 1);
// elements.remove(i); // 이건 remove(int index) 임.. -> IndexOutOfBoundsException 발생함
elements.remove(elements.size() - 1);
}
}
주석으로 만든 코드 elements.remove(i)를 했던 이유는 element에서 i 값을 찾아 리스트에서 지우려고 했던 것이다.
그러니까 내가 쓰려고 했던 메소드의 시그니처는 boolean remove(Object o)이고, 실제로 호출된 메소드의 시그니처는 E remove(int index)이다.
왜 i 값을 찾아서 지우는데 인덱스 관련 에러가 나나 해서 디버깅을 해봤더니 index를 매개변수로 받는 remove가 호출된 것을 보고 문제를 알게 되었다.
remove 메소드는 int를 받아 index로 값을 지우는 메소드, Object 타입을 받아 해당 object에 일치하는 값을 찾아 지우는 메소드로 각각 오버로딩되어 있었다.
int를 Wrapper 클래스인 Integer로 감싸야 하는데 그걸 생각못했다..
dfs 메소드를 재귀호출하는 전후로 elements에서 현재 i값을 추가하고 지우는데,
간단히 말해서 dfs 실행시키고 return, return되다가 다시 현재의 메소드로 돌아오면 elements에 방금 추가한걸 바로 빼는 거니까 elements에서 제일 마지막의 요소를 제거하면 되기 때문에 elements.remove(size()-1)을 해주면 된다.
또는 elements.remove(new Integer(i))로 i 값을 찾아서 지워도 된다.
하지만 배열을 사용하는 ArrayList이므로 기왕 배열 쓰는거 index로 찾는게 더 좋을 것이다.
끝🤪