उच्चतम जनसंख्या के साथ वर्ष का पता लगाएं (सबसे कुशल समाधान)


9

दो सरणियाँ दीं; $birthsजन्म के वर्षों की एक सूची जिसमें यह संकेत दिया गया है कि किसी का जन्म हुआ था, और $deathsमृत्यु की वर्षों की एक सूची जिसमें यह दर्शाता है कि किसी की मृत्यु कब हुई, हम उस वर्ष को कैसे पा सकते हैं जिस पर जनसंख्या सबसे अधिक थी?

निम्नलिखित सरणियों के उदाहरण के लिए:

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

जिस वर्ष जनसंख्या सबसे अधिक होनी चाहिए थी 1996, क्योंकि 3उस वर्ष के दौरान लोग जीवित थे, जो उन सभी वर्षों की सबसे अधिक जनसंख्या गणना थी।

यहाँ उस पर चल रहे गणित है:

| जन्म | मौत | जनसंख्या |
| ------- | ------- | ------------ |
| 1981 | | 1 |
| 1984 | | 2 |
| 1984 | 1984 | 2 |
| 1991 | 1991 | 2 |
| 1996 | | 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 */

इसके अतिरिक्त, समाधान के बिग ओ सहित सहायक होगा।


ऐसा करने का मेरा सबसे अच्छा प्रयास निम्नलिखित होगा:

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मृत्यु की संख्या है। हालांकि, मुझे यकीन नहीं है कि कोई अधिक कुशल समाधान है।

मौजूदा एल्गोरिथ्म में कम्प्यूटेशनल जटिलता के एक बेहतर बिग ओ में मेरे हित विशुद्ध रूप से हैं । मेमोरी जटिलता का कोई सरोकार नहीं है। न ही रनटाइम ऑप्टिमाइजेशन है। कम से कम यह एक प्राथमिक चिंता का विषय नहीं है । किसी भी छोटे / प्रमुख रनटाइम अनुकूलन का स्वागत है, लेकिन यहां महत्वपूर्ण कारक नहीं है।


2
यदि आप एक काम कर समाधान है, यह बेहतर करने के लिए फिट किया जाएगा codereview.stackexchange.com ?
निगेल रेन

1
सवाल सबसे कुशल समाधान की मांग कर रहा है , जरूरी नहीं कि कोई भी काम करने वाला समाधान। मुझे लगता है कि एसओ पर यह पूरी तरह से मान्य है।
शेरिफ

1
मैं यह नहीं कह रहा हूं कि यह एसओ पर मान्य नहीं है (मैंने उस मामले को बंद करने के लिए मतदान किया होगा), मैं बस सोच रहा हूं कि क्या आपको सीआर पर प्रतिक्रिया मिल सकती है।
निगेल रेन

@NigelRen मैं कोशिश करने में नुकसान नहीं देखता। हालांकि मैं कुछ दिनों के लिए इसे खुला छोड़ना चाहूंगा। अगर यह जवाब नहीं मिलता है तो मैं इस पर एक इनाम दूंगा।
शेरिफ

1
यदि आप जन्म मृत्यु के कीवर्ड खोजते हैं, तो SO के पास आपकी समस्या का बहुत सवाल है। एक सस्ता सुधार सॉर्ट को बेहतर बनाने के लिए होगा: लंबाई की एक सरणी बनाओ जन्म / मृत्यु की अवधि (प्रत्येक सेल डिफ़ॉल्ट रूप से मान 0 के लिए होल्डिंग एक तारीख है)। 1 जोड़ें या 1 को जन्म और मृत्यु के बारे में सेल में
बदलें

जवाबों:


4

मुझे लगता है कि हमारे पास पहली छँटाई करके अतिरिक्त जगह के O(n log n)साथ समय हो सकता है O(1), फिर वर्तमान जनसंख्या और वैश्विक अधिकतम को बनाए रखने के रूप में हम पुनरावृति करते हैं। मैंने वर्तमान वर्ष को संदर्भ बिंदु के रूप में उपयोग करने की कोशिश की, लेकिन तर्क अभी भी थोड़ा मुश्किल लग रहा था इसलिए मुझे यकीन नहीं है कि यह पूरी तरह से काम कर रहा है। उम्मीद है, यह दृष्टिकोण का एक विचार दे सकता है।

