Tìm năm có dân số cao nhất (giải pháp hiệu quả nhất)


9

Cho hai mảng; $birthschứa một danh sách các năm sinh cho biết khi ai đó được sinh ra và $deathschứa một danh sách các năm chết cho biết khi ai đó chết, làm thế nào chúng ta có thể tìm thấy năm mà dân số cao nhất?

Ví dụ cho các mảng sau:

$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];

Năm mà dân số cao nhất nên là 1996bởi vì 3mọi người còn sống trong năm đó, đó là số dân cao nhất trong tất cả các năm đó.

Đây là phép toán đang chạy trên đó:

| Sinh | Cái chết | Dân số |
| ------- | ------- | ------------ |
| 1981 | | 1 |
| 1984 | | 2 |
| 1984 | 1984 | 2 |
| 1991 | 1991 | 2 |
| 1996 | | 3 |

Giả định

Chúng ta có thể giả định một cách an toàn rằng năm mà một người nào đó được sinh ra, dân số có thể tăng thêm một và năm mà một người nào đó chết, dân số có thể giảm đi một. Vì vậy, trong ví dụ này, 2 người sinh năm 1984 và 1 người chết năm 1984, nghĩa là dân số tăng thêm 1 vào năm đó.

Chúng ta cũng có thể giả định một cách an toàn rằng số người chết sẽ không bao giờ vượt quá số ca sinh và không có trường hợp tử vong nào có thể xảy ra khi dân số ở mức 0.

Chúng ta cũng có thể giả định một cách an toàn rằng các năm ở cả hai $deaths$birthssẽ không bao giờ là giá trị âm hoặc dấu phẩy động ( chúng luôn là các số nguyên dương lớn hơn 0 ).

Chúng tôi không thể giả định rằng các mảng sẽ được sắp xếp hoặc tuy nhiên sẽ không có giá trị trùng lặp.

Yêu cầu

Chúng ta phải viết một hàm để trả về năm có dân số cao nhất xuất hiện, lấy hai mảng này làm đầu vào. Các chức năng có thể trở lại 0, false, "", hoặc NULL( bất kỳ giá trị falsey là chấp nhận được ) nếu các mảng đầu vào là rỗng hoặc nếu dân số luôn ở mức 0 trong suốt. Nếu dân số cao nhất xảy ra trong nhiều năm, chức năng có thể trở lại vào năm đầu tiên mà dân số cao nhất đã đạt được hoặc bất kỳ năm tiếp theo nào.

Ví dụ:

$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];

/* The highest population was 3 on 1997, 1998 and 1999, either answer is correct */

Ngoài ra, bao gồm cả Big O của giải pháp sẽ hữu ích.


Nỗ lực tốt nhất của tôi trong việc này sẽ là như sau:

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;
}

Các thuật toán trên nên làm việc trong thời gian đa thức cho nó là lúc tồi tệ nhất O(((n log n) * 2) + k)nlà số nguyên tố được sắp xếp từ từng mảng và klà số năm sinh ( kể từ khi chúng ta biết rằng kluônk >= y ), nơi ylà số năm cái chết. Tuy nhiên, tôi không chắc có giải pháp nào hiệu quả hơn không.

Sở thích của tôi hoàn toàn là một Big O cải tiến về độ phức tạp tính toán dựa trên thuật toán hiện có. Bộ nhớ phức tạp là không quan tâm. Cũng không phải là tối ưu hóa thời gian chạy. Ít nhất nó không phải là mối quan tâm chính . Bất kỳ tối ưu hóa thời gian chạy nhỏ / chính đều được chào đón, nhưng không phải là yếu tố chính ở đây.


2
Khi bạn có một giải pháp làm việc, điều này có phù hợp hơn với codereview.stackexchange.com không?
Nigel Ren

1
Câu hỏi là tìm kiếm giải pháp hiệu quả nhất, không nhất thiết là bất kỳ giải pháp làm việc nào . Tôi nghĩ điều đó hoàn toàn hợp lệ trên SO.
Sherif

1
Tôi không nói rằng nó không hợp lệ trên SO (tôi đã bỏ phiếu để đóng trong trường hợp đó), tôi chỉ tự hỏi liệu bạn có thể nhận được nhiều phản hồi hơn về CR không.
Nigel Ren

