题目
题目链接:
https://www.nowcoder.com/practice/b4d7edc45759453e9bc8ab71f0888e0f
知识点
二分查找;找到第一个大于等于x的数的位置idx;
然后从idx开始往两边扩展
Java代码
java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型ArrayList
* @param k int整型
* @param x int整型
* @return int整型ArrayList
*/
public ArrayList<Integer> closestElement (ArrayList<Integer> nums, int k,
int x) {
//二分+双指针
int n = nums.size();
int right = firstGt(nums, x);
int left = right - 1;
ArrayList<Integer> ans = new ArrayList<>();
LinkedList<Integer> ll = new LinkedList<>();
if (right == 0) {
for (int i = 0; i < k ; i++) {
ll.add(nums.get(i));
}
} else if (right == n - 1) {
for (int i = n - 1 - k; i < n ; i++) {
ll.add(nums.get(i));
}
} else {
while (left >= 0 || right < n) {
int diffleft = -1;
int diffright = -1;
if (left >= 0) {
diffleft = x - nums.get(left);
}
if (right < n) {
diffright = nums.get(right) - x;
}
if (diffleft != -1 && diffright != -1) {
if (diffleft <= diffright) {
ll.addFirst(nums.get(left--));
} else {
ll.addLast(nums.get(right++));
}
} else if (diffleft != -1) {
ll.addFirst(nums.get(left--));
} else if (diffright != -1) {
ll.addLast(nums.get(right++));
}
if (ll.size() == k)
break;
}
}
return new ArrayList<>(ll);
}
//找到大于等于x的下标位置
public int firstGt(ArrayList<Integer> nums, int x) {
int n = nums.size();
int left = 0;
int right = n;
while (left < right) {
int m = left + (right - left) / 2;
if (nums.get(m) > x) {
right = m - 1;
} else if (nums.get(m) < x) {
left = m + 1;
} else {
return m;
}
}
return left;
}
}
Go代码
go
package main
//import "fmt"
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @param k int整型
* @param x int整型
* @return int整型一维数组
*/
func closestElement(nums []int, k int, x int) []int {
//二分+双指针
n := len(nums)
right := firstGt(nums, x)
arrleft := []int{}
arrright := []int{}
ans := []int{}
if right == 0 {
for i := 0; i < k; i++ {
ans = append(ans, nums[i])
}
} else if right == n-1 {
for i := n - 1 - k; i < n; i++ {
ans = append(ans, nums[i])
}
} else {
left := right - 1
cnt := 0
for left >= 0 || right < n {
diffleft := -1
diffright := -1
if left >= 0 {
diffleft = x - nums[left]
}
if right < n {
diffright = nums[right] - x
}
if diffleft != -1 && diffright != -1 {
if diffleft <= diffright {
arrleft = append(arrleft, nums[left])
left--
} else {
arrright = append(arrright, nums[right])
right++
}
} else if diffleft != -1 {
arrleft = append(arrleft, nums[left])
left--
} else if diffright != -1 {
arrright = append(arrright, nums[right])
right++
}
cnt++
if cnt == k {
for i := len(arrleft) - 1; i >= 0; i-- {
ans = append(ans, arrleft[i])
}
for i := 0; i < len(arrright); i++ {
ans = append(ans, arrright[i])
}
break
}
}
}
return ans
}
//找到大等于x的位置
func firstGt(nums []int, x int) int {
n := len(nums)
left := 0
right := n - 1
for left < right {
m := left + (right-left)/2
if nums[m] > x {
right = m - 1
} else if nums[m] < x {
left = m + 1
} else {
return m
}
}
return left
}
PHP代码
php
<?php
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @param k int整型
* @param x int整型
* @return int整型一维数组
*/
function closestElement( $nums , $k , $x )
{
// 二分+双指针
$n = count($nums);
$right = firstGt($nums,$x);
$ans = [];
$arrleft=[];
$arrright =[];
if($right ==0 ){
for($i=0;$i<$k;$i++){
$ans[$i] = $nums[$i];
}
}else if($right ==$n-1){
for($i=$n-1-$k;$i>=0;$i++){
$ans[count($ans)] = $nums[$i];
}
}else {
$left = $right-1;
$cnt =0;
while ($left>=0 || $right < $n){
$diffleft=-1;
$diffright =-1;
if($left>=0) {
$diffleft = $x-$nums[$left];
}
if($right<$n){
$diffright = $nums[$right]-$x;
}
if($diffleft!=-1 && $diffright!=-1){
if($diffleft<=$diffright){
$arrleft[count($arrleft)] = $nums[$left--];
}else{
$arrright[count($arrright)] = $nums[$right++];
}
}else if($diffleft!=-1){
$arrleft[count($arrleft)] = $nums[$left--];
}else if($diffright!=-1){
$arrright[count($arrright)] = $nums[$right++];
}
$cnt++;
if($cnt==$k){
for($i=count($arrleft)-1;$i>=0;$i--){
$ans[count($ans)] = $arrleft[$i];
}
for($i=0;$i<count($arrright);$i++){
$ans[count($ans)] = $arrright[$i];
}
break;
}
}
}
return $ans;
}
//找到大于等于x的位置
function firstGt($nums,$x){
$n = count($nums);
$left =0;
$right = $n;
while ($left<$right){
$m = $left+(($right-$left)>> 1);
if($nums[$m] > $x){
$right = $m-1;
}else if($nums[$m] < $x){
$left = $m+1;
}else{
return $m;
}
}
return $left;
}