ค้นหา axe สูงสุด + b


14

คุณจะได้รับรายชื่อของ (เป็นA, B ) และรายการของx คำนวณสูงสุดขวาน + Bสำหรับแต่ละx คุณสามารถสมมติa , bและxเป็นจำนวนเต็มไม่เป็นลบ

โปรแกรมหรือฟังก์ชั่นของคุณจะต้องทำงานตามที่คาดไว้ (ตามแบบแผนหากโค้ดของคุณเกี่ยวข้องกับสิ่งนั้นไม่ใช่อินพุต) เวลาO ( n log n )โดยที่nคือความยาวอินพุตทั้งหมด (ผลรวมหรือความยาวสูงสุดของความยาวของทั้งสองรายการ)

นี่คือรหัสกอล์ฟ รหัสที่สั้นที่สุดชนะ

ตัวอย่าง

[[2 8] [4 0] [2 1] [1 10] [3 3] [0 4]] [1 2 3 4 5]

เอาท์พุท:

[11 12 14 16 20]

คำอธิบาย:

11 = 1*1 + 10
12 = 1*2 + 10 = 2*2 + 8
14 = 2*3 + 8
16 = 2*4 + 8 = 4*4 + 0
20 = 4*5 + 0

หมายเหตุเกี่ยวกับความซับซ้อน:

หากคุณใช้ตัวบิวอินที่มีความซับซ้อนในระดับปานกลางและสามารถสุ่มเพื่อให้ได้ความซับซ้อนที่คาดหวังได้อย่างง่ายดายในทางทฤษฎีคุณสามารถสันนิษฐานได้ว่าภาษาของคุณเป็นเช่นนั้น

ซึ่งหมายความว่าหากโปรแกรมของคุณสามารถทดสอบได้ใน O ( n log n ) อาจมีข้อยกเว้นกรณี edge เนื่องจากการใช้ภาษาของคุณ แต่ไม่สามารถเห็นเหตุผลในรหัสของคุณเองเราจะบอกว่ามันเป็น O ( nบันทึกn )


ดูเหมือนว่าผลลัพธ์ที่คาดหวังควรเป็น [11 12 12 15 4] ???
Bob Jarvis - Reinstate Monica

@BobJarvis มันคือ ax + สูงสุดสำหรับ x ที่สอดคล้องกัน แต่สำหรับทั้งหมด (a, b) ในรายการ เปลี่ยนเพื่อทำให้ตัวอย่างเข้าใจผิดน้อยลง
jimmy23013

ความยาวอินพุตรวม = ความยาวของคู่ (a, b) บวกความยาวของอาร์เรย์ของ x?
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ใช่
jimmy23013

ทำไมมันชัดเจนว่ามันเป็นไปได้แม้ในO(n log(n))? คุณสามารถให้อัลกอริทึมอ้างอิงได้หรือไม่?
ข้อบกพร่อง

คำตอบ:


1

Pyth - 99 98 ไบต์

นี่เป็นการแปลโดยตรงของคำตอบ Python ของ @ KeithRandall มันสามารถเล่นกอล์ฟได้มากขึ้นอย่างแน่นอน ผมจะโพสต์คำอธิบายในเร็ว ๆ นี้

K[_1Z;FNShQAkdNW&>K2>+*k@K_3d+*@K_2@K_3eK=K<K_3)~K[c-eKd-k@K_2kd;FNSeQW&>K2>N@K2=K>K3)aY+*hKN@K1;Y

รับรายการที่คั่นด้วยจุลภาคสองรายการคั่นด้วยเครื่องหมายจุลภาคผ่าน stdin

ลองที่นี่

K                  K=
 [  )              A List containing
  _1               Negative 1
  Z                Zero
FN                 For N in
 ShQ               Sorted first input
Akd                Double assign k and d
 N                 To N
 W                 While
  &                Logical And
   >K2             K>2
   >               Greater Than
    +*k@K_3d       K[-3]*k+d
    +              Plus
     *@K_2@K_3     K[-2]*K[-3]
     eK            K[-1]
  =K               K=
   <K_3            K[:-3]
  )                Close while loop
 ~K                K+=
  [      )         List constructor
   c               Float division
    -              Minus
     eK            K[-1]
     d             d
    -              Minus
     k             k
     @K_2          K[-2]
   k               k
   d               d
 ;                 End list and for loop
FN                 For N in
  SeQ              Sorted second input
  W                While loop
   &               Logical and
    >K2            K[2:]
    >              Greater than
     N             N
     @K2           K[2]
   =K              K=
   >K3             K[3:]
  )                Close while loop
  aY               Y.append - Y is empty list
   +               Plus
    *hKN           (K+1)*N
    @K1            K[1]
;                  Close out everything
Y                  Print Y

10