@NigelRen Tôi không thấy tác hại khi thử. Mặc dù tôi muốn để mở này trong một vài ngày. Nếu nó không nhận được câu trả lời, tôi sẽ trả tiền cho nó.
Sherif

1
Bản thân SO có rất nhiều câu hỏi về vấn đề của bạn nếu bạn tìm kiếm từ khóa khai sinh. Một cải tiến giá rẻ sẽ là cải thiện cách sắp xếp: tạo một mảng có độ dài khoảng thời gian sinh / tử (mỗi ô là một ngày giữ giá trị 0 theo mặc định). thêm 1 hoặc trừ 1 vào ô liên quan đến sinh và tử, sau đó cộng tổng và giữ tổng số tiền tối đa được tìm thấy
grodzi

Câu trả lời:


4

Tôi nghĩ rằng chúng ta có thể có O(n log n)thời gian với O(1)không gian bổ sung bằng cách sắp xếp trước, sau đó duy trì dân số hiện tại và tối đa toàn cầu khi chúng ta lặp lại. Tôi đã cố gắng sử dụng năm hiện tại làm điểm tham chiếu nhưng logic vẫn có vẻ hơi phức tạp nên tôi không chắc nó hoàn toàn có hiệu quả. Hy vọng, nó có thể đưa ra một ý tưởng về cách tiếp cận.

Mã JavaScript (counterexamples / bug welcome)

function f(births, deaths){
  births.sort((a, b) => a - b);
  deaths.sort((a, b) => a - b);

  console.log(JSON.stringify(births));
  console.log(JSON.stringify(deaths));
  
  let i = 0;
  let j = 0;
  let year = births[i];
  let curr = 0;
  let max = curr;

  while (deaths[j] < births[0])
    j++;

  while (i < births.length || j < deaths.length){
    while (year == births[i]){
      curr = curr + 1;
      i = i + 1;
    }
    
    if (j == deaths.length || year < deaths[j]){
      max = Math.max(max, curr);
      console.log(`year: ${ year }, max: ${ max }, curr: ${ curr }`);
    
    } else if (j < deaths.length && deaths[j] == year){
      while (deaths[j] == year){
        curr = curr - 1;
        j = j + 1;
      }
      max = Math.max(max, curr);
      console.log(`year: ${ year }, max: ${ max }, curr: ${ curr }`);
    }

    if (j < deaths.length && deaths[j] > year && (i == births.length || deaths[j] < births[i])){
      year = deaths[j];
      while (deaths[j] == year){
        curr = curr - 1;
        j = j + 1;
      }
      console.log(`year: ${ year }, max: ${ max }, curr: ${ curr }`);
    }

    year = births[i];
  }
  
  return max;
}

var input = [
  [[1997, 1997, 1997, 1998, 1999],
  [1998, 1999]],
  [[1, 2, 2, 3, 4],
  [1, 2, 2, 5]],
  [[1984, 1981, 1984, 1991, 1996],
  [1991, 1984, 1997]],
  [[1984, 1981, 1984, 1991, 1996],
  [1991, 1982, 1984, 1997]]
]

for (let [births, deaths] of input)
  console.log(f(births, deaths));

Nếu phạm vi năm, mtheo thứ tự n, chúng ta có thể lưu trữ số lượng cho mỗi năm trong phạm vi và có O(n)độ phức tạp về thời gian. Nếu chúng ta muốn có được sự ưa thích, chúng ta cũng có thể có O(n * log log m)sự phức tạp về thời gian, bằng cách sử dụng bộ ba Y-fast cho phép tìm kiếm người kế nhiệm O(log log m)kịp thời.


