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+=...
นิพจน์เสมอซึ่งจะใช้การลงทะเบียนเดียวกับที่ใช้สำหรับค่าส่งคืน)