【问题标题】:Given an array of integers, find the second largest and second smallest within the array给定一个整数数组,找出数组中第二大和第二小的整数
【发布时间】:2015-09-01 21:04:07
【问题描述】:

我正在尝试提出一个函数,该函数将采用整数数组并输出第二大数字和第二小数字。该函数将考虑浮点数、重复数和负数。

除了 test2 之外,两个函数都通过了下面的所有测试。

var test1 = [7, 7, 12, 98, 106]
  answer1 = {2nd Min: 12, 2nd Max: 98}

var test2 = [5, 23, -112, 6, 70, 70, -112]
  answer2 = {2nd Min: 5, 2nd Max: 23}

var test3 = [-22, 22]
  answer3 = {2nd Min: 22, 2nd Max: -22}

var test4 = [10, 89, 3]
   answer = {2nd Min: 10, 2nd Max: 10}

var test5 = [10.4, -12.09, .75, 22]
  answer3 = {2nd Min: 0.75, 2nd Max: 10.4}

 /*/          \ \
 ---SOLUTION 1---
 \ \          /*/
function secondGreatLow1(arr) {
  //make copy of array because it will be spliced in the following functions
  var arrCopy = arr.slice();
  //push returned values of each function into this the answer array
  var answer = []
  answer.push(secondMin(arrCopy));
  answer.push(secondMax(arrCopy));
  return answer;
};

//helper function 1
var secondMin = function (arr){
  var arrCopy = arr.slice();
  //check length of array
  if (arr.length == 2) {
    return arr[1];
  } else {
    var min = Math.min.apply(null, arrCopy);
    arrCopy.splice(arrCopy.indexOf(min), 1);
    //check for duplicates
    for (var i = 0; i < arrCopy.length; i++) {
      if (arrCopy.indexOf(min) === -1) {
        //.apply is used for arrays
        return Math.min.apply(null, arrCopy);
      } else {
        arrCopy.splice(arrCopy.indexOf(min), 1);
        return Math.min.apply(null, arrCopy);
      }
    };
  }
};

//helper function 2
var secondMax = function (arr){
  var arrCopy = arr.slice();
  if (arr.length == 2) {
    return arr[0];
  } else {
    var max = Math.max.apply(null, arrCopy);
    arrCopy.splice(arrCopy.indexOf(max), 1);
    //check for duplicates
    for (var i = 0; i < arrCopy.length; i++) {
      if (arrCopy.indexOf(max) === -1) {
        return Math.max.apply(null, arrCopy);
      } else {
        arrCopy.splice(arrCopy.indexOf(max), 1);
        return Math.min.apply(null, arrCopy);
      }
    };
  }
};



 /*/          \ \
 ---SOLUTION 2---
 \ \         /*/
function secondGreatLow2 (numbers) {
  var arr = withoutDuplicates(numbers);
  arr.sort(function(a,b) { return a-b; });
  return arr[1] + ' ' + arr[arr.length-2];
};

// helpers
var withoutDuplicates = function(arr) {
  var out = [];
  for(var i=0; i<arr.length; i++) {
    if(i === 0 || arr[i] !== arr[i-1]) {
      out.push(arr[i]);
    }
  }
  return out;
};

【问题讨论】:

  • 为什么2nd Max: 12 而不是98 in [7, 7, 12, 98, 106]
  • 哦,这是一个错字,很好!更新了!
  • @xgrioux 有什么问题?您必须以问题格式明确说明

标签: javascript arrays


【解决方案1】:

在您的第二个解决方案中,您的 withoutDuplicates 函数似乎在假设列表已排序(通过将元素与前一个元素进行比较来检查重复项)的假设下运行;但是,在secondGreatLow2 中,您调用withoutDuplicates 而不执行某种排序。

如果您更改了这两行的顺序,则解决方案 #2 看起来有效假设您没有任何浮点不匹配,即3.9999999999997 != 3.99999999998

