Skip to content

Commit 62b973f

Browse files
committed
feat: product-of-array solve 1차 개선 필요
1 parent 864ddca commit 62b973f

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
4+
class Solution {
5+
/**
6+
* 풀이요약: 범위를 반씩 나누며 곱을 캐싱하고, 제외할 인덱스만 골라 탐색하는 분할 정복 기반 배타 곱 계산
7+
*
8+
*
9+
* 풀이결과:
10+
*
11+
* Runtime: 872 ms (Beats 3.62%)
12+
* Memory: 137.29 MB (Beats 5.61%)
13+
* Space Complexity: O(NlogN)
14+
* - 길이 N인 배열을 절반씩 자른 범위 안에 수들을 곱한 값을 저장 O(NlogN)
15+
* - 길이 N인 출력 배열 생성 O(N)
16+
* > O(N) + O(NlogN) > O(NlogN)
17+
*
18+
* Time Complexity: O(NlogN)
19+
* - 길이 N인 배열을 절반씩 잘라가면서 안에 수들을 곱하기 O(NlogN)
20+
* - 0~N 범위를 절반씩 잘라가면서 i가 포함되지 않은 범위 수를 곱하기 O(logN)
21+
* - N개의 숫자에 대해서 찾기 => O(NlogN)
22+
* > O(NlogN) + O(NlogN) > O(NlogN)
23+
*/
24+
public int[] productExceptSelf1(int[] nums) {
25+
Map<String, Integer> mp = new HashMap<>();
26+
fndRngMul(mp, nums, 0, nums.length);
27+
int[] ans = new int[nums.length];
28+
for (int i = 0; i < nums.length; i++) {
29+
int val = binaryFnd(mp, i, 0, nums.length);
30+
ans[i] = val;
31+
}
32+
33+
return ans;
34+
}
35+
36+
/***
37+
* 특정 idx를 제외한 구간 곱을 재귀적으로 찾는다.
38+
*
39+
* - 범위가 단일 원소면 곱에 포함될 값이 없으므로 1 반환
40+
* - 범위를 반으로 자르고, idx가 속하지 않은 부분의 곱을 즉시 사용
41+
* - idx가 속한 쪽은 계속 재귀 탐색
42+
*/
43+
private int binaryFnd(Map<String, Integer> mp, int idx, int str, int end) {
44+
int val = 1;
45+
46+
if (end - str == 1) {
47+
return val;
48+
}
49+
50+
int mid = (str + end) / 2;
51+
String leftKey = str + "_" + mid;
52+
String rightKey = mid + "_" + end;
53+
// System.out.println("----idx->"+idx+" mid->"+mid);
54+
// idx는 좌측에 위치하기 때문에 우측 값을 곱함.
55+
if (idx < mid) {
56+
// 하지만 다은 idx가 포함된 범위를 탐색
57+
int leftVal = binaryFnd(mp, idx, str, mid);
58+
// System.out.println(". ----leftVal->"+leftVal+" base->"+mp.get(rightKey)+"
59+
// val-> "+val);
60+
val = mp.get(rightKey) * leftVal;
61+
} else { // idx는 우측에 위치하기 때문에 좌측 값을 곱함.
62+
int rightVal = binaryFnd(mp, idx, mid, end);
63+
// System.out.println(". ----rightVal->"+rightVal+" base->"+mp.get(leftKey)+"
64+
// val-> "+val);
65+
val = mp.get(leftKey) * rightVal;
66+
}
67+
return val;
68+
}
69+
70+
/**
71+
* 배열의 범위 [str, end) 내 값들의 곱을 구해 캐싱한다.
72+
*
73+
* - 원소가 하나만 있는 구간이면 nums[str] 저장
74+
* - 구간을 반으로 나누어 왼쪽/오른쪽 곱을 재귀적으로 계산
75+
* - 전체 구간이 아니라면 left * right 를 캐싱
76+
* - 전체 구간(0~N)은 제외 곱 계산 시 무시해야 하므로 '1' 저장
77+
*/
78+
private int fndRngMul(Map<String, Integer> mp, int[] nums, int str, int end) {
79+
String k = str + "_" + end;
80+
81+
if (end - str == 1) {
82+
// System.out.println("put k->"+k+" v->"+v);
83+
mp.put(k, nums[str]);
84+
return nums[str];
85+
}
86+
int mid = (str + end) / 2;
87+
int leftRngMul = fndRngMul(mp, nums, str, mid);
88+
int rightRngMul = fndRngMul(mp, nums, mid, end);
89+
90+
int v = 1;
91+
// 전체 곱은 구하지 않음.
92+
if (str == 0 && end == nums.length) {
93+
v = 1;
94+
} else {
95+
v = leftRngMul * rightRngMul;
96+
}
97+
mp.put(k, v);
98+
// System.out.println("put2 k->"+k+" v->"+v);
99+
return v;
100+
}
101+
}

0 commit comments

Comments
 (0)