假设我有2个相同大小的未排序数组,例如:
A = {1, 4, 3, 2}
B = {5, 12, 1, 5}
我想找到每2个单元格的最小乘数 - 每个数组一个,意思是 - A[i] * B[j]
的总和(i
是A
中的索引,{ {1}}是j
)中的索引。我应该将哪些值乘以另一个数组中的哪些值以获得最小的乘积总和?
(我希望很明显,一旦你执行了B
,你就无法再触摸那些细胞......)
编辑:对于上面的示例,最小总和是: 1 * 4 + 3 * 5 + 5 * 2 + 1 * 12 = 31
答案 0 :(得分:4)
为了找到最小的总和,请按顺序排列一组,另一组按降序排列,然后沿同样的顺序相乘。
这是因为每个配对a[i] * b[j]
的最小可能产品(对于固定a[i]
,因为需要为每个元素生成结果)是b[j]
的最小可能值反之亦然。
这也适用于否定因为最大的负数是最小数,因此与推论数组中的最正数配对。即使两个集合都是负数,这也会继续进行,因为每个乘法的结果都等同于两个集合都具有其值的负数。
答案 1 :(得分:3)
Aravol给出了一些关于为什么反向排序匹配是最优的直觉,但是对于这种事情,我认为真正严格证明它始终有效是有用的。
证明这一点的一种方法是显示,给定任何尚未反向排序的匹配,稍微更改该匹配以使其“更像”反向排序匹配永远不会增加总数。如果我们能够证明这个过程
然后我们已经证明反向排序匹配并不比任何其他匹配更差 - 这与显示它具有最低可能总数相同。我想强调的是,任何算法都不会实际执行以下任何计算 。出于证明的目的,我们必须表明的是,可以执行,并且如果是这样,他们将具有所需的行为。
为此,我们假设我们以一组对的形式给出任意匹配。作为第一步,让我们按照第一个元素按顺序对它们进行排序。 (我们可以这样做,因为列出对的顺序不会影响它们的总和。)在排序后调用第i对(x [i],y [i]);根据定义,在排序之后我们对所有i都有x [i]&lt; = x [i + 1]。现在,如果匹配尚未进行反向排序,则必须存在一对违反反向排序的相邻y值 - 即必须有一些i使得y [i]&lt;值Y [i + 1]。让我们选择i发生的第一个(最低)值,看看如何交换y [i]和y [i + 1]将影响总数。为此,我们可以减去两个旧对的贡献,并添加两个新对的贡献:x [i] y [i + 1] + x [i + 1] y [i] - x [i] y [i] - x [i + 1] y [i + 1] = x [i](y [i + 1] - y [i])+ x [i + 1](y [i ] - y [i + 1])。设d = y [i + 1] - y [i],这简化为x [i] d - x [i + 1] d = d(x [i] - x [i + 1])。我们知道x [i] - x [i + 1] <= 0,并且由于我们如何选择i,我们也知道d&gt; 0,所以他们的产品必须<= 0.换句话说,执行此交换永远不会增加总数。
但它是否让我们“更接近”反向排序匹配,从而终止?是的,因为重复此查找违规然后交换过程就像插入排序第一个i + 1元素一样。我们称之为y [i + 1] z的原始值。在交换y [i]和y [i + 1]之后,z值刚刚移回对中列表中的一个位置。如果我们重新运行查找第一个反向排序违规的过程,我们现在可能会发现它发生在i-1(即我们发现y [i-1]&lt; y [i]) - 在这种情况下,我们可以将y [i-1]与y [i]交换,将z值移回另一个地方。我们可以继续这样做,直到z到达y [1],或者我们发现第一个位置j使得y [j]&lt; y [j + 1]也具有y [j-1]&gt; = y [j + 1]的属性:后者意味着z值已到达其最终位置,因为我们知道y [k]&gt ; = y [j-1]表示所有k&lt; J-1。在任何情况下,z将在最多i次交换之后到达其最终位置,并且下一次违规查找运行将比原始i更晚找到位置 - 或者确定没有这样的位置(即,y值是现在反向排序)。
总而言之,在最多n ^ 2次违规然后交换操作之后,y值将按反向排序顺序,总数最多为原始总数。由于我们没有对给出的初始匹配做出任何假设,因此该结果适用于给定匹配的任何,因此我们已经证明反向排序匹配至少与所有匹配一样好。 (请注意,此证明的任何方面都不取决于非负数,因此这也适用于包含负数的数组。)
答案 2 :(得分:1)
这个定理名为Rearrangement inequality
制作证明:
最简单的证据是矛盾而不是@ j_random_hacker。
我们假设a按递增顺序排序。
由于每个单元格从不接触多个单元格,因此一个选项对应于排列s
,总和为f(s) = sum(a[i]*b[s(i)], i=1..n)
由于排列的数量是有限的,至少有一个最小值。
我们将s1
命名为此最低要求之一。所有的f(s1)<=f(s)
我们可以使用相同的总和s2
(例如f(s1)=f(s2)<=f(s)
)通过简单地按子序列b [s1(k)]降序排序来转换if a[i] = a[i+1] then b[s2(i+1)] >= b[s2(i)] (1)
。[[其中a[k] = a[k+1] = .. q[k+n]
所以f(s2)
也很小。让我们证明b(s2[k])
正在逐渐减少。
我们假设它存在i
,例如b[s2(i)] < b[s2(i+1)] (2)
因为(1), a[i]!= a[i+1]
所以a[i] < a[i+1] (3)
b[s2(i)] - b[s2(i+1)] < 0 (4)
而导致(2)
a[i] - a[i+1] < 0 (5)
因(3)
而导致a[i]*b[s2(i)]+a[i+1]*b[s2(i+1)]-(a[i]*b[s2(i+1)]+a[i+1]*b[s2(i)])
=a[i]*(b[s2(i)]-b[s2(i+1)])+a[i+1](b[s2(i+1)-b[s2(i)])
=(a[i]-a[i+1])(b[s2(i)]-b[s2(i+1)]) >=0 (because of product of two negative number because of (4) and (5)
so a[i]*b[s2(i)]+a[i+1]*b[s2(i+1)] - (a[i]*b[s2(i+1)]+a[i+1]*b[s2(i)])>0
so a[i]*b[s2(i)]+a[i+1]*b[s2(i+1)] > (a[i]*b[s2(i+1)]+a[i+1]*b[s2(i)]) (6)
s3
在这种情况下
i
让我们设置排列i+1
交换s3(n) = i+1 if n = i
i if n = i+1
s2(n)
a[i]*b[s2(i)]+a[i+1]*b[s2(i+1)] > (a[i]*b[s3(i)]+a[i+1]*b[s3(i+1)])
and
a[n]*b[s2(n)]=s[n]*b[s3(n)] for n!= i and n!=i+1
so f(s2)>f(s3)
和s3
s2
所以(2)
是比i
存在矛盾,因此假设b[s2(i)] < b[s2(i+1)] (2)
是错误的。
因此对于所有b[s2(i)] >= b[s2(i+1)] for all i
s2
都是假的
所以b[s2(k)]
所以<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#btn").click(function() {
var index = $("#txtIndex").val();
alert($('.ThreeWayCol .OddVal').eq(index).text());
});
});
</script>
</head>
<body>
<div class="ThreeWayCol OddsCol1">
<div class="OddVal ng-pristine ng-untouched ng-valid ng-binding ng-scope ng-not-empty" ng-repeat="sel in event._matchMarket.selections" ng-model="sel" ng-class="{'Sel': oddSelections[event.id].sels[sel.id]}" ng-click="selectOdd(event,event._matchMarket,sel)">3.37</div>
<div class="OddVal ng-pristine ng-untouched ng-valid ng-binding ng-scope ng-not-empty" ng-repeat="sel in event._matchMarket.selections" ng-model="sel" ng-class="{'Sel': oddSelections[event.id].sels[sel.id]}" ng-click="selectOdd(event,event._matchMarket,sel)">3.21</div>
<div class="OddVal ng-pristine ng-untouched ng-valid ng-binding ng-scope ng-not-empty" ng-repeat="sel in event._matchMarket.selections" ng-model="sel" ng-class="{'Sel': oddSelections[event.id].sels[sel.id]}" ng-click="selectOdd(event,event._matchMarket,sel)">2.07</div>
</div>
<hr />
<input type="text" placeholder="Enter index like: 0,1" id="txtIndex" />
<input type="button" value="Get Value" id="btn" />
</body>
</html>
如ProcessBuilder builder = new ProcessBuilder("/system/bin/sh");
builder.redirectErrorStream(true);
builder.directory(f);
p = builder.start();
stdOut = p.getInputStream();
stdIn = p.getOutputStream();
stdIn.write(("ls\n").getBytes());
stdIn.write(("echo EOF\n").getBytes());
while(true) {
int n;
try {
n = stdOut.read();
} catch (Exception | Error e) {
return;
}
if(n == -1) continue;
char c = (char) n;
if(c == '\n') {
if(line.equals("EOF")) break;
else {
if(write) outputable.onOutput(line);
outputMsg[0] = outputMsg[0] + "\n" + line;
line = "";
}
} else {
line = line + c;
}
}
递减顺序。因此,选择b的递减给出最佳结果。
通过类似证明,可以证明产品的最大总和是通过按升序排序a和b来给出的。