จำนวนอักขระสูงสุดโดยใช้การกดแป้นพิมพ์ A, Ctrl + A, Ctrl + C และ Ctrl + V


106

นี่คือคำถามสัมภาษณ์จาก google ฉันไม่สามารถแก้มันได้ด้วยตัวเอง ใครช่วยส่องแสงบ้าง

เขียนโปรแกรมเพื่อพิมพ์ลำดับของการกดแป้นพิมพ์เพื่อให้ได้จำนวนอักขระสูงสุด 'A คุณได้รับอนุญาตให้ใช้เพียง 4 ปุ่ม: A, Ctrl+ A, Ctrl+ Cและ+Ctrl Vอนุญาตให้กดแป้นพิมพ์ N เท่านั้น Ctrlอักขระ + ทั้งหมดถือเป็นการกดแป้นพิมพ์หนึ่งครั้งดังนั้นCtrl+ จึงAเป็นการกดแป้นพิมพ์หนึ่งครั้ง

ตัวอย่างเช่นลำดับA, Ctrl+ A, Ctrl+ C, Ctrl+ Vสร้าง A สองตัวใน 4 การกดแป้นพิมพ์

  • Ctrl + A คือเลือกทั้งหมด
  • Ctrl + C คือ Copy
  • Ctrl + V คือ Paste

ฉันเรียนคณิตศาสตร์ สำหรับ N ใด ๆ โดยใช้ x ตัวเลขของ A หนึ่งCtrl+ Aหนึ่งCtrl+ Cและ y Ctrl+ Vเราสามารถสร้างจำนวนสูงสุด ((N-1) / 2) 2จำนวนของ A สำหรับ N> M บางตัวจะเป็นการดีกว่าที่จะใช้ลำดับCtrl+ A's, Ctrl+ CและCtrl+ Vจำนวนมากเนื่องจากจะเพิ่มจำนวน A เป็นสองเท่า

ลำดับCtrl+ A, Ctrl+ V, Ctrl+ Cจะไม่เขียนทับการเลือกที่มีอยู่ มันจะต่อท้ายการเลือกที่คัดลอกกับรายการที่เลือก


ในโปรแกรมแก้ไขข้อความจำนวนมาก^Aมักจะ "เลือกทั้งหมด" ^Cคือ "คัดลอก" ^Vคือ "วาง" ที่ให้ความคิด?
Nikolai Fetissov

ฉันหมายถึงจำนวน "A's ตัวอย่างเช่นสำหรับ N = 7 เราสามารถพิมพ์ 9 A โดยใช้การกดแป้นพิมพ์ A, A, A, CTRL + A, CTRL + C, CTRL + V, CTRL + V
munda

เอ่อนั่นคือ 7 การกดแป้นพิมพ์
John Dibling

@John "อักขระ CTRL + ทั้งหมดถือเป็นการกดแป้นพิมพ์เดียวดังนั้น CTRL + A จึงเป็นการกดแป้นพิมพ์เดียว"
fredley

1
ฉันได้ลบแท็ก C ++ ออกไปแล้วนี่เป็นคำถามอัลกอริทึมเท่านั้นและหวังว่าจะป้องกันไม่ให้ผู้ติดตาม c ++ ที่ไม่พึงพอใจในการลงคะแนน / โหวตเพื่อปิด
Matthieu M.

คำตอบ:


43

มีโซลูชันการเขียนโปรแกรมแบบไดนามิก เราเริ่มต้นด้วยการรู้ว่า 0 คีย์สามารถทำให้เราเป็น 0 A ได้ จากนั้นเราวนซ้ำไปiมาnโดยทำสองสิ่ง: กด A หนึ่งครั้งและกด select all + copy ตามด้วยjเวลาวาง(ตามจริงj-i-1ด้านล่างสังเกตเคล็ดลับที่นี่: เนื้อหายังอยู่ในคลิปบอร์ดดังนั้นเราจึงสามารถวางได้หลายครั้งโดยไม่ต้อง คัดลอกแต่ละครั้ง) เราต้องพิจารณาการวางติดต่อกันสูงสุด 4 รายการเท่านั้นเนื่องจากการเลือกคัดลอกวาง x 5 เทียบเท่ากับการเลือกคัดลอกวางเลือกคัดลอกวางและอย่างหลังจะดีกว่าเนื่องจากทำให้เรามีมากขึ้นในคลิปบอร์ด เมื่อเราไปถึงnเราก็ได้ผลลัพธ์ที่ต้องการ

ความซับซ้อนอาจดูเหมือนเป็น O (N) แต่เนื่องจากตัวเลขเพิ่มขึ้นในอัตราเลขชี้กำลังจริงๆแล้วจึงเป็น O (N 2 ) เนื่องจากความซับซ้อนของการคูณจำนวนมาก ด้านล่างนี้คือการใช้งาน Python ใช้เวลาประมาณ 0.5 วินาทีในการคำนวณสำหรับ N = 50,000

def max_chars(n):
  dp = [0] * (n+1)
  for i in xrange(n):
    dp[i+1] = max(dp[i+1], dp[i]+1) # press a
    for j in xrange(i+3, min(i+7, n+1)):
      dp[j] = max(dp[j], dp[i]*(j-i-1)) # press select all, copy, paste x (j-i-1)
  return dp[n]

ในรหัสjแสดงจำนวนปุ่มทั้งหมดที่กดหลังจากลำดับการกดแป้นใหม่ของเรา iในขั้นตอนนี้เรามีการกดแป้นพิมพ์แล้วและการกดแป้นใหม่ 2 ครั้งจะไปที่เลือกทั้งหมดและคัดลอก ดังนั้นเราจึงกดปุ่มj-i-2เวลาวาง ตั้งแต่การวางเพื่อเพิ่มลำดับที่มีอยู่ของdp[i] Aของเราต้องเพิ่มทำให้มัน1 j-i-1สิ่งนี้จะอธิบายj-i-1ในบรรทัดที่ 2 - สุดท้าย

