【问题标题】:Javascript: Check if array is an almost increasing sequenceJavascript:检查数组是否是一个几乎递增的序列
【发布时间】:2019-12-23 22:27:07
【问题描述】:

我正在处理一些关于 Code Signal 的 Javascript 挑战,并遇到了这个问题:

给定一个整数序列作为数组,判断它是否是 可以通过不再删除来获得严格递增的序列 数组中的一个元素以上。**

注意:序列 a0, a1, ..., an 被认为是严格的 如果 a0

示例 对于序列 = [1, 3, 2, 1],输出应为 几乎IncreasingSequence(sequence) = false。

这个数组中没有一个元素可以被移除 得到一个严格递增的序列。对于序列 = [1, 3, 2], 输出应该是几乎IncreasingSequence(sequence) = true。

您可以从数组中删除 3 以获得严格递增的 序列 [1, 2]。或者,您可以删除 2 以获得严格的 递增序列 [1, 3]。

我的做法是遍历序列数组,检查当前元素是否大于下一个元素,如果是则删除当前元素。然后,增加一个计数器,如果计数器小于2返回true,否则返回false。

这是我的代码:

function almostIncreasingSequence(sequence) {
    // If array has 1 or 2 elements it passes
    if(sequence.length <= 2) {
        return true;
    }

    // Keeps track of numbers removed
    let numberRemoved = 0;

    // Iterate through array, check if current element is greater than next element
    // If so, increment numberRemoved and remove current element
    for(let i = 0; i < sequence.length; i++) {        
        if(sequence[i] >= sequence[i + 1]) {
            numberRemoved++;

            // Removed element if it's greater than next element
            let removed = sequence.splice([i], 1);
            i = 0;

            console.log(sequence);
        }

    }

    // Second pass through the array checks if there are 2 or more out of order        
    // elements. Inefficient and sloppy, need to find a better approach
    for(let j = 0; j < sequence.length; j++) {
        if(sequence[j] >= sequence[j + 1]) {
            numberRemoved++;
        }
    }

    // If number is less than 2, the sequence passes
    if(numberRemoved < 2) {
        return true;
    }
    else {
        return false;
    }  
}

此解决方案解决了 17/19 个测试用例。我遇到了一个极端情况,有时如果 i >= [i + 1] 正确的方法是删除 [i + 1],而不是 >我。例如:

  • 在序列的情况下:[3, 5, 67, 98, 3]
  • For 循环检查 98 是否 >= 3
  • 删除 98
  • 序列失败,因为 [3, 5, 67, 3] 失败
  • 在这种情况下,我们不应该删除 98,我们应该删除 3
  • 序列然后通过:[3, 5, 67, 98] 返回 true
  • 对于这种极端情况,我们不想这样做:let removed = sequence.splice([i], 1);
  • 我们想做:let removed = sequence.splice([i + 1], 1);
  • 这将删除 3
  • [3, 5, 67, 98] 返回真

我该如何处理这种极端情况?在某些情况下如果 sequence[i] >= [i + 1] 您需要删除 sequence[i],在其他情况下您需要删除 [i + 1]。如何在不使用第二个 for 循环并再次通过数组的情况下解决此问题?

【问题讨论】:

  • 检查是否[i+1] &lt; [i-1]。如果是,则删除 [i+1] 而不是 [i]

标签: javascript arrays for-loop iteration comparison


【解决方案1】:

每当找到一个递减的数字时,我们需要确定应该删除 2 个连续数字中的哪一个。它可以是:

  1. 最后一个数字太大
  2. 当前数字太小

如果他们都不能解决减少的问题,那么数组已经不是一个“几乎增加的序列”,因为这意味着至少需要另一个删除。

function almostIncreasingSequence(sequence) {
  let removed = 0;
  let i = 0;
  let prev = -Infinity;
  
  // as long as removed less than 2 times, and i is under arrays length
  while(removed < 2 && i < sequence.length) {
    if(sequence[i] > prev) { // if current is bigger the previous
      prev = sequence[i]; // assign current to previous
      // remove the latter number, if it fixes the decrease
    } else if (i === sequence.length - 1 || sequence[i+1] > sequence[i-1]) {
      removed++; // increment removed
    } else if (i < 2 || sequence[i] > sequence[i-2]) {
      // remove the former number, if it fixes the decrease
      removed++;
      prev = sequence[i];
    } else {
      // neither option fixes the decrease, so at least 2 removal is needed
      return false;
    }
    i++;
  }

  return removed < 2; // true if removed are under 2
}

console.log(almostIncreasingSequence([1, 3, 2, 1])); // false
console.log(almostIncreasingSequence([1, 3, 2])); // true
console.log(almostIncreasingSequence([3, 5, 67, 98, 3])); // true
console.log(almostIncreasingSequence([4, 3, 5, 67, 98, 3])); // false
console.log(almostIncreasingSequence([1, 4, 2, 3])); // true
console.log(almostIncreasingSequence([10, 13, 2, 9])); // false

【讨论】:

  • 好收获。我已从您的答案中删除了“它会失败”部分,因为它已修复。下次对我的回答发表评论,详细说明问题,会很好。
  • 感谢您的更新。我也认为评论会更合适,但我的帐户还不能添加 cmets。
