พิมพ์เล็กที่สุดถัดไปจาก 2 ^ i * 5 ^ j โดยที่ i, j> = 0


10

ฉันถูกถามคำถามนี้ในระหว่างการคัดกรองโทรศัพท์ทางเทคนิคเมื่อเร็ว ๆ นี้และทำไม่ดี คำถามรวมอยู่ด้วยคำต่อคำด้านล่าง

สร้าง{2^i * 5^j | i,j >= 0}คอลเลกชันเรียง พิมพ์ค่าที่น้อยที่สุดถัดไปอย่างต่อเนื่อง

ตัวอย่าง: { 1, 2, 4, 5, 8, 10...}

"เล็กที่สุดถัดไป" ทำให้ฉันคิดว่ามีส่วนเกี่ยวข้องกับกอง - เล็ก ๆ น้อย ๆ แต่ฉันไม่รู้ว่าจะไปจากที่นั่นจริง ๆ และไม่มีการให้ความช่วยเหลือจากผู้สัมภาษณ์

ไม่มีใครมีคำแนะนำเกี่ยวกับวิธีการแก้ปัญหาดังกล่าวหรือไม่?


ฉันคิดว่าการสัมภาษณ์ต้องการให้คุณทำในความทรงจำคงที่ การใช้หน่วยความจำ O (n) ทำให้ค่อนข้างน่ารำคาญ หรืออย่างน้อยก็ใช้หน่วยความจำ O (logn) เพราะขนาดการเข้ารหัสสำหรับอินพุต n จะเป็น logn O (n) สำหรับโซลูชันหน่วยความจำเป็นโซลูชันหน่วยความจำแบบเอ็กซ์โพเนนเชียล
InformedA

คำตอบ:


14

ลอง reword ปัญหา: เอาท์พุททุกหมายเลขจาก 1 ถึงอินฟินิตี้โดยที่จำนวนนั้นไม่มีปัจจัยยกเว้น 2 และ 5

ด้านล่างนี้เป็นข้อมูลโค้ด C # แบบง่าย:

for (int i = 1;;++i)
{
    int num = i;
    while(num%2 == 0) num/=2;
    while(num%5 == 0) num/=5;
    if(num == 1) Console.WriteLine(i);
}

วิธีการของ Kilian / QuestionCนั้นมีประสิทธิภาพมากกว่า ตัวอย่าง C # ด้วยวิธีนี้:

var itms = new SortedSet<int>();
itms.Add(1);
while(true)
{
    int cur = itms.Min;
    itms.Remove(itms.Min);
    itms.Add(cur*2);
    itms.Add(cur*5);
    Console.WriteLine(cur);
}

SortedSet ป้องกันการแทรกซ้ำ

โดยพื้นฐานแล้วจะทำงานโดยตรวจสอบให้แน่ใจว่าหมายเลขถัดไปในลำดับนั้นitmsมา

พิสูจน์ให้เห็นว่าวิธีนี้คือการที่ถูกต้อง:
ขั้นตอนวิธีการอธิบายเพื่อให้แน่ใจว่าหลังจากที่สำหรับการส่งออกหมายเลขใด ๆ ในรูปแบบ2^i*5^jชุดตอนนี้มีและ2^(i+1)*5^j สมมติว่าตัวเลขในลำดับถัดไปคือ2^i*5^(j+1) 2^p*5^qต้องมีหมายเลขเอาต์พุตก่อนหน้านี้ของฟอร์ม2^(p-1)*5^(q)หรือ2^p*5^(q-1)(หรือทั้งสองอย่างถ้าทั้ง p หรือ q เท่ากับ 0) ถ้าไม่เช่นนั้น2^p*5^qไม่ใช่หมายเลขถัดไปเนื่องจาก2^(p-1)*5^(q)และ2^p*5^(q-1)ทั้งคู่มีขนาดเล็กลง

