【问题标题】:Finding the Median given the index of three elements给定三个元素的索引找到中位数
【发布时间】:2015-09-14 18:09:09
【问题描述】:

作为我的快速排序算法的一部分,我试图从给定第一个、中间和最后一个元素的索引的 Arraylist 中找到中值。我使用了几个 if/else 语句来查找它,但它是不正确的,而且逻辑相当复杂。

注意:对数组进行排序不是一种选择。

public static int findMedian(ArrayList <Integer> A, int first, int mid, int last) {
    if(first == mid || first == last || last == mid) {
        return first;
    }
    if(A.get(first) >= A.get(last)) {
        if(A.get(first) <= A.get(mid)) {
            return first;
        }
        else if(A.get(last) >= A.get(mid)) {
            return last;
        }
        return mid;
    }
    else {
        if(A.get(first) > A.get(mid)) {
            return first;
        }
        else if(A.get(mid) > A.get(last)) {
            return last;
        }
        return mid;
    }
}

【问题讨论】:

  • 我找到了一些方法来解决三个值都不同的情况。但是,我必须考虑到这一点,因为我生成的数组具有随机值。

标签: java algorithm


【解决方案1】:

这个方法怎么样?

public static int findMedian(ArarayList<Integer> A, int first, int mid, int \last) {
    if (first == mid || first == last || last == mid)
        return first;

    int v = (A.get(first) >= A.get(mid)  ? 1 : 0) +
            (A.get(first) >= A.get(last) ? 2 : 0) +
            (A.get(mid)   >= A.get(last) ? 4 : 0);

    switch (v) {
    case 0: /* a < b && a < c && b < c */
        return mid;
    case 1: /* a >= b && a < c && b < c */
        return first;
    case 2: /* a < b && a >= c && b < c -> not possible */
        return -1;
    case 3: /* a >= b && a >= c && b < c */
        return last;
    case 4: /* a < b && a < c && b >= c */
        return last;
    case 5: /* a >= b && a < c && b >= c -> not possible */
        return -1;
    case 6: /* a < b && a >= c && b >= c */
        return first;
    case 7: /* a >= b && a >= c && b >= c */
        return mid;
    }

    /* won't come here */
    return first;
}

或者以更紧凑的形式。

public static int findMedian(ArarayList<Integer> A, int first, int mid, int \last) {    
    if (first == mid || first == last || last == mid)
        return first;

    int result[] = new int[] { mid, first, -1, last, last, -1, first, mid };

    int v = (A.get(first) >= A.get(mid)  ? 1 : 0) +
            (A.get(first) >= A.get(last) ? 2 : 0) +
            (A.get(mid)   >= A.get(last) ? 4 : 0);

    return result[v];
}

【讨论】:

    【解决方案2】:

    有一点看起来很奇怪,如果 last==mid 你先返回。

    如果你只是删除这些行可能会更好:

        if(first == mid || first == last || last == mid) {
            return first;
        }
    

    【讨论】:

    • 实际上去掉这些行会破坏程序,但我明白你关于如果 last == mid 先返回的观点。
    【解决方案3】:

    你能在你的索引上使用Arrays.sort吗(我知道你不能在列表本身上使用排序)?如果是这样,您可以按值对索引进行排序,然后选择中间的:

    int findMedian(List<Integer> list, int first, int mid, int last) {
        int[] indices = {first, mid, last};
        Arrays.sort(indices, (i1, i2) -> list.get(i1) - list.get(i2));
        return indices[1];
    }
    

    如果您因任何原因不能使用排序,那么您可以进行自己的简单插入排序:

    int findMedian(List<Integer> list, int first, int mid, int last) {
        List<Integer> indices = new ArrayList<>();
        for (int i: Arrays.asList(first, mid, last) {
            int j = 0;
            while (j < indices.size() && list.get(i) > list.get(j))
                j++;
            indices.add(j, i);
        }
        return indices.get(1);
    }
    

    如果您不想使用其中任何一个,那么我建议您将if 声明完全明确:

    if (list.get(first) >= list.get(mid) && list.get(first) <= list.get(last)) {
        return first;
    else if (list.get(mid) >= list.get(first) && list.get(mid) <= list.get(last)) {
        return mid;
    } else {
        return last;
    }
    

    【讨论】:

    • 好的,我会添加一个替代方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多