นี่คือผลลัพธ์บางส่วน ( n=> จำนวน A):

  • 7 => 9
  • 8 => 12
  • 9 => 16
  • 10 => 20
  • 100 => 1391569403904
  • 1,000 => 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245 174442911064952028008546304
  • 50,000 => จำนวนมาก!

ฉันเห็นด้วยกับ @SB ว่าคุณควรระบุสมมติฐานของคุณเสมอ: ของฉันคือคุณไม่จำเป็นต้องวางสองครั้งเพื่อเพิ่มจำนวนอักขระเป็นสองเท่า สิ่งนี้ได้คำตอบสำหรับ 7 ดังนั้นเว้นแต่คำตอบของฉันจะผิดสมมติฐานก็ต้องถูก

ในสิ่งมหัศจรรย์คนกรณีที่ว่าทำไมฉันไม่ได้ตรวจสอบลำดับของรูปแบบCtrl+ A, Ctrl+ C, A, Ctrl+ V: ผลลัพธ์ที่ได้มักจะเป็นเช่นเดียวกับA, Ctrl+ A, Ctrl+ C, Ctrl+ Vซึ่งผมไม่พิจารณา


นั่นn => resultหรือresult => n? ทั้งสองวิธีฉันคิดว่ามันผิด เราสามารถพิมพ์ 9 เช่นเดียวกับ 7 การกดแป้นพิมพ์ ถ้ามันn => resultผิดแน่นอน. nจำนวนในฐานะที่คุณสามารถพิมพ์ไม่สามารถจะต่ำกว่า
IVlad

@IVlad มันn => result. คุณพูดว่า "เราพิมพ์ 9 ได้เหมือนกับ 7 การกดแป้นพิมพ์" ซึ่งเป็นสิ่งที่ฉันได้รับ อ่าน "เคล็ดลับ" ที่ฉันเพิ่งแก้ไข
moinudin

สิ่งนี้ดูดีมากยกเว้นว่าคำถามคือการหาจำนวนสูงสุดของ As สำหรับจำนวนการกดแป้นพิมพ์ที่กำหนดไม่ใช่จำนวนการกดแป้นพิมพ์ขั้นต่ำเพื่อให้ได้จำนวน As ที่กำหนด
Andrew Clark

1
@marcog - สัญกรณ์ของคุณอย่างน้อยก็สับสนและผิดพลาดมากที่สุด nคือการกดแป้นพิมพ์ที่คุณได้รับอนุญาตให้ใช้ คุณต้องคำนวณจำนวนเท่าที่คุณสามารถพิมพ์ด้วยการnกดแป้นพิมพ์ จึง7 => 7ไม่สมเหตุสมผล
IVlad

1
ดูถูกแล้ว +1 ทีนี้มาดูกันว่ามีใครสามารถลงไปถึงO(n)หรือแม้กระทั่งO(1):)
IVlad

41

โดยใช้วิธี marcog n=16ของผมพบว่ารูปแบบที่เริ่มต้นที่ เพื่อแสดงให้เห็นถึงสิ่งนี้ต่อไปนี้คือการกดแป้นพิมพ์n=24ได้สูงสุดn=29ฉันแทนที่ ^ A ด้วย S (เลือก), ^ C ด้วย C (สำเนา) และ ^ V ด้วย P (วาง) เพื่อให้อ่านง่าย:

24: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4     = 1024
25: A,A,A,A,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *   3   *   3   *   3   *   3    = 1296
26: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *   3   *   3   *   3    = 1728
27: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *    4    *   3   *   3    = 2304
28: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P
       4   *    4    *    4    *    4    *    4    *   3    = 3072
29: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4    *    4     = 4096

หลังจากเริ่มต้น 4 As รูปแบบที่ดีที่สุดคือการเลือกคัดลอกวางวางวางและทำซ้ำ สิ่งนี้จะคูณจำนวน As ด้วย 4 ทุก ๆ การกดแป้น 5 ครั้ง หากรูปแบบการกดแป้นพิมพ์ 5 แบบนี้ไม่สามารถใช้การกดแป้นพิมพ์ที่เหลืออยู่ได้ด้วยตัวเองจำนวน 4 รูปแบบการกดแป้นพิมพ์ (SCPP) จะใช้การกดแป้นพิมพ์ครั้งสุดท้ายแทนที่ SCPPP (หรือลบหนึ่งในน้ำพริก) ตามความจำเป็น รูปแบบการกดแป้นพิมพ์ทั้ง 4 แบบจะคูณจำนวนทั้งหมดด้วย 3 ครั้งต่อการกดแป้นพิมพ์ 4 ครั้ง

การใช้รูปแบบนี้เป็นรหัส Python บางส่วนที่ได้ผลลัพธ์เช่นเดียวกับโซลูชันของ marcog แต่เป็นการแก้ไข O (1) : นี่คือ O (log n) อันเนื่องมาจากการยกกำลังด้วย IVlad ที่ชี้ให้เห็น

def max_chars(n):
  if n <= 15:
    return (0, 1, 2, 3, 4, 5, 6, 9, 12, 16, 20, 27, 36, 48, 64, 81)[n]
  e3 = (4 - n) % 5
  e4 = n // 5 - e3
  return 4 * (4 ** e4) * (3 ** e3)