जावास्क्रिप्ट कोड (प्रतिकृतियां / बग का स्वागत)

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

यदि वर्ष सीमा, mके आदेश पर है n, तो हम प्रत्येक वर्ष के लिए सीमा में गणना कर सकते हैं और O(n)समय की जटिलता हो सकती है। यदि हम फैंसी प्राप्त करना चाहते थे, तो हम O(n * log log m)समय की जटिलता भी कर सकते थे , एक वाई-फास्ट ट्राई का उपयोग करके जो O(log log m)समय में उत्तराधिकारी को देखने की अनुमति देता है ।


1. मुझे वाई-फास्ट ट्राई के अस्तित्व को पढ़ाने के लिए। एल्गो के बारे में: घटने के बाद अधिकतम जांच करने की आवश्यकता नहीं है। वेतन वृद्धि के बाद ही। अंतिम बार जब ब्लॉक अपवित्र है: दो क्रमबद्ध सूची को क्रमबद्ध करने पर विचार करें: आपको बस दोनों के सिर (i, j) की आवश्यकता है, प्रत्येक के सिर को चुनें, और छोटे को आगे बढ़ाएं। if(birth_i < death_j){//increment stuff + check max} else{//decrement}; birth_i||=infty; death_j||=infty। इसके अलावा, आप कर सकते हैं min(birthSize, deathSize)। यदि मिनट जन्म है, तो रुकें। यदि न्यूनतम मृत्यु (संदिग्ध ..) है, तो रोकें और जांचें(max + birth.length-i)
::

@grodzi मैंने मर्ज सॉर्ट पर विचार करना शुरू किया, लेकिन यह निष्कर्ष निकालने के लिए अतिरिक्त हैंडलिंग की आवश्यकता थी कि कैसे नकल के साथ-साथ जन्म बनाम मृत्यु का क्रम गिनती को प्रभावित करता है। जब मुझे जन्म के वर्षों में बेमिसाल मौतें आती हैं, तो आखिरी बार लूप मुझे जरूरी लगता है। आप सही हैं कि उस लूप में अधिकतम अनावश्यक है।
לעג ברקן

@ Etלעגברקן रैखिक समय के लिए बाल्टी प्रकार का उपयोग करें।
डेव

मैंने अपने उत्तर में पहले ही यह विचार कह दिया था, "यदि वर्ष की श्रेणी, मी, n के क्रम पर है, तो हम प्रत्येक वर्ष के लिए सीमा में गणना कर सकते हैं और O (n) समय की जटिलता है।"
לעג ברקן

यह कार्यकुशलता नहीं है, मुझे नहीं पता कि आप इनाम हाहा क्यों देते हैं
एमिलियानो

4

हम इसे बकेट सॉर्ट के साथ रैखिक समय में हल कर सकते हैं। मान लीजिए कि इनपुट का आकार n है, और वर्षों की सीमा 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.

सबसे बड़ा संचयी अधिकतम आपका उत्तर है।

चलने का समय O (n + m) है, और आवश्यक अतिरिक्त स्थान O (m) है।

यह n में एक रैखिक समाधान है यदि m O (n) है; यानी, अगर जन्म और मृत्यु की संख्या की तुलना में वर्षों की सीमा अधिक तेज़ी से नहीं बढ़ रही है। वास्तविक दुनिया के आंकड़ों के लिए यह लगभग निश्चित रूप से सच है।


1
क्या आप कृपया कार्यशील कार्यान्वयन शामिल कर सकते हैं?
शेरिफ़

1
@ शरीफ कार्यान्वयन पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है ... यह वैसे भी तुच्छ है। क्या कुछ भी स्पष्ट नहीं है?
डेव

मैं ध्यान देता हूं कि क्योंकि आपकी ग्रैन्युलैरिटी वर्ष है, कुछ अस्पष्टता है। उस में हम प्रभावी रूप से जनसंख्या को वर्ष के अंत तक माप रहे हैं, और मध्य वर्ष के कुछ अन्य बिंदु हो सकते हैं जहां जन्म और मृत्यु के समय के कारण जनसंख्या अधिक है।
डेव

1
यदि हमें "सरणी का अधिकतम max_yr - min_yr + 1" पार्स करना है तो यह रैखिक समय कैसा है? (cc @Sherif)
cלעב ברק

1
@ क्या: बिंदु 1 और 2 के लिए ओ (2 एन) जटिलता नहीं है? 1. iterate एक बार सभी जन्मों + मृत्यु के माध्यम से: O(n): Find the min and max year across births and deaths 2. पुन : सभी जन्मों के माध्यम से पुनरावृति + मृत्यु: O(n): Parse the births+death array, incrementing the appropriate index of the array तो आप करते हैं: O (m): अपने सरणी पार्स, संचयी राशि और इसके अधिकतम मूल्य का ट्रैक रखते हुए। (आपको इस सरणी को पार्स करने की आवश्यकता नहीं है - आप 2 में सूचकांकों को बढ़ाते हुए मैक्स का ट्रैक रख सकते हैं)
एंटनी

3

पहले जन्मों और मौतों को एक नक्शे में एकत्र करें ( year => population change), उस तरह से क्रमबद्ध करें, और उस पर चल रही आबादी की गणना करें।

यह लगभग होना चाहिए O(2n + n log n), जहां nजन्मों की संख्या है।

$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));

