|
| 1 | +import java.util.HashMap; |
| 2 | +import java.util.Map; |
| 3 | + |
| 4 | +/** |
| 5 | + * |
| 6 | + * ๋ง์ง๋ง ํ์ด๊ฐ ์ต์ข
ํ์ด๊ณ ์ ์ฐจ ๋ณต์ก๋๊ฐ ๊ฐ์ ๋ฉ๋๋ค. |
| 7 | + * |
| 8 | + * 1๋ฒ์งธ ํ์ด: ์๊ทธ๋จผํธ ํธ๋ฆฌ๋ฅผ ์์ฉํ ๋ฒ์ ๊ณฑ ๊ฒ์ฐ ๊ตฌํ |
| 9 | + * 2๋ฒ์งธ ํ์ด: ๊ธฐ๋ณธ์ ์ธ prefix, suffix product ๊ตฌํ |
| 10 | + * 3๋ฒ์งธ ํ์ด: ์ต์ข
ํ์ด๋ก prefix, suffix product์ ๊ณต๊ฐ๋ณต์ก๋๋ฅผ O(1)๋ก ์ต์ ํ |
| 11 | + * |
| 12 | + */ |
| 13 | +class Solution { |
| 14 | + |
| 15 | + /** |
| 16 | + * ํ์ด์์ฝ: ๋ฒ์๋ฅผ ๋ฐ์ฉ ๋๋๋ฉฐ ๊ณฑ์ ์บ์ฑํ๊ณ , ์ ์ธํ ์ธ๋ฑ์ค๋ง ๊ณจ๋ผ ํ์ํ๋ ๋ถํ ์ ๋ณต ๊ธฐ๋ฐ ๋ฐฐํ ๊ณฑ ๊ณ์ฐ |
| 17 | + * |
| 18 | + * ํ์ด๊ฒฐ๊ณผ: |
| 19 | + * Runtime: 872 ms (Beats 3.62%) |
| 20 | + * Memory: 137.29 MB (Beats 5.61%) |
| 21 | + * Space Complexity: O(NlogN) |
| 22 | + * - ๊ธธ์ด N์ธ ๋ฐฐ์ด์ ์ ๋ฐ์ฉ ์๋ฅธ ๋ฒ์ ์์ ์๋ค์ ๊ณฑํ ๊ฐ์ ์ ์ฅ O(NlogN) |
| 23 | + * - ๊ธธ์ด N์ธ ์ถ๋ ฅ ๋ฐฐ์ด ์์ฑ O(N) |
| 24 | + * > O(N) + O(NlogN) > O(NlogN) |
| 25 | + * |
| 26 | + * Time Complexity: O(NlogN) |
| 27 | + * - ๊ธธ์ด N์ธ ๋ฐฐ์ด์ ์ ๋ฐ์ฉ ์๋ผ๊ฐ๋ฉด์ ์์ ์๋ค์ ๊ณฑํ๊ธฐ O(NlogN) |
| 28 | + * - 0~N ๋ฒ์๋ฅผ ์ ๋ฐ์ฉ ์๋ผ๊ฐ๋ฉด์ i๊ฐ ํฌํจ๋์ง ์์ ๋ฒ์ ์๋ฅผ ๊ณฑํ๊ธฐ O(logN) |
| 29 | + * - N๊ฐ์ ์ซ์์ ๋ํด์ ์ฐพ๊ธฐ => O(NlogN) |
| 30 | + * > O(NlogN) + O(NlogN) > O(NlogN) |
| 31 | + */ |
| 32 | + public int[] productExceptSelf1(int[] nums) { |
| 33 | + Map<String, Integer> mp = new HashMap<>(); |
| 34 | + fndRngMul(mp, nums, 0, nums.length); |
| 35 | + int[] ans = new int[nums.length]; |
| 36 | + for (int i = 0; i < nums.length; i++) { |
| 37 | + int val = binaryFnd(mp, i, 0, nums.length); |
| 38 | + ans[i] = val; |
| 39 | + } |
| 40 | + |
| 41 | + return ans; |
| 42 | + } |
| 43 | + |
| 44 | + /*** |
| 45 | + * ํน์ idx๋ฅผ ์ ์ธํ ๊ตฌ๊ฐ ๊ณฑ์ ์ฌ๊ท์ ์ผ๋ก ์ฐพ๋๋ค. |
| 46 | + * |
| 47 | + * - ๋ฒ์๊ฐ ๋จ์ผ ์์๋ฉด ๊ณฑ์ ํฌํจ๋ ๊ฐ์ด ์์ผ๋ฏ๋ก 1 ๋ฐํ |
| 48 | + * - ๋ฒ์๋ฅผ ๋ฐ์ผ๋ก ์๋ฅด๊ณ , idx๊ฐ ์ํ์ง ์์ ๋ถ๋ถ์ ๊ณฑ์ ์ฆ์ ์ฌ์ฉ |
| 49 | + * - idx๊ฐ ์ํ ์ชฝ์ ๊ณ์ ์ฌ๊ท ํ์ |
| 50 | + */ |
| 51 | + private int binaryFnd(Map<String, Integer> mp, int idx, int str, int end) { |
| 52 | + int val = 1; |
| 53 | + |
| 54 | + if (end - str == 1) { |
| 55 | + return val; |
| 56 | + } |
| 57 | + |
| 58 | + int mid = (str + end) / 2; |
| 59 | + String leftKey = str + "_" + mid; |
| 60 | + String rightKey = mid + "_" + end; |
| 61 | + // System.out.println("----idx->"+idx+" mid->"+mid); |
| 62 | + // idx๋ ์ข์ธก์ ์์นํ๊ธฐ ๋๋ฌธ์ ์ฐ์ธก ๊ฐ์ ๊ณฑํจ. |
| 63 | + if (idx < mid) { |
| 64 | + // ํ์ง๋ง ๋ค์ idx๊ฐ ํฌํจ๋ ๋ฒ์๋ฅผ ํ์ |
| 65 | + int leftVal = binaryFnd(mp, idx, str, mid); |
| 66 | + // System.out.println(". ----leftVal->"+leftVal+" base->"+mp.get(rightKey)+" |
| 67 | + // val-> "+val); |
| 68 | + val = mp.get(rightKey) * leftVal; |
| 69 | + } else { // idx๋ ์ฐ์ธก์ ์์นํ๊ธฐ ๋๋ฌธ์ ์ข์ธก ๊ฐ์ ๊ณฑํจ. |
| 70 | + int rightVal = binaryFnd(mp, idx, mid, end); |
| 71 | + // System.out.println(". ----rightVal->"+rightVal+" base->"+mp.get(leftKey)+" |
| 72 | + // val-> "+val); |
| 73 | + val = mp.get(leftKey) * rightVal; |
| 74 | + } |
| 75 | + return val; |
| 76 | + } |
| 77 | + |
| 78 | + /** |
| 79 | + * ๋ฐฐ์ด์ ๋ฒ์ [str, end) ๋ด ๊ฐ๋ค์ ๊ณฑ์ ๊ตฌํด ์บ์ฑํ๋ค. |
| 80 | + * |
| 81 | + * - ์์๊ฐ ํ๋๋ง ์๋ ๊ตฌ๊ฐ์ด๋ฉด nums[str] ์ ์ฅ |
| 82 | + * - ๊ตฌ๊ฐ์ ๋ฐ์ผ๋ก ๋๋์ด ์ผ์ชฝ/์ค๋ฅธ์ชฝ ๊ณฑ์ ์ฌ๊ท์ ์ผ๋ก ๊ณ์ฐ |
| 83 | + * - ์ ์ฒด ๊ตฌ๊ฐ์ด ์๋๋ผ๋ฉด left * right ๋ฅผ ์บ์ฑ |
| 84 | + * - ์ ์ฒด ๊ตฌ๊ฐ(0~N)์ ์ ์ธ ๊ณฑ ๊ณ์ฐ ์ ๋ฌด์ํด์ผ ํ๋ฏ๋ก '1' ์ ์ฅ |
| 85 | + */ |
| 86 | + private int fndRngMul(Map<String, Integer> mp, int[] nums, int str, int end) { |
| 87 | + String k = str + "_" + end; |
| 88 | + |
| 89 | + if (end - str == 1) { |
| 90 | + // System.out.println("put k->"+k+" v->"+v); |
| 91 | + mp.put(k, nums[str]); |
| 92 | + return nums[str]; |
| 93 | + } |
| 94 | + int mid = (str + end) / 2; |
| 95 | + int leftRngMul = fndRngMul(mp, nums, str, mid); |
| 96 | + int rightRngMul = fndRngMul(mp, nums, mid, end); |
| 97 | + |
| 98 | + int v = 1; |
| 99 | + // ์ ์ฒด ๊ณฑ์ ๊ตฌํ์ง ์์. |
| 100 | + if (str == 0 && end == nums.length) { |
| 101 | + v = 1; |
| 102 | + } else { |
| 103 | + v = leftRngMul * rightRngMul; |
| 104 | + } |
| 105 | + mp.put(k, v); |
| 106 | + // System.out.println("put2 k->"+k+" v->"+v); |
| 107 | + return v; |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * ํ์ด์์ฝ: ์ข์ฐ๋ก ๋์ ๊ณฑํ๋ ๋ฐฐ์ญ์ ๋ง๋ค๊ณ , i๋ฅผ ์ ์ธํ ์ข์ฐ ๋ฒ์ ๋์ ๊ณฑ์ ๊ณฑํ๋ค. |
| 112 | + * prefix-product์ suffix-product๋ฅผ ๊ตฌํ๊ธฐ |
| 113 | + * |
| 114 | + * ํ์ด๊ฒฐ๊ณผ: |
| 115 | + * Runtime: 3 ms (Beats 21.34%) |
| 116 | + * Memory: 64.97 MB (Beats 19.65%) |
| 117 | + * Space Complexity: O(N) |
| 118 | + * - ๊ธธ์ด๊ฐ N์ธ ๋ฐฐ์ด์ 3๊ฐ๋ฅผ ๋ง๋ค๊ธฐ |
| 119 | + * > O(N) + O(N) + O(N) > O(N) |
| 120 | + * Time Complexity: O(N) |
| 121 | + * - ๊ธธ์ด N์ธ ๋ฐฐ์ด 2๋ฒ ์ํํ๊ธฐ > O(N) |
| 122 | + * - 0~N์ ์ํํ๋ฉด์ ๋์ ๊ณฑ ๊ณฑํ๊ธฐ > O(N) |
| 123 | + * > O(N) + O(N) > O(N) |
| 124 | + */ |
| 125 | + public int[] productExceptSelf2(int[] nums) { |
| 126 | + int L = nums.length; |
| 127 | + int[] leftAccMul = new int[L]; |
| 128 | + int[] rightAccMul = new int[L]; |
| 129 | + int[] ans = new int[L]; |
| 130 | + |
| 131 | + // 0๋ถํฐ ๋์ ๊ณฑํ๊ธฐ |
| 132 | + leftAccMul[0] = nums[0]; |
| 133 | + for (int i = 1; i < L; i++) { |
| 134 | + leftAccMul[i] = leftAccMul[i - 1] * nums[i]; |
| 135 | + } |
| 136 | + |
| 137 | + // L-1๋ถํฐ ๋์ ๊ณฑํ๊ธฐ |
| 138 | + rightAccMul[L - 1] = nums[L - 1]; |
| 139 | + for (int i = L - 2; i >= 0; i--) { |
| 140 | + rightAccMul[i] = rightAccMul[i + 1] * nums[i]; |
| 141 | + } |
| 142 | + |
| 143 | + // i๋ฅผ ์ ์ธํ ๋์ ๊ณฑ์ ๊ณฑํ๊ธฐ |
| 144 | + for (int i = 0; i < L; i++) { |
| 145 | + int val = 1; |
| 146 | + if (i == 0) { // ์ค๋ฅธ์ชฝ ๋์ ๊ณฑ๋ง ๊ณฑํ๊ธฐ |
| 147 | + val *= rightAccMul[i + 1]; // i+1 ~ L-1๊น์ง ๊ณฑํ ๊ฐ |
| 148 | + } else if (i == L - 1) { // ์ผ์ชฝ ๋์ ๊ณฑ๋ง ๊ณฑํ๊ธฐ |
| 149 | + val *= leftAccMul[i - 1]; // 0~L-2๊น์ง ๊ณฑํ ๊ฐ |
| 150 | + } else { |
| 151 | + val *= leftAccMul[i - 1] * rightAccMul[i + 1]; |
| 152 | + } |
| 153 | + ans[i] = val; |
| 154 | + } |
| 155 | + return ans; |
| 156 | + } |
| 157 | + |
| 158 | + /** |
| 159 | + * ํ์ด์์ฝ: ์ข์ฐ๋ก ๋์ ๊ณฑํ๋ ๋ฐฐ์ญ์ ๋ง๋ค๊ณ , i๋ฅผ ์ ์ธํ ์ข์ฐ ๋ฒ์ ๋์ ๊ณฑ์ ๊ณฑํ๋ค. |
| 160 | + * prefix-product ๋ฐฐ์ด์ ์ถ๋ ฅ ๋ฐฐ์ด๋ก ์ฌ์ฉํ๊ธฐ |
| 161 | + * suffix-product ๋ฐฐ์ด ๋์ ์ค๋ฅธ์ชฝ ๋์ ๊ณฑ์ ํ ๋ณ์๋ก๋ง ๊ด๋ฆฌํ๋ค. |
| 162 | + * |
| 163 | + * ํ์ด๊ฒฐ๊ณผ: |
| 164 | + * Runtime: 2 ms (Beats 89.36%) |
| 165 | + * Memory: 72.28 MB (Beats 5.61%) |
| 166 | + * Space Complexity: O(1) |
| 167 | + * - ๊ธธ์ด๊ฐ N์ธ ๋ฐฐ์ด์ 1๊ฐ๋ฅผ ๋ง๋ค์ง๋ง, return์ ์ฐ์ด๋ฏ๋ก ์นด์ดํ
์๋จ. |
| 168 | + * - suffix-product ๊ฒ์ฐ์ฉ ๋ณ์ 1๊ฐ |
| 169 | + * > O(1) > O(1) |
| 170 | + * Time Complexity: O(N) |
| 171 | + * - ๊ธธ์ด N์ธ ๋ฐฐ์ด 2๋ฒ ์ํํ๊ธฐ > O(N) |
| 172 | + * > O(N) > O(N) |
| 173 | + * |
| 174 | + */ |
| 175 | + public int[] productExceptSelf3(int[] nums) { |
| 176 | + int L = nums.length; |
| 177 | + int[] leftAccMul = new int[L]; |
| 178 | + |
| 179 | + // 0๋ถํฐ ๋์ ๊ณฑํ๊ธฐ |
| 180 | + leftAccMul[0] = 1; |
| 181 | + for (int i = 1; i < L; i++) { |
| 182 | + leftAccMul[i] = leftAccMul[i - 1] * nums[i - 1]; |
| 183 | + // System.out.println("i->"+i+" val->"+leftAccMul[i]); |
| 184 | + } |
| 185 | + // System.out.println("--------------"); |
| 186 | + // L-1๋ถํฐ ๋์ ๊ณฑํ๊ธฐ |
| 187 | + int rightAccMul = nums[L - 1]; |
| 188 | + for (int i = L - 2; i >= 0; i--) { |
| 189 | + // L-1๋ฒ์งธ ์ซ์๋ suffix-product์์ ๊ณฑํ ๊ฒ ์๋ค.. |
| 190 | + // 0๋ฒ์งธ ์ซ์๋ 1~L-1 ๋ฒ์ ๋์ ๊ณฑ๋ง ๊ณฑํด์ผํ๋ค. |
| 191 | + leftAccMul[i] *= rightAccMul; |
| 192 | + rightAccMul *= nums[i]; |
| 193 | + // System.out.println("i->"+i+" val->"+leftAccMul[i]); |
| 194 | + } |
| 195 | + return leftAccMul; |
| 196 | + } |
| 197 | +} |
0 commit comments