1. thx đã dạy tôi sự tồn tại của Y-trie nhanh. Về thuật toán: không cần kiểm tra max sau khi giảm. Chỉ sau khi tăng. Khối cuối cùng là không cần thiết: xem xét sắp xếp hai danh sách được sắp xếp: bạn chỉ cần đầu của cả hai (i, j), chọn đầu của mỗi danh sách và tiến lên danh sách nhỏ hơn. if(birth_i < death_j){//increment stuff + check max} else{//decrement}; birth_i||=infty; death_j||=infty. Ngoài ra, bạn có thể lặp đi lặp lại lên đến min(birthSize, deathSize). nếu min là sinh, dừng lại. nếu min là cái chết (đáng ngờ ..), hãy dừng lại và kiểm tra(max + birth.length-i)
grodzi

@grodzi Tôi đã bắt đầu xem xét sắp xếp hợp nhất nhưng kết luận điều này cần xử lý thêm vì cách trùng lặp cũng như thứ tự sinh và tử ảnh hưởng đến số lượng. Vòng lặp while cuối cùng có vẻ cần thiết với tôi khi có những năm chết không thể so sánh với năm sinh. Bạn đúng rằng max trong vòng lặp đó là không cần thiết.
גלעד ברקן

@ גלעדב ž קן Sử dụng sắp xếp xô cho thời gian tuyến tính.
Dave

Tôi đã nêu ý tưởng này trong câu trả lời của mình, "Nếu phạm vi năm, m, theo thứ tự n, chúng ta có thể lưu trữ số lượng cho mỗi năm trong phạm vi và có độ phức tạp thời gian O (n)."
גלעד ברקן

Đây không phải là hiệu quả, tôi không biết tại sao lại cho bạn phần thưởng hahaha
Emiliano

4

Chúng ta có thể giải quyết điều này trong thời gian tuyến tính với loại xô. Giả sử kích thước của đầu vào là n và phạm vi năm là m.

O(n): Find the min and max year across births and deaths.
O(m): Create an array of size max_yr - min_yr + 1, ints initialized to zero. 
      Treat the first cell of the array as min_yr, the next as min_yr+1, etc...
O(n): Parse the births array, incrementing the appropriate index of the array. 
      arr[birth_yr - min_yr] += 1
O(n): Ditto for deaths, decrementing the appropriate index of the array.
      arr[death_yr - min_yr] -= 1
O(m): Parse your array, keeping track of the cumulative sum and its max value.

Tối đa tích lũy lớn nhất là câu trả lời của bạn.

Thời gian chạy là O (n + m) và không gian bổ sung cần thiết là O (m).

Đây là một giải pháp tuyến tính trong n nếu m là O (n); tức là, nếu phạm vi năm không tăng nhanh hơn số lần sinh và tử. Điều này gần như chắc chắn đúng với dữ liệu thế giới thực.


1
Bạn có thể bao gồm một thực hiện làm việc xin vui lòng?
Sherif

1
@Sherif Thực hiện được để lại như một bài tập cho người đọc ... Dù sao nó cũng tầm thường. Có điều gì không rõ ràng?
Dave

Tôi sẽ lưu ý rằng vì độ chi tiết của bạn là năm, có một chút mơ hồ. trong đó chúng ta đang đo lường dân số một cách hiệu quả vào cuối năm, và có thể có một số thời điểm khác vào giữa năm khi dân số cao hơn do thời gian sinh và tử.
Dave

1
Làm thế nào là thời gian tuyến tính này nếu chúng ta phải phân tích một "mảng kích thước max_yr - min_yr + 1"? (cc @Sherif)
גלעד ברקן

1
@Dave: độ phức tạp không phải là O (2n) cho điểm 1 và 2? 1. lặp lại một lần qua tất cả các lần sinh + tử: O(n): Find the min and max year across births and deaths 2. lặp lại qua tất cả các lần sinh + tử: O(n): Parse the births+death array, incrementing the appropriate index of the array sau đó bạn làm: O (m): Phân tích mảng của bạn, theo dõi tổng tích lũy và giá trị tối đa của nó. (bạn không cần phân tích mảng này - bạn có thể theo dõi MAX trong khi tăng các chỉ số trong 2)
Antony

3

Trước tiên, tổng hợp các ca sinh và tử thành một bản đồ ( year => population change), sắp xếp theo khóa và tính toán dân số đang chạy trên đó.

Điều này nên được xấp xỉ O(2n + n log n), nơi nsinh số.

$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];

function highestPopulationYear(array $births, array $deaths): ?int
{
    $indexed = [];

    foreach ($births as $birth) {
        $indexed[$birth] = ($indexed[$birth] ?? 0) + 1;
    }

    foreach ($deaths as $death) {
        $indexed[$death] = ($indexed[$death] ?? 0) - 1;
    }

    ksort($indexed);

    $maxYear = null;
    $max = $current = 0;

    foreach ($indexed as $year => $change) {
        $current += $change;
        if ($current >= $max) {
            $max = $current;
            $maxYear = $year;
        }
    }

    return $maxYear;
}

