সর্বাধিক জনসংখ্যার সাথে বছরটি সন্ধান করুন (সবচেয়ে কার্যকর সমাধান)


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 এ সবসময় ছিল। একাধিক বছরে সর্বাধিক জনসংখ্যা দেখা দিলে এই ফাংশনটি প্রথম বছরে ফিরে আসতে পারে যেখানে সর্বোচ্চ জনসংখ্যা পৌঁছেছিল বা পরবর্তী কোনও বছর year

উদাহরণ স্বরূপ:

$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মৃত্যুর বছর রয়েছে। তবে, আরও কার্যকর সমাধান আছে কিনা তা সম্পর্কে আমি নিশ্চিত নই।

আমার আগ্রহগুলি সম্পূর্ণরূপে বিদ্যমান অ্যালগরিদমের উপর গণ্য জটিলতার উন্নত বিগ ও are স্মৃতি জটিলতা কোন উদ্বেগের নয়। না রানটাইম অপ্টিমাইজেশন। কমপক্ষে এটি প্রাথমিক উদ্বেগ নয় । যে কোনও ছোট / বড় রানটাইম অপ্টিমাইজেশান স্বাগত, তবে এখানে মূল ফ্যাক্টর নয়।


2
আপনার যেমন একটি কার্যক্ষম সমাধান রয়েছে, তবে এটি কি কোডেরভিউ.স্ট্যাকেক্সেক্সঞ্জ.কমের সাথে আরও ভাল লাগানো যাবে ?
নাইজেল রেন

1
প্রশ্নটি সবচেয়ে কার্যকর সমাধান চাইছে, অগত্যা কোনও কার্যনির্বাহী সমাধান নয়। আমি মনে করি এটি সম্পূর্ণরূপে বৈধ।
শেরিফ

1
আমি এটি বলছি না যে এটি এসও-তে বৈধ নয় (আমি এই ক্ষেত্রে বন্ধ করার পক্ষে ভোট দিয়েছি), আমি কেবল ভাবছি যে আপনি সিআর সম্পর্কে আরও বেশি সাড়া পেতে পারেন কিনা।
নাইজেল রেন

@ নিজেলেন আমি চেষ্টা করেও ক্ষতি দেখতে পাচ্ছি না। যদিও আমি এই খোলাটি কয়েক দিনের জন্য রেখে যেতে চাই। যদি এর উত্তর না পাওয়া যায় তবে আমি এটিতে একটি অনুগ্রহ রেখে দেব।
শেরিফ

1
আপনি যদি জন্ম মৃত্যুর কীওয়ার্ডগুলি অনুসন্ধান করেন তবে নিজেই আপনার সমস্যার অনেকগুলি প্রশ্ন রয়েছে। সস্তার উন্নতি করার জন্য একটি সস্তা উন্নতি হবে: জন্ম / মৃত্যুর স্প্যান দৈর্ঘ্যের একটি অ্যারে তৈরি করুন (প্রতিটি ঘর একটি তারিখ ডিফল্টরূপে 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. আমাকে ওয়াই-ফাস্ট ট্রাইয়ের অস্তিত্ব শেখানোর জন্য THX অ্যালগো সম্পর্কিত: হ্রাসের পরে সর্বোচ্চ পরীক্ষা করার দরকার নেই। কেবল ইনক্রিমেন্টিংয়ের পরে। অবশেষে ব্লকটি অনিবার্য: দুটি বাছাই করা তালিকা বাছাইয়ের বিষয়টি বিবেচনা করুন: আপনার কেবল দু'জনের মাথা প্রয়োজন (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)
গ্রডজি

@ গ্রেডজি আমি মার্জ সাজানোর বিষয়টি বিবেচনা করেই শুরু করেছিলাম তবে ডুপ্লিকেটগুলির পাশাপাশি জন্মের ক্রম ও মৃত্যুর ক্রম গণনাতে কীভাবে প্রভাব ফেলবে সে কারণে এটির জন্য অতিরিক্ত হ্যান্ডলিং দরকার। সর্বশেষ যখন লুপটি আমার কাছে প্রয়োজনীয় মনে হয় যখন জন্মের বছরের সাথে মৃত্যুর বছরগুলি তুলনা না করে। আপনি সঠিক যে op লুপের সর্বোচ্চটি অপ্রয়োজনীয়।
ברקן

@ Line রৈখিক সময়ের জন্য বালতি সাজানোর ব্যবহার করুন।
ডেভ

আমি ইতিমধ্যে আমার উত্তরে এই ধারণাটি জানিয়েছি, "যদি বছরের পরিসর, এম, এন এর নির্দেশে থাকে তবে আমরা প্রতি বছরের জন্য গণনাগুলি সীমার মধ্যে সঞ্চয় করতে পারি এবং ও (এন) সময়ের জটিলতা রাখতে পারি।"
ברקן ברקן

এটি দক্ষতা নয়, কেন আমি আপনাকে পুরষ্কার দিচ্ছি তা জানি না
এমিলিয়ানো

4

আমরা এটি রৈখিক সময়ে বালতি বাছাইয়ের মাধ্যমে সমাধান করতে পারি। ধরা যাক ইনপুটটির আকার n, এবং বছরের পরিসর মি।

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.

বৃহত্তম জমে থাকা আপনার উত্তর।

চলমান সময়টি হ'ল (এন + মি) এবং অতিরিক্ত স্থানের প্রয়োজন হ'ল ও (এম)।

এটি n এ লিনিয়ার সলিউশন যদি এম হে (এন) হয়; অর্থাত্, যদি বছরের বিভিন্ন পরিসীমা জন্ম ও মৃত্যুর সংখ্যার চেয়ে দ্রুত বৃদ্ধি না পায়। বাস্তব বিশ্বের ডেটাগুলির জন্য এটি প্রায় অবশ্যই সত্য।


1
আপনি একটি কাজের বাস্তবায়ন অন্তর্ভুক্ত করতে পারেন দয়া করে?
শেরিফ

1
@ শরীফ বাস্তবায়ন পাঠকের জন্য অনুশীলন হিসাবে রেখে গেছে ... যাইহোক এটি ক্ষুদ্র। কিছুই পরিষ্কার হয় না?
ডেভ

আমি নোট করব যেহেতু আপনার গ্রানুলারিটি বছর, তাই কিছুটা অস্পষ্টতা রয়েছে। এতে আমরা কার্যকরভাবে বছরের শেষের হিসাবে জনসংখ্যা পরিমাপ করছি এবং জন্ম-মৃত্যুর সময়কালের কারণে জনসংখ্যা বেশি হ'ল মাঝ বছরের মধ্যবর্তী সময়ে এমন আরও কিছু বিষয় থাকতে পারে।
ডেভ

1
লিনিয়ার সময়টি কীভাবে হয় যদি আমাদের একটি "আকারের অ্যারে ম্যাক্স_ ইয়ার - মিনিট_আর + 1" পার্স করতে হয়? (সিসি @ শরীফ)
23

1
@ ডেভ: জটিলতা 1 এবং 2 পয়েন্টের জন্য ও (2 এন) নয়? ১. সমস্ত জন্ম + মৃত্যুর মধ্য দিয়ে একবারে পুনরাবৃত্তি করুন: O(n): Find the min and max year across births and deaths ২. সমস্ত জন্মের মধ্য দিয়ে আবার পুনরাবৃত্তি করুন + মৃত্যু: O(n): Parse the births+death array, incrementing the appropriate index of the array তারপরে আপনি করুন: ও (এম): ক্রমসংখ্যার যোগফল এবং এর সর্বোচ্চ মানের সন্ধান করে আপনার অ্যারে পার্স করুন। (আপনার এই অ্যারেটি বিশ্লেষণের দরকার নেই - 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));

