竞赛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); };