var_dump(highestPopulationYear($births, $deaths));

Như tôi thấy: Với n = số sự kiện (sinh + tử) và m = số năm sự kiện (năm sinh hoặc tử), đây thực sự sẽ là O (n + m log m) . Nếu n >> m - điều này có thể được coi là O (n) . Nếu bạn có hàng tỷ lần sinh và tử trong khoảng thời gian (giả sử) 100 năm - việc sắp xếp một mảng với 100 phần tử ( ksort($indexed)) trở nên không liên quan.
Paul Spiegel

Bạn có thể xử lý các ca sinh với $indexed = array_count_values($births);.
Nigel Ren

3

Tôi đã giải quyết vấn đề này với yêu cầu bộ nhớ là O(n+m)[trong trường hợp xấu nhất, trường hợp tốt nhất O(n)]

và, độ phức tạp thời gian của O(n logn).

Ở đây, n & mlà chiều dài birthsdeathsmảng.

Tôi không biết PHP hoặc javascript. Tôi đã triển khai nó với Java và logic rất đơn giản. Nhưng tôi tin rằng ý tưởng của tôi cũng có thể được thực hiện bằng các ngôn ngữ đó.

Chi tiết kỹ thuật:

Tôi đã sử dụng TreeMapcấu trúc java để lưu trữ hồ sơ sinh và tử.

TreeMapchèn dữ liệu được sắp xếp ( dựa trên khóa) thành cặp (khóa, giá trị), ở đây khóa là năm và giá trị là tổng tích lũy của sinh và tử (âm đối với tử vong).

Chúng ta không cần chèn giá trị tử vong xảy ra sau năm sinh cao nhất .

Khi TreeMap được điền với các hồ sơ sinh và tử, tất cả các khoản tiền tích lũy được cập nhật và lưu trữ dân số tối đa theo năm khi nó tiến triển.

Đầu vào và đầu ra mẫu: 1

Births: [1909, 1919, 1904, 1911, 1908, 1908, 1903, 1901, 1914, 1911, 1900, 1919, 1900, 1908, 1906]

Deaths: [1910, 1911, 1912, 1911, 1914, 1914, 1913, 1915, 1914, 1915]

Year counts Births: {1900=2, 1901=1, 1903=1, 1904=1, 1906=1, 1908=3, 1909=1, 1911=2, 1914=1, 1919=2}

Year counts Birth-Deaths combined: {1900=2, 1901=1, 1903=1, 1904=1, 1906=1, 1908=3, 1909=1, 1910=-1, 1911=0, 1912=-1, 1913=-1, 1914=-2, 1915=-2, 1919=2}

Yearwise population: {1900=2, 1901=3, 1903=4, 1904=5, 1906=6, 1908=9, 1909=10, 1910=9, 1911=9, 1912=8, 1913=7, 1914=5, 1915=3, 1919=5}

maxPopulation: 10
yearOfMaxPopulation: 1909

Đầu vào và đầu ra mẫu: 2

Births: [1906, 1901, 1911, 1902, 1905, 1911, 1902, 1905, 1910, 1912, 1900, 1900, 1904, 1913, 1904]

Deaths: [1917, 1908, 1918, 1915, 1907, 1907, 1917, 1917, 1912, 1913, 1905, 1914]

Year counts Births: {1900=2, 1901=1, 1902=2, 1904=2, 1905=2, 1906=1, 1910=1, 1911=2, 1912=1, 1913=1}

Year counts Birth-Deaths combined: {1900=2, 1901=1, 1902=2, 1904=2, 1905=1, 1906=1, 1907=-2, 1908=-1, 1910=1, 1911=2, 1912=0, 1913=0}

Yearwise population: {1900=2, 1901=3, 1902=5, 1904=7, 1905=8, 1906=9, 1907=7, 1908=6, 1910=7, 1911=9, 1912=9, 1913=9}

maxPopulation: 9
yearOfMaxPopulation: 1906

Ở đây, cái chết xảy ra ( 1914 & later) sau năm sinh cuối cùng 1913, không được tính vào tất cả, mà tránh các tính toán không cần thiết.

Đối với tổng số 10 milliondữ liệu (kết hợp sinh và tử) 1000 years range, chương trình đã 3 sec.hoàn tất.

Nếu cùng kích thước dữ liệu với 100 years range, nó mất 1.3 sec.

