C(gcc),82个字节
n;f(x,y,a,b)int*x,*y;{for(n=0;a;)--b&&*x*2-*y>y[1]?++y:(++b,--a,n+=abs(*x++-*y));}
这将输入作为两个整数数组及其长度(因为C无法以其他方式获取其长度)。可以证明这是O(a+b)
因为循环中的a
或b
在循环的每个迭代中递减而导致的,它在a
到达时终止0
(并且b
不能在以下递减0
)。
在线尝试!
n; // define sum as an integer
f(x,y,a,b) // function taking two arrays and two lengths
int*x,*y; // use k&r style definitions to shorten function declaration
{
for(n=0; // initialize sum to 0
a;) // keep looping until x (the first array) runs out
// we'll decrement a/b every time we increment x/y respectively
--b&& // if y has ≥1 elements left (b>1, but decrements in-place)...
*x*2-*y>y[1]? // ... and x - y > [next y] - x, but rearranged for brevity...
++y: // increment y (we already decremented b earlier);
(++b, // otherwise, undo the in-place decrement of b from before...
--a,n+=abs(*x++-*y)) // decrement a instead, add |x-y| to n, and then increment x
;}
一些注意事项:
不用索引数组,而是增加指针并直接取消引用可以节省足够的字节数,以使其值得使用(*x
vs x[a]
和y[1]
vs y[b+1]
)。
该--b&&
条件检查b>1
以一种迂回的方式-如果b
是1
,它会评估为零。由于此操作已修改b
,因此我们无需在三进制的第一个分支中更改它(前进y
),但确实需要在第二个分支中更改它(前进x
)。
不需要return
声明,因为黑魔法。(我认为这是因为最后一个要求值的语句将始终是n+=...
表达式,它使用与用于返回值的寄存器相同的寄存器。)