Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在线性时间内求2-和?_Java_Arrays_Algorithm_Sorting_Data Structures - Fatal编程技术网

Java 如何在线性时间内求2-和?

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)。此解决方案满足问题中所述的时间要求 对数组排序,然后从开始和结束分别运行两

我参加了Coursera课程,其中一个面试问题(未评分)如下:

2-sum。给定由
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,因此无法满足问题中规定的时间要求

  • 考虑到这个问题是在基数排序讲座之后给出的,我假设其目的是使用一个基数排序。由于问题指定了64位整数,使用长的二进制表示,并使用,因此可以在线性时间内对数组进行适当排序。这似乎是最好的办法

  • 其他想法

    顺便说一句,我已经看过了,但是它假设一个排序数组,所有的答案都使用了某种散列


    我也看到了这一点,但对于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)。虽然理论上是可能的,但我们知道