การคำนวณ e3: มีรูปแบบ SCPP อยู่ระหว่าง 0 ถึง 4 รูปแบบที่ส่วนท้ายของรายการการกดแป้นพิมพ์เนื่องจากn % 5 == 4มี 4 n % 5 == 1มี 3 n % 5 == 2มี 2 n % 5 == 3มี 1 และn % 5 == 4มี 0 ซึ่งสามารถทำให้ง่าย(4 - n) % 5ขึ้นได้

การคำนวณ e4: จำนวนรูปแบบทั้งหมดจะเพิ่มขึ้น 1 เมื่อใดก็ตามn % 5 == 0ที่ปรากฎว่าจำนวนนี้เพิ่มขึ้นถึงเท่าn / 5กัน โดยใช้การแบ่งชั้นเราจะได้รับจำนวนรวมของรูปแบบจำนวนรวมสำหรับเป็นจำนวนรวมของรูปแบบลบe4 e3สำหรับผู้ที่ไม่คุ้นเคยกับ Python //เป็นสัญกรณ์สำหรับการแบ่งชั้นในอนาคต


1
ทำได้ดีนี่! ผ่านการทดสอบแล้วและใช้งานได้n=3000จึงน่าจะใช่ (เสียดายวันนี้ฉันไม่โหวต: /)
moinudin

5
+1 ดีมาก nitpick ผู้เยาว์แม้ว่า: มันไม่ใช่การO(1)ยกกำลังที่ไม่สามารถทำได้ในเวลาคงที่ มันO(log n).
IVlad

2
จริงๆแล้วลำดับ 'SCPPP' จะคูณจำนวนอักขระด้วยสามตัวเท่านั้น: การวางครั้งแรกจะเขียนทับข้อความที่เลือกเท่านั้น
Nick Johnson

4
@ คลิกบรรทัดสุดท้ายในคำถาม: "ลำดับ Ctrl + A, Ctrl + V, Ctrl + C จะไม่เขียนทับการเลือกที่มีอยู่ แต่จะเพิ่มการเลือกที่คัดลอกต่อท้ายกับรายการที่เลือก"
moinudin

2
@marcog ใช่ฉันไม่ได้สังเกตเห็นสิ่งนั้น ฉันไม่รู้ว่ามีระบบปฏิบัติการใดบ้างที่ทำงานในลักษณะนั้น
Nick Johnson

15

นี่คือวิธีที่ฉันจะเข้าใกล้:

  • สมมติCtrlA= เลือกทั้งหมด
  • สมมติCtrlC= คัดลอกการเลือก
  • สมมติCtrlV= วางการเลือกที่คัดลอก

เมื่อได้รับข้อความบางส่วนจะต้องใช้การกดแป้นพิมพ์ 4 ครั้งในการทำซ้ำ:

  • CtrlA เพื่อเลือกทั้งหมด
  • CtrlC เพื่อคัดลอก
  • CtrlV เพื่อวาง (สิ่งนี้จะวางทับส่วนที่เลือก - ระบุข้อสันนิษฐานของคุณ)
  • CtrlV เพื่อวางอีกครั้งซึ่งเพิ่มเป็นสองเท่า

จากตรงนั้นคุณสามารถลองทำ 4 หรือ 5 A แล้ววนซ้ำด้านบน โปรดทราบว่าการทำเช่นctrl + a, c, v, vนี้จะทำให้ข้อความของคุณเติบโตขึ้นอย่างทวีคูณเมื่อคุณวนซ้ำ หากจังหวะที่เหลือ <4 ให้ทำCtrlV

กุญแจสำคัญในการสัมภาษณ์ @ places เช่น Google คือการระบุสมมติฐานของคุณและสื่อสารความคิดของคุณ พวกเขาอยากรู้ว่าคุณแก้ปัญหาอย่างไร


6
ประเด็นดีๆเกี่ยวกับเทคนิคการสัมภาษณ์การได้คำตอบที่ถูกต้องมีความสำคัญน้อยกว่าการสื่อสารอย่างชัดเจนในตอนท้าย!
fredley

2
คำตอบที่ดี. สำหรับอัลกอริทึมข้อผิดพลาด off-by-two แบบโลภ: ACVV-VVVVVคูณด้วย 7 ACVV-ACVV-Vคูณด้วย 6 ดังนั้น Ctrl-V สำหรับจังหวะที่เหลือ <6 แทนที่จะเป็น 4
Marcel Jackwerth

5

สามารถแก้ไขได้ใน O (1): เช่นเดียวกับตัวเลข Fibonacci มีสูตรในการคำนวณจำนวน As ที่พิมพ์ (และลำดับการกดแป้นพิมพ์):


1) เราสามารถทำให้คำอธิบายปัญหาง่ายขึ้น:

  • มีเพียง [A], [Ca] + [Cc], [Cv] และบัฟเฟอร์คัดลอกวางว่าง

เท่ากับ

  • มีเพียง [Ca] + [Cc], [Cv] และ "A" ใน copy-paste-buffer

2) เราสามารถอธิบายลำดับของการกดแป้นพิมพ์เป็นสตริงของ N อักขระจาก {'*', 'V', 'v'} โดยที่ 'v' หมายถึง [Cv] และ '*' หมายถึง [Ca] และ 'V 'หมายถึง [Cc] ตัวอย่าง: "vvvv * Vvvvv * Vvvv"

ความยาวของสตริงนั้นยังคงเท่ากับ N

ผลคูณของความยาวของคำ Vv ในสตริงนั้นเท่ากับจำนวนที่ผลิตเป็น


3) กำหนดความยาวคงที่ N สำหรับสตริงนั้นและจำนวนคำคงที่ K ผลลัพธ์จะมีค่าสูงสุดหากทุกคำมีความยาวเกือบเท่ากัน ความแตกต่างของคู่ที่ชาญฉลาดไม่เกิน± 1

