Java 如何在线性时间内求2-和?
我参加了Coursera课程,其中一个面试问题(未评分)如下: 2-sum。给定由Java 如何在线性时间内求2-和?,java,arrays,algorithm,sorting,data-structures,Java,Arrays,Algorithm,Sorting,Data Structures,我参加了Coursera课程,其中一个面试问题(未评分)如下: 2-sum。给定由n64位整数组成的数组a和目标值T, 确定是否有两个不同的整数i和j,以便 a[i]+a[j]=T。你的算法应该在最坏的情况下以线性时间运行 案例 提示:按线性时间对数组排序 我可以用几种方法来解决这个问题: 一次将元素插入哈希表中。然后进行第二次遍历,在哈希表中查找T-a[i]。哈希表的空间复杂度为O(n),2次传递的空间复杂度为O(n)。此解决方案满足问题中所述的时间要求 对数组排序,然后从开始和结束分别运行两
n
64位整数组成的数组a
和目标值T
,
确定是否有两个不同的整数i
和j
,以便
a[i]+a[j]=T
。你的算法应该在最坏的情况下以线性时间运行
案例
提示:按线性时间对数组排序
我可以用几种方法来解决这个问题:
T-a[i]
。哈希表的空间复杂度为O(n),2次传递的空间复杂度为O(n)。此解决方案满足问题中所述的时间要求i
和j
,查找a[i]+a[j]=T
。如果a[i]+a[j]
,则递增i
,否则递减j
。空间复杂度取决于排序算法;假设,快速排序,无需额外空间。时间复杂度,nlogn,因此无法满足问题中规定的时间要求我也看到了这一点,但对于2-sum的具体情况来说似乎过于复杂了。我分析了您的观察结果,并针对似乎符合要求的观察结果: 一次将元素插入哈希表中。然后第二次通过, 在哈希表中查找T-a[i]。空间复杂度为O(n) 哈希表,以及2次传递的O(n)。此解决方案满足以下要求: 问题中所述的时间要求 我认为这种方法不符合要求,因为
哈希表
最坏情况下的插入复杂性理论上是O(n)
正如您所说,您研究了基数排序,我认为这是一种方法,您可以在时间要求内对数组进行排序,然后可以使用两个指针technque检查是否存在求和T
:
int left = 0, right = array_size - 1;
boolean found = false;
while (left < right) {
if (a[left] + a[right] == T) {
found = true;
}
else if (a[left] + a[right] < T) {
left++;
}
else {
right--;
}
}
int left=0,right=array\u size-1;
布尔值=false;
while(左<右){
如果(a[左]+a[右]==T){
发现=真;
}
如果(a[左]+a[右]
遍历数组时,将值放入一个散列,将值映射到索引。因为我们只寻找两个数字的和,所以寻找当前数字和散列中余数的和来获得目标
public static int[] twoSumInOnePass(int[] values, int target) throws Exception {
// value => index
Map<Integer, Integer> valueToIndexMap = new HashMap<Integer, Integer>();
for (int i = 0; i < values.length; i++) {
int remainder = target - values[i];
if (valueToIndexMap.containsKey(remainder)) {
return new int[] { valueToIndexMap.get(remainder), i };
}
valueToIndexMap.put(values[i], i);
}
throw new Exception("Could not find indexes that sum to " + target);
}
public static int[]twoSumInOnePass(int[]值,int目标)引发异常{
//值=>索引
Map valueToIndexMap=新HashMap();
对于(int i=0;i
回答我自己的问题,以下是Java的有效解决方案:
public class RadixSortsInterviewQuestions {
private static final int MSB = 64;
static Map.Entry<Integer, Integer> twoSum(long[] a, long sum) {
int n = a.length - 1;
sort(a, MSB, 0, n);
for (int i = 0, j = n; i < j; ) {
long t = a[i] + a[j];
if (t == sum) {
return new SimpleImmutableEntry<>(i, j);
} else if (t < sum) {
i++;
} else {
j--;
}
}
return null;
}
// Binary MSD radix sort: https://en.wikipedia.org/wiki/Radix_sort#In-place_MSD_radix_sort_implementations
private static void sort(long[] a, int d, int lo, int hi) {
if (hi < lo || d < 1) return;
int left = lo - 1;
int right = hi + 1;
for (int i = left + 1; i < right; ) {
if (isBitSet(a[i], d)) {
swap(a, i, --right);
} else {
left++;
i++;
}
}
sort(a, d - 1, lo, left);
sort(a, d - 1, right, hi);
}
private static boolean isBitSet(long x, int k) {
boolean set = (x & 1L << (k - 1)) != 0;
// invert signed bit so that all positive integers come after negative ones
return (k == MSB) != set;
}
private static void swap(long[] a, int i, int j) {
long tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
public类RadixSortsInterviewQuestions{
私有静态final int MSB=64;
静态映射。条目twoSum(long[]a,long sum){
int n=a.长度-1;
排序(a,MSB,0,n);
对于(int i=0,j=n;i 布尔集=(x&1L@lexicore标记的问题不是重复的,因为数组被指定在那里而不是在这里排序!我投票赞成重新打开。你能分享你尝试的代码吗?@pamcevoy没有必要,这是一个关于算法的问题,应该很清楚我已经考虑过了。你有什么要添加到这张光盘上的吗ussion?使用基数排序,您可能可以立即拒绝初始数组中的几个高数字。如果T=15,则可以立即拒绝位为5或更高的任何数字,从而缩短要搜索匹配项的数组。最坏情况下的复杂性仅取决于哈希函数的兼容性或不兼容性。如您所知,使用一个坏的哈希函数,整个哈希表都是“无用的”。在这些场景中,我们是否可以想当然地认为哈希函数完成了它的工作,并且复杂性确实是O(1)摊销?@JohEker我们可以讨论这个话题,但无论如何,我不认为这是解决这个问题的方法。暗示需要进行排序。不可想象的是,整数的哈希函数会退化为O(n)。虽然理论上是可能的,但我们知道