JavaScript问题解决者的最小子序列

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

这是有关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个变量: sumsubsubSum

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

Nice.

真好

最终的解决方案 (THE FINAL SOLUTION)

Let’s take a final look at our solution without the comments, and clean up some of our syntax:

让我们最后看一下不带注释的解决方案,并清理一些语法:

LeetCode Submission Detail

LeetCode提交详细信息

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值