ตอนนี้หมายเลข K ที่เหมาะสมที่สุดคืออะไรถ้าให้ N?


4) สมมติว่าเราต้องการเพิ่มจำนวนคำโดยต่อท้ายคำเดียวที่มีความยาว L จากนั้นเราต้องลด L + 1 เท่าของคำก่อนหน้าด้วย 'v' หนึ่งคำ ตัวอย่าง: "… * Vvvv * Vvvv * Vvvv * Vvvv" -> "… * Vvv * Vvv * Vvv * Vvv * Vvv"

ตอนนี้ความยาวคำที่เหมาะสมที่สุดคืออะไร L?

(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3

=> เหมาะสมที่สุดคือ L = 4


5) สมมติว่าเรามี N ขนาดใหญ่เพียงพอที่จะสร้างสตริงที่มีความยาว 4 หลายคำ แต่เหลือการกดแป้นเพียงไม่กี่ครั้ง เราจะใช้มันอย่างไร?

  • ถ้าเหลือ 5 หรือมากกว่า: ต่อท้ายคำอื่นที่มีความยาว 4

  • หากเหลือ 0: เสร็จสิ้น

  • ถ้าเหลือ 4 เราก็ทำได้เช่นกัน

    a) ต่อท้ายคำหนึ่งคำที่มีความยาว 3: 4 * 4 * 4 * 4 * 3 = 768

    b) หรือเพิ่ม 4 คำเป็นความยาว 5: 5 * 5 * 5 * 5 = 625 => ต่อท้ายคำเดียวจะดีกว่า

  • หากเหลือ 3: เราทำได้เช่นกัน

    a) หรือต่อท้ายคำหนึ่งคำที่มีความยาว 3 โดยปรับคำที่เหนือกว่าจากความยาว 4 เป็น 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144

    b) เพิ่ม 3 คำเพื่อความยาว 5: 5 * 5 * 5 = 125 => ต่อท้ายคำเดียวจะดีกว่า

  • หากเหลือ 2: เราทำได้เช่นกัน

    a) หรือต่อท้ายคำหนึ่งคำที่มีความยาว 3 โดยปรับคำสองคำก่อนหน้าจากความยาว 4 เป็น 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27

    b) เพิ่ม 2 คำเพื่อความยาว 5: 5 * 5 = 25 => ต่อท้ายคำเดียวจะดีกว่า

  • ถ้าเหลือ 1: เราทำได้เช่นกัน

    a) หรือต่อท้ายคำหนึ่งคำที่มีความยาว 3 โดยปรับคำสามคำก่อนหน้าจากความยาว 4 เป็น 3: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81

    b) เพิ่มหนึ่งคำเพื่อความยาว 5: 4 * 4 * 5 = 80 => ต่อท้ายคำเดียวจะดีกว่า


6) ทีนี้จะเกิดอะไรขึ้นถ้าเราไม่มี "N ขนาดใหญ่เพียงพอที่จะใช้กฎใน 5)? เราต้องยึดตามแผน b) ถ้าเป็นไปได้! สตริงสำหรับ N ขนาดเล็กคือ:

1: "v", 2: "vv", 3: "vvv", 4: "vvvv"

5: "vvvvv" → 5 (แผน b)

6: "vvvvvv" → 6 (แผนข)

7: "vvv * Vvv" → 9 (แผนก)

8: "vvvv * Vvv" → 12 (แผนก)

9: "vvvv * Vvvv" → 16

10: "vvvv * Vvvvv" → 20 (แผน b)

11: "vvv * Vvv * Vvv" → 29 (แผนก)

12: "vvvv * Vvv * Vvv" → 36 (แผนก)

13: "vvvv * Vvvv * Vvv" → 48 (แผนก)

14: "vvvv * Vvvv * Vvvv" → 64

15: "vvv * Vvv * Vvv * Vvv" → 81 (แผนก)


7) ตอนนี้ K ของคำที่เหมาะสมที่สุดในสตริงความยาว N คือเท่าใด?

ถ้า N <7 แล้ว K = 1 อื่นถ้า 6 <N <11 แล้ว K = 2; มิฉะนั้น: K = ceil ((N + 1) / 5)

เขียนด้วยภาษา C / C ++ / Java: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);

และถ้า N> 10 จำนวนคำที่มีความยาว 3 จะเป็น: K * 5-1-N ด้วยสิ่งนี้เราสามารถคำนวณจำนวนการพิมพ์เป็น:

ถ้า N> 10 จำนวน As จะเป็น: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}


ดูเหมือนจะถูกต้องใช้ได้กับตัวอย่างที่ให้ไว้โดยคำตอบของ @ Andrew แต่คำตอบของคุณก็คือ O (log N) แทนที่จะเป็น O (1) ใช่ไหม
rsenna

มันจะเป็น O (log N) ได้อย่างไร? สูตรทางคณิตศาสตร์ในการคำนวณจำนวน As จะคำนวณใน O (1) อัลกอริทึมในการพิมพ์การกดแป้นพิมพ์เป็น O (N) เนื่องจากมี O (N) การกดแป้นพิมพ์เพื่อพิมพ์หรือ O (1) iff ที่คุณอนุญาตให้พิมพ์เป็นนิพจน์ทั่วไป
comonad

การคำนวณเลขชี้กำลังคือ O (log N) เนื่องจากเลขชี้กำลังของ 4 เพิ่มขึ้นด้วย N ถ้าคุณพิมพ์จำนวนของ As ในรูปแบบตัวประกอบจะเป็น O (1)
Andrew Clark

