diff --git a/combination-sum/rivkode.java b/combination-sum/rivkode.java new file mode 100644 index 0000000000..69a35f554c --- /dev/null +++ b/combination-sum/rivkode.java @@ -0,0 +1,102 @@ +/* + +1. 문제 이해 + +모든 조합 (중복 허용) 을 통해 target 숫자를 찾는다. + +2 +2, 2 +2, 2, 2 +2, 2, 2, 2 - 초과 +2, 2, 3 - 타겟 +2, 2, 6 - 초과 +2, 3 +2, 3, 3 +... +6, +6, 6 + + + +2. 알고리즘 + +dfs ? + +3. 예외 케이스 +일치 케이스 없는 경우 ? +다 돌면 예외가 있을까 ? + +4. 구현 + +종료 트리거는 일치할 경우 +target 숫자보다 높은 경우는 뒤로 감 +뒤로 가서 다음 숫자를 넣어 보자 + +candidates 정렬 +dfs 로 진행, 입력 파라미터는 더할 숫자 ? +대소 비교해서 만약 더 작으면 같은 숫자 넣고 더 크면 뒤로 이동 + +dfs 함수 + +새로운 Num 입력받음 +입력받은 숫자를 tmp 리스트에 더하고 +전체 합이 target 에 대해 대소 관계 비교 + +1. 크다면 뒤로 이동하고 다음 숫자 입력 +2. 같다면 result에 넣고 뒤로 이동 +3. 작다면 동일한 숫자 넣기 + +이상하게 dfs 를 구현했다. 순서도 맞지 않고 +for문 구현, 인자, 접근 방법 모두 틀렸다. +기억하자 +1. 호출은 main 에서 dfs() 한다 +2. 백트래킹 for 문은 dfs() 내에서 구현한다. + +답변을 보고 오니 백트래킹을 어떻게 해야겠다는 감이 왔다. + +뒤로 가는걸 어떻게 구현할까 생각했는데 For 문에서 tmp에 새로운 숫자를 넣고 제거하면서 그 사이에 dfs 를 넣으면 되는거였다. + +즉 +for loop +tmp.add num +dfs() +tmp.remove num + +식으로 말이다. + +*/ + +import java.util.*; + +class Solution { + private int t; + private List> result; + + public List> combinationSum(int[] candidates, int target) { + t = target; + result = new ArrayList<>(); + Arrays.sort(candidates); + List nums = new ArrayList<>(); + + dfs(candidates, 0, nums, 0); + + return result; + } + + public void dfs(int[] candidates, int total, List nums, int start) { + if (total > t) return; // total이 target 보다 크다면 이전으로 돌아가기 위해 return + if (total == t) { // 정답일 경우 해당 값 추가 및 return + result.add(new ArrayList<>(nums)); // nums 와 new ArrayList<>(nums) 차이 이해하기 + // 빈 배열로 저장되길래 왜 저때의 값이 저장안되지 ? 라고 생각했지만 + // 당연히 안됨. ref 주소값을 저장했으므로 나중에는 이 Nums가 모두 빈배열이 되므로 + return; + } + + for (int i=start; i < candidates.length; i++) { // start 부터 시작하는것 포인트! + int num = candidates[i]; + nums.add(num); + dfs(candidates, total + num, nums, i); + nums.remove(nums.size() - 1); // 다음에는 stack 사용하자 + } + } +} diff --git a/maximum-subarray/rivkode.java b/maximum-subarray/rivkode.java new file mode 100644 index 0000000000..f1acaf1b27 --- /dev/null +++ b/maximum-subarray/rivkode.java @@ -0,0 +1,69 @@ +/* +1. 문제 이해 + +[-2,1,-3,4,-1,2,1,-5,4] +* 정답부분 참고 +각 인덱스를 시작점으로 잡고 모든 부분에 대한 부분 배열의 합을 구한다 +이전에 계산했던 내용을 저장해서 사용한다 +-> 이렇게 계산해도 Time Limit Exceeded 발생하네 .. + +결국엔 이렇게 해도 n^2 시간이 발생하므로 시간초과 +포인트는 n^2 가 걸리는 시간을 어떻게 nlogn이나 n으로 줄일 수 있는지임 + +* 정답 부분 참고 +누적합이 음수라면 시작 인덱스를 다음으로 과감하게 옮긴다 + + +이 문제는 직관적으로 문제를 바라보는것이 중요했다. +아마도 이렇게 접근하는건 어떨까 ? +나는 최대합을 구하고싶었다. 부분 배열로! +부분배열이라는 것은 연속된다는 것이 특징이다. + +즉, 연속되어야 하므로 이전의 합들이 만약 음수라면 ? 이 부분들은 필요가 없어지므로 과감히 버릴 수 있다는 것을 아는 것이 포인트였다. + +버린다는 것의 의미는 ? -> 현재 인덱스의 값과 이전 전체의 값들의 합을 비교해서 현재 인덱스부터 다시 출발한다는 것이다. 그러므로 비교해서 더 큰값을 total로 가져가는 것이다. + +만약 이걸 처음부터 알았다면 그리고 기존에 작성한 n^2 를 소요하면서 모든 합을 구하려 했을때 비효율적인것을 직감했다면 다른 방법으로 접근할 수 있었어야 했다. + +그리고 처음 total, maxTotal을 첫번째 인덱스로 지정해줬기 때문에 i 인덱스는 1부터 시작해야한다 + + +*/ + +import java.util.*; + +class Solution { + public int maxSubArray(int[] nums) { + int total = nums[0]; + int maxTotal = nums[0]; + + + for (int i=1; i