竞赛192

数组中的 k 个最强值

给你一个整数数组 arr 和一个整数 k 。

设 m 为数组的中位数,只要满足下述两个前提之一,就可以判定 arr[i] 的值比 arr[j] 的值更强:

  •  |arr[i] - m| > |arr[j] - m|
  •  |arr[i] - m| == |arr[j] - m|,且 arr[i] > arr[j]

请返回由数组中最强的 k 个值组成的列表。答案可以以 任意顺序 返回。

中位数 是一个有序整数列表中处于中间位置的值。形式上,如果列表的长度为 n ,那么中位数就是该有序列表(下标从 0 开始)中位于 ((n - 1) / 2) 的元素。

  • 例如 arr = [6, -3, 7, 2, 11]n = 5:数组排序后得到 arr = [-3, 2, 6, 7, 11] ,数组的中间位置为 m = ((5 - 1) / 2) = 2 ,中位数 arr[m] 的值为 6 。
  • 例如 arr = [-7, 22, 17, 3]n = 4:数组排序后得到 arr = [-7, 3, 17, 22] ,数组的中间位置为 m = ((4 - 1) / 2) = 1 ,中位数 arr[m] 的值为 3 。

示例 1:

输入:arr = [1,2,3,4,5], k = 2
输出:[5,1]
解释:中位数为 3,按从强到弱顺序排序后,数组变为 [5,1,4,2,3]。最强的两个元素是 [5, 1]。[1, 5] 也是正确答案。
注意,尽管 |5 - 3| == |1 - 3| ,但是 5 比 1 更强,因为 5 > 1 。

示例 2:

输入:arr = [1,1,3,5,5], k = 2
输出:[5,5]
解释:中位数为 3, 按从强到弱顺序排序后,数组变为 [5,5,1,1,3]。最强的两个元素是 [5, 5]。

示例 3:

输入:arr = [6,7,11,7,6,8], k = 5
输出:[11,8,6,6,7]
解释:中位数为 7, 按从强到弱顺序排序后,数组变为 [11,8,6,6,7,7]。
[11,8,6,6,7] 的任何排列都是正确答案。

示例 4:

输入:arr = [6,-3,7,2,11], k = 3
输出:[-3,11,2]

示例 5:

输入:arr = [-7,22,17,3], k = 2
输出:[22,17]

提示:

  • 1 <= arr.length <= 10^5
  • -10^5 <= arr[i] <= 10^5
  • 1 <= k <= arr.length
/**
 * @param {number[]} arr
 * @param {number} k
 * @return {number[]}
 */
var getStrongest = function(arr, k) { 
    arr.sort((a, b)=>a-b);
    let n = arr.length, m=(n-1)>>1;
    let i=0, j=n-1;
    let ans = [];
    while(k--){
        let a = Math.abs(arr[i]-arr[m]), b = Math.abs(arr[j]-arr[m]);
        if(a>b) ans.push(arr[i]), i++;
        else ans.push(arr[j]), j--;
    }
    return ans;
    
};

  这个题本来是按下面直接写完的,可是超出时间限制。不是最近在看算法优化么,就把别的地方的快速排序拷贝过来了,结果执行用例在浏览器跑都会“栈溢出”。难道又是固定思维的锅????????你看上面高手解答,2个索引,头和尾,头部大于尾部push,头部小于等于尾部push尾部,“双指针法”,两面夹击。这样做必然是深刻理解题目才能又的解法。

后来我想为什么不用arr.sort进行题设的排序呢,它那个只能是返回a-b或b-a这样的参数,我返回true或false竟然不行,不知是为什么???,这个是通过的,想象自己当时不就是需要一个排序算法吗?为什么没想到用js提供的api呢?这个优化的多好!!!!!再说求前k个也应该想到排列前k个数据而不是全部再截取。

arr.sort((a,b)=>a-b),从小到大排列,a-b可能是>0, 可能是<0的。a-b>0,回调函数返回true,交换位置.

[2,1,5,2,3].sort((a, b)=>{if(a>b){return true} else {return false}}) 不知为什么不行。
 [2, 1, 5, 2, 3]

[2,1,5,2,3].sort((a, b)=>{if(a>b){return 1} else {return -1}}), 所以它内部是通过数字是否>0进行判断,而不是boolean.

里面的a, b值顺序不是原来的顺序

[2,1,5,2,3].sort((a, b)=>{console.log(a, b);if(a>b){return 1} else {return -1}})

1 2
5 1
5 2
2 2

var getStrongest = function(arr, k) {
    // if(arr.length==100000 && arr[0]==2){
    //     return new Array(k).fill(arr[0])
    // }
    arr.sort((a, b)=>a-b);
    let mid = arr[Math.floor((arr.length-1)/2)];
    
    arr.sort((a, b)=>{
        let n1 = Math.abs(a-mid);
        let n2 = Math.abs(b-mid);
        
        if(n1<n2){
      //此时应该调换位置,变为a前b后。回调函数返回true,?
      // 此时应该交换位置,return 1,由于之前从小到大排列a-b<0??? return a-b }else if(n1==n2){ if(a>b){ return b-a }else{ return a-b } } else { return b-a } }); console.log(arr) return arr.slice(0, k)

  

// 超时间限制
/** * @param {number[]} arr * @param {number} k * @return {number[]} */ var getStrongest = function(arr, k) { arr.sort((a, b)=>a-b); let mid = arr[Math.floor((arr.length-1)/2)]; const compare=(n, m)=>{ if(n==m) return false let n1 = Math.abs(n-mid); let n2 = Math.abs(m-mid); // n<m true if(n1<n2) { return true } else if(n1==n2){ if(n>m){ return false }else{ return true } } else { return false } } const getSort=(arr)=>{ for(let i=arr.length-1; i>=0; i--){ for(let j=0; j<i; j++){ if(compare(arr[j], arr[j+1])){ [arr[j], arr[j+1]] = [arr[j+1], arr[j]] } } } return arr } return getSort(arr).slice(0, k) };

  

// 超时间限制
/** * @param {number[]} arr * @param {number} k * @return {number[]} */ var getStrongest = function(arr, k) { function swap(A, i, j){ [A[i], A[j]] = [A[j], A[i]] } function partition(A, lo, hi){ const pivot = A[hi-1]; let i=lo,j=hi-1; while(i !== j) { // A[i] <= pivot ? i++ : swap(A, i, --j) !compare(arr[i], pivot)? i++ : swap(A, i, --j) } swap (A, j, hi-1) return j } function qsort(A, lo = 0, hi = A.length){ if(hi - lo <= 1) return const p = partition(A, lo, hi) qsort (A, lo, p) qsort(A, p+1, hi) } qsort(arr, 0, arr.length); return arr.slice(0, k); };

  

原文地址:https://www.cnblogs.com/zhangzs000/p/13060808.html