Java 在排序数组列表中查找2个最近的上一个值和2个最近的下一个值
这是一个修改过的二进制搜索,它返回排序数组列表中与给定值最近的元素。如何调整它,使其能够返回2个最近的前一个元素和2个最近的下一个元素Java 在排序数组列表中查找2个最近的上一个值和2个最近的下一个值,java,search,arraylist,binary-search,Java,Search,Arraylist,Binary Search,这是一个修改过的二进制搜索,它返回排序数组列表中与给定值最近的元素。如何调整它,使其能够返回2个最近的前一个元素和2个最近的下一个元素 private static Long search(long value, ArrayList<Long> a) { if(value < a.get(0)) { return a.get(0); } if(value > a.get(a.size()-1)) { return
private static Long search(long value, ArrayList<Long> a) {
if(value < a.get(0)) {
return a.get(0);
}
if(value > a.get(a.size()-1)) {
return a.get(a.size()-1);
}
int lo = 0;
int hi = a.size() - 1;
while (lo <= hi) {
int mid = (hi + lo) / 2;
if (value < a.get(mid)) {
hi = mid - 1;
} else if (value > a.get(mid)) {
lo = mid + 1;
} else {
return a.get(mid);
}
}
return (a.get(lo) - value) < (value - a.get(hi)) ? a.get(lo) : a.get(hi);
}
私有静态长搜索(长值,ArrayList a){
if(值a.get(a.size()-1)){
返回a.get(a.size()-1);
}
int-lo=0;
int hi=a.大小()-1;
while(loa.get(mid)){
lo=中间+1;
}否则{
返回a.get(mid);
}
}
返回值(a.get(lo)-value)<(value-a.get(hi))?a、 得到(lo):得到(hi);
}
例如,让我考虑一下我的数组列表是由这些元素组成的:
[10120130140150160170180190110001]
我得到了730的值。我希望搜索返回一个由4个元素组成的数组,其中601、701作为前一个值,801和901作为下一个值。有一种简单的方法可以扩展原始代码,以适应返回四个值的列表,而且相对容易:
private static List<Long> search(long value, ArrayList<Long> a) {
List<Long> returnList = new ArrayList<>();
if (null == a) {
return null;
}
if (a.isEmpty()) {
return a;
}
if (a.size()==1) {
return a;
}
if(value < a.get(0)) {
returnList.add(a.get(0));
returnList.add(a.get(1));
return returnList;
}
if(value > a.get(a.size()-1)) {
returnList.add(a.get(a.size()-1));
returnList.add(a.get(a.size()-2));
return returnList;
}
int lo = 0;
int hi = a.size() - 1;
while (lo <= hi) {
int mid = (hi + lo) / 2;
if (value < a.get(mid)) {
hi = mid - 1;
} else if (value > a.get(mid)) {
lo = mid + 1;
} else {
if (mid>1) returnList.add(a.get(mid-2));
if (mid>0) returnList.add(a.get(mid-1));
if (mid<=a.size()-1) returnList.add(a.get(mid+1));
if (mid<=a.size()-2) returnList.add(a.get(mid+2));
return returnList;
}
}
if ((a.get(lo) - value) < (value - a.get(hi))) {
if (lo > 0) returnList.add(a.get(lo-1));
returnList.add(a.get(lo));
if (lo<=a.size()-1) returnList.add(a.get(lo+1));
if (lo<=a.size()-2) returnList.add(a.get(lo+2));
} else {
if (lo > 1) returnList.add(a.get(hi-2));
if (lo > 0) returnList.add(a.get(hi-1));
ReturnList.add(a.get(hi));
if (hi<=a.size()-1) returnList.add(a.get(hi+1));
}
return returnList;
}
私有静态列表搜索(长值,ArrayList a){
List returnList=new ArrayList();
如果(null==a){
返回null;
}
如果(a.isEmpty()){
返回a;
}
如果(a.size()==1){
返回a;
}
if(值a.get(a.size()-1)){
returnList.add(a.get(a.size()-1));
returnList.add(a.get(a.size()-2));
退货清单;
}
int-lo=0;
int hi=a.大小()-1;
while(loa.get(mid)){
lo=中间+1;
}否则{
如果(mid>1)returnList.add(a.get(mid-2));
如果(mid>0)returnList.add(a.get(mid-1));
如果(mid使用非常简单的方法,此代码将根据lo
、hi
和mid
值之间的差异向结果列表添加元素
在边缘情况下,返回的元素数可以小于4。例如,如果左侧或右侧没有元素(由于列表边界),则返回的列表大小可以是2或3,具体取决于最近值的位置
如果这是您想要的,那么下面是代码:
private static List<Long> search(long value, List<Long> a) {
if (a.size() < 3) return new ArrayList<>(a);
List<Long> result = new ArrayList<>();
if (value < a.get(0)) {
result.add(a.get(0));
result.add(a.get(1));
return result;
}
if (value > a.get(a.size() - 1)) {
result.add(a.get(a.size() - 2));
result.add(a.get(a.size() - 1));
return result;
}
int lo = 0;
int hi = a.size() - 1;
int match = -1;
while (lo <= hi) {
int mid = (hi + lo) / 2;
if (value < a.get(mid)) {
hi = mid - 1;
} else if (value > a.get(mid)) {
lo = mid + 1;
} else {
match = mid;
break;
}
}
if (match >= 0) {
if (match > 1) result.add(a.get(match - 2));
if (match > 0) result.add(a.get(match - 1));
if (match < a.size() - 1) result.add(a.get(match + 1));
if (match < a.size() - 2) result.add(a.get(match + 2));
} else if (a.get(lo) < value) {
result.add(a.get(hi));
result.add(a.get(lo));
if (lo < a.size() - 1) result.add(a.get(lo + 1));
if (lo < a.size() - 2) result.add(a.get(lo + 2));
} else if (a.get(hi) > value) {
if (hi > 1) result.add(a.get(hi - 2));
if (hi > 0) result.add(a.get(hi - 1));
result.add(a.get(hi));
result.add(a.get(lo));
} else {
if (hi > 0) result.add(a.get(hi - 1));
result.add(a.get(hi));
result.add(a.get(lo));
if (lo < a.size() - 1) result.add(a.get(lo + 1));
}
return result;
}
私有静态列表搜索(长值,列表a){
如果(a.size()<3)返回新的ArrayList(a);
列表结果=新建ArrayList();
if(值a.get(a.size()-1)){
结果.添加(a.get(a.size()-2));
添加(a.get(a.size()-1));
返回结果;
}
int-lo=0;
int hi=a.大小()-1;
int match=-1;
while(loa.get(mid)){
lo=中间+1;
}否则{
匹配=中间;
打破
}
}
如果(匹配>=0){
如果(匹配>1)结果。添加(a.get(匹配-2));
如果(匹配>0)结果。添加(a.get(匹配-1));
if(match值,则为else{
如果(hi>1)结果,则添加(a.get(hi-2));
如果(hi>0)结果,则添加(a.get(hi-1));
结果。添加(a.get(hi));
结果。添加(a.get(lo));
}否则{
如果(hi>0)结果,则添加(a.get(hi-1));
结果。添加(a.get(hi));
结果。添加(a.get(lo));
如果(lo
是否总是有两个前一个值和两个下一个值?如果值
已经在列表中,输出应该是什么?我在下面写了一个答案-让我知道它是否有用。列表中已经存在的值对于我的实际数据集来说非常罕见。但是如果发生这种情况,它应该忽略该值并返回2 pr前一个值和2个下一个值。例如,如果给我值501,我希望列表返回[301、401、601、701]。非常感谢您的回答。这真的很有帮助。但是,也许我在问题中没有明确指出,我总是希望它返回两个以前的值和两个以后的值。例如,如果在您的代码中我输入700,则列表将返回[601、701、801、901]。我希望它返回[501、601、701、801].501和601是以前的值,701和801是下一个值。如果值已经在列表中,请检查我问题中关于该案例的注释。@法律我已根据您的规范对其进行了修改。它按您的预期工作。@法律根据您的注释进行编辑以忽略精确匹配谢谢!这正是我所需要的。@thelaw我很乐意帮忙!
public static void main(String[] args) {
ArrayList<Long> list = new ArrayList(Arrays.asList(101l, 201l, 301l, 401l, 501l, 601l, 701l, 801l, 901l, 1001l));
System.out.println(search(1020l,5,list));
}
[801, 901, 1001]
System.out.println(search(730l,4,list));
[601, 701, 801, 901]
System.out.println(search(601l,5,list));
[401, 501, 701, 801, 901]
private static List<Long> search(long value, List<Long> a) {
if (a.size() < 3) return new ArrayList<>(a);
List<Long> result = new ArrayList<>();
if (value < a.get(0)) {
result.add(a.get(0));
result.add(a.get(1));
return result;
}
if (value > a.get(a.size() - 1)) {
result.add(a.get(a.size() - 2));
result.add(a.get(a.size() - 1));
return result;
}
int lo = 0;
int hi = a.size() - 1;
int match = -1;
while (lo <= hi) {
int mid = (hi + lo) / 2;
if (value < a.get(mid)) {
hi = mid - 1;
} else if (value > a.get(mid)) {
lo = mid + 1;
} else {
match = mid;
break;
}
}
if (match >= 0) {
if (match > 1) result.add(a.get(match - 2));
if (match > 0) result.add(a.get(match - 1));
if (match < a.size() - 1) result.add(a.get(match + 1));
if (match < a.size() - 2) result.add(a.get(match + 2));
} else if (a.get(lo) < value) {
result.add(a.get(hi));
result.add(a.get(lo));
if (lo < a.size() - 1) result.add(a.get(lo + 1));
if (lo < a.size() - 2) result.add(a.get(lo + 2));
} else if (a.get(hi) > value) {
if (hi > 1) result.add(a.get(hi - 2));
if (hi > 0) result.add(a.get(hi - 1));
result.add(a.get(hi));
result.add(a.get(lo));
} else {
if (hi > 0) result.add(a.get(hi - 1));
result.add(a.get(hi));
result.add(a.get(lo));
if (lo < a.size() - 1) result.add(a.get(lo + 1));
}
return result;
}