티스토리 뷰
Problem
Given an integer array arr, and an integer target, return the number of tuples i, j, k such that i < j < k and arr[i] + arr[j] + arr[k] == target.
As the answer can be very large, return it modulo 10^9 + 7.
Example 1:
Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8
Output: 20
Explanation:
Enumerating by the values (arr[i], arr[j], arr[k]):
(1, 2, 5) occurs 8 times;
(1, 3, 4) occurs 8 times;
(2, 2, 4) occurs 2 times;
(2, 3, 3) occurs 2 times.
Example 2:
Input: arr = [1,1,2,2,2,2], target = 5
Output: 12
Explanation:
arr[i] = 1, arr[j] = arr[k] = 2 occurs 12 times:
We choose one 1 from [1,1] in 2 ways,
and two 2s from [2,2,2,2] in 6 ways.
Constraints:
- 3 <= arr.length <= 3000
- 0 <= arr[i] <= 100
- 0 <= target <= 300
Solution
정수 배열과 타겟 정수가 주어질 때 배열의 세 정수의 합이 타겟 정수가 되는 모든 경우의 수를 구하는 문제입니다.
정답이 매우 커질 수 있으니 10^9 + 7로 나눈 값을 반환합니다.
package io.lcalmsky.leetcode._3sum_with_multiplicity;
import java.util.Arrays;
public class Solution {
private static final int MOD = 1_000_000_007;
public int threeSumMulti(int[] array, int target) {
long answer = 0;
Arrays.sort(array); // (1)
for (int i = 0; i < array.length; ++i) {
int twoSum = target - array[i]; // (2)
int j = i + 1, k = array.length
- 1; // (3)
while (j < k) { // (4)
if (array[j] + array[k] < twoSum) { // (5)
j++;
} else if (array[j] + array[k] > twoSum) { // (6)
k--;
} else if (array[j] != array[k]) { // (7)
int left = 1, right = 1;
while (j + 1 < k && array[j] == array[j + 1]) { // (8)
left++;
j++;
}
while (k - 1 > j && array[k] == array[k - 1]) { // (9)
right++;
k--;
}
answer += (long) left * right; // (10)
answer %= MOD;
j++;
k--;
} else { // (11)
answer += (long) (k - j + 1) * (k - j) / 2;
answer %= MOD;
break;
}
}
}
return (int) answer;
}
}
- 배열을 정렬합니다.
- i를 제외한 j와 k의 합이 되어야 하는 수 입니다.
- i, j, k 포인터 세 개를 사용합니다. i가 기준이고 j는 i보다 큰 수 중 가장 작은 수, k는 가장 큰 수 입니다.
- 여기부터는 두 개의 포인터를 다루듯이 구현할 수 있습니다.
- j와 k의 합이 목표보다 작으면 j를 올려줍니다.
- j와 k의 합이 목표보다 크면 k를 줄여줍니다.
- j와 k의 합이 목표(twoSum)와 같은데 j와 k가 다를 때
- j가 같은 수인 개수를 셉니다.
- k도 마찬가지로 같은 수 개수를 셉니다.
- j 같은 수의 개수와 k 같은 수의 개수를 곱해줍니다.
- j와 k의 합이 목표와 같고 j와 k가 같을 때, j부터 k까지 모두 동일한 수라는 뜻이기 때문에, k-j+1 개 중 2개를 뽑는 경우의 수만큼 결과에 추가합니다.
Test
package io.lcalmsky.leetcode._3sum_with_multiplicity;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class SolutionTest {
@Test
void testAll() {
assertAll(
() -> test(new int[]{1, 1, 2, 2, 3, 3, 4, 4, 5, 5}, 8, 20),
() -> test(new int[]{1, 1, 2, 2, 2, 2,}, 5, 12)
);
}
private void test(int[] array, int target, int expected) {
// when
Solution solution = new Solution();
int actual = solution.threeSumMulti(array, target);
// then
assertEquals(expected, actual);
}
}
'Algorithm > LeetCode' 카테고리의 다른 글
344. Reverse String (0) | 2022.04.22 |
---|---|
1046. Last Stone Weight (0) | 2022.04.19 |
11. Container With Most Water (0) | 2022.04.16 |
1721. Swapping Nodes in a Linked List (0) | 2022.04.15 |
881. Boats to Save People (0) | 2022.04.09 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- intellij
- 헥사고날 아키텍처
- Jackson
- 알고리즘
- Spring Boot
- Spring Boot JPA
- @ManyToOne
- 스프링 부트
- Spring Data JPA
- Java
- spring boot jwt
- JPA
- Spring Boot Tutorial
- spring boot application
- proto3
- JSON
- gRPC
- 스프링 부트 튜토리얼
- leetcode
- 스프링 데이터 jpa
- 스프링 부트 애플리케이션
- 클린 아키텍처
- Linux
- r
- 스프링 부트 회원 가입
- spring boot app
- 스프링부트
- 함께 자라기
- QueryDSL
- 함께 자라기 후기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함