जैसा कि मैं देख रहा हूँ: n = घटनाओं की संख्या (जन्म + मृत्यु) और m = घटना वर्षों की संख्या (जन्म या मृत्यु वाले वर्ष) यह वास्तव में O (n + m log m) होगा । यदि n >> m - इसे O (n) माना जा सकता है । यदि आपके पास 100 वर्ष की अवधि (कह) में अरबों जन्म और मृत्यु हैं, तो 100 तत्वों ( ksort($indexed)) के साथ एक सरणी को छांटना अप्रासंगिक हो जाता है।
पॉल स्पीगेल

आप जन्म के साथ प्रक्रिया कर सकते हैं $indexed = array_count_values($births);
निगेल रेन

3

मैंने इस समस्या को एक स्मृति आवश्यकता के साथ हल किया O(n+m)[सबसे खराब स्थिति में, सबसे अच्छा मामला O(n)]

और, समय की जटिलता O(n logn)

यहां, n & mलंबाई birthsऔर deathsसरणियाँ हैं।

मैं PHP या जावास्क्रिप्ट नहीं जानता। मैंने इसे जावा के साथ लागू किया है और तर्क बहुत सरल है। लेकिन मेरा मानना ​​है कि मेरा विचार उन भाषाओं में भी लागू किया जा सकता है।

तकनीक विवरण:

मैंने TreeMapजन्म और मृत्यु रिकॉर्ड को स्टोर करने के लिए जावा संरचना का उपयोग किया ।

TreeMapसम्मिलित डेटा ( कुंजी आधारित ) को (कुंजी, मान) जोड़ी के रूप में सम्मिलित किया जाता है, यहां कुंजी वर्ष है और मान जन्मों और मौतों की संचयी राशि (मौतों के लिए नकारात्मक) है।

हमें उच्चतम जन्म वर्ष के बाद हुई मौतों के मूल्य को सम्मिलित करने की आवश्यकता नहीं है

एक बार जब ट्रीपार्ट जन्म और मृत्यु रिकॉर्ड के साथ आबाद हो जाता है, तो सभी संचयी रकम अपडेट हो जाती हैं और वर्ष की प्रगति के साथ अधिकतम आबादी को संग्रहीत करती हैं।

नमूना इनपुट और आउटपुट: 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

नमूना इनपुट और आउटपुट: 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

यहां, 1914 & laterपिछले जन्म के वर्ष के बाद मौतें हुईं 1913

कुल 10 millionडेटा (जन्म और मृत्यु संयुक्त) और अधिक के लिए 1000 years range, कार्यक्रम 3 sec.समाप्त होने के बारे में लिया ।

अगर एक ही आकार के डेटा के साथ 100 years range, यह लिया 1.3 sec

सभी इनपुट को यादृच्छिक रूप से लिया जाता है।


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

