1099. Two Sum Less Than K
Easy
Given an array nums of integers and integer k, return the maximum sum such that there exists i < j with nums[i] + nums[j] = sum and sum < k. If no i, j exist satisfying this equation, return -1.
Example 1:
Input: nums = [34,23,1,24,75,33,54,8], k = 60
Output: 58
Explanation: We can use 34 and 24 to sum 58 which is less than 60.
Example 2:
Input: nums = [10,20,30], k = 15
Output: -1
Explanation: In this case it is not possible to get a pair sum less that 15.
Constraints:
- 1 <= nums.length <= 100
- 1 <= nums[i] <= 1000
- 1 <= k <= 2000
문제 풀이
- 주어진 배열에서 숫자 두개를 더한 값이 K보다 작을때 가장 큰 값을 구해야한다.
부루트 포스
- 배열을 각각 더해보면서 K 값보다 작을때 최대값을 저장한다.
- 정렬 + 투포인터
- 배열을 정렬하고 배열의 양끝에서 인덱스를 옮기면서 값을 계산한다.
- 만약 두개의 숫자를 더한 값이 K보다 작다면 최대값을 구하고 왼쪽 포인터를 하나 올린다.
- 정렬이 되어있기 때문에 왼쪽 포인터를 오른쪽으로 옮기면 숫자가 커져서 합도 증가할 것이다.
바이너리 서치
- 투포인터와 비슷한 로직이다.
- 배열을 먼저 정렬한다.
- 가장 작은 값부터 진행하는데, 값을 K에서 뺀것을 Lower boundery 바이너리 서치로 위치를 검색한다.
- bisect_left를 사용하면되는데, K에서 현재 위치의 값을 뺀것에 가장 가까우면서 왼쪽 위치의 값을 찾는다, 즉, K - nums[i] 보다 작은 값을 찾게 된다.
- (bisect_right는 반대이다.)
- 만약 j 가 i 보다 크면 최대값을 구해준다.
- (이진 탐색의 시작 위치를 정해주었어도 i 보다 작은 인덱스를 결과로 가져올 수 있기 때문이다.)
카운팅 소트
- 숫자의 최대값인 1000까지 빈 배열을 만든다.
- 이 배열은 숫자의 개수를 저장할 배열이다.
- 1부터 최대 값인 1000까지 진행을 하는데 투포인터처럼 양끝에서 시작한다.
- 만일 두개의 값의 합이 K보다 같거나 크면 오른쪽 포인터를 하나 줄여준다.
- 혹은 오른쪽 포인터의 값이 배열에 존재하지 않으면 오른쪽 포인터를 하나 줄여준다.
- 만일 두 값의 합이 K보다 작을때, l이 r보다 작고 배열에 l 숫자가 존재하면 맥스 값을 설정한다.
- 반대로 l 과 r 값이 같을때는 l의 개수가 1개 초과이어야한다.
소스 코드
브루트 포스 O(N^2)
class Solution:
def twoSumLessThanK(self, nums: List[int], k: int) -> int:
m = -1
for i in range(len(nums)):
for j in range(i+1, len(nums)):
t = nums[i] + nums[j]
if t < k:
m = max(m, t)
return m
정렬 + 투포인터 O(NlogN)
class Solution:
def twoSumLessThanK(self, nums: List[int], k: int) -> int:
nums.sort()
m = -1
l, r = 0, len(nums) - 1
while l < r:
total = nums[l] + nums[r]
if total < k:
m = max(m, total)
l += 1
else:
r -= 1
return m
바이너리 서치 O(NlogN)
class Solution:
def twoSumLessThanK(self, nums: List[int], k: int) -> int:
m = -1
nums.sort()
for i in range(len(nums)):
# nums은 배열, k - nums[i]는 찾을 값, i + 1은 시작점
j = bisect_left(nums, k - nums[i], i + 1) - 1
if j > i:
m = max(m, nums[i] + nums[j])
return m
카운팅 소트 O(N + M) M은 입력으로 들어온 배열의 길이이다.
class Solution:
def twoSumLessThanK(self, nums: List[int], k: int) -> int:
m = -1
cnt = [0] * 1001
for num in nums:
cnt[num] += 1
l, r = 1, 1000
while l <= r:
if l + r >= k or cnt[r] == 0:
r -= 1
else:
if l < r and cnt[l] > 0 or l == r and cnt[l] > 1:
m = max(m, l + r)
l += 1
return m
'컴퓨터공학 > LeetCode 1000' 카테고리의 다른 글
[LeetCode] 328. Odd Even Linked List (0) | 2022.12.07 |
---|---|
[LeetCode] 1165. Single-Row Keyboard (0) | 2022.12.02 |
[LeetCode] 1704. Determine if String Halves Are Alike (0) | 2022.12.02 |
[LeetCode] 1207. Unique Number of Occurrences (0) | 2022.12.01 |
[LeetCode] 380. Insert Delete GetRandom O(1) (0) | 2022.11.30 |