ตัวอย่างที่สองใช้O(n)หน่วยความจำ (โดยที่ n คือจำนวนตัวเลขที่มีเอาต์พุต) เนื่องจากO(i+j) = O(n)(เนื่องจาก i และ j น้อยกว่า n) และจะค้นหาตัวเลข n ในO(n log n)เวลา ตัวอย่างแรกค้นหาหมายเลขในเวลาเอ็กซ์โปเนนเชียล


1
สวัสดีคุณจะเห็นว่าทำไมฉันถึงสับสนในระหว่างการสัมภาษณ์ที่ฉันหวังว่า ในความเป็นจริงตัวอย่างที่ให้ไว้เป็นผลลัพธ์จากชุดที่อธิบายไว้ในคำถาม 1 = 2^0*5^0, 2 = 2^1*5^0, 4 = 2^2*5^0, 5 = 2^0*5^1, 8 = 2^3*5^0, 10 = 2^1*5^1.
Justin Skiles

เหล่านั้นซ้ำแล้วซ้ำเล่า.Remove()และ.Add()จะก่อให้เกิดพฤติกรรมที่ไม่ดีจากตัวเก็บขยะหรือจะคิดออก?
Snowbody

1
@Snowbody: คำถามของ op เป็นคำถามเกี่ยวกับอัลกอริทึมดังนั้นมันจึงค่อนข้างไม่เกี่ยวข้องเลย ไม่ต้องสนใจข้อกังวลแรกของคุณที่ควรจัดการกับจำนวนเต็มที่มีขนาดใหญ่มากเนื่องจากนี่จะกลายเป็นปัญหาเร็วกว่าค่าใช้จ่ายในการรวบรวมขยะ
Brian

8

นี่เป็นคำถามสัมภาษณ์ทั่วไปที่มีประโยชน์ในการทราบคำตอบ นี่คือรายการที่เกี่ยวข้องในแผ่นเปลส่วนตัวของฉัน:

  • เพื่อสร้างตัวเลขของแบบฟอร์ม 3 a 5 b 7 c ตามลำดับเริ่มต้นด้วย 1 เรียงลำดับผู้สืบทอดที่เป็นไปได้ทั้งสาม (3, 5, 7) ไว้ในโครงสร้างเสริมจากนั้นเพิ่มจำนวนที่น้อยที่สุดลงในรายการของคุณ

คุณต้องมีวิธีการสองขั้นตอนพร้อมกับบัฟเฟอร์ที่เรียงลำดับเพิ่มเติมเพื่อแก้ปัญหานี้ได้อย่างมีประสิทธิภาพ (คำอธิบายที่ยาวกว่านี้อยู่ในการสัมภาษณ์แคร็กการเข้ารหัสโดย Gayle McDowell


3

นี่คือคำตอบที่ทำงานด้วยหน่วยความจำคงที่โดยมีค่าใช้จ่ายของ CPU นี่ไม่ใช่คำตอบที่ดีในบริบทของคำถามเดิม (เช่นคำตอบในระหว่างการสัมภาษณ์) แต่ถ้าการสัมภาษณ์ยาว 24 ชั่วโมงมันก็ไม่เลว ;)

แนวคิดก็คือถ้าฉันมี n ซึ่งเป็นคำตอบที่ถูกต้องดังนั้นลำดับต่อไปจะเท่ากับ n คูณกำลังสอง, หารด้วยพลัง 5 หรือมิฉะนั้น n คูณกำลัง 5, หารด้วย a พลังของสอง ให้มันแบ่งเท่า ๆ กัน (... หรือตัวหารสามารถเป็น 1;) ซึ่งในกรณีนี้คุณแค่คูณด้วย 2 หรือ 5)

ตัวอย่างเช่นหากต้องการจาก 625 ถึง 640 ให้คูณด้วย 5 ** 4/2 ** 7. หรือโดยทั่วไปแล้วคูณด้วยค่าบางค่าของ2 ** m * 5 ** nบาง m, n โดยที่หนึ่งเป็นบวกและหนึ่งเป็นลบหรือศูนย์และ ตัวคูณหารจำนวนอย่างเท่าเทียมกัน