यह एक बंधे हुए वर्ष की संभावना को ध्यान में रखेगा, साथ ही अगर किसी की मृत्यु का एक वर्ष किसी के जन्म के अनुरूप नहीं होगा।


यह उत्तर शैक्षणिक बिग ओ स्पष्टीकरण प्रदान करने का कोई प्रयास नहीं करता है जो ओपी द्वारा अनुरोध किया गया है।
मिकमैकुसा

0

मेमोरी वार इसे रखना currentPopulationऔर currentYearगणना करना है। दोनों $birthsऔर $deathsसरणियों को क्रमबद्ध करके शुरू करना एक बहुत अच्छा बिंदु है, क्योंकि बुलबुला छंटाई उस भारी काम नहीं है, फिर भी कुछ कोनों को काटने की अनुमति देता है:

<?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);

वास्तव में बिग ओ में गोता लगाने के लिए उत्सुक नहीं है, यह आप पर छोड़ दिया।

इसके अलावा, यदि आप currentYearComputingहर लूप को फिर से खोजते हैं, तो आप लूप को ifस्टेटमेंट में बदल सकते हैं और सिर्फ एक लूप के साथ छोड़ सकते हैं ।

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

सरणी शिफ्ट मेमोरी के लिए एक अच्छा विकल्प है, लेकिन प्रदर्शन के लिए नहीं, इस cmljnelson.blog/2018/10/16/phps-array_shift-performance पर जांचें
एमिलियानो

आप हमेशा अवरोही छँटाई कर सकते हैं, वृद्धि के साथ घटाव के साथ जा सकते हैं, और शिफ्ट के बजाय पॉप के साथ।
यारगो

0

मैं इस समाधान के बहुत आराम से भरता हूं, जटिलता बिग ओ 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));
?>

नहीं $tmpArray--होना चाहिए $tmpArray[$death]--? कृपया इसके साथ परीक्षण करें $births=[1997,1997,1998]; $deaths=[];- क्या इसे 1998वैसा ही लौटना चाहिए जैसा कि इसे करना चाहिए?
पॉल स्पीगेल

हां तुम सही हो।
एमिलियानो

यह कोड न केवल जटिल धार के मामलों में विफल रहता है, बल्कि यह सबसे सरल मामलों में भी विफल रहता है, जैसे कि इनपुट सरणियां दी गई हैं $births = [3,1,2,1,3,3,2]और $deaths = [2,3,2,3,3,3]मुझे 2उच्चतम जनसंख्या वर्ष के रूप में वापस मिलने की उम्मीद है , फिर भी आपका कोड वापस आ जाता है 1। वास्तव में आपका कोड मेरे यूनिट परीक्षणों में से 15 में से 9 में विफल रहा । मैं न केवल इसे सबसे कुशल उत्तर के रूप में स्वीकार कर सकता हूं, बल्कि मैं इसे एक कुशल उत्तर भी स्वीकार नहीं कर सकता क्योंकि यह बिल्कुल भी काम नहीं करता है।
शेरिफ

आप प्रश्न को ध्यान से पढ़ने में विफल रहे और इस प्रकार एक अच्छा उत्तर देने में विफल रहे। आप यहाँ यह धारणा बनाते हैं कि मैंने आपको बताया था कि नहीं बनाना है ( कि सरणियाँ क्रमबद्ध हैं )। तो कृपया इस प्रश्न में अपनी आपत्तिजनक टिप्पणी को हटा दें कि मैंने कैसे एक गैर-कुशल उत्तर देने के लिए इनाम दिया है और यह किसी भी तरह से " ठीक " है।
शेरिफ

0

आपकी समस्या के लिए सबसे सरल और स्पष्ट दृष्टिकोण है।

$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);

आउटपुट :

1909

जटिलता :

O(m + log(n))

1 मिलियन रिकॉर्ड के निष्पादन के समय के लिए है29.64 milliseconds
रौनक धूत

जैसा कि सवाल में कहा गया है कि मैं रनटाइम अनुकूलन के बाद नहीं हूं, लेकिन यह ध्यान दिया जाना चाहिए कि आपकी बिग ओ गणना यहां से थोड़ी दूर है। साथ ही, आपका कोड थोड़ा टूट गया है। यह कई धार मामलों में विफल रहता है।
शेरिफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.