查找元素是否存在于给定范围内

时间:2014-09-14 16:18:03

标签: java arrays algorithm

我有两个数组AB。我必须找到数组C所需的元素数量以适应特定的长度。

Length = B[i]-A[i]

例如:

A[0] = 1    B[0] = 4
A[1] = 4    B[1] = 5
A[2] = 5    B[2] = 9
A[3] = 8    B[3] = 10
and 
C[0] = 4
C[1] = 6
C[2] = 7
C[3] = 10
C[4] = 2

答案是4

说明:

C[0] is falling in the range of (A[0],B[0]) and (A[1],B[1])
C[1] is falling in the range of (A[2],B[2]) 
C[2] is of no use
C[3] is falling in the range of (A[3],B[3])
so the total is 4

我的方法:
传统方法:简单循环数组CA的每个元素,如果在范围内找到,则将A[i]B[i]的值设置为减去无限或删除它们(对于Arraylist)。

  • 时间复杂性是一个问题,因此不是一个好方法。

HashTable :将哈希表中的值存储为A[i]作为键,将B[i]存储为值。然后找到给定C[i]的元素并删除密钥。我认为这不是一个好方法

请为我提供一个有效的算法。

6 个答案:

答案 0 :(得分:1)

好的,基于你的答案,我们别无选择,只能检查C的每个元素对A和B.但由于A和B按升序排列,性能应该是合理的:

    int len = A.length;
    boolean[] eliminated = new boolean[len]; // initially all elements are false
    int totalEliminated = 0;

    for (int i = 0; i < C.length; i++) {
        int c = C[i];
        for (int j = 0; j < len && A[j] <= c; j++) {
            if (B[j] >= c && !eliminated[j]) {
                System.out.println(c + " eliminates " + A[j] + " - " + B[j]);
                eliminated[j] = true;
                if (++totalEliminated == len) {
                    return i+1;
                }
            }
        }
    }
    return 0;

答案 1 :(得分:1)

如果输入范围已从最小到最大排序(B [i] <= A [i + 1]):

int bottomRangeIndex = 0;
int topRangeIndex = numberOfABRangesYouHave - 1;
int answerCounter = 0;

C.sort(); // Sort C so that it goes from smallest to largest number.

for number in C: {
    if (number < A[bottomRangeIndex]) {
        continue;
    } else if (number > B[topRangeIndex]) {
        return answerCounter;
    } else {
        while ((number > B[bottomRangeIndex++]) && (bottomRangeIndex <= topRangeIndex)) {
            // Just keeps incrementing bottomRangeIndex.
        }
        if (bottomRangeIndex > topRangeIndex) {
            return answerCounter;
        } else {
            answerCounter++;
            bottomRangeIndex++;
        }
    }
}

这可能有一些我没想到的错误,但基本上它的作用是:

  1. 排序C.我知道你说你不能这样做,但我不明白为什么除非这是一个家庭作业问题。
  2. 如果C中的数字完全超出这些范围,则跳过检查A,B范围内的任何内容。如果当前数字大于A,B范围中的最大数字(B [topRangeIndex]),则返回当前答案计数器,因为C(已排序)中的其他元素不能再次出现在A,B范围内。
  3. 由于C被排序并且当前数量大于所有A,B范围中的底部元素,因此开始检查C中的数字是否落在每个A范围的B端内。被检查的数字始终是C中的最小元素,因此如果它不能落在A范围的B端,则不应再次检查A,B范围,因此bottomRangeIndex会递增。
  4. 如果while循环消除了每个范围,我们就完成了检查(C中的当前元素大于任何A,B范围内的最大数字,我们不需要检查其他任何内容。
  5. 如果要检查的C中的数字不大于A,B范围(位于bottomRangeIndex)末尾的数字,则A,B范围包含来自C的元素。我们递增应答计数器,移动bottomRangeIndex up,并继续。
  6. 试试这个,看它是否有效。如果这是家庭作业,你真的不能对C进行排序,那么你可以通过少量的调整来修改它以给你正确的答案,但我不会说如何......

答案 2 :(得分:1)

这是使用ArrayLists的更高效版本:

        int len = arrA.length;
        ArrayList<Integer> A = new ArrayList<Integer>(len);
        ArrayList<Integer> B = new ArrayList<Integer>(len);
        for (int i=0; i<len; i++) {
            A.add(arrA[i]);
            B.add(arrB[i]);
        }

        for (int i = 0; i < C.length; i++) {
            int c = C[i];
            int j = 0;
            while (j<A.size() && A.get(j) <= c) {
                if (B.get(j) >= c) {
                    A.remove(j);
                    if (A.isEmpty()) return i+1;
                    B.remove(j);
                }
                else {
                    j++;
                }
            }
        }
        return 0;

答案 3 :(得分:0)

这是在O(n log n)中解决它的一个快速草图。它可能不是实践中最好的方法,但只是为了提供一种n log n方法。

总而言之,这是一种全面的技术。或者更确切地说,在这种情况下。

1. Sort arrays A, B, and C (cost: n log n). Think of the arrays as queues
   (that is, "remove" elements from the left by increasing a start index).
2. Create current-intervals set (initially empty. Has O(log n) operations.)
2. While A not empty or B not empty or C not empty:
3.   get the lowest element from the first (if any) elements in A, B, and C.
4.   if it's an A:
5.     Add the corresponding interval to the current-intervals list
6.   else if it's a B:
7.      Remove the corresponding interval from the current-intervals list
8.   else it must be a C, so:
9.      The answer to the query corresponding to C is the current-intervals list
        (in the current state)

答案 4 :(得分:0)

for(int i =0 ;i<C.length;i++)
for(int j=0;j<A.length;j++)
{
    if(A[i]<=C[i] && B[i]>=C[i])
   {   answer++;
       A[i] = Integer.Max_Value;
     }
}

会的  给你一个正确的答案

答案 5 :(得分:0)

我尝试了一些树形结构,但最终我又回到了一个简单的二元搜索,所以现在是O(nlogn):

static int getAnswerV2a(int[] A, int[] B, int[] C) {
    int len = A.length;
    ArrayList<Interval> intervals = new ArrayList<Interval>(len);
    for (int i=0; i<len; i++) {
        intervals.add(new Interval(A[i], B[i]));
    }

    for (int i = 0; i < C.length; i++) {
        int c = C[i];
        binarySearch(intervals, 0, intervals.size(), c);
        if (intervals.isEmpty()) return i+1;
    }
    return -1;
}

static class Interval {
    int start, end;

    Interval(int start, int end) {
        this.start = start;
        this.end = end;
    }

    boolean matches(int c) {
        return start <= c && c <= end;
    }
}

// Find an interval (between indices i and j) that matches c
// When found, remove it from the List and adjust indices accordingly
static void binarySearch(ArrayList<Interval> intervals, int i, int j, int c) {
    if (i==j)
        return;
    else if (i+1==j) {
        if (intervals.get(i).matches(c))
            intervals.remove(i);
    }
    else {
        int mid = (int) Math.floor((i+j) / 2);
        Interval interval = intervals.get(mid);
        if (interval.start > c)
            binarySearch(intervals, i, mid, c);
        else if (interval.end < c)
            binarySearch(intervals, mid+1, j, c);
        else {
            intervals.remove(mid);
            binarySearch(intervals, i, j-1, c);
        }
    }
}