ตอนนี้ส่วนที่ยุ่งยากคือการหาตัวคูณ แต่เรารู้ว่า a) ตัวหารต้องหารจำนวนอย่างเท่าเทียมกัน b) ตัวคูณต้องมากกว่าหนึ่ง (ตัวเลขเพิ่มขึ้นเรื่อย ๆ ) และ c) ถ้าเราเลือกตัวคูณต่ำสุดที่มากกว่า 1 (เช่น 1 <f อื่น ๆ ทั้งหมดของ f ) จากนั้นรับประกันได้ว่าจะเป็นขั้นตอนต่อไปของเรา ขั้นตอนหลังจากนั้นจะเป็นขั้นตอนที่ต่ำที่สุด

ส่วนที่น่ารังเกียจคือการหาค่าของ m, n มีเพียงความเป็นไปได้ในการบันทึก (n) เพราะมีเพียง 2 หรือ 5 เท่านั้นที่จะยอมแพ้ แต่ฉันต้องเพิ่มปัจจัยที่ -1 ถึง +1 เป็นวิธีเลอะเทอะเพื่อจัดการกับ roundoff ดังนั้นเราต้องทำซ้ำผ่าน O (log (n)) แต่ละขั้นตอน ดังนั้นจึงเป็น O (n log (n)) โดยรวม

ข่าวดีก็คือเพราะมันต้องใช้ค่าและหาค่าต่อไปคุณสามารถเริ่มต้นได้ทุกที่ในลำดับ ดังนั้นหากคุณต้องการหนึ่งถัดไปหลังจาก 1 พันล้านมันก็สามารถหาได้โดยวนซ้ำ 2/5 หรือ 5/2 และเลือกตัวคูณที่เล็กที่สุดที่มากกว่า 1

(งูใหญ่)

MAX = 30
F = - math.log(2) / math.log(5)

def val(i, j):
    return 2 ** i * 5 ** j

def best(i, j):
    f = 100
    m = 0
    n = 0
    max_i = (int)(math.log(val(i, j)) / math.log(2) + 1) if i + j else 1
    #print((val(i, j), max_i, x))
    for mm in range(-i, max_i + 1):
        for rr in {-1, 0, 1}:
            nn = (int)(mm * F + rr)
            if nn < -j: continue
            ff = val(mm, nn)
            #print('  ' + str((ff, mm, nn, rr)))
            if ff > 1 and ff < f:
                f = ff
                m = mm
                n = nn
    return m, n

def detSeq():

    i = 0
    j = 0
    got = [val(i, j)]

    while len(got) < MAX:
        m, n = best(i, j)

        i += m
        j += n
        got.append(val(i, j))

        #print('* ' + str((val(i, j), m, n)))
        #print('- ' + str((v, i, j)))

    return got

ฉันตรวจสอบความถูกต้อง 10,000 หมายเลขแรกที่สิ่งนี้สร้างขึ้นจาก 10,000 รายการแรกที่สร้างขึ้นโดยโซลูชันรายการที่เรียงลำดับและทำงานได้อย่างน้อยที่สุด

BTW หนึ่งถัดไปหลังจากล้านล้านดูเหมือนจะ 1,024,000,000,000

...

ฮึ่ม ฉันสามารถรับประสิทธิภาพ O (n) - O (1) ต่อค่า (!) - และการใช้หน่วยความจำ O (log n) โดยbest()ถือเป็นตารางการค้นหาที่ฉันขยายเพิ่มขึ้นทีละส่วน ตอนนี้มันช่วยประหยัดหน่วยความจำด้วยการวนซ้ำทุกครั้ง แต่มันทำการคำนวณซ้ำซ้อนมากมาย โดยการเก็บค่ากลางเหล่านั้น - และรายการค่าต่ำสุด - ฉันสามารถหลีกเลี่ยงการทำงานซ้ำ ๆ และเพิ่มความเร็วได้มาก อย่างไรก็ตามรายการของค่ากลางจะเพิ่มขึ้นด้วย n ดังนั้นหน่วยความจำ O (log n)