Python ขนาด 214 ไบต์

S=sorted
def M(L,X):
 H=[-1,0];R={}
 for a,b in S(L):
    while H[2:]and a*H[-3]+b>H[-2]*H[-3]+H[-1]:H=H[:-3]
    H+=[1.*(H[-1]-b)/(a-H[-2]),a,b]
 for x in S(X):
    while H[2:]and x>H[2]:H=H[3:]
    R[x]=H[0]*x+H[1]
 return R

คำนวณฮัลล์นูนโดยวนซ้ำผ่านอินพุตa,bในaลำดับที่เพิ่มขึ้น ฮัลล์นูนจะถูกบันทึกHโดยใช้รูปแบบ-1,0,x1,a1,b1,x2,a2,b2,x2,...,xn,an,bnโดยที่xiพิกัด x ของจุดตัดของa{i-1},b{i-1}ai,biและ

จากนั้นฉันก็วนซ้ำอินพุต xที่เรียงตามลำดับจะตัดส่วนของนูนออกเพื่อให้ทันตามที่ฉันไป

ทุกอย่างเป็นเส้นตรงยกเว้นประเภทที่เป็น O (n lgn)

เรียกใช้เช่น:

>>> print M([[2,8],[4,0],[2,1],[1,10],[3,3],[0,4]], [1,2,3,4,5])
{1: 11, 2: 12, 3: 14, 4: 16, 5: 20}

@ user23013: แก้ไขแล้ว
Keith Randall

@KeithRandall ในขั้นตอนสุดท้ายคุณค้นหาHเป็นเส้นตรงxในแต่ละครั้งXใช่มั้ย เป็นไปไม่ได้หรือที่เราจะมีความซับซ้อนO (n ^ 2)เมื่อทั้งสองรายการมีความยาวเท่ากัน?
coredump

1
@coredump: ฉันค้นหาHแต่ละรายการเป็นเส้นตรงxแต่เนื่องจากฉันทำตามxลำดับฉันจำได้ว่าการค้นหาครั้งสุดท้ายหยุดที่ไหนและเริ่มการค้นหาถัดไปที่นั่น ดังนั้นwhileวงในสามารถเรียกใช้งานได้มากที่สุด O (n) เท่าของทุกคนx(แม้ว่ามันจะใช้เวลา O (n) สำหรับบุคคลใดก็ตามx)
Keith Randall

@coredump: โปรดทราบว่าสิ่งเดียวกันนี้เกิดขึ้นกับwhileลูปด้านในในforลูปแรก
Keith Randall

@ KeithRandall ฉันพลาดไปขอบคุณ ฉลาด!
coredump

6

Haskell, 204 271ไบต์

แก้ไข : golfed มากขึ้นโดยการอัพเดตตัวเรือนูนเป็นรายการ (แต่มีความซับซ้อนเช่นเดียวกับรุ่น ungolfed) โดยใช้ "split (x + 1)" แทน "splitLookup x" และลบการเรียกฟังก์ชันที่มีคุณสมบัติทั้งหมดเช่น Predule foldl

สิ่งนี้จะสร้างฟังก์ชั่นfซึ่งต้องการรายการคู่ (a, b) และรายการค่า x ฉันเดาว่ามันจะถูกพัดหายไปในระยะทางไกลโดยทุกสิ่งในตระกูล APL โดยใช้แนวคิดเดียวกัน

import Data.Map
r=fromListWith max
[]%v=[(0,v)]
i@((p,u):j)%v|p>v#u=j%v|0<1=(v#u,v):i
(a,b)#(c,d)=1+div(b-d)(c-a)
o i x=(\(a,b)->a*x+b)$snd$findMax$fst$split(x+1)$r$foldl'(%)[]$r$zip(fmap fst i)i
f=fmap.o

ตัวอย่างการใช้งาน:

[1 of 1] Compiling Main             ( linear-min.hs, interpreted )
Ok, modules loaded: Main.
λ> f [(2,8), (4,0), (2,1), (1,10), (3,3), (0,4)] [1..5]
[11,12,14,16,20]
λ> f [(1,20), (2,12), (3,11), (4,8)] [1..5]
[21,22,23,24,28]

มันทำงานได้ในเวลา O (n log n); ดูด้านล่างสำหรับการวิเคราะห์

แก้ไข:นี่เป็นรุ่นที่ไม่ได้รับการตอบโต้กับการวิเคราะห์ขนาดใหญ่และคำอธิบายวิธีการทำงานทั้งหมด:

import Prelude hiding (null, empty)
import Data.Map hiding (map, foldl)

-- Just for clarity:
type X = Int
type Y = Int
type Line = (Int,Int)
type Hull = Data.Map.Map X Line
slope (a,b) = a