যেমনটি আমি দেখতে পেয়েছি: এন = সংখ্যার (জন্ম + মৃত্যু) এবং মি = ইভেন্টের বছরের সংখ্যার সাথে (জন্ম বা মৃত্যুর বছর) এটি আসলে ও (এন + মি লগ এম) হবে । যদি এন >> মি - এটি ও (এন) হিসাবে বিবেচিত হতে পারে । যদি আপনার 100 মিলিয়ন (বলুন) সময়কালে কোটি কোটি জন্ম এবং মৃত্যু হয় - 100 টি উপাদান ( ksort($indexed)) দিয়ে একটি অ্যারে বাছাই করা অপ্রাসঙ্গিক হয়ে যায়।
পল স্পিগেল

আপনি জন্মের সাথে প্রক্রিয়া করতে পারেন $indexed = array_count_values($births);
নাইজেল রেন

3

O(n+m)[সবচেয়ে খারাপ ক্ষেত্রে, সেরা ক্ষেত্রে O(n)] একটি মেমরির প্রয়োজনীয়তা দিয়ে আমি এই সমস্যাটি সমাধান করেছি

এবং সময় জটিলতা O(n logn)

এখানে n & mদৈর্ঘ্য birthsএবং deathsঅ্যারে রয়েছে।

আমি পিএইচপি বা জাভাস্ক্রিপ্ট জানি না। আমি এটি জাভা দিয়ে প্রয়োগ করেছি এবং যুক্তিটি খুব সহজ। তবে আমি বিশ্বাস করি আমার ধারণাগুলি সেই ভাষাগুলিতেও প্রয়োগ করা যেতে পারে।

প্রযুক্তি সম্পর্কিত বিবরণ:

আমি জাভা TreeMapকাঠামো জন্ম ও মৃত্যুর রেকর্ড সংরক্ষণ করতে ব্যবহার করি ।

TreeMap(কী, মান) জোড়া হিসাবে সাজানো ( কী ভিত্তিক ) ডেটা সন্নিবেশ করানো হয়, এখানে কীটি বছর এবং মান হ'ল জন্ম ও মৃত্যুর যোগফল (মৃত্যুর জন্য নেতিবাচক)।

আমাদের সর্বোচ্চ জন্ম বছরের পরে ঘটে যাওয়া মৃত্যুর মূল্য সন্নিবেশ করার দরকার নেই

একবার ট্রিম্যাপ জন্ম ও মৃত্যুর রেকর্ডে জনবহুল হয়ে গেলে, সমস্ত ক্রমসংখ্যাগুলি আপডেট হয় এবং অগ্রগতির সাথে সাথে বছরের সাথে সর্বোচ্চ জনসংখ্যা সংরক্ষণ করে store

নমুনা ইনপুট এবং আউটপুট: 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

আমি এই সমাধানটি খুব আরামদায়ক পূরণ করি, জটিলতা বড় ও + এন + এম

<?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
রোনাক ধৃত

প্রশ্নে যেমনটি বলা হয়েছে আমি রানটাইম অপ্টিমাইজেশনের পরে নই, তবে এটি আপনার বিগ হে গণনাটি এখানে কিছুটা বন্ধ রয়েছে বলে মনে করা উচিত। এছাড়াও, আপনার কোডটি কিছুটা ভাঙা। এটি বেশ কয়েকটি প্রান্তের ক্ষেত্রে ব্যর্থ হয়।
শেরিফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.