คำตอบที่ดี ฉันมีความคิดคล้าย ๆ กันซึ่งฉันไม่ได้เข้ารหัส ในความคิดนี้ฉันจะติดตามตัวที่ 2 และ 5 สิ่งนี้จะติดตามจำนวนสูงสุดnและmมันถูกใช้จนหมดจำนวนตามลำดับจนถึงตอนนี้ ในการทำซ้ำแต่ละครั้งnหรือmอาจจะหรืออาจจะไม่ขึ้นไป เราสร้างหมายเลขใหม่2^(max_n+1)*5^(max_m+1)จากนั้นลดจำนวนนี้ด้วยวิธีเรียกซ้ำโดยละเอียดแต่ละการโทรจะลดเลขชี้กำลัง 1 จนกว่าเราจะได้รับจำนวนขั้นต่ำที่มากกว่าจำนวนปัจจุบัน เราอัพเดตmax_n, max_mตามความจำเป็น mem คงที่นี้ สามารถเป็นO(log^2(n))mem ได้หากมีการใช้แคช DP ในการลดการโทร
InformedA

น่าสนใจ การเพิ่มประสิทธิภาพที่นี่คือมันไม่จำเป็นต้องพิจารณาคู่ทั้งหมดของ m & n เพราะเรารู้ว่า m ถูกต้อง n จะสร้างตัวคูณที่ใกล้เคียงที่สุดถึง 1 ดังนั้นฉันจะต้องประเมิน m = -i ถึง max_i เท่านั้นและฉัน สามารถคำนวณ n, ทิ้งขยะบางส่วนสำหรับ roundoff (ฉันเลอะเทอะและทำซ้ำ -1 ถึง 1 แต่มันคิดมากกว่า;))
Rob

อย่างไรก็ตามฉันคิดเหมือนคุณ ... ลำดับจะกำหนดขึ้น ... มันเหมือนกับสามเหลี่ยมขนาดใหญ่ของปาสคาล i + 1 ในทิศทางเดียวและ j + 1 ในอีกด้านหนึ่ง ดังนั้นลำดับควรกำหนดทางคณิตศาสตร์ สำหรับโหนดใด ๆ ในรูปสามเหลี่ยมจะมีโหนดถัดไปที่กำหนดทางคณิตศาสตร์เสมอ
Rob

1
อาจมีสูตรสำหรับรายการถัดไปเราอาจไม่จำเป็นต้องทำการค้นหา ฉันไม่รู้แน่
InformedA

เมื่อฉันคิดถึงมันรูปแบบพีชคณิตของอันถัดไปอาจไม่มีอยู่ (ไม่ใช่ปัญหาที่กำหนดขึ้นมาทั้งหมดมีรูปแบบพีชคณิตสำหรับการแก้ปัญหา) นอกจากนี้เมื่อมีจำนวนเฉพาะมากกว่า 2 และ 5 สูตรอาจหายาก ต้องการสูตรนี้จริงๆ หากมีใครรู้สูตรฉันอาจจะอ่านเกี่ยวกับเรื่องนี้เล็กน้อยฟังดูน่าสนใจ
แจ้งเมื่อ

2

ไบรอันพูดถูก - คำตอบอื่นของฉันซับซ้อนเกินไป นี่เป็นวิธีที่ง่ายและรวดเร็วกว่าในการทำ

ลองนึกภาพ Quadrant I ของระนาบ Euclidean ที่ จำกัด เฉพาะจำนวนเต็ม เรียกแกน i แกนหนึ่งและอีกแกนหนึ่งเป็นแกน j

เห็นได้ชัดว่าจุดที่อยู่ใกล้กับจุดกำเนิดจะถูกเลือกก่อนที่จะห่างจากจุดกำเนิด โปรดทราบว่าพื้นที่ที่ใช้งานจะย้ายออกจากแกน i ก่อนที่จะย้ายออกจากแกน j

เมื่อมีการใช้งานจุดก็จะไม่ถูกใช้อีกครั้ง และจุดหนึ่งสามารถใช้ได้ก็ต่อเมื่อจุดที่อยู่ด้านล่างหรือด้านซ้ายของจุดนั้นถูกใช้ไปแล้วเท่านั้น