Tất cả các đầu vào được lấy ngẫu nhiên.


1
$births = [1984, 1981, 1984, 1991, 1996];
$deaths = [1991, 1984];
$years = array_unique(array_merge($births, $deaths));
sort($years);

$increaseByYear = array_count_values($births);
$decreaseByYear = array_count_values($deaths);
$populationByYear = array();

foreach ($years as $year) {
    $increase = $increaseByYear[$year] ?? 0;
    $decrease = $decreaseByYear[$year] ?? 0;
    $previousPopulationTally = end($populationByYear);
    $populationByYear[$year] = $previousPopulationTally + $increase - $decrease;
}

$maxPopulation = max($populationByYear);
$maxPopulationYears = array_keys($populationByYear, $maxPopulation);

$maxPopulationByYear = array_fill_keys($maxPopulationYears, $maxPopulation);
print_r($maxPopulationByYear);

Điều này sẽ giải thích cho khả năng của một năm gắn liền, cũng như nếu một năm cái chết của ai đó không tương ứng với sự ra đời của ai đó.


Câu trả lời này không cố gắng cung cấp lời giải thích Big O hàn lâm được OP yêu cầu.
mickmackusa

0

Trí nhớ khôn ngoan là giữ currentPopulationcurrentYeartính toán. Bắt đầu bằng cách sắp xếp cả hai $births$deathsmảng là một điểm rất tốt, bởi vì sắp xếp bong bóng không phải là nhiệm vụ nặng nề, nhưng vẫn cho phép cắt giảm một số góc:

<?php

$births = [1997, 1999, 2000];
$deaths = [2000, 2001, 2001];

function highestPopulationYear(array $births, array $deaths): Int {

    // sort takes time, but is neccesary for futher optimizations
    sort($births);
    sort($deaths);

    // first death year is a first year where population might decrase 
    // sorfar max population
    $currentYearComputing = $deaths[0];

    // year before first death has potential of having the biggest population
    $maxY = $currentYearComputing-1;

    // calculating population at the begining of the year of first death, start maxPopulation
    $population = $maxPop = count(array_splice($births, 0, array_search($deaths[0], $births)));

    // instead of every time empty checks: `while(!empty($deaths) || !empty($births))`
    // we can control a target time. It reserves a memory, but this slot is decreased
    // every iteration.
    $iterations = count($deaths) + count($births);

    while($iterations > 0) {
        while(current($births) === $currentYearComputing) {
            $population++;
            $iterations--;
            array_shift($births); // decreasing memory usage
        }

        while(current($deaths) === $currentYearComputing) {
            $population--;
            $iterations--;
            array_shift($deaths); // decreasing memory usage
        }

        if ($population > $maxPop) {
            $maxPop = $population;
            $maxY = $currentYearComputing;
        }

        // In $iterations we have a sum of birth/death events left. Assuming all 
        // are births, if this number added to currentPopulation will never exceed
        // current maxPoint, we can break the loop and save some time at cost of
        // some memory.
        if ($maxPop >= ($population+$iterations)) {
            break;
        }

        $currentYearComputing++;
    }

    return $maxY;
}

echo highestPopulationYear($births, $deaths);

không thực sự quan tâm đến việc lặn vào điều Big O , để lại cho bạn.

