Subsequences have always been a concept that trips me up a bit. I don’t know why. But as with anything, the more time I spend working with subsequences, the more I slowly learn and get more comfortable with them.
子序列一直是一个让我有些困惑的概念。 我不知道为什么 但是,与其他任何事情一样,我花在子序列上的时间越多,我越会慢慢学习并逐渐适应它们。
Either way, the problem we are going to tackle today might seem complicated at first glance, and will provide a good challenge for our critical thinking skills (hopefully).
无论哪种方式,我们今天要解决的问题乍一看似乎都很复杂,并且(希望)将对我们的批判性思维能力提出很好的挑战。
So, let’s get solving.
所以,让我们解决。
问题 (THE PROBLEM)
Here is a link to the problem on LeetCode
Given the array nums, obtain a subsequence of the array whose sum of elements is strictly greater than the sum of the non included elements in such subsequence.If there are multiple solutions, return the subsequence with minimum size and if there still exist multiple solutions, return the subsequence with the maximum total sum of all its elements. A subsequence of an array can be obtained by erasing some (possibly zero) elements from the array.Note that the solution with the given constraints is guaranteed to be unique. Also return the answer sorted in non-increasing order.
约束 (THE CONSTRAINTS)
The provided constraints don’t really yield any noteworthy pieces of information, but as always let’s through each one and see if we can uncover any clues to a solution:
所提供的约束条件实际上并不会产生任何值得注意的信息,但是像往常一样,让我们逐一检查并了解我们是否可以找到解决方案的任何线索:
1 <= nums.length <= 500
The first constraint gives us a range of numbers we should expect in the nums
array. With a lower limit of 1 <= nums.length
, we don’t have to worry about nums
being empty or not having any elements. The upper limit of nums.length <= 500
also doesn’t give us any particular information other than the largest amount of elements we would need to iterate through.
第一个约束为我们提供了nums
数组中应有的数字范围。 下限为1 <= nums.length
,我们不必担心nums
为空或没有任何元素。 nums.length <= 500
上限也没有给我们提供任何特定的信息,除了我们需要迭代的最大元素数量。
1 <= nums[i] <= 100
The second constraint is the range for elements in nums
. We learn that we won’t have to deal with any negative numbers or if an element in nums
is 0, as the lower limit of elements in nums
is 1 <= nums[i]
. With the upper limit of nums[i] <= 100
, we also do not have to worry about any really big numbers. Relatively speaking, an upper limit of 100 is quite small.
第二个约束是nums
元素的范围。 我们了解到,不必处理任何负数,也无需处理nums
的元素为0,因为nums
的元素的下限为1 <= nums[i]
。 由于nums[i] <= 100
上限,我们也不必担心任何真正大的数字。 相对而言,上限100很小。
测试 (THE TESTS)
Test Case #1:
Input: nums = [4,3,10,9,8]
Output: [10,9]
Explanation: The subsequences [10,9] and [10,8] are minimal
such that the sum of their elements is strictly greater than the sum of elements not included, however,
the subsequence [10,9] has the maximum total sum of its elements.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Test Case #2:
Input: nums = [4,4,7,6,7]
Output: [7,7,6]
Explanation: The subsequence [7,7] has the sum of its elements equal to 14
which is not strictly greater than the sum of elements not included (14 = 4 + 4 + 6).
Therefore, the subsequence [7,6,7] is the minimal satisfying the conditions.
Note the subsequence has to returned in non-decreasing order.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Test Case #3:
Input: nums = [6]
Output: [6]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
崩溃 (THE BREAK DOWN)
This problem has a lot of little parts to it that, as stated before, might make minSubsequences
seem complex. But, as usual, if we go through each piece of information provided for us, I think we can simplify and organize things in a way that makes everything easier to understand:
如前所述,这个问题有很多小部分,可能会使minSubsequences
看起来很复杂。 但是,像往常一样,如果我们仔细阅读提供给我们的每条信息,我认为我们可以通过简化和组织事情的方式使所有内容更易于理解:
Given the array nums
Our argument for minSubsequences
will always be an array whose elements will always be integers. Simple enough.
我们的minSubsequences
参数将始终是一个数组,其元素将始终是整数。 很简单。
obtain a subsequence of the array whose sum of elements is strictly greater than the sum of the non included elements in such subsequence.
This is where things start to get a little tricky.
这是开始变得有些棘手的地方。
Here is our task. We need to find a group of numbers in nums
, where if we add all of the numbers in the group together, the sum will be greater than the rest of the numbers in nums
that are not included in the group.
这是我们的任务。 我们需要找到一组以nums
为单位的数字,如果将该组中的所有数字加在一起,则总和将大于未包含在该组中的以nums
为单位的其余数字。
The first thing that this tells me is that we are going to have to keep a running sum of the subsequence we are building, and subtract that running sum from the total sum of elements in nums
.
这告诉我的第一件事是,我们将必须保持正在构建的子序列的运行总和,并从以nums
为单位的元素总和中减去该运行总和。
If there are multiple solutions, return the subsequence with minimum size
We might have scenarios where nums
will have multiple subsequences of different sizes. This might mean we will have to keep track of each subsequence we find, and push each subsequence into an array in order to compare them. That is, if we even want to keep track of each subsequence.
我们可能会nums
包含多个大小不同的子序列的情况。 这可能意味着我们将必须跟踪找到的每个子序列,并将每个子序列推入数组以进行比较。 也就是说,如果我们甚至想跟踪每个子序列。
...if there still exist multiple solutions, return the subsequence with the maximum total sum of all its elements.
This gives me a raging clue. We can avoid keeping track of every subsequence we find if we sort nums
in non-decreasing order (or lowest to highest). We can then iterate through sorted nums
from the last element to the first element (or backwards).
这给了我一个汹涌的线索。 我们可以避免跟踪每一个序列的,我们发现,如果我们的排序nums
非递减的顺序(或最低到最高)。 然后,我们可以迭代从最后一个元素到第一个元素(或向后)的nums
。
This will allow us to find the subsequence with the minimum size AND maximum total sum of any subsequence in nums.
这将使我们能够找到任何子序列的最小大小和最大总和(以num为单位)。
If we look at Test Case #1 for example:
例如,如果我们看一下测试用例#1:
[4,3,10,9,8]
and sort Test Case #1 in non-decreasing order:
并以降序排列测试用例#1:
[3,4,8,9,10]
We can iterate through nums
starting at the last element 10 and work backwards:
我们可以从最后一个元素10开始遍历nums
并向后工作:
1st iteration:
subsequence : [10]
subsequence sum: 10
nums sum: 34
elements in nums not included in subsequence: [3,4,8,9]
nums sum excluding subsequence sum: 24
~
〜
2nd iteration:
subsequence : [10, 9]
subsequence sum: 19
nums sum: 34
elements in nums not included in subsequence: [3,4,8]
nums sum excluding subsequence sum: 15
On the 2nd iteration, we have already found a subsequence who’s sum is greater than the sum of the rest of the elements in nums
: [10, 9]
在第二次迭代中,我们已经找到一个子序列,其和大于nums
其余元素的总和: [10, 9]
nums
[10, 9]
Since we have already sorted nums
in non-decreasing order, [10,9]
is the subsequence whose length is equal to the minimum possible size of all possible subsequences when a subsequence’s sum is strictly greater than the sum of the non included elements. We know this because any other subsequence would need have at least 2 elements.
由于我们已经按非降序对nums
进行排序,因此[10,9]
是子序列,其长度等于当子序列的总和严格大于未包含元素的总和时,所有可能子序列的最小可能大小。 我们知道这一点是因为任何其他子序列都需要至少包含2个元素。
And since the sorted nums
array is sorted in non-decreasing order, [10,9]
is also the smallest subsequence whose sum is the maximum sum of all possible subsequences when a subsequence’s sum is strictly greater than the sum of the non included elements.
并且由于已排序的nums
数组以非降序排序,因此[10,9]
也是最小的子序列,当子序列的总和严格大于不包括的元素的总和时,其总和是所有可能的子序列的最大和。
All other possible subsequences must have at least 2 elements, and even if they did, there is no possible way that their sum will be greater than [10,9]
since [10,9]
are the two largest numbers in nums
.
所有其他可能的子序列都必须至少包含2个元素,即使它们确实存在,也无法以总和大于[10,9]
因为[10,9]
是nums
中的两个最大数字。
I think we are onto something here.
我认为我们正在这里。
A subsequence of an array can be obtained by erasing some (possibly zero) elements from the array.
I am going to ignore this piece of information. It might be useful for an alternative solution, but it remains irrelevant for the potential solution I began outlining above. Mark this as the first time I am passing over a piece of information provided for us.
我将忽略此信息。 它可能对替代解决方案很有用,但与我上面概述的潜在解决方案无关。 将此标记为我第一次传递给我们的信息。
Note that the solution with the given constraints is guaranteed to be unique.
This tells me that we will only and always be returning a single subsequence. Each instance of nums
will only have 1 answer. This helps re enforce what I was explaining before since the solution above with sorting and iterating through sorted nums
backwards will only be building 1 subsequence.
这告诉我,我们将仅并将始终返回单个子序列。 每个nums
实例只有1个答案。 这有助于重新执行我之前解释过的内容,因为上面对排序的nums
反向排序和迭代的解决方案将仅构建1 nums
序列。
Also return the answer sorted in non-increasing order.
Here is the kicker. If we sort nums
in non-decreasing order, then iterate through sorted nums
from the last element to the first (or backwards), we can build our minimum-sized, maximum-summed subsequence by pushing each number into an empty array. This will naturally sort them into a non-increasing order.
这是踢脚线。 如果我们以非降序对nums
进行排序,然后从最后一个元素到第一个(或向后)迭代经过排序的nums
,则可以通过将每个数字推入一个空数组来构建最小大小,最大总和的子序列。 这自然会将它们排序为非递增顺序。
犯罪嫌疑人 (THE SUSPECT)
The order in which we perform various operations on each iteration through nums
is going to be important. What might make minSubsequences
seem more confusing is that the problem’s explanation gives us a lot of information that is all out of order relative to how we will need to execute each part.
在每次迭代中以nums
执行各种操作的顺序将很重要。 minSubsequences
似乎更令人困惑的是,问题的解释为我们提供了很多信息,这些信息相对于我们执行每个部分的方式而言是混乱的。
Because of this, I am going to outline each thing we have to do when we are iterating through nums
in the order we have to do it, and provide some explanation to each part. Then, we can step through some pseudo code to get a better idea of how our solution needs to function:
因此,我将概述按顺序迭代nums
时必须要做的每一件事,并为每个部分提供一些解释。 然后,我们可以逐步执行一些伪代码,以更好地了解我们的解决方案如何起作用:
1.) Find the total sum of nums, store it as a variable named sum
First, we need a starting point. We need to find the total sum
of nums
before we do anything else. Since we need to subtract the sum of the subsequence we are building from the total sum
, we need to store sum
as a variable.
首先,我们需要一个起点。 在执行其他任何操作之前,我们需要找到nums
sum
。 由于我们需要从总和中减去正在构建的子序列的sum
,因此需要将sum
存储为变量。
There are a couple different ways we can find the total sum of nums
before we do anything else, but I am going to use .reduce()
.
在执行其他任何操作之前,有几种方法可以找到nums
总和,但是我将使用.reduce()
。
2.) Create 2 extra variables: sub (an empty array), and subSum (an integer)
We need an empty array to build our subsequence into, and we can call it sub
. We will also return sub
at the end of our solution.
我们需要一个空数组来构建子序列,我们可以将其称为sub
。 我们还将在解决方案结束时返回sub
。
As we iterate through sorted nums
, we will want to push elements from nums
into sub
which will be initialized as an empty array.
当我们遍历排序的nums
,我们将需要将nums
元素推入sub
并将其初始化为一个空数组。
We also need another variable called subSum
to keep track of the sum of the sub sequence we are building into sub
. On each iteration, we will want to push nums[i]
(or each element) into sub
, and add nums[i]
to subSum
.
我们还需要另一个名为subSum
变量来跟踪要构建到sub
中的子序列的总和。 在每次迭代中,我们都希望将nums[i]
(或每个元素)推入sub
,并将nums[i]
添加到subSum
。
3.) Sort nums in non-decreasing order
We need to sort the elements in nums
from least to greatest. We don’t need to save this to a variable since .sort()
will mutate the array it is being called on.
我们需要按从小到大的nums
对元素进行排序。 我们不需要将其保存到变量,因为.sort()
将使正在调用的数组发生突变。
4.) Iterate through nums (which is now sorted) backwards
To find the minimum-sized, maximum-summed subsequence, we can iterate through sorted nums
backwards, starting with the last element (which is now the largest number) to the first element (which is now the smallest number) in the array.
为了找到最小大小,最大总和的子序列,我们可以向后遍历排序的nums
,从数组中的最后一个元素(现在是最大的数字)到第一个元素(现在是最小的数字)开始。
5.) On each iteration, check to see if sum is greater than or equal to subSum
On each iteration, we are going to check if sum >= subSum
. If it isn’t, then we have to continue looking for a subsequence of nums
whose sum is larger than the sum of the non included elements in nums
.
在每次迭代中,我们将检查sum >= subSum
。 如果不是,那么我们必须继续寻找nums
的子序列,其总和大于nums
未包含元素的总和。
That means we are going to have to do a bunch of things:
这意味着我们将不得不做一堆事情:
5a.) Add nums[i] to subSum
This will increase subSum
based off each element in sorted nums
. On each iteration, if subSum
is less than sub
, we want to push nums[i]
into sub
until we find a collection of numbers whose sum is larger than the sum of the non included elements in nums
.
这将增加subSum
基于关闭排序中的每个元素nums
。 在每次迭代中,如果subSum
小于sub
,我们希望将nums[i]
推入sub
直到找到一个总和大于nums
未包含元素之和的数字集合。
5b.) Subract nums[i] from Sum
While subSum
is less than sum
, we want to also subtract nums[i]
from sum
. This will keep track of the total sum of the numbers we are continuing to exclude from the subsequence we are building.
当subSum
小于sum
,我们还要从sum
减去nums[i]
。 这将跟踪我们继续从我们正在构建的子序列中排除的总数。
5c.) Push nums[i] into sub
This builds our subsequence. We want to continue building sub
while subSum
is less than sum
. Once subSum
is larger than sum
, we have found a subsequence whose sum of elements is larger than the sum of non included elements.
这建立了我们的子序列。 我们希望在subSum
小于sum
时继续构建sub
。 一旦subSum
大于sum
,我们就找到了一个子序列,其子元素的总和大于未包含元素的总和。
6.) Break out of the iteration once sum is less than subSum
Once we have found we have found a subsequence whose sum of elements is larger than the sum of non included elements, we no longer have a need to continue iterating through sorted nums
. This means we can break out of the for
loop.
一旦找到子元素的子序列大于未包含的元素的子序列,就不再需要继续遍历已排序的nums
。 这意味着我们可以打破for
循环。
7.) Return sub
Since we have sorted nums
in non-decreasing order, and since we are iterating through sorted nums
backwards, once we have found a subsequence whose sum of elements is larger than the sum of non included elements, we have also found the minimum-sized/maximum-summed subseqence.
由于我们以非降序对nums
进行了排序,并且由于我们是向后遍历排序的nums
,因此一旦找到子元素的总和大于未包含元素的总和的子序列,我们还发现了最小大小/最大总和子序列。
sub
will represent that subsequence, so we can return it.
sub
将代表该sub
序列,因此我们可以将其返回。
计划 (THE PLAN)
Before we put anything to code, let’s write some pseudo code to try to visualize our solution a little better:
在向代码添加任何内容之前,让我们编写一些伪代码,以尝试更好地可视化我们的解决方案:
// - create 3 variables:
// - sum: an integer. the total sum of nums without any mutations
// - subSum: an integer. the total sum of the subsequence we are building
// - sub: an empty array. the subsequence we want to build, then return at the end of the solution
// - since we need to return a subsequence with the maximum total sum of all its elements
// - sort nums from least to greatest and iterate from the last element to the first
// - this will allow us to add each element of num so that every sum of the subsequence will be the maximum possible sum of a subsequence
// - this will also allow us to build the subsequence in non-increasing order
// since the last number in nums will always be the largest number in nums,
// we can push each element we iterate through into a new array,
// thus ordering the elements in the new array in non increasing order
// - iterate through nums (which is now sorted) backwards
// - if sum is greater than or equal to subSum,
// - add nums[i] to subSum keep track of the sum of the current subsequence
// - subtract nums[i] from sum to keep track of the sum of non-included numbers
// - push nums[i] into sub to build the subsequence
// - otherwise
// - break out of the iteration
// - once sum is less than subSum,
// - it means we have found:
// - a subsequence whose sum of elements is strictly greater than the sum of the non included elements
// - the subsequence with minimum size, even if there are multiple solutions
// - the subsequence with the maximum total sum of all its elements, even if there are multiple solutions
// - all of the above with the elements of sub in non-increasing order
// - return the subsequence once we break out of the for loop
// - return sub
代码 (THE CODE)
Okay, let’s try to put our solution into practice and see if it works:
好的,让我们尝试将我们的解决方案付诸实践,看看它是否有效:
First, let’s start by defining the 3 variables we are going to need: sum
, sub
, and subSum
:
首先,让我们开始定义我们需要的3个变量: sum
, sub
和subSum
:
var minSubsequence = function(nums) {
// sum: an integer. the total sum of nums without any mutations
let sum = nums.reduce((a, b) => a + b )
// the total sum of the subsequence we are building
let subSum = 0
// the subsequence we want to build, then return at the end of the solution
let sub = []
};
Let’s also sort nums
:
让我们也对nums
排序:
var minSubsequence = function(nums) {
let sum = nums.reduce((a, b) => a + b )
let subSum = 0
let sub = []
// sort nums from least to greatest
nums.sort((a, b) => a - b)
};
Next, let’s set up the for
loop that will iterate through nums
backwards:
接下来,让我们设置for
循环,该循环将向后迭代nums
:
var minSubsequence = function(nums) {
let sum = nums.reduce((a, b) => a + b )
let subSum = 0
let sub = []
nums.sort((a, b) => a - b)
// iterate through nums (which is now sorted) backwards
for(i = nums.length - 1; i >= 0; i--){
}
};
We can then add the if
statement that checks if sum
is greater than or equal to subSum
. If it isn’t, break out of the iteration:
然后,我们可以添加if
语句,该语句检查sum
是否大于或等于subSum
。 如果不是,请中断迭代:
var minSubsequence = function(nums) {
let sum = nums.reduce((a, b) => a + b )
let subSum = 0
let sub = []
nums.sort((a, b) => a - b)
for(i = nums.length - 1; i >= 0; i--){
// if sum is greater than or equal to subSum
if(sum >= subSum) {
// otherwise
} else {
// break out of the iteration
break
}
}
};
Then, we can add our three operations: adding nums[i]
to subSum
, subtracting nums[i]
from sum
, and pushing nums[i]
to sub
:
然后,我们可以添加三个操作:将nums[i]
添加到subSum
,从sum
减去nums[i]
,并将nums[i]
推送到sub
:
var minSubsequence = function(nums) {
let sum = nums.reduce((a, b) => a + b )
let subSum = 0
let sub = []
nums.sort((a, b) => a - b)
for(i = nums.length - 1; i >= 0; i--){
if(sum >= subSum) {
// add nums[i] to subSum keep track of the sum of the current subsequence
subSum += nums[i]
// subtract nums[i] from sum to keep track of the sum of non-included numbers
sum = sum - nums[i]
// push nums[i] into sub to build the subsequence
sub.push(nums[i])
} else {
break
}
}
};
Finally, we can add our return value of sub
:
最后,我们可以添加sub
的返回值:
var minSubsequence = function(nums) {
let sum = nums.reduce((a, b) => a + b )
let subSum = 0
let sub = []
nums.sort((a, b) => a - b)
for(i = nums.length - 1; i >= 0; i--){
if(sum >= subSum) {
subSum += nums[i]
sum = sum - nums[i]
sub.push(nums[i])
} else {
break
}
}
// return the subsequence once we break out of the for loop
return sub
};
Let’s see if it works:
让我们看看它是否有效:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/3e9b55aec1ddb35196a13972f06c6a56.png)
Nice.
真好
最终的解决方案 (THE FINAL SOLUTION)
Let’s take a final look at our solution without the comments, and clean up some of our syntax:
让我们最后看一下不带注释的解决方案,并清理一些语法:
var minSubsequence = function(nums) {
let sum = nums.reduce((a, b) => a + b ), subSum = 0, sub = []
nums.sort((a, b) => a - b)
for(i = nums.length - 1; i >= 0; i--){
if(sum >= subSum) {
subSum += nums[i]
sum = sum - nums[i]
sub.push(nums[i])
} else break
}
return sub
};
任务完成 (MISSION COMPLETE)
I really liked this problem as it forced me out of my comfort zone. I felt like the solution was one of the more efficient solutions I have written about, and definitely pushed me to work on visualizing a solution before writing one.
我真的很喜欢这个问题,因为它迫使我离开了舒适区。 我觉得该解决方案是我写过的更有效的解决方案之一,并且肯定促使我在编写解决方案之前先进行可视化工作。
I definitely understand my solutions won’t be the best or most efficient, but either way I hope they help you or someone else figure out a way to solve a problem you encounter on this journey we call JavaScript.
我绝对知道我的解决方案不是最佳或最有效的,但是我希望它们能帮助您或其他人找到解决您在我们称为JavaScript的过程中遇到的问题的方法。
Either way, I hope you got some useful information, and may all your functions return true, and all your requests respond with 200.
无论哪种方式,我都希望您能获得一些有用的信息,并希望所有函数都返回true,并且所有请求均以200响应。
Stay safe…stay healthy…and keep fighting the good fight.
保持安全……保持健康……并继续打好仗。
翻译自: https://levelup.gitconnected.com/javascript-problem-solvers-minimum-subsequence-71216e07dd2f