เมื่อรวมเข้าด้วยกันคุณสามารถจินตนาการว่า "ชายแดน" หรือ "นำหน้า" ที่เริ่มต้นรอบจุดกำเนิดและกระจายไปทางขวาและกระจายไปตามแกน i ที่ไกลกว่าบนแกน j

ในความเป็นจริงเราสามารถหาข้อมูลได้มากกว่านี้: จะมีจุดหนึ่งบนขอบ / ขอบสำหรับค่า i ใด ๆ ที่กำหนด (คุณต้องเพิ่มค่า i มากกว่า 2 ครั้งเพื่อให้เท่ากับการเพิ่มขึ้นของ j) ดังนั้นเราสามารถแทนค่า frontier เป็นรายการที่มีองค์ประกอบหนึ่งองค์ประกอบสำหรับแต่ละค่าพิกัดฉันต่างกันเฉพาะค่าพิกัด j และค่าฟังก์ชัน

แต่ละรอบเราเลือกองค์ประกอบขั้นต่ำที่ขอบนำแล้วเลื่อนไปในทิศทาง j หนึ่งครั้ง หากเรากำลังเพิ่มองค์ประกอบสุดท้ายเราจะเพิ่มองค์ประกอบสุดท้ายใหม่อีกครั้งด้วยค่า i ที่เพิ่มขึ้นและค่า j เป็น 0

using System;
using System.Collections.Generic;
using System.Text;

namespace TwosFives
{
    class LatticePoint : IComparable<LatticePoint>
    {
      public int i;
      public int j;
      public double value;
      public LatticePoint(int ii, int jj, double vvalue)
      {
          i = ii;
          j = jj;
          value = vvalue;
      }
      public int CompareTo(LatticePoint rhs)
      {
          return value.CompareTo(rhs.value);
      }
    }


    class Program
    {
        static void Main(string[] args)
        {
            LatticePoint startPoint = new LatticePoint(0, 0, 1);

            var leadingEdge = new List<LatticePoint> { startPoint } ;

            while (true)
            {
                LatticePoint min = leadingEdge.Min();
                Console.WriteLine(min.value);
                if (min.j + 1 == leadingEdge.Count)
                {
                    leadingEdge.Add(new LatticePoint(0, min.j + 1, min.value * 2));
                }
                min.i++;
                min.value *= 5;
            }
        }
    }
}

Space: O (n) ในจำนวนองค์ประกอบที่พิมพ์จนถึงปัจจุบัน

ความเร็ว: เม็ดมีด O (1) แต่เม็ดมีดไม่ได้ทำทุกครั้ง (บางครั้งนานเมื่อList<>ต้องเติบโต แต่ยังคง O (1) ตัดจำหน่าย) sink ครั้งใหญ่คือการค้นหาค่าต่ำสุด O (n) ในจำนวนองค์ประกอบที่พิมพ์จนถึงปัจจุบัน


1
อัลกอริทึมนี้ใช้อะไร? ทำไมมันทำงาน ส่วนสำคัญของคำถามที่ถูกถามคือDoes anyone have advice on how to solve such a problem?การพยายามทำความเข้าใจปัญหาพื้นฐาน การถ่ายโอนข้อมูลรหัสไม่ตอบคำถามนั้นดี

จุดดีฉันอธิบายความคิดของฉัน
Snowbody

+1 แม้ว่าสิ่งนี้จะเทียบเท่ากับตัวอย่างที่สองของฉันการใช้ขอบที่ไม่เปลี่ยนรูปของคุณทำให้ชัดเจนยิ่งขึ้นว่าการนับจำนวนขอบเพิ่มขึ้นอย่างไร
Brian

สิ่งนี้ช้ากว่าข้อมูลโค้ดที่ปรับปรุงใหม่ของ Brian แต่พฤติกรรมการใช้หน่วยความจำควรดีกว่ามากเนื่องจากไม่ได้ลบและเพิ่มองค์ประกอบอย่างต่อเนื่อง (เว้นแต่ CLR หรือ SortedSet <> มีวิธีการใช้องค์ประกอบที่ฉันไม่รู้)
Snowbody