【讨论】:

  • 那么您唯一需要担心的另一件事是列表长度为 2 的情况,因为您不会有第二个最小/最大的。
  • 谢谢我添加了行 [ numbers.sort(function(a,b) { return a-b; }); ] 上面 [ var arr = withoutDuplicates(numbers); ] 这通过了所有测试!你知道我可以在哪里更新第一个解决方案吗?
【解决方案2】:

对于大型数组而言性能效率不高,但简洁:

var a = [5, 23, -112, 6, 70, 70, -112], b = [];

// remove duplicates 
b = a.filter(function (item, pos) {
    return a.indexOf(item) == pos;
});

// sort
b.sort(function (a, b) {
    return a > b;
});

console.log(b[1]); // 2nd min:12
console.log(b[b.length-2]); // 2nd max:12

【讨论】:

  • 您应该更好地描述为什么这样做。特别是因为OP来自学生。此外,这并不能真正识别 OP 代码中发现的问题。
  • @Thomas 你听说过Talk is cheap. Show me the code. 的谈话,不是吗?如果代码不能自己说话,那有什么意义(这不是幼儿园)?另外,标签是JSarrays,不是算法。
  • 因为它是这样的:stackoverflow.com/help/how-to-answer 另外,值得注意的是答案标准中的最后一个注释 - 您会在多个地方找到它。您正在使用一些“高级”过滤和排序技术,这些技术对于 JS 新手来说可能不熟悉(显然 OP 就是这样)。我不明白为什么扩大这种礼貌甚至会引起争论。
【解决方案3】:
function get_seconds(a) {
  var b = uniq(a); // remove duplicates and sort
  var l = b.length;
  return [b[1], b[l-2]];
}

检查以下完整测试:

var tests = {
  "case1": {
    "input": [7, 7, 12, 98, 106],
    "output": [12, 98]
  },
  "case2": {
    "input": [5, 23, -112, 6, 70, 70, -112],
    "output": [5, 23]
  },
  "case3": {
    "input": [-22, 22],
    "output": [22, -22]
  },
  "case4": {
    "input": [10, 89, 3],
    "output": [10, 10]
  },
  "case5": {
    "input": [10.4, -12.09, .75, 22],
    "output": [0.75, 10.4]
  }
};

function do_tests() {
  var res, logs = '',
    j_exp, j_res;
  $.each(tests, function(c, io) {
    j_exp = JSON.stringify(io.output);
    res = get_seconds(io.input);
    j_res = JSON.stringify(res);
    if (j_res == j_exp) {
      logs += '<div class="success">' + c + ' passed.</div>';
    } else {
      logs += '<div class="failed">' + c + ' failed.  Expected: ' + j_exp + ', Got: ' + j_res + '</div>';
    }
  });
  $("#log").html(logs);

}

function get_seconds(a) {
  var b = uniq(a);
  console.log(b, a);
  var l = b.length;
  return [b[1], b[l - 2]];
}

function uniq(a) {
  return a.sort(sortNumber).filter(function(item, pos, ary) {
    return !pos || item != ary[pos - 1];
  })
}