อาโอเค. ไม่เคยคิดเกี่ยวกับการคำนวณตัวเลขด้วยเลขคณิตจำนวนเต็ม ฉันสนใจแค่สูตรหรือการประมาณค่าทศนิยมเท่านั้น แต่แน่นอนว่าจะเปรียบเทียบกับตัวเลขอื่นได้นั้นจะต้องมีการคำนวณอย่างแน่นอน
comonad

5

การใช้CtrlA+ CtrlC+ CtrlVจะได้เปรียบหลังจาก 4 'A's เท่านั้น

ดังนั้นฉันจะทำสิ่งนี้ (ในรหัสหลอกพื้นฐานเนื่องจากคุณไม่ได้ระบุภาษาที่เหมาะสม):

// We should not use the clipboard for the first four A's:
FOR I IN 1 TO MIN(N, 4)
    PRINT 'CLICK A'
NEXT
LET N1 = N - 4

// Generates the maximum number of pastes allowed:
FOR I IN 1 TO (N1 DIV 3) DO
    PRINT 'CTRL-A'
    PRINT 'CTRL-C'
    PRINT 'CTRL-V'
    LET N1 = N1 - 3
NEXT

// If we still have same keystrokes left, let's use them with simple CTRL-Vs
FOR I IN N1 TO N
    PRINT 'CTRL-V'
NEXT

แก้ไข

  1. กลับไปใช้ single CtrlVในลูปหลัก
  2. เพิ่มความคิดเห็นเพื่ออธิบายสิ่งที่ฉันพยายามทำที่นี่
  3. แก้ไขปัญหาเกี่ยวกับบล็อก "A สี่ตัวแรก"

@SB: ฉันกำลังใช้ CTRL-V สำหรับพาสสุดท้ายเท่านั้น ซึ่งเป็นสิ่งที่คุณพูดในคำตอบของคุณโดยวิธีการ ซึ่งหมายความว่าเราคิดคล้าย ๆ กันดังนั้นฉันไม่รู้ว่าทำไมคุณถึงวิจารณ์ฉัน - หรือบางทีฉันอาจพลาดอะไรไป?
rsenna

1
Google ไม่เคยระบุภาษาที่เหมาะสมที่จะเขียนในแบบที่คุณต้องการ
Spooks

3

การกดแป้นพิมพ์ต้องใช้เวลา 3 ครั้งเพื่อเพิ่มจำนวน As ของคุณเป็นสองเท่า มันสมเหตุสมผลแล้วที่จะเริ่มเพิ่มเป็นสองเท่าเมื่อคุณมี 3 ตัวขึ้นไปตามที่พิมพ์ไปแล้ว คุณต้องการให้การกดแป้นพิมพ์ครั้งสุดท้ายของคุณเป็นCtrlVไปเพื่อให้แน่ใจว่าคุณเพิ่มจำนวนที่มากที่สุดเป็นสองเท่าที่ทำได้ดังนั้นในการจัดแนวนั้นเราจะเติมการกดแป้นพิมพ์เพิ่มเติมหลังจากสามครั้งแรกเมื่อเริ่มต้นด้วย As

for (i = 3 + n%3; i>0 && n>0; n--, i--) {
    print("a");
}

for (; n>0; n = n-3) {
    print("ctrl-a");
    print("ctrl-c");
    print("ctrl-v");
}

แก้ไข:

นี่แย่มากฉันนำหน้าตัวเองโดยสมบูรณ์และไม่ได้พิจารณาน้ำพริกหลายรายการสำหรับแต่ละสำเนา

แก้ไข 2:

ฉันเชื่อว่าการวาง 3 ครั้งนั้นเหมาะสมที่สุดเมื่อคุณมีการกดแป้นพิมพ์มากพอที่จะทำได้ ในการกดแป้นพิมพ์ 5 ครั้งคุณจะต้องคูณจำนวน As ด้วย 4 ซึ่งดีกว่าการคูณด้วย 3 โดยใช้การกดแป้นพิมพ์ 4 ครั้งและดีกว่าการคูณด้วย 5 โดยใช้ 6 การกดแป้นพิมพ์ ฉันเปรียบเทียบสิ่งนี้โดยให้แต่ละวิธีมีจำนวนการกดแป้นพิมพ์เท่ากันเพียงพอดังนั้นแต่ละวิธีจึงจะจบรอบในเวลาเดียวกัน (60) ปล่อยให้ตัวคูณ 3 ทำ 15 รอบตัวคูณ 4 ทำ 12 รอบและ 5- ตัวคูณทำ 10 รอบ 3 ^ 15 = 14,348,907, 4 ^ 12 = 16,777,216 และ 5 ^ 10 = 9,765,625 หากมีการกดแป้นพิมพ์เหลือเพียง 4 ครั้งการทำตัวคูณ 3 จะดีกว่าการวางอีก 4 ครั้งโดยพื้นฐานแล้วตัวคูณ 4 ตัวก่อนหน้าจะกลายเป็นตัวคูณ 8 หากมีการกดแป้นพิมพ์เหลือเพียง 3 ครั้งตัวคูณ 2 จะดีที่สุด


2

สมมติว่าคุณมีอักขระ x ในคลิปบอร์ดและอักขระ x ในพื้นที่ข้อความ เรียกว่า "สถานะ x"

ลองกด "Paste" สองสามครั้ง (ฉันหมายถึงm-1เพื่อความสะดวก) จากนั้น "Select-all" และ "Copy"; หลังจากลำดับนี้เราจะไปที่ "state m * x" ที่นี่เราเสียการกดแป้น m + 1 ทั้งหมด ดังนั้นการเจริญเติบโต asymptotic เป็น (อย่างน้อย) บางอย่างเช่นf^nที่ f m^(1/(m+1))= ฉันเชื่อว่ามันเป็นการเติบโตแบบไม่แสดงอาการสูงสุดที่เป็นไปได้แม้ว่าฉันจะไม่สามารถพิสูจน์ได้ (ยัง)

