我有一个整数数组,其中包含一些有限数量的值。我的任务是找到数组中任意两个元素之间的最小差异。
请注意,该数组包含:
4, 9, 1, 32, 13
在这里,4和1之间的差异最小,因此答案是3。
应该如何设计算法来解决这个问题。另外,我不知道为什么,但我觉得使用树结构可以相对容易地解决这个问题。能做到吗?
我有一个整数数组,其中包含一些有限数量的值。我的任务是找到数组中任意两个元素之间的最小差异。
请注意,该数组包含:
4, 9, 1, 32, 13
在这里,4和1之间的差异最小,因此答案是3。
应该如何设计算法来解决这个问题。另外,我不知道为什么,但我觉得使用树结构可以相对容易地解决这个问题。能做到吗?
最小差值将是排序后连续对中的差异之一。对数组进行排序,遍历相邻数字对并寻找最小差值:
int[] a = new int[] {4, 9, 1, 32, 13};
Arrays.sort(a);
int minDiff = a[1]-a[0];
for (int i = 2 ; i != a.length ; i++) {
minDiff = Math.min(minDiff, a[i]-a[i-1]);
}
System.out.println(minDiff);
O(N*LogN)
更快地完成。你至少需要遍历一次数组中的元素,而且对于每个元素,你都需要找到它最佳的“对应项”以进行减法运算。如果你使用树,那么你能做到的最好性能是 Log(N)
。 - Sergey KalinichenkoLog(N)
的时间复杂度,总时间复杂度为O(N*Log(N))
。 - Sergey KalinichenkoN
方面是线性的,但也会对 max-min
产生线性依赖,这可能会导致效果很差。 - DarioP一般算法:
以下是我用Javascript创建的样例:
// Points in 1-D
var points = [4, 9, 1, 32, 13];
var smallestDiff;
function mergeSort(arr) {
if (arr.length == 1)
return arr;
if (arr.length > 1) {
let breakpoint = Math.ceil((arr.length / 2));
// Left list starts with 0, breakpoint-1
let leftList = arr.slice(0, breakpoint);
// Right list starts with breakpoint, length-1
let rightList = arr.slice(breakpoint, arr.length);
// Make a recursive call
leftList = mergeSort(leftList);
rightList = mergeSort(rightList);
var a = merge(leftList, rightList);
return a;
}
}
function merge(leftList, rightList) {
let result = [];
while (leftList.length && rightList.length) {
// Sorting the x coordinates
if (leftList[0] <= rightList[0]) {
result.push(leftList.shift());
} else {
result.push(rightList.shift());
}
}
while (leftList.length)
result.push(leftList.shift());
while (rightList.length)
result.push(rightList.shift());
let diff;
if (result.length > 1) {
diff = result[1] - result[0];
} else {
diff = result[0];
}
if (smallestDiff) {
if (diff < smallestDiff)
smallestDiff = diff;
} else {
smallestDiff = diff;
}
return result;
}
mergeSort(points);
console.log(`Smallest difference: ${smallestDiff}`);
我会把它们放在一个堆(heap)中,时间复杂度为O(nlogn)
,然后一个一个地弹出并获取每个弹出的元素之间的最小差异。最终我将得到最小差异。不过,可能会有更好的解决方案。
function FindMin(arr) {
//sort the array in increasing order
arr.sort((a,b) => {
return a-b;
});
let min = arr[1]-arr[0];
let n = arr.length;
for (var i=0;i<n;i++) {
let m = arr[i+1] - arr[i];
if(m < min){
m = min;
}
}
return m; // minimum difference.
}
对于那些正在寻找一行Python答案(或多或少),这里有两个可能的解决方案:
l = sorted([4, 9, 1, 32, 13])
min(map(lambda x: x[1] - x[0], pairwise(l)))
pairwise()
函数来处理可迭代对象并返回所有连续的对。在我们对初始列表进行排序后,我们只需要找到差异最小的一对即可。
l = sorted([4, 9, 1, 32, 13])
min(map(lambda x: x[1] - x[0], zip(l[:-1], l[1:])))
zip()
方法重现1pairwise()
方法的行为。
1. pairwise()
的实际实现可能在空间方面更有效,因为它不需要创建列表的 2 个(浅层)副本。在大多数情况下,这应该是不必要的,但您可以使用 itertools.islice
在不创建副本的情况下迭代列表。然后,您将编写类似于 zip(islice(a, len(a) - 1), islice(a, 1, None))
的东西。
import java.util.Scanner;
public class Solution {
public static void main(String [] args) {
Scanner input = new Scanner(System.in);
int i, minDistance = 999999;
boolean flag = false;
int capacity = input.nextInt();
int arr[] = new int[capacity];
for (i = 0; i < capacity; i++) {
arr[i] = input.nextInt();
}
int firstElement = input.nextInt();
int secondElement = input.nextInt();
int prev = 0;
for (i = 0; i < capacity; i++) {
if (arr[i] == firstElement || arr[i] == secondElement) {
prev = i;
break;
}
}
for (; i < capacity; i++) {
if(arr[i] == firstElement || arr[i] == secondElement) {
if(arr[i] != arr[prev] && minDistance > Math.abs(i - prev)) {
minDistance = Math.abs(i - prev);
flag = true;
prev = i;
} else {
prev = i;
}
}
}
if(flag)
System.out.println(minDistance);
else
System.out.println("-1");
}
}
import itertools
arr = [4, 9, 1, 32, 13]
if len(arr) > 1:
min_diff = abs(arr[0] - arr[1])
else:
min_diff = 0
for n1, n2 in itertools.combinations(arr, 2): # Get the combinations of numbers
diff = abs(n1-n2) # Find the absolute difference of each combination
if min_diff > diff:
min_diff = diff # Replace incase a least differnce found
print(min_diff)
len(arr)
²个元素的列表以一种“非Python风格”的方式构建。 - greybeard