计算 3 个整数的中间整数

Posted

技术标签:

【中文标题】计算 3 个整数的中间整数【英文标题】:Calculating middle int out of 3 ints 【发布时间】:2017-09-20 14:04:33 【问题描述】:

对于计算 a、b 和 c 之间的中间 int,这 one-liner 是否正确?

注意: 我不想计算平均值,如果这 3 个按从最小到 最大(中位数)。

示例:17734的中间值为34.

public static int midpoint(int a, int b, int c) 

    return a <= b ? (c <= a ? a : c <= b ? c : b ) : c <= b ? b : c <= a ? c : a;

【问题讨论】:

是...但很少进行测试... “代码有效” == codereview.stackexchange.com/tour 如果您正在寻找比您更好的解决方案,您必须查看这里***.com/questions/1582356/… 你的意思是“很少做测试”?有 6 种可能的顺序:a &lt; b &lt; ca &lt; c &lt; bb &lt; a &lt; cb &lt; c &lt; ac &lt; a &lt; bc &lt; b &lt; a。如果所有这六种情况都有效,那么您的代码就可以了。 你说“我不想计算中位数......只是中间那个......”这几乎就是中位数的定义。 【参考方案1】:

我尝试了三个不同的选项,并计算了每个选项在 1,000,000 次迭代中所花费的时间

    使用复三元 对 List 使用 Collections 排序方法 使用数学最小值和最大值

它们都给出相同的结果,但 2 和 3 几乎在零毫秒内执行

性能测试

int iterationCount = 1000000; // 1 million iterations
        Long t1 = Calendar.getInstance().getTimeInMillis();
        for (int i = 0; i < iterationCount; i++) 
            middle = a <= b ? (c <= a ? a : c <= b ? c : b) : c <= b ? b : c <= a ? c : a;
        
        Long t2 = Calendar.getInstance().getTimeInMillis();


        // #2 Using Collection + List + Sort
        Long t3 = Calendar.getInstance().getTimeInMillis();
        for (int i = 0; i < iterationCount; i++) 
            List<Integer> list = Arrays.asList(a, b, c);
            Collections.sort(list);
            middle = list.get(1);
        
        Long t4 = Calendar.getInstance().getTimeInMillis();

        // #3Using Math's min and max
        Long t5 = Calendar.getInstance().getTimeInMillis();
        for (int i = 0; i < iterationCount; i++) 
            middle = Math.max(Math.min(a, b), Math.min(Math.max(a, b), c));
        
        Long t6 = Calendar.getInstance().getTimeInMillis();

        System.out.println("Time Taken #1 -> " + (t2 - t1));
        System.out.println("Time Taken #2 -> " + (t4 - t3));
        System.out.println("Time Taken #3 -> " + (t6 - t5));

输出

Time Taken #1 -> 16
Time Taken #2 -> 71
Time Taken #3 -> 6

查看输出,就性能而言,选项 #3 是最好的。

三者之最

 middle = Math.max(Math.min(a, b), Math.min(Math.max(a, b), c));

【讨论】:

您的“基准测试”仅测量计算的 1 次迭代,包括对 System.out.println() 的调用。修复它,我将删除我的反对票。 更好,谢谢。尽管即使是 100 也太短了。试试十万? :-) @JasonS 尝试了 100 万次迭代,这实际上突出了差异 :-) 感谢您的建议【参考方案2】:

这个单行是正确的吗?

让我们一步一步来:

return a <= b ? (c <= a ? a : c <= b ? c : b ) : c <= b ? b : c <= a ? c : a;

假设 a

现在假设 a a。现在如果 c b 和 b > a,所以我们将返回 a。请注意,您有一个额外的比较。 (我们已经知道 b > a,我们刚刚知道 c > b,这给了我们排序)

请注意有关此单行的两件事:虽然事实证明您的逻辑是正确的,但要确定其正确性既困难又耗时,而且它无法扩展(想象一下这个单行用于五个项目。 ..)

正确的做法是对列表进行排序,取中间项。

(这正是您所要求的:“如果这 3 个按从小到大的顺序排列,那就是中间那个。”)

【讨论】:

【参考方案3】:
Math.max(Math.min(a, b), Math.min(Math.max(a, b), c));

适用于所有情况。

【讨论】:

虽然不能扩展。 [1, 6, 3, -1, 98, 2, 7] 的中位数呢? 我正在实现快速排序算法的轴心选择。从这个 POV 来看,没有必要,但非常感谢。 好的,所以如果你正在编写一个排序,那么你假设你没有排序 - 如果你知道你正在处理一个包含三个的列表,总是,这是一个更好的答案。 是的,至少三个。

以上是关于计算 3 个整数的中间整数的主要内容,如果未能解决你的问题,请参考以下文章

计算3个连续正整数的和,你能发现啥?用字母表示你发现的共同规律

CCF CSP 201612-1 中间数

15中间数

用for循环,求1~100之间所有整数的和

201612-1 中间数

ccf——201612-1中间数