1

วิธีการแก้ปัญหาแบบ set-based อาจเป็นสิ่งที่ผู้สัมภาษณ์ของคุณกำลังมองหา แต่มันมีผลลัพธ์ที่น่าเสียดายที่มีO(n)หน่วยความจำและO(n lg n)เวลาทั้งหมดสำหรับการเรียงลำดับnองค์ประกอบ

คณิตศาสตร์เล็กน้อยช่วยให้เราหาวิธีแก้ปัญหาO(1)พื้นที่และO(n sqrt(n))เวลา 2^i * 5^j = 2^(i + j lg 5)ขอให้สังเกตว่า หาคนแรกnองค์ประกอบของการ{i,j > 0 | 2^(i + j lg 5)}ลดการหาแรกnองค์ประกอบของ{i,j > 0 | i + j lg 5}เพราะฟังก์ชั่น(x -> 2^x)เป็นอย่างเคร่งครัด monotonically เพิ่มขึ้นดังนั้นวิธีเดียวสำหรับบางคนa,bที่คือถ้า2^a < 2^ba < b

ตอนนี้เราแค่ต้องการอัลกอริทึมเพื่อค้นหาลำดับของi + j lg 5ซึ่งi,jเป็นจำนวนธรรมชาติ กล่าวอีกนัยหนึ่งตามมูลค่าปัจจุบันของเราi, jสิ่งที่ลดการย้ายครั้งต่อไป (กล่าวคือให้จำนวนถัดไปในลำดับ) คือการเพิ่มขึ้นของค่าใดค่าหนึ่ง (พูดj += 1) พร้อมกับการลดลงของอีกค่าหนึ่ง ( i -= 2) สิ่งเดียวที่ จำกัด เราคือi,j > 0เราคือว่า

มีเพียงสองกรณีที่ต้องพิจารณา - iเพิ่มหรือjเพิ่ม หนึ่งในนั้นต้องเพิ่มขึ้นเนื่องจากลำดับของเราเพิ่มขึ้นและทั้งคู่จะไม่เพิ่มขึ้นเพราะมิฉะนั้นเราจะข้ามคำที่เรามีเพียงหนึ่งi,jเพิ่ม ดังนั้นหนึ่งเพิ่มและอื่น ๆ ยังคงเหมือนเดิมหรือลดลง แสดงใน C ++ 11 ขั้นตอนวิธีการทั้งหมดและเปรียบเทียบเพื่อแก้ปัญหาชุดที่มีอยู่ที่นี่

สิ่งนี้ประสบความสำเร็จในหน่วยความจำคงที่เนื่องจากมีเพียงจำนวนคงที่ของวัตถุที่จัดสรรในวิธีการนอกเหนือจากอาร์เรย์ออก (ดูลิงค์) วิธีการที่ประสบความสำเร็จในเวลาลอการิทึมทุกย้ำตั้งแต่ใดก็ตาม(i,j)ก็ลัดเลาะสำหรับคู่ที่ดีที่สุด(a, b)เช่นที่เป็นเพิ่มขึ้นน้อยที่สุดในค่าของ(i + a, j + b) i + j lg 5การสำรวจเส้นทางนี้คือO(i + j):

Attempt to increase i:
++i
current difference in value CD = 1
while (j > 0)
  --j
  mark difference in value for
     current (i,j) as CD -= lg 5
  while (CD < 0) // Have to increase the sequence
    ++i          // This while will end in three loops at most.
    CD += 1
find minimum among each marked difference ((i,j) -> CD)

Attempt to increase j:
++j
current difference in value CD = lg 5
while (j > 0)
  --i
  mark difference in value for
     current (i,j) as CD -= 1
  while (CD < 0) // have to increase the sequence
    ++j          // This while will end in one loop at most.
    CD += lg 5
find minimum among each marked difference ((i,j) -> CD)

ทุกความพยายามในการทำซ้ำเพื่ออัปเดตiแล้วjและไปด้วยการปรับปรุงเล็ก ๆ สอง

