-
[Leetcode] 923. 3Sum With Multiplicity 문제 풀이Algorithm/문제풀이 2022. 4. 6. 13:38
https://leetcode.com/problems/3sum-with-multiplicity/
3Sum With Multiplicity - LeetCode
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
문제 내용
배열 중에 숫자 3개의 합이 target이 되는 경우의 수가 몇개 있는 지 찾는 문제
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.
문제 풀이
1. two pointer 사용
정렬된 배열에서 1개를 선택하면 2개의 변수가 남는다.
2개 변수를 양쪽 끝에서 오면서 target 이 되는 지 확인했다.
여기서 2개의 case가 나왔는데
- 양쪽 변수가 같은 경우에는 1~n까지 더하는 수학공식을 사용했다.
양쪽 변수가 같다는 뜻은 내부 변수도 전부 같다는 의미이다.
변수가 다 같을 경우 2개 뽑는 경우의 수는
첫번째 선택했을 때 n-1개
두번째 선택했을 때 n-2개
...
하면 결국 1부터 n까지 더하는 공식 = n*(n+1) / 2 이 된다. - 양쪽 변수가 다를 경우에는 각각 중복되는 개수를 구해서 곱셈으로 경우의수를 구했다.
양쪽 변수가 다르면 양쪽에서 한개씩 뽑는다고 생각하면 결국 왼쪽 n개 랑 오른쪽 m개가 서로 곱한게 경우의 수가 된다.
그리고 target - arr[i] - arr[s] - arr[e] 한 값이
음수면, 큰 수가 필요하니 왼쪽에 있는 작은 숫자를 한칸 이동하면 되고
양수면, 작은 수가 필요하니 오른쪽에 있는 큰 숫자를 줄이게 한칸 이동하면 된다.
2. count hash 사용
2개 변수를 2중 for문으로 돌면서 마지막 변수를 count hash로 몇개인지 구하는 방법이다.
값의 범위가 0~100까지로 작기 때문에 값을 해시키로 사용 가능하다.
값 v = target - arr[i] - arr[j]가 hash에 몇개 있는 지 ans에 계속 더하면 된다.
그리고 j가 한칸 갔을 때 hash에 arr[j] 을 추가한다.
j가 지나는 값이 몇개인지 count 해서 사용하기 때문이다.
i를 기준으로 새로 count hash 기록한다.
hash는 사용할 수 있는 값의 집합같은 개념으로 보면 된다.
즉, 어떤 값 x가 몇개가 있는 지 저장하는 count hash이다.
예를 들어, count[1] = 2 이면 x=1이 2개가 집합에 있고 그 2개를 쓸 수 있다는 뜻이 된다.
2개를 쓸 수 있다는 것은 2번 가능 하다는 뜻이고 경우의 수가 2라는 의미이다.
그래서 ans += count[1] 을 할 수 있다.
count[v] 의 의미는 target = arr[i] + arr[j] + v 인데 해당 값 v가 몇개 있는 지 찾는 다는 뜻이다.
count[arr[j]]++ 의 의미는 arr[j] 값을 count hash 집합에 1개 추가한다는 뜻이다.
j는 한칸씩 ++ 하기 때문에 사용한 arr[j]는 count hash 집합에 추가하고,
다음 arr[j+1] 때 count hash 집합에 요긴하게 사용할 수 있다.
코드
two pointer 사용
class Solution { public: const int mod = 1e9+7; int threeSumMulti(vector<int>& arr, int target) { sort(arr.begin(), arr.end()); long ans = 0; for (int i = 0; i < arr.size(); ++i) { int newTarget = target - arr[i]; int s = i+1; int e = arr.size()-1; while (s < e) { int value = newTarget - (arr[s] + arr[e]); if (value == 0) { if (arr[s] == arr[e]) { int n = e - s; ans += n*(n+1)/2; break; } int s_count = 1; while (s+1 < e && arr[s] == arr[s+1]) { ++s; ++s_count; } int e_count = 1; while (s < e-1 && arr[e] == arr[e-1]) { --e; ++e_count; } ans += s_count * e_count; } if (value > 0) { ++s; } else { --e; } } } return ans % mod; } };
count hash 사용
class Solution { public: const int mod = 1e9+7; int threeSumMulti(vector<int>& arr, int target) { int ans = 0; for (int i = 2; i < arr.size(); ++i) { vector<int> count(101, 0); for (int j = 0; j < i; ++j) { int v = target - arr[i] - arr[j]; if (0 <= v && v <= 100) { ans = (ans + count[v]) % mod; } count[arr[j]]++; } } return ans; } };
'Algorithm > 문제풀이' 카테고리의 다른 글
[Leetcode] 703. Kth Largest Element in a Stream 문제 풀이 (0) 2022.04.08 [Leetcode] 1046. Last Stone Weight 문제 풀이 (0) 2022.04.07 [Leetcode] 31. Next Permutation 문제 풀이 (0) 2022.04.05 [Leetcode] 1721. Swapping Nodes in a Linked List 문제 풀이 (0) 2022.04.04 [Leetcode] 540. Single Element in a Sorted Array 문제풀이 (0) 2021.11.20 - 양쪽 변수가 같은 경우에는 1~n까지 더하는 수학공식을 사용했다.