พยายามค่าต่างๆของการแสดงม. m=4ที่สูงสุดสำหรับฉจะได้รับสำหรับ

ลองใช้อัลกอริทึมต่อไปนี้:

Press A a few times
Press Select-all
Press Copy
Repeat a few times:
    Press Paste
    Press Paste
    Press Paste
    Press Select-all
    Press Copy
While any keystrokes left:
    Press Paste

(ไม่แน่ใจว่าเป็นวิธีที่ดีที่สุด)

จำนวนครั้งในการกด A เริ่มต้นคือ 3: หากคุณกด 4 ครั้งคุณจะพลาดโอกาสที่จะเพิ่มจำนวน A เป็นสองเท่าในการกดอีก 3 ครั้ง

จำนวนครั้งในการกด Paste ที่จุดสิ้นสุดไม่เกิน 5: หากคุณมีการกดแป้นพิมพ์เหลือ 6 ครั้งขึ้นไปคุณสามารถใช้ Paste, Paste, Paste, Select-all, Copy, Paste แทน

ดังนั้นเราจึงได้รับอัลกอริทึมต่อไปนี้:

If (less than 6 keystrokes - special case)
    While (any keystrokes left)
        A
Else
    First 5 keystrokes: A, A, A, Select-all, Copy
    While (more than 5 keystrokes left)
        Paste, Paste, Paste, Select-all, Copy
    While (any keystrokes left)
        Paste

(ไม่แน่ใจว่าเป็นวิธีที่ดีที่สุด) จำนวนอักขระหลังจากดำเนินการแล้วจะเป็นดังนี้

3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5).

ค่าตัวอย่าง: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...


2

สิ่งต่อไปนี้ใช้การแก้ไขครั้งที่สองของ OP ซึ่งการวางไม่ได้แทนที่ข้อความที่มีอยู่

สังเกตบางสิ่ง:

  • ^ A และ ^ C ถือได้ว่าเป็นการดำเนินการเดียวที่ต้องใช้การกดแป้นพิมพ์สองครั้งเนื่องจากไม่สมเหตุสมผลที่จะทำทีละรายการ ในความเป็นจริงเราสามารถแทนที่อินสแตนซ์ทั้งหมดของ ^ A ^ C ด้วย ^ K ^ V โดยที่ ^ K เป็นการดำเนินการ "ตัด" แบบคีย์เดียว (ขอย่อว่า X) เราจะเห็นว่าการจัดการกับ ^ K นั้นดีกว่าสองต้นทุนมาก ^ A ^ C
  • สมมติว่า 'A' เริ่มต้นในคลิปบอร์ด ดังนั้น ^ V (ขอย่อว่า Y) เหนือกว่า A อย่างเคร่งครัดและเราสามารถละทิ้งสิ่งหลังได้จากการพิจารณาทั้งหมด (ในปัญหาจริงถ้าคลิปบอร์ดเริ่มว่างเปล่าสิ่งที่ตามมาเราจะแทนที่ Y ด้วย A แทน ^ V จนถึง X แรก)

ดังนั้นทุกลำดับการกดแป้นพิมพ์ที่เหมาะสมสามารถตีความได้ว่าเป็นกลุ่มของ Y ที่คั่นด้วย Xs ตัวอย่างเช่น YYYXYXYYXY แสดงโดย V จำนวนของ 'A ที่เกิดจากลำดับ s จากนั้น V (nXm) = V (n) * V (m) เนื่องจาก X แทนที่ทุก Y ใน m ด้วย V (n) 'A's