【解决方案2】:

问题主要是“我们是否需要删除一项或更少才能获得递增的序列?”。所以你实际上不需要删除任何东西,只需计算需要删除的项目数量即可。

此外,您需要继续检查,而不会使无序编号无法通过下一次检查。在这种情况下,将当前和prev 之间的较小数字分配给prev

function almostIncreasingSequence(sequence) {
  let removed = 0;
  let i = 0;
  let prev = -Infinity;
  
  // as long as removed less than 2 times, and i is under arrays length
  while(removed < 2 && i < sequence.length) {
    if(sequence[i] > prev) { // if current is bigger the previous
      prev = sequence[i]; // assign current to previous
    } else {
      prev = Math.min(prev, sequence[i]); // take the lowest
      removed++; // increment removed
    }
    
    i++;
  }

  return removed < 2; // true if removed are under 2
}

console.log(almostIncreasingSequence([1, 3, 2, 1])); // false
console.log(almostIncreasingSequence([1, 3, 2])); // true
console.log(almostIncreasingSequence([3, 5, 67, 98, 3])); // true
console.log(almostIncreasingSequence([4, 3, 5, 67, 98, 3])); // false
console.log(almostIncreasingSequence([1, 4, 2, 3])); // true

【讨论】:

    【解决方案3】:

    你可以取一个找到的索引。

    这种方法测试三个连续的元素,比如

                v
    1   2  [3   8   4]  5   6   7   -> found at index 3
    

    或者对下一个循环进行检查,通过检查找到的索引来省略找到的值。

                    v
    1   2   3  [8   4   5]  6   7
                ^ omit value on found index
    

    然后如果不按顺序,则检查相邻项以防止这种模式

                v
    1   2   3   1   2   5   6   7
            3   >   2
    
                v
    1   2   3   8   2   5   6   7
            3   >   2
    

    如果找到,多个元素的位置错误。

    function inSequence(array) {
        var i,
            found;
            
        for (i = 1; i < array.length - 1; i++) {
            if ((found === i - 1 || array[i - 1] < array[i]) && array[i] < array[i + 1]) continue;
            if (array[i - 1] >= array[i + 1] || found !== undefined) return false;
            found = i;
        }
        return true;
    }
    
    console.log(inSequence([2, 1]));
    console.log(inSequence([1, 2, 3]));
    console.log(inSequence([2, 1, 3]));
    console.log(inSequence([1, 2, 4, 3]));
    console.log(inSequence([1, 2, 3, 8, 4, 5, 6, 7]));
    console.log(inSequence([1, 2, 3, 8, 4, 5, 6, 9, 7]));
    console.log(inSequence([2, 1, 3, 4, 5, 2]));
    console.log(inSequence([1, 2, 3, 1, 2, 5, 6, 7]));
    console.log(inSequence([1, 2, 3, 8, 2, 5, 6, 7]));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案4】:

      不确定是否真的理解这个问题,但我认为这个问题可能是你的答案......

      function testSequence(arraySequence)
        {
        let prev = -Infinity
          , ret  = true
          , out  = false
          ;
        for(let val of arraySequence) 
          {
          if (val<=prev)
            {
            if (out) { ret=false; break }
            else     { out=true         }
            }
          prev=val
          }
        return ret
        }
      
      
      console.log(testSequence([1, 3, 2, 1]));         // false
      console.log(testSequence([1, 3, 2]));            // true
      console.log(testSequence([3, 5, 67, 98, 3]));    // true
      console.log(testSequence([4, 3, 5, 67, 98, 3])); // false

      【讨论】:

        【解决方案5】:

        该问题要求您发现当数组中的索引被删除时,该数组是否会是一个递增序列。因此,如果我们忽略一个违反规则的索引

        a i i+1

        那么其他索引应该遵守规则。

        function almostIncreasingSequence(sequence) {
        let unorderedIndex = 0;
        for(let i = 1; i < sequence.length; i++ ){
        if( sequence[i-1] >= sequence[i] ) {
            unorderedIndex++;
        
        // an array that's almost increasing would just have one unordered index
            if( unorderedIndex > 1 ) return false;
            
            if( sequence[i-2] >= sequence[i] && sequence[i-1] >= sequence[i+1])
                return false;
            }
        } 
        return true;
            }
        

        【讨论】:

          【解决方案6】:

          这是一个简单的解决方案。

          function almostIncreasingSequence(sequence) {
            // initialize removedCount to 0.
            let removedCount = 0;
          
            // iterate through sequence
            for(let i=0; i<sequence.length-1; i++) {
              // if current value is greater than the next value ex. [3, 1, 2]; 3 > 1
              if(sequence[i] > sequence[i+1]) {
                // increase count
                removedCount++;
              } 
            }
            // if our count is more than 2 return false, otherwise return true 
            return removedCount <= 1;
          }
          

          【讨论】:

          • 对 [1,2,1,2] 失败
          猜你喜欢
          • 2012-10-17
          • 2018-10-30
          • 1970-01-01
          • 2014-03-26
          • 1970-01-01
          • 2012-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多