LeetCode之找到K个最接近的元素

题目:
给定一个排序好的数组,两个整数 k 和 x,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。如果有两个数与 x 的差值一样,优先选择数值较小的那个数。
示例:
在这里插入图片描述
说明:
在这里插入图片描述
方法一:双指针

import java.util.Vector;
class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int n = arr.length, distance = Integer.MAX_VALUE;
		Vector<Integer> v = new Vector<>();
		int index_min = -1;// 找到那个最接近第一个的数的下标
		for (int i = 0; i < n; i++) {
			if (arr[i] == x) {
				index_min = i;
				break;
			}
			if(index_min!=-1&&Math.abs(arr[i] - x) == distance)continue;
			if (Math.abs(arr[i] - x) <= distance) {
				index_min = i;
				distance = Math.abs(arr[i] - x);
			} else {
				break;
			}
		}
		int i = index_min - 1, j = index_min;
		int t = 0;
		while (t < k && i >= 0 && j < n) {

			if (Math.abs(x - arr[i]) <= Math.abs(x - arr[j])) {
				v.insertElementAt(arr[i], 0);
				i--;
			} else {
				v.insertElementAt(arr[j], v.size());
				j++;
			}
			t++;
		}
		if (t < k) {
			if (i > 0) {
				while (t < k) {
					v.insertElementAt(arr[i--], 0);
					t++;
				}
			} else if (j < n) {
				while (t < k) {
					v.insertElementAt(arr[j++], v.size());
					t++;
				}
			}
		}
		return Collections.list(v.elements());
    }
}

方法二:使用Collection.sort()
算法
直观地,我们可以将数组中的元素按照与目标 x 的差的绝对值排序,排好序后前 k 个元素就是我们需要的答案。

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        List<Integer> ret = Arrays.stream(arr).boxed().collect(Collectors.toList());
        Collections.sort(ret, (a,b) -> a == b ? a - b : Math.abs(a-x) - Math.abs(b-x));
        ret = ret.subList(0, k);
        Collections.sort(ret);
        return ret;
    }
}

复杂度分析:在这里插入图片描述
方法三:二叉查找和双指针
在这里插入图片描述

public class Solution {
 	public List<Integer> findClosestElements(int[] arr, int k, int x) {
        List<Integer> ret = Arrays.stream(arr).boxed().collect(Collectors.toList());
		int n = ret.size();
		if (x <= ret.get(0)) {
			return ret.subList(0, k);
		} else if (ret.get(n - 1) <= x) {
			return ret.subList(n - k, n);
		} else {
			int index = Collections.binarySearch(ret, x);
			if (index < 0)
				index = -index - 1;
			int low = Math.max(0, index - k - 1), high = Math.min(ret.size() - 1, index + k - 1);

			while (high - low > k - 1) {
				if ((x - ret.get(low)) <= (ret.get(high) - x))
					high--;
				else if ((x - ret.get(low)) > (ret.get(high) - x))
					low++;
				else
					System.out.println("unhandled case: " + low + " " + high);
			}
			return ret.subList(low, high + 1);
		}
	}
}

复杂度分析:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值