{-- Take a list of pairs (a,b) representing lines a*x + b and sort by
    ascending slope, dropping any lines which are parallel to but below
    another line.

    This composition is O(n log n); n for traversing the input and
    the output, log n per item for dictionary inserts during construction.
    The input and output are both lists of length <= n.
--}
sort :: [Line] -> [Line]
sort = toList . fromListWith max

{-- For lines ax+b, a'x+b' with a < a', find the first value of x
    at which a'x + b' exceeds ax + b. --}
breakEven :: Line -> Line -> X
breakEven p@(a,b) q@(a',b') = if slope p < slope q
                                 then 1 + ((b - b') `div` (a' - a))
                                 else error "unexpected ordering"

{-- Update the convex hull with a line whose slope is greater
    than any other lines in the hull.  Drop line segments
    from the hull until the new line intersects the final segment.
    split is used to find the portion of the convex hull
    to the right of some x value; it has complexity O(log n).
    insert is also O(log n), so one invocation of this 
    function has an O(log n) cost.

    updateHull is recursive, but see analysis for hull to
    account for all updateHull calls during one execution.
--}
updateHull :: Line -> Hull -> Hull
updateHull line hull
    | null hull = singleton 0 line
    | slope line <= slope lastLine = error "Hull must be updated with lines of increasing slope"
    | hull == hull' = insert x line hull
    | otherwise = updateHull line hull''
    where (lastBkpt, lastLine) = findMax hull
          x = breakEven lastLine line
          hull' = fst $ x `split` hull
          hull'' = fst $ lastBkpt `split` hull

{-- Build the convex hull by adding lines one at a time,
    ordered by increasing slope.

    Each call to updateHull has an immediate cost of O(log n),
    and either adds or removes a segment from the hull. No
    segment is added more than once, so the total cost is
    O(n log n).
--}
hull :: [Line] -> Hull
hull = foldl (flip updateHull) empty . sort

{-- Find the highest line for the given x value by looking up the nearest
    (breakpoint, line) pair with breakpoint <= x.  This uses the neat
    function splitLookup which looks up a key k in a dictionary and returns
    a triple of:
        - The subdictionary with keys < k.
        - Just v if (k -> v) is in the dictionary, or Nothing otherwise
        - The subdictionary with keys > k.

    O(log n) for dictionary lookup.
--}
valueOn :: Hull -> X -> Y
valueOn boundary x = a*x + b
    where (a,b) = case splitLookup x boundary of
                    (_  , Just ab, _) -> ab
                    (lhs,       _, _) -> snd $ findMax lhs


{-- Solve the problem!

    O(n log n) since it maps an O(log n) function over a list of size O(n).
    Computation of the function to map is also O(n log n) due to the use
    of hull.
--}
solve :: [Line] -> [X] -> [Y]
solve lines = map (valueOn $ hull lines)

-- Test case from the original problem
test = [(2,8), (4,0), (2,1), (1,10), (3,3), (0,4)] :: [Line]
verify = solve test [1..5] == [11,12,14,16,20]

-- Test case from comment
test' = [(1,20),(2,12),(3,11),(4,8)] :: [Line]
verify' = solve test' [1..5] == [21,22,23,24,28]

2

เสียงกระเพื่อมสามัญ - 648 692

ด้วยการค้นหาไบนารีจริง