ปัญหาการคัดลอกวางจึงเป็นปัญหาที่ไม่เหมาะสมสำหรับปัญหาต่อไปนี้: "การใช้ตัวเลข m + 1 ซึ่งรวมเป็น Nm ทำให้ผลิตภัณฑ์ของมันขยายใหญ่สุด" ตัวอย่างเช่นเมื่อ N = 6 คำตอบคือ m = 1 และตัวเลข (2,3) 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (หรือ V (YYYXYY) = V (AAA ^ A ^ C ^ V)

เราสามารถสังเกตได้เล็กน้อย:

สำหรับค่าคงที่ของmตัวเลขที่ต้องเลือกคือceil( (N-m)/(m+1) )และfloor( (N-m)/(m+1) )(ในชุดค่าผสมใดก็ตามที่ทำให้ผลรวมออกมาโดยเฉพาะคุณจะต้องการ(N-m) % (m+1) ceilsและส่วนที่เหลือfloorมากขึ้น) เพราะนี่คือสำหรับ,a < b(a+1)*(b-1) >= a*b

น่าเสียดายที่ฉันไม่เห็นวิธีง่ายๆในการค้นหาค่าของmไฟล์. หากนี่เป็นการสัมภาษณ์ของฉันฉันจะเสนอสองวิธีแก้ไข ณ จุดนี้:

ตัวเลือกที่ 1 mห่วงมากกว่าเป็นไปได้ทั้งหมด n log nโซลูชันO ( )

รหัส C ++:

long long ipow(int a, int b)
{
  long long val=1;
  long long mul=a;

  while(b>0)
    {
      if(b%2)
    val *= mul;
      mul *= mul;
      b/=2;
    }
  return val;
}

long long trym(int N, int m)
{
  int floor = (N-m)/(m+1);
  int ceil = 1+floor;
  int numceils = (N-m)%(m+1);
  return ipow(floor, m+1-numceils) * ipow(ceil, numceils);
}

long long maxAs(int N)
{
  long long maxval=0;
  for(int m=0; m<N; m++)
    {
      maxval = std::max(maxval, trym(N,m));
    }
  return maxval;
}

ตัวเลือกที่ 2 อนุญาตให้mบรรลุค่าที่ไม่ใช่จำนวนเต็มและค้นหาค่าที่เหมาะสมที่สุดโดยการหาอนุพันธ์ของ[(N-m)/(m+1)]^mเทียบเคียงmและแก้ปัญหาสำหรับรากของมัน ไม่มีวิธีการแก้ปัญหาเชิงวิเคราะห์ แต่สามารถหารากได้โดยใช้วิธีของนิวตัน จากนั้นใช้พื้นและเพดานของรูทนั้นตามค่าmและเลือกแบบใดก็ได้ที่ดีที่สุด


0
public int dp(int n) 
{
    int arr[] = new int[n];
    for (int i = 0; i < n; i++)
        arr[i] = i + 1;
    for (int i = 2; i < n - 3; i++) 
    {
        int numchars = arr[i] * 2;
        int j = i + 3;
        arr[j] = Math.max(arr[j], numchars);
        while (j < n - 1) 
        {
            numchars = numchars + arr[i];
            arr[++j] = Math.max(arr[j], numchars);
        }
    }
    return arr[n - 1];
}

0

นี่คือแนวทางและวิธีแก้ปัญหาของฉันพร้อมรหัสด้านล่าง

แนวทาง:

มีการดำเนินการที่แตกต่างกันสามอย่างที่สามารถทำได้

  1. การกดแป้นพิมพ์ A - แสดงอักขระหนึ่งตัว 'A'
  2. การกดแป้นพิมพ์ (Ctrl-A) + (Ctrl-C) - ไม่ส่งผลอะไรเลย การกดแป้นพิมพ์ทั้งสองนี้สามารถรวมกันเป็นการดำเนินการเดียวได้เนื่องจากการกดแป้นพิมพ์แต่ละครั้งไม่สมเหตุสมผล นอกจากนี้การกดแป้นพิมพ์นี้จะตั้งค่าผลลัพธ์สำหรับการดำเนินการวางครั้งต่อไป
  3. การกดแป้นพิมพ์ (Ctrl-V) - ผลลัพธ์สำหรับการกดแป้นพิมพ์นี้ขึ้นอยู่กับการดำเนินการก่อนหน้า (วินาที) ดังนั้นเราจึงจำเป็นต้องคำนึงถึงสิ่งนั้นในรหัสของเรา

ตอนนี้ด้วยการดำเนินการที่แตกต่างกันสามรายการและผลลัพธ์ที่เกี่ยวข้องเราจึงต้องเรียกใช้การเรียงสับเปลี่ยนทั้งหมดของการดำเนินการเหล่านี้


สมมติฐาน:

ตอนนี้บางเวอร์ชันของปัญหานี้ระบุว่าลำดับของการกดแป้น Ctrl + A -> Ctrl + C -> Ctrl + V จะเขียนทับการเลือกที่ไฮไลต์ ในการแยกตัวประกอบของสมมติฐานนี้จำเป็นต้องเพิ่มโค้ดเพียงบรรทัดเดียวในโซลูชันด้านล่างโดยที่ตัวแปรที่พิมพ์ในกรณีที่ 2 ถูกตั้งค่าเป็น 0

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

สำหรับวิธีนี้

โค้ดด้านล่างนี้จะพิมพ์สองลำดับและลำดับสุดท้ายคือคำตอบที่ถูกต้องสำหรับ N. ที่กำหนดเช่น N = 11 ซึ่งจะเป็นลำดับที่ถูกต้อง

ด้วยสมมติฐาน

A, A, A, A, A, C, S, V, V, V, V,: 20:

โดยไม่มีข้อสันนิษฐาน

A, A, A, C, S, V, V, C, S, V, V,: 27:

ฉันได้ตัดสินใจที่จะคงสมมติฐานสำหรับการแก้ปัญหานี้


ตำนานการกดแป้นพิมพ์:

'ก' - ก

'C' - Ctrl + A

'S' - Ctrl + C

'V' - Ctrl + V


รหัส:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void maxAprinted(int count, int maxKeys, int op, int printed, int pOutput, int *maxPrinted, char *seqArray)
{
    if(count > maxKeys)
        return;

    if(count == maxKeys)
    {
        if((*maxPrinted) < printed)
        {
            //new sequence found which is an improvement over last sequence
            (*maxPrinted) = printed;

            printf("\n");
            int i;
            for(i=0; i<maxKeys; i++)
                printf(" %c,",seqArray[i]);
        }

        return;
    }

    switch(op)
    {
        case 1:
        //A keystroke
            printed++;

            seqArray[count] = 'A';
            count++;
            break;

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

            seqArray[count] = 'C';
            count++;
            seqArray[count] = 'S';
            count++;
            break;

        case 3:
        //Ctrl-V
            printed = printed + pOutput;

            seqArray[count] = 'V';
            count++;
            break;
    }

    maxAprinted(count, maxKeys, 1, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 2, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 3, printed, pOutput, maxPrinted, seqArray);    
}

int main()
{
    const int keyStrokes = 11;

    //this array stores the sequence of keystrokes
    char *sequence;
    sequence = (char*)malloc(sizeof(char)*(keyStrokes + 1));

    //stores the max count for As printed for a sqeuence
    //updated in the recursive call.
    int printedAs = 0;

    maxAprinted(0, keyStrokes,  1, 0, 0, &printedAs, sequence);

    printf(" :%d:", printedAs);

    return 0;
}    

0

การใช้เทคนิคที่กล่าวถึงในคำตอบข้างต้นทางคณิตศาสตร์สามารถอธิบายวิธีแก้ปัญหาได้ในสมการเดียวเช่น

4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5] โดยที่ [] เป็นตัวประกอบจำนวนเต็มมากที่สุด