ตั้งแต่iและjเป็นอย่างมากO(sqrt(n))เรามีO(n sqrt(n))เวลาทั้งหมด iและjเติบโตในอัตราของสแควร์nตั้งแต่สำหรับค่าสูงสุดใด ๆimaxและjmaxมีO(i j)คู่ที่ไม่ซ้ำกันซึ่งจะทำให้ลำดับของเราถ้าลำดับของเราเป็นnข้อตกลงและiและjเติบโตในปัจจัยคงที่ของกันและกัน (เพราะเลขชี้กำลังประกอบด้วยเส้นตรง การรวมกันสำหรับทั้งสอง) เรารู้ว่าiและมีjO(sqrt(n))

ไม่ต้องกังวลเกี่ยวกับข้อผิดพลาดของ floating point มากนัก - เนื่องจากคำศัพท์นั้นเพิ่มขึ้นอย่างมากเราจึงต้องจัดการกับ overflow ก่อนที่จะเกิดข้อผิดพลาด flop ที่จับกับเราหลายขนาด ฉันจะเพิ่มการสนทนาเพิ่มเติมหากมีเวลา


คำตอบที่ดีฉันคิดว่านอกจากนี้ยังมีรูปแบบในการเพิ่มลำดับสำหรับช่วงเวลาใด ๆ
InformedA

@ randomA ขอบคุณ หลังจากความคิดเพิ่มเติมฉันถึงข้อสรุปว่าขณะนี้มันหมายถึงอัลกอริทึมของฉันไม่เร็วอย่างที่ฉันคิด หากมีวิธีที่เร็วกว่าในการประเมิน "พยายามเพิ่ม i / j" ฉันคิดว่านั่นเป็นกุญแจสำคัญในการรับเวลาลอการิทึม
VF1

ฉันคิดในเรื่องนั้น: เรารู้ว่าการเพิ่มจำนวนเราต้องเพิ่มจำนวนเฉพาะช่วงเวลาหนึ่ง ตัวอย่างเช่นวิธีหนึ่งที่จะเพิ่มขึ้นคือการลบด้วย 8 และหารด้วย 5 ดังนั้นเราจึงได้ชุดของวิธีทั้งหมดเพื่อเพิ่มและลดจำนวน สิ่งนี้จะมีวิธีพื้นฐานเช่น mul 8 div 5 เท่านั้นและไม่ใช่ mul 16 div 5 นอกจากนี้ยังมีอีกวิธีหนึ่งในการลดระดับพื้นฐาน จัดเรียงสองชุดนี้ตามปัจจัยเพิ่มหรือลด ได้รับตัวเลขหนึ่งสามารถพบได้โดยการหาวิธีการเพิ่มที่ใช้บังคับกับปัจจัยที่เล็กที่สุดจากชุดเพิ่ม ..
ข้อมูลเมื่อ

.. หมายถึงการใช้งานมีจำนวนเฉพาะพอที่จะดำเนินการ mul และ div จากนั้นเราจะหาวิธีลดจำนวนใหม่ดังนั้นเริ่มต้นด้วยจำนวนที่ลดลงมากที่สุด ใช้วิธีการใหม่ ๆ เพื่อลดจำนวนลงเรื่อย ๆ และเราจะหยุดเมื่อหมายเลขใหม่มีขนาดเล็กกว่าหมายเลขเดิมที่ให้ไว้ เนื่องจากชุดของช่วงเวลาเป็นค่าคงที่นี่หมายถึงขนาดคงที่สำหรับสองชุด สิ่งนี้ต้องการการพิสูจน์สักเล็กน้อยเช่นกัน แต่ดูเหมือนว่าเวลาคงที่ความทรงจำคงที่ของแต่ละหมายเลข หน่วยความจำคงที่และเวลาเชิงเส้นสำหรับการพิมพ์ตัวเลข
InformedA

@randomA คุณได้รับการแบ่งจากที่ไหน คุณสนใจที่จะให้คำตอบแบบเต็ม - ฉันไม่เข้าใจความคิดเห็นของคุณ
VF1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.