牛客NC404 最接近的K个元素【中等 二分查找+双指针 Java/Go/PHP】

题目

题目链接:

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;
}
相关推荐
福大大架构师每日一题25 分钟前
文心一言 VS 讯飞星火 VS chatgpt (396)-- 算法导论25.2 1题
算法·文心一言
EterNity_TiMe_40 分钟前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip
机器学习之心1 小时前
一区北方苍鹰算法优化+创新改进Transformer!NGO-Transformer-LSTM多变量回归预测
算法·lstm·transformer·北方苍鹰算法优化·多变量回归预测·ngo-transformer
yyt_cdeyyds1 小时前
FIFO和LRU算法实现操作系统中主存管理
算法
alphaTao1 小时前
LeetCode 每日一题 2024/11/18-2024/11/24
算法·leetcode
kitesxian2 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
VertexGeek2 小时前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
石小石Orz2 小时前
Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~
javascript·人工智能·算法
jiao_mrswang3 小时前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca3 小时前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法