function sortNumber(a, b) {
  return a - b;
}
div#log {
  font-family: monospace;
}
div#log > div {
  padding: 4px;
  margin: 2px;
}
.success {
  color: green;
}
.failed {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button onclick="do_tests();">Run tests</button>

<div id="log"></div>

【讨论】:

    【解决方案4】:

    这也可以,而且看起来确实更快(没有排序)。大家觉得呢?

    var secondMax = function(arr){
        return Math.min(...arr.reduce((acc, val) =>
             (val > Math.min(...acc)) ? [Math.max(...acc), val] : acc
        , [-Infinity, -Infinity]))
    }
    var secondMin = function(arr){
        return Math.max(...arr.reduce((acc, val) =>
           (val < Math.max(...acc)) ? [Math.min(...acc), val] : acc
        , [Infinity, Infinity]))
    }
    var unique = function(arr) {
        return arr.filter((value, index, arr) =>
            arr.indexOf(value) === index
        )
    }
    var arr = [7, 7, 12, 98, 106, 106];
    console.log(secondMin(unique(arr)));// => 12
    console.log(secondMax(unique(arr)));// => 98
    console.log(secondMin(arr));// => 7
    console.log(secondMax(arr));// => 106
    

    【讨论】:

      【解决方案5】:

      很高兴您找到了解决方案。我将其发布给那些正在寻找更简单解决方案的人。这将在 O(n) 时间内运行。

      var fl = arr[0],sl = arr[0];
      var fs = Infinity,ss = Infinity;
      
      //find the largest and smallest.
      for(var i = 0;i < arr.length;i ++) {
        if(arr[i] > fl) fl = arr[i];
        if(arr[i] < fs) fs = arr[i];    
      }
      //let us assume smallest is second largest and vice versa.
      sl = fs;
      ss = fl;
      //find second smallest and largest.
      for(var i = 0;i < arr.length;i ++) {
        if(arr[i] < fl && arr[i] > sl) sl = arr[i];
        if(arr[i] > fs && arr[i] < ss) ss = arr[i];
      }
      console.log("first and second largest : ",fl,sl);
      console.log("first and second smallest : ",fs,ss);
      

      【讨论】:

        【解决方案6】:

        对于第二大数字,这是一种简单易行的方法,但问题是如果数组中存在重复,我们将无法获得数字。

         function getSecondLargest(nums) {
        
        if(nums.length<2){
            return nums;
        }
        var first=0;
        var second=0;
        for(var i=0; i<nums.length;i++)
            {
                if(nums[i]>first)
                    {
                        second = first;
                        first = nums[i]
                    }
                else(nums[i]>second && nums[i]!=first)
                {
                    second = nums[i];
                }
        
            }
        return second;
        }
        

        【讨论】:

          【解决方案7】:

          如果数组包含 nums = [2, 3, 6, 6, 5] 之类的重复项,则以下解决方案有效,

          let sortedArray = new Set(nums.sort((a, b) => b - a ));
          console.log('second smallest', [...sortedArray][sortedArray.size - 2])
          console.log('second largest',[...sortedArray][1]);
          

          【讨论】:

            【解决方案8】:

            用于数组的 C 程序,用于查找数组中的第二大和第二小。

            #include<stdio.h>
            void main()
            {
                int arr[20];
                int small,big,big2,small2;
                int i,num;
                printf("Enter Number of elements:");
                scanf("%d",&num);
                printf("Enter the elements: \n");
                for(i=0;i<num;i++)
                    scanf("%d",&arr[i]);//Entering elements 
                big = arr[0];//For big in array
                small = arr[0];// For small in array
                for(i=0;i<num;i++)
                {
                    if(arr[i]>big)
                  {
                    big2 = big;
                    big = arr[i];
                  }
                    if(arr[i]<small)
                  {
                    small2 = small;
                    small = arr[i];
                  }
                }
                printf("The biggest is %d\n",big);
                printf("The smallest is %d\n",small);
                printf("The second biggest is %d\n",big2);
                printf("The second smallest is %d\n",small2);
            
                }
            

            #tej

            【讨论】:

              【解决方案9】:

              let ar = [1,4,76,80,90,3,6,82];
              
              var big = 0,sbig=0;
              for(let i=0; i<ar.length;i++){
                if(big < ar[i]) {
                  sbig = big;
                  big = ar[i]
                  continue; 
                }
                if(sbig < ar[i]) {
                  sbig = ar[i];
                }
              }
              console.log(sbig,big);

              【讨论】:

              • 这段代码似乎找到了两个最大值。 OP 的问题是找到第二大和第二小的。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-02-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-04-07
              • 2012-06-05
              相关资源
              最近更新 更多