Ngoài ra, nếu bạn khám phá lại currentYearComputingmọi vòng lặp, bạn có thể thay đổi các vòng lặp thành các ifcâu lệnh và rời đi chỉ với một vòng lặp.

    while($iterations > 0) {

        $changed = false;

        if(current($births) === $currentYearComputing) {
            // ...
            $changed = array_shift($births); // decreasing memory usage
        }

        if(current($deaths) === $currentYearComputing) {
            // ...
            $changed = array_shift($deaths); // decreasing memory usage
        }

        if ($changed === false) {
            $currentYearComputing++;
            continue;
        }

dịch chuyển mảng là một lựa chọn tốt cho bộ nhớ nhưng không phải cho hiệu năng, hãy kiểm tra cmljnelson.blog/2018/10/16/phps-array_shift-performance
Emiliano

Bạn luôn có thể sắp xếp giảm dần, đi với giảm dần thay vì tăng dần và với pop thay vì thay đổi.
yergo

0

Tôi điền rất thoải mái với giải pháp này, độ phức tạp Big O là n + m

<?php
function getHighestPopulation($births, $deaths){
    $max = [];
    $currentMax = 0;
    $tmpArray = [];

    foreach($deaths as $key => $death){
        if(!isset($tmpArray[$death])){
            $tmpArray[$death] = 0;    
        }
        $tmpArray[$death]--;
    }
    foreach($births as $k => $birth){
        if(!isset($tmpArray[$birth])){
            $tmpArray[$birth] = 0;
        }
        $tmpArray[$birth]++;
        if($tmpArray[$birth] > $currentMax){
            $max = [$birth];
            $currentMax = $tmpArray[$birth];
        } else if ($tmpArray[$birth] == $currentMax) {
            $max[] = $birth;
        }
    }

    return [$currentMax, $max];
}

$births = [1997, 1997, 1997, 1998, 1999];
$deaths = [1998, 1999];

print_r (getHighestPopulation($births, $deaths));
?>

Không nên $tmpArray--$tmpArray[$death]--? Ngoài ra, vui lòng kiểm tra với $births=[1997,1997,1998]; $deaths=[];- Nó có trở lại 1998như bình thường không?
Paul Spiegel

vâng bạn đúng
Emiliano

Mã này không chỉ thất bại trong các trường hợp cạnh phức tạp, mà thậm chí còn thất bại trong các trường hợp đơn giản nhất như được đưa ra các mảng đầu vào $births = [3,1,2,1,3,3,2]$deaths = [2,3,2,3,3,3]tôi sẽ mong đợi được lấy lại 2là năm dân số cao nhất, nhưng mã của bạn trở lại 1. Trong thực tế, mã của bạn đã thất bại 9 trong số 15 bài kiểm tra đơn vị của tôi . Tôi không chỉ không thể chấp nhận đây là câu trả lời hiệu quả nhất , mà tôi thậm chí không thể chấp nhận nó là một câu trả lời hiệu quả vì nó hoàn toàn không hoạt động.
Sherif

Bạn đã không đọc kỹ câu hỏi và do đó không thể đưa ra một câu trả lời hay. Bạn đưa ra giả định ở đây mà tôi đã nói với bạn là không thực hiện ( rằng các mảng được sắp xếp ). Vì vậy, vui lòng xóa nhận xét gây khó chịu của bạn trong câu hỏi về cách tôi trao tiền thưởng cho câu trả lời không hiệu quả và đây là cách " khắc phục ".
Sherif

0

Một trong những cách tiếp cận đơn giản và rõ ràng nhất cho vấn đề của bạn.

$births = [1909, 1919, 1904, 1911, 1908, 1908, 1903, 1901, 1914, 1911, 1900, 1919, 1900, 1908, 1906];
$deaths = [1910, 1911, 1912, 1911, 1914, 1914, 1913, 1915, 1914, 1915];

/* for generating 1 million records

for($i=1;$i<=1000000;$i++) {
    $births[] = rand(1900, 2020);
    $deaths[] = rand(1900, 2020);
}
*/

function highestPopulationYear(Array $births, Array $deaths): Int {
    $start_time = microtime(true); 
    $population = array_count_values($births);
    $deaths = array_count_values($deaths);

    foreach ($deaths as $year => $death) {
        $population[$year] = ($population[$year] ?? 0) - $death;
    }
    ksort($population, SORT_NUMERIC);
    $cumulativeSum = $maxPopulation = $maxYear = 0;
    foreach ($population as $year => &$number) {
        $cumulativeSum += $number;
        if($maxPopulation < $cumulativeSum) {
            $maxPopulation = $cumulativeSum;
            $maxYear = $year;
        }
    }
    print " Execution time of function = ".((microtime(true) - $start_time)*1000)." milliseconds"; 
    return $maxYear;
}

print highestPopulationYear($births, $deaths);

đầu ra :

1909

phức tạp :

O(m + log(n))

cho 1 triệu hồ sơ thời gian thực hiện chỉ là29.64 milliseconds
Ronak Dhoot

Như đã nêu trong câu hỏi Tôi không phải sau khi tối ưu hóa thời gian chạy, nhưng cần lưu ý rằng tính toán Big O của bạn hơi bị tắt ở đây. Ngoài ra, mã của bạn hơi bị hỏng. Nó thất bại trong một số trường hợp cạnh.
Sherif
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.