(use-package :optima)(defun z(l e)(labels((i(n m)(/(-(cadr m)(cadr n))(-(car n)(car m))))(m(l)(match l((list* a b c r)(if(<(i a b)(i b c))(list* a(m(list* b c r)))(m(list* a c r))))(_ l)))(f(x &aux(x(cdr x)))`(+(*,(car x)x),(cadr x)))(g(s e)(let*((q(- e s))(h(+ s(floor q 2)))d)(if(> q 1)(let((v(g s h))(d(pop l)))`(if(< x,(car d)),v,(g(1+ h)e)))(cond((not(car (setq d (pop l))))(f d))((> q 0)`(if(< x,(car d)),(f d),(f(pop l))))(t(f d)))))))(setq l(loop for(a b)on(m(remove-duplicates(#3=stable-sort(#3# l'< :key'cadr)'< :key'car):key 'car)) by #'cdr collect`(,(when b(i a b)),(car a),(cadr a))))`(mapcar(eval(lambda(x),(g 0(1-(length l)))))',e)))

(z '((2 8) (4 0) (2 1) (1 10) (3 3) (0 4)) '(1 2 3 4 5))
=> (11 12 14 16 20)

คำอธิบาย

ให้nเป็นความยาวของ (a, b) และkความยาวของคะแนน

  • จัดเรียง (a, b) โดย a จากนั้น b - O (n.ln (n))
  • ลบรายการที่ซ้ำกันa(เส้นคู่ขนาน) โดยรักษาเฉพาะเส้นคู่ขนานที่มีค่าสูงสุดbซึ่งมากกว่ารายการอื่นเสมอ (เราป้องกันการหารด้วยศูนย์เมื่อคำนวณจุดตัด) - O (n)
  • บีบอัดผลลัพธ์ - O (n) : เมื่อเรามีองค์ประกอบ consecutives (a0, b0) (a1, b1) (a2, b2) ในรายการที่เรียงลำดับเช่นที่จุดตัดของ (a0, b0) และ (a1, b1 ) ยิ่งใหญ่กว่าหนึ่ง (A1, B1) และ (A2, B2) แล้ว (A1, B1) สามารถได้อย่างปลอดภัยถูกละเว้น
  • สร้างรายการขององค์ประกอบ (xab) โดยที่xคือค่าขึ้นกับบรรทัดที่ax + bสูงสุดสำหรับx (รายการนี้ถูกจัดเรียงตามxขอบคุณขั้นตอนก่อนหน้า) - O (n)
  • รับรายการนั้นสร้างแลมบ์ดาที่ดำเนินการตรวจสอบช่วงเวลาสำหรับอินพุตและคำนวณค่าสูงสุด - ต้นไม้ไบนารีสร้างขึ้นในO (n) (ดู/programming//a/4309901/124319 ) การค้นหาแบบไบนารีที่จะนำไปใช้มีความซับซ้อนO (ln (n)) ด้วยอินพุตตัวอย่างเราสร้างฟังก์ชั่นต่อไปนี้ (ฟังก์ชั่นนั้นจะรวบรวมแล้ว):

    (LAMBDA (X)
      (IF (< X 4)
          (IF (< X 2)
              (IF (< X -6)
                  (+ (* 0 X) 4)
                  (+ (* 1 X) 10))
              (+ (* 2 X) 8))
          (+ (* 4 X) 0)))
    
  • ใช้ฟังก์ชันนั้นสำหรับองค์ประกอบทั้งหมด - O (k.ln (n))

ความซับซ้อนที่เกิดขึ้น: O ((n + k) (ln n))ในสถานการณ์ที่เลวร้ายที่สุด

เราไม่สามารถให้การประเมินความซับซ้อนสำหรับจำนวนอินพุตทั้งหมด (n + k) เนื่องจากkและnเป็นอิสระ ตัวอย่างเช่นถ้าnเป็น negligeable asymptotically WRT kแล้วซับซ้อนทั้งหมดจะเป็นO (k)

แต่ถ้าเราคิดว่าk = O (n)แล้วความซับซ้อนที่เกิดคือO (n.ln (n))

ตัวอย่างอื่น ๆ

(z '((1 10) (1 8) (1 7)) '(1 2 3 4 5))
=> (11 12 13 14 15)

และถ้าเราย้าย backquotes เพื่อดูว่ามีการคำนวณอะไรเราจะเห็นว่าเราไม่จำเป็นต้องทำการเปรียบเทียบใด ๆ (เมื่อรายการแรกถูกประมวลผลล่วงหน้า):

(MAPCAR (LAMBDA (X) (+ (* 1 X) 10)) '(1 2 3 4 5))

นี่เป็นอีกตัวอย่าง (นำมาจากความคิดเห็น):

(z '((1 20) (2 12) (3 11) (4 8)) '(1 2 3 4 5))
=> (21 22 23 24 28)

ฟังก์ชั่นที่มีประสิทธิภาพ:

(MAPCAR
  (LAMBDA (X)
    (IF (< X 4)
        (+ (* 1 X) 20)
        (+ (* 4 X) 8)))
  '(1 2 3 4 5))

O (n log n + k) แน่นอนใน O ((n + k) log (n + k))
jimmy23013

คุณใช้ล่ามคนไหน Ideone(LIST* A B C R) should be a lambda expressionให้
jimmy23013

@ user23013 ขออภัยฉันลืม(use-package :optima) (แก้ไข ... )
coredump

@ user23013 ฉันกลัวว่าฉันไม่สามารถทำให้ Ideone โหลดไลบรารีภายนอกได้ สำหรับการทดสอบโปรดดาวน์โหลด SBCL (หรืออาจจะอีก แต่ผมทดสอบเฉพาะใน SBCL) และติดตั้ง quicklisp จากนั้นคุณสามารถ (ql: quickload: optima) เพื่อดาวน์โหลดและติดตั้งoptimaเพื่อดาวน์โหลดและติดตั้ง สุดท้ายรหัสที่ฉันให้มาควรจะประเมินได้
coredump

มันกลับ(MAPCAR (EVAL (LAMBDA (X) ...ซึ่งประเมินเพื่อตอบ คุณทิ้งรหัสการแก้ปัญหาไว้ที่นั่นหรือไม่
jimmy23013
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.