0

มีการออกระหว่างการพิมพ์ของแม่ด้วยตนเองแล้วใช้เป็นCtrl+ A, Ctrl+ Cและนิวตันเมตรที่ 2 +Ctrl Vทางออกที่ดีที่สุดอยู่ตรงกลาง หากจังหวะคีย์สูงสุด = 10 วิธีที่ดีที่สุดคือพิมพ์ 5 A หรือ 4 A

ลองใช้รูปลักษณ์นี้ที่http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/และอาจเพิ่มประสิทธิภาพเล็กน้อยเพื่อหาผลลัพธ์รอบกลาง จุด.


0

นี่คือวิธีแก้ปัญหาของฉันด้วยการเขียนโปรแกรมแบบไดนามิกโดยไม่มีลูปซ้อนและยังพิมพ์อักขระจริงที่คุณต้องพิมพ์:

N = 52

count = [0] * N
res = [[]] * N
clipboard = [0] * N

def maybe_update(i, new_count, new_res, new_clipboard):
  if new_count > count[i] or (
      new_count == count[i] and new_clipboard > clipboard[i]):
    count[i] = new_count
    res[i] = new_res
    clipboard[i] = new_clipboard

for i in range(1, N):
  # First option: type 'A'.
  # Using list concatenation for 'res' to avoid O(n^2) string concatenation.
  maybe_update(i, count[i - 1] + 1, res[i - 1] + ['A'], clipboard[i - 1])

  # Second option: type 'CTRL+V'.
  maybe_update(i, count[i - 1] + clipboard[i - 1],  res[i - 1] + ['v'],
               clipboard[i - 1])

  # Third option: type 'CTRL+A, CTRL+C, CTRL+V'.
  # Assumption: CTRL+V always appends.
  if i >= 3:
    maybe_update(i, 2 * count[i - 3],  res[i - 3] + ['acv'], count[i - 3])

for i in range(N):
  print '%2d %7d %6d %-52s' % (i, count[i], clipboard[i], ''.join(res[i]))

นี่คือผลลัพธ์ ('a' หมายถึง 'CTRL + A' ฯลฯ )

 0       0      0                                                     
 1       1      0 A                                                   
 2       2      0 AA                                                  
 3       3      0 AAA                                                 
 4       4      0 AAAA                                                
 5       5      0 AAAAA                                               
 6       6      3 AAAacv                                              
 7       9      3 AAAacvv                                             
 8      12      3 AAAacvvv                                            
 9      15      3 AAAacvvvv                                           
10      18      9 AAAacvvacv                                          
11      27      9 AAAacvvacvv                                         
12      36      9 AAAacvvacvvv                                        
13      45      9 AAAacvvacvvvv                                       
14      54     27 AAAacvvacvvacv                                      
15      81     27 AAAacvvacvvacvv                                     
16     108     27 AAAacvvacvvacvvv                                    
17     135     27 AAAacvvacvvacvvvv                                   
18     162     81 AAAacvvacvvacvvacv                                  
19     243     81 AAAacvvacvvacvvacvv                                 
20     324     81 AAAacvvacvvacvvacvvv                                
21     405     81 AAAacvvacvvacvvacvvvv                               
22     486    243 AAAacvvacvvacvvacvvacv                              
23     729    243 AAAacvvacvvacvvacvvacvv                             
24     972    243 AAAacvvacvvacvvacvvacvvv                            
25    1215    243 AAAacvvacvvacvvacvvacvvvv                           
26    1458    729 AAAacvvacvvacvvacvvacvvacv                          
27    2187    729 AAAacvvacvvacvvacvvacvvacvv                         
28    2916    729 AAAacvvacvvacvvacvvacvvacvvv                        
29    3645    729 AAAacvvacvvacvvacvvacvvacvvvv                       
30    4374   2187 AAAacvvacvvacvvacvvacvvacvvacv                      
31    6561   2187 AAAacvvacvvacvvacvvacvvacvvacvv                     
32    8748   2187 AAAacvvacvvacvvacvvacvvacvvacvvv                    
33   10935   2187 AAAacvvacvvacvvacvvacvvacvvacvvvv                   
34   13122   6561 AAAacvvacvvacvvacvvacvvacvvacvvacv                  
35   19683   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvv                 
36   26244   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvv                
37   32805   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvvv               
38   39366  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacv              
39   59049  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvv             
40   78732  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvv            
41   98415  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvvv           
42  118098  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacv          
43  177147  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv         
44  236196  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv        
45  295245  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv       
46  354294 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv      
47  531441 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv     
48  708588 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv    
49  885735 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv   
50 1062882 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv  
51 1594323 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv 

0

หากอนุญาตให้ใช้ N key Strokes ผลลัพธ์คือ N-3

A's -> N-3

CTRL+ A-> การเลือกอักขระ N เหล่านั้น: +1

CTRL+ C-> คัดลอกอักขระ N เหล่านั้น: +1

Ctrl+ V-> การวางอักขระ N : +1 เช่น (เนื่องจากเราได้เลือกอักขระทั้งหมดโดยใช้CTRL+ A) การแทนที่อักขระ N-3 ที่มีอยู่เหล่านี้ด้วยอักขระ N-3 ที่คัดลอก (ซึ่งแทนที่อักขระเดียวกัน) และผลลัพธ์คือ N-3


ยินดีต้อนรับสู่ StackOverflow! เรียนรู้วิธีการเพิ่มการจัดรูปแบบเนื้อหาและอาจใช้สัญลักษณ์ลูกศรที่เกิดขึ้นจริง ซึ่งจะช่วยเพิ่มความสามารถในการอ่านคำตอบของคุณ!
M. Mimpen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.