รับสองอาร์เรย์ $birthsมีรายการปีเกิดแสดงเมื่อมีคนเกิดและ$deathsมีรายการปีแห่งความตายที่ระบุเมื่อมีคนตายเราจะหาปีที่ประชากรสูงสุดได้อย่างไร
ตัวอย่างเช่นกำหนดอาร์เรย์ต่อไปนี้:
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];ปีที่ประชากรสูงสุดควรเป็น1996เพราะ3ประชาชนยังมีชีวิตอยู่ในช่วงปีนั้นซึ่งเป็นประชากรที่สูงที่สุดนับจากทุกปี
นี่คือคณิตศาสตร์ที่ใช้อยู่ในนั้น:
| เกิด | ความตาย | ประชากร | ------- | ------- | ------------ | | 1981 | | 1 | | 2527 | | 2 | | 2527 | 2527 | 2 | | 2534 | 2534 | 2 | | 2539 | | 3 |
สมมติฐาน
เราสามารถสรุปได้อย่างปลอดภัยว่าปีที่ใครบางคนเกิดมาประชากรสามารถเพิ่มขึ้นได้หนึ่งปีและปีที่บางคนเสียชีวิตประชากรสามารถลดลงได้หนึ่งคน ดังนั้นในตัวอย่างนี้ 2 คนเกิดในปี 1984 และอีก 1 คนเสียชีวิตในปี 1984 ซึ่งหมายความว่าจำนวนประชากรที่เพิ่มขึ้น 1 ในปีนั้น
เราสามารถสรุปได้อย่างปลอดภัยว่าจำนวนผู้เสียชีวิตจะไม่เกินจำนวนการเกิดและจะไม่มีการเสียชีวิตเกิดขึ้นเมื่อประชากรอยู่ที่ 0
เราสามารถสันนิษฐานได้อย่างปลอดภัยว่าหลายปีในทั้งสองนี้$deathsและ$birthsจะไม่เป็นค่าลบหรือทศนิยม ( พวกมันมักเป็นจำนวนเต็มบวกมากกว่า 0 )
เราไม่สามารถสรุปได้ว่าอาร์เรย์จะถูกเรียงลำดับหรือจะไม่มีค่าซ้ำกัน
ความต้องการ
เราจะต้องเขียนฟังก์ชั่นเพื่อคืนปีที่มีประชากรมากที่สุดเกิดขึ้นเนื่องจากทั้งสองอาร์เรย์เป็นอินพุต ฟังก์ชั่นอาจจะกลับมา0, false, ""หรือNULL ( ค่า falsey ใด ๆ ที่เป็นที่ยอมรับได้ ) ถ้าอาร์เรย์การป้อนข้อมูลที่ว่างเปล่าหรือถ้าประชากรที่เป็นเสมอที่ 0 ตลอด หากจำนวนประชากรสูงสุดเกิดขึ้นในหลายปีฟังก์ชันอาจส่งคืนปีแรกที่มีจำนวนประชากรสูงถึงหรือในปีต่อ ๆ มา
ตัวอย่างเช่น:
$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];
/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */นอกจากนี้รวมถึงBig Oของโซลูชันจะเป็นประโยชน์
ความพยายามที่ดีที่สุดของฉันในการทำเช่นนี้จะเป็นดังนี้:
function highestPopulationYear(Array $births, Array $deaths): Int {
    sort($births);
    sort($deaths);
    $nextBirthYear = reset($births);
    $nextDeathYear = reset($deaths);
    $years = [];
    if ($nextBirthYear) {
        $years[] = $nextBirthYear;
    }
    if ($nextDeathYear) {
        $years[] = $nextDeathYear;
    }
    if ($years) {
        $currentYear = max(0, ...$years);
    } else {
        $currentYear = 0;
    }
    $maxYear = $maxPopulation = $currentPopulation = 0;
    while(current($births) !== false || current($deaths) !== false || $years) {
        while($currentYear === $nextBirthYear) {
            $currentPopulation++;
            $nextBirthYear = next($births);
        }
        while($currentYear === $nextDeathYear) {
            $currentPopulation--;
            $nextDeathYear = next($deaths);
        }
        if ($currentPopulation >= $maxPopulation) {
            $maxPopulation = $currentPopulation;
            $maxYear = $currentYear;
        }
        $years = [];
        if ($nextBirthYear) {
            $years[] = $nextBirthYear;
        }
        if ($nextDeathYear) {
            $years[] = $nextDeathYear;
        }
        if ($years) {
            $currentYear = min($years);
        } else {
            $currentYear = 0;
        }
    }
    return $maxYear;
}อัลกอริทึมด้านบนควรทำงานในเวลาพหุนามเนื่องจากมันแย่ที่สุดO(((n log n) * 2) + k)โดยที่nจำนวนขององค์ประกอบที่จะเรียงลำดับจากแต่ละอาร์เรย์และkเป็นจำนวนปีเกิด ( เนื่องจากเรารู้ว่าkเป็นเสมอk >= y ) โดยที่yเป็นจำนวนปีการเสียชีวิต อย่างไรก็ตามฉันไม่แน่ใจว่ามีวิธีแก้ปัญหาที่มีประสิทธิภาพมากกว่านี้หรือไม่
ความสนใจของฉันล้วนๆในBig O ที่ปรับปรุงใหม่ของความซับซ้อนในการคำนวณตามอัลกอริทึมที่มีอยู่ ความซับซ้อนของหน่วยความจำไม่เกี่ยวข้อง ไม่เป็นการเพิ่มประสิทธิภาพรันไทม์ อย่างน้อยก็ไม่ได้เป็นความกังวลหลัก การปรับแต่งรันไทม์เล็กน้อย / หลักใด ๆ ยินดีต้อนรับ แต่ไม่ใช่ปัจจัยสำคัญที่นี่