Skip to content

Commit 66a9ad2

Browse files
committed
feat: add solution 1755. Closest Subsequence Sum
1 parent 11e6e88 commit 66a9ad2

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# [1755. Closest Subsequence Sum](https://leetcode.com/problems/closest-subsequence-sum)
2+
3+
## Description
4+
5+
<div class="elfjS" data-track-load="description_content"><p>You are given an integer array <code>nums</code> and an integer <code>goal</code>.</p>
6+
7+
<p>You want to choose a subsequence of <code>nums</code> such that the sum of its elements is the closest possible to <code>goal</code>. That is, if the sum of the subsequence's elements is <code>sum</code>, then you want to <strong>minimize the absolute difference</strong> <code>abs(sum - goal)</code>.</p>
8+
9+
<p>Return <em>the <strong>minimum</strong> possible value of</em> <code>abs(sum - goal)</code>.</p>
10+
11+
<p>Note that a subsequence of an array is an array formed by removing some elements <strong>(possibly all or none)</strong> of the original array.</p>
12+
13+
<p>&nbsp;</p>
14+
<p><strong class="example">Example 1:</strong></p>
15+
16+
<pre><strong>Input:</strong> nums = [5,-7,3,5], goal = 6
17+
<strong>Output:</strong> 0
18+
<strong>Explanation:</strong> Choose the whole array as a subsequence, with a sum of 6.
19+
This is equal to the goal, so the absolute difference is 0.
20+
</pre>
21+
22+
<p><strong class="example">Example 2:</strong></p>
23+
24+
<pre><strong>Input:</strong> nums = [7,-9,15,-2], goal = -5
25+
<strong>Output:</strong> 1
26+
<strong>Explanation:</strong> Choose the subsequence [7,-9,-2], with a sum of -4.
27+
The absolute difference is abs(-4 - (-5)) = abs(1) = 1, which is the minimum.
28+
</pre>
29+
30+
<p><strong class="example">Example 3:</strong></p>
31+
32+
<pre><strong>Input:</strong> nums = [1,2,3], goal = -7
33+
<strong>Output:</strong> 7
34+
</pre>
35+
36+
<p>&nbsp;</p>
37+
<p><strong>Constraints:</strong></p>
38+
39+
<ul>
40+
<li><code>1 &lt;= nums.length &lt;= 40</code></li>
41+
<li><code>-10<sup>7</sup> &lt;= nums[i] &lt;= 10<sup>7</sup></code></li>
42+
<li><code>-10<sup>9</sup> &lt;= goal &lt;= 10<sup>9</sup></code></li>
43+
</ul>
44+
</div>
45+
46+
<p>&nbsp;</p>
47+
48+
## Solutions
49+
50+
**Solution: `Depth-First Search + Binary Search`**
51+
52+
- Time complexity: <em>O(n\*2<sup>n/2</sup>)</em>
53+
- Space complexity: <em>O(2<sup>n/2</sup>)</em>
54+
55+
<p>&nbsp;</p>
56+
57+
### **JavaScript**
58+
59+
```js
60+
/**
61+
* @param {number[]} nums
62+
* @param {number} goal
63+
* @return {number}
64+
*/
65+
const minAbsDifference = function (nums, goal) {
66+
const n = nums.length;
67+
const half = Math.floor(n / 2);
68+
const lNums = nums.slice(0, half);
69+
const rNums = nums.slice(half, n);
70+
let lSums = new Set();
71+
let rSums = new Set();
72+
let result = Number.MAX_SAFE_INTEGER;
73+
74+
const getSums = (values, index, sum, sums) => {
75+
if (index >= values.length) {
76+
sums.add(sum);
77+
return;
78+
}
79+
const value = values[index];
80+
81+
getSums(values, index + 1, sum, sums);
82+
getSums(values, index + 1, sum + value, sums);
83+
};
84+
85+
getSums(lNums, 0, 0, lSums);
86+
getSums(rNums, 0, 0, rSums);
87+
lSums = [...lSums];
88+
rSums = [...rSums].sort((a, b) => a - b);
89+
90+
const findFirstGreaterEqual = (sums, target) => {
91+
let left = 0;
92+
let right = sums.length - 1;
93+
94+
while (left <= right) {
95+
const mid = Math.floor((left + right) / 2);
96+
97+
sums[mid] >= target ? (right = mid - 1) : (left = mid + 1);
98+
}
99+
100+
return left;
101+
};
102+
103+
for (const sum of lSums) {
104+
const index = findFirstGreaterEqual(rSums, goal - sum);
105+
106+
if (index < rSums.length) {
107+
result = Math.min(Math.abs(goal - sum - rSums[index]), result);
108+
}
109+
110+
if (index > 0) {
111+
result = Math.min(Math.abs(goal - sum - rSums[index - 1]), result);
112+
}
113+
}
114+
115+
return result;
116+
};
117+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @param {number[]} nums
3+
* @param {number} goal
4+
* @return {number}
5+
*/
6+
const minAbsDifference = function (nums, goal) {
7+
const n = nums.length;
8+
const half = Math.floor(n / 2);
9+
const lNums = nums.slice(0, half);
10+
const rNums = nums.slice(half, n);
11+
let lSums = new Set();
12+
let rSums = new Set();
13+
let result = Number.MAX_SAFE_INTEGER;
14+
15+
const getSums = (values, index, sum, sums) => {
16+
if (index >= values.length) {
17+
sums.add(sum);
18+
return;
19+
}
20+
const value = values[index];
21+
22+
getSums(values, index + 1, sum, sums);
23+
getSums(values, index + 1, sum + value, sums);
24+
};
25+
26+
getSums(lNums, 0, 0, lSums);
27+
getSums(rNums, 0, 0, rSums);
28+
lSums = [...lSums];
29+
rSums = [...rSums].sort((a, b) => a - b);
30+
31+
const findFirstGreaterEqual = (sums, target) => {
32+
let left = 0;
33+
let right = sums.length - 1;
34+
35+
while (left <= right) {
36+
const mid = Math.floor((left + right) / 2);
37+
38+
sums[mid] >= target ? (right = mid - 1) : (left = mid + 1);
39+
}
40+
41+
return left;
42+
};
43+
44+
for (const sum of lSums) {
45+
const index = findFirstGreaterEqual(rSums, goal - sum);
46+
47+
if (index < rSums.length) {
48+
result = Math.min(Math.abs(goal - sum - rSums[index]), result);
49+
}
50+
51+
if (index > 0) {
52+
result = Math.min(Math.abs(goal - sum - rSums[index - 1]), result);
53+
}
54+
}
55+
56+
return result;
57+
};

0 commit comments

Comments
 (0)