Intersection of the interval set

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












Recently I had an interview where it was asked:
Given a list of people with their birth and end years find the year with the most number of people alive.
I implemented in Java and was trying to find the optimal solution. I am sure there might be some data structure which will be optimal to use in this scenario.



static class Person 
int born;
int died;

Person(int born, int died)
this.born = born;
this.died = died;



/*
* (1920, 1939),
* (1911, 1944),
* (1920, 1955),
* (1938, 1939),
* (1920, 1939),
* (1911, 1944),
* (1920, 1955),
* (1938, 1939),
* (1937, 1940)
*
*/

public static void main(String args)
List<Person> people = new ArrayList<>();
people.add(new Person(1933, 1989));
people.add(new Person(1920, 1939));
people.add(new Person(1911, 1944));
people.add(new Person(1920, 1955));
people.add(new Person(1938, 1939));
people.add(new Person(1920, 1939));
people.add(new Person(1911, 1944));
people.add(new Person(1920, 1955));
people.add(new Person(1938, 1939));
people.add(new Person(1937, 1940));
System.out.println(solution1(people));



public static int solution1(List<Person> people)
HashMap<Integer, Integer> peopleMap = new HashMap<>();
int maxCount = 0;
int year = 0;
for (Person p : people)
for (int i = p.born; i <= p.died; i++)
Integer value = peopleMap.get(i);
if (value == null)
peopleMap.put(i, 1);
else
value++;
if (maxCount < value)
maxCount = value;
year = i;

peopleMap.put(i, value);



return year;







share|improve this question



























    up vote
    1
    down vote

    favorite












    Recently I had an interview where it was asked:
    Given a list of people with their birth and end years find the year with the most number of people alive.
    I implemented in Java and was trying to find the optimal solution. I am sure there might be some data structure which will be optimal to use in this scenario.



    static class Person 
    int born;
    int died;

    Person(int born, int died)
    this.born = born;
    this.died = died;



    /*
    * (1920, 1939),
    * (1911, 1944),
    * (1920, 1955),
    * (1938, 1939),
    * (1920, 1939),
    * (1911, 1944),
    * (1920, 1955),
    * (1938, 1939),
    * (1937, 1940)
    *
    */

    public static void main(String args)
    List<Person> people = new ArrayList<>();
    people.add(new Person(1933, 1989));
    people.add(new Person(1920, 1939));
    people.add(new Person(1911, 1944));
    people.add(new Person(1920, 1955));
    people.add(new Person(1938, 1939));
    people.add(new Person(1920, 1939));
    people.add(new Person(1911, 1944));
    people.add(new Person(1920, 1955));
    people.add(new Person(1938, 1939));
    people.add(new Person(1937, 1940));
    System.out.println(solution1(people));



    public static int solution1(List<Person> people)
    HashMap<Integer, Integer> peopleMap = new HashMap<>();
    int maxCount = 0;
    int year = 0;
    for (Person p : people)
    for (int i = p.born; i <= p.died; i++)
    Integer value = peopleMap.get(i);
    if (value == null)
    peopleMap.put(i, 1);
    else
    value++;
    if (maxCount < value)
    maxCount = value;
    year = i;

    peopleMap.put(i, value);



    return year;







    share|improve this question























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      Recently I had an interview where it was asked:
      Given a list of people with their birth and end years find the year with the most number of people alive.
      I implemented in Java and was trying to find the optimal solution. I am sure there might be some data structure which will be optimal to use in this scenario.



      static class Person 
      int born;
      int died;

      Person(int born, int died)
      this.born = born;
      this.died = died;



      /*
      * (1920, 1939),
      * (1911, 1944),
      * (1920, 1955),
      * (1938, 1939),
      * (1920, 1939),
      * (1911, 1944),
      * (1920, 1955),
      * (1938, 1939),
      * (1937, 1940)
      *
      */

      public static void main(String args)
      List<Person> people = new ArrayList<>();
      people.add(new Person(1933, 1989));
      people.add(new Person(1920, 1939));
      people.add(new Person(1911, 1944));
      people.add(new Person(1920, 1955));
      people.add(new Person(1938, 1939));
      people.add(new Person(1920, 1939));
      people.add(new Person(1911, 1944));
      people.add(new Person(1920, 1955));
      people.add(new Person(1938, 1939));
      people.add(new Person(1937, 1940));
      System.out.println(solution1(people));



      public static int solution1(List<Person> people)
      HashMap<Integer, Integer> peopleMap = new HashMap<>();
      int maxCount = 0;
      int year = 0;
      for (Person p : people)
      for (int i = p.born; i <= p.died; i++)
      Integer value = peopleMap.get(i);
      if (value == null)
      peopleMap.put(i, 1);
      else
      value++;
      if (maxCount < value)
      maxCount = value;
      year = i;

      peopleMap.put(i, value);



      return year;







      share|improve this question













      Recently I had an interview where it was asked:
      Given a list of people with their birth and end years find the year with the most number of people alive.
      I implemented in Java and was trying to find the optimal solution. I am sure there might be some data structure which will be optimal to use in this scenario.



      static class Person 
      int born;
      int died;

      Person(int born, int died)
      this.born = born;
      this.died = died;



      /*
      * (1920, 1939),
      * (1911, 1944),
      * (1920, 1955),
      * (1938, 1939),
      * (1920, 1939),
      * (1911, 1944),
      * (1920, 1955),
      * (1938, 1939),
      * (1937, 1940)
      *
      */

      public static void main(String args)
      List<Person> people = new ArrayList<>();
      people.add(new Person(1933, 1989));
      people.add(new Person(1920, 1939));
      people.add(new Person(1911, 1944));
      people.add(new Person(1920, 1955));
      people.add(new Person(1938, 1939));
      people.add(new Person(1920, 1939));
      people.add(new Person(1911, 1944));
      people.add(new Person(1920, 1955));
      people.add(new Person(1938, 1939));
      people.add(new Person(1937, 1940));
      System.out.println(solution1(people));



      public static int solution1(List<Person> people)
      HashMap<Integer, Integer> peopleMap = new HashMap<>();
      int maxCount = 0;
      int year = 0;
      for (Person p : people)
      for (int i = p.born; i <= p.died; i++)
      Integer value = peopleMap.get(i);
      if (value == null)
      peopleMap.put(i, 1);
      else
      value++;
      if (maxCount < value)
      maxCount = value;
      year = i;

      peopleMap.put(i, value);



      return year;









      share|improve this question












      share|improve this question




      share|improve this question








      edited Apr 6 at 17:17









      200_success

      123k14142399




      123k14142399









      asked Apr 6 at 15:13









      MrA

      93128




      93128




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          HashMap is overkill here.



          Depending on the constraints of the problem (mainly the minimum and maximum allowable years), you could simply use an array instead of a HashMap.



          Sure HashMaps have a O(1) complexity, but nothing is going to beat just indexing an array.



          Better algorithm



          Coming up with a better algorithm is very tricky.



          Your solution is O(NL) where N is the number of people and L is the average lifetime. But keep in mind that L is practically a constant, so it does not really matter that much.



          You could most certainly come up with a O(NlogN) solution, based on creating a sorted list of relevant dates. This would outperform your current solution for small values of N, but better performance at the low end is rarely useful (it can be, but that's the exception, not the rule).



          Edit Thinking about this, I suspect that's the "trick" part of that interview question. Overlapping intervals is a classic interview problem. However, making the intervals happen on a fully discretized space makes the hashmap solution viable, whereas it can't be used when dealing with "traditional" float-bound intervals.






          share|improve this answer























          • The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
            – Bill K
            Apr 6 at 16:24










          • @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
            – Frank
            Apr 6 at 16:27











          • Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
            – Bill K
            Apr 6 at 17:43

















          up vote
          0
          down vote













          Nothing wrong with using the HashMap, but…



          … all you actually need to store is the overall change for each year. Not even total births or deaths, just the total change. You can iterate at the end, and (keeping a high water mark) to find the maximum you only need to check when your change for the year is positive.



          Things that might help



          • Sort by birth, and keep a priority queue of deaths.

          • Separate the birth and death, sort both lists.

          Plenty wrong with the question, though



          (the interviewer’s, not your posting here).



          • Should changes be considered to happen at the start of the year?

          • The end?

          • When do you measure?

          • Is it the average number for the year, or the maximum possible? Do any of the births happen before any of the deaths?

          .. and so on. The problem is a little under-specified.






          share|improve this answer





















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191416%2fintersection-of-the-interval-set%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            HashMap is overkill here.



            Depending on the constraints of the problem (mainly the minimum and maximum allowable years), you could simply use an array instead of a HashMap.



            Sure HashMaps have a O(1) complexity, but nothing is going to beat just indexing an array.



            Better algorithm



            Coming up with a better algorithm is very tricky.



            Your solution is O(NL) where N is the number of people and L is the average lifetime. But keep in mind that L is practically a constant, so it does not really matter that much.



            You could most certainly come up with a O(NlogN) solution, based on creating a sorted list of relevant dates. This would outperform your current solution for small values of N, but better performance at the low end is rarely useful (it can be, but that's the exception, not the rule).



            Edit Thinking about this, I suspect that's the "trick" part of that interview question. Overlapping intervals is a classic interview problem. However, making the intervals happen on a fully discretized space makes the hashmap solution viable, whereas it can't be used when dealing with "traditional" float-bound intervals.






            share|improve this answer























            • The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
              – Bill K
              Apr 6 at 16:24










            • @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
              – Frank
              Apr 6 at 16:27











            • Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
              – Bill K
              Apr 6 at 17:43














            up vote
            0
            down vote













            HashMap is overkill here.



            Depending on the constraints of the problem (mainly the minimum and maximum allowable years), you could simply use an array instead of a HashMap.



            Sure HashMaps have a O(1) complexity, but nothing is going to beat just indexing an array.



            Better algorithm



            Coming up with a better algorithm is very tricky.



            Your solution is O(NL) where N is the number of people and L is the average lifetime. But keep in mind that L is practically a constant, so it does not really matter that much.



            You could most certainly come up with a O(NlogN) solution, based on creating a sorted list of relevant dates. This would outperform your current solution for small values of N, but better performance at the low end is rarely useful (it can be, but that's the exception, not the rule).



            Edit Thinking about this, I suspect that's the "trick" part of that interview question. Overlapping intervals is a classic interview problem. However, making the intervals happen on a fully discretized space makes the hashmap solution viable, whereas it can't be used when dealing with "traditional" float-bound intervals.






            share|improve this answer























            • The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
              – Bill K
              Apr 6 at 16:24










            • @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
              – Frank
              Apr 6 at 16:27











            • Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
              – Bill K
              Apr 6 at 17:43












            up vote
            0
            down vote










            up vote
            0
            down vote









            HashMap is overkill here.



            Depending on the constraints of the problem (mainly the minimum and maximum allowable years), you could simply use an array instead of a HashMap.



            Sure HashMaps have a O(1) complexity, but nothing is going to beat just indexing an array.



            Better algorithm



            Coming up with a better algorithm is very tricky.



            Your solution is O(NL) where N is the number of people and L is the average lifetime. But keep in mind that L is practically a constant, so it does not really matter that much.



            You could most certainly come up with a O(NlogN) solution, based on creating a sorted list of relevant dates. This would outperform your current solution for small values of N, but better performance at the low end is rarely useful (it can be, but that's the exception, not the rule).



            Edit Thinking about this, I suspect that's the "trick" part of that interview question. Overlapping intervals is a classic interview problem. However, making the intervals happen on a fully discretized space makes the hashmap solution viable, whereas it can't be used when dealing with "traditional" float-bound intervals.






            share|improve this answer















            HashMap is overkill here.



            Depending on the constraints of the problem (mainly the minimum and maximum allowable years), you could simply use an array instead of a HashMap.



            Sure HashMaps have a O(1) complexity, but nothing is going to beat just indexing an array.



            Better algorithm



            Coming up with a better algorithm is very tricky.



            Your solution is O(NL) where N is the number of people and L is the average lifetime. But keep in mind that L is practically a constant, so it does not really matter that much.



            You could most certainly come up with a O(NlogN) solution, based on creating a sorted list of relevant dates. This would outperform your current solution for small values of N, but better performance at the low end is rarely useful (it can be, but that's the exception, not the rule).



            Edit Thinking about this, I suspect that's the "trick" part of that interview question. Overlapping intervals is a classic interview problem. However, making the intervals happen on a fully discretized space makes the hashmap solution viable, whereas it can't be used when dealing with "traditional" float-bound intervals.







            share|improve this answer















            share|improve this answer



            share|improve this answer








            edited Apr 6 at 16:32


























            answered Apr 6 at 16:04









            Frank

            2,947319




            2,947319











            • The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
              – Bill K
              Apr 6 at 16:24










            • @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
              – Frank
              Apr 6 at 16:27











            • Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
              – Bill K
              Apr 6 at 17:43
















            • The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
              – Bill K
              Apr 6 at 16:24










            • @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
              – Frank
              Apr 6 at 16:27











            • Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
              – Bill K
              Apr 6 at 17:43















            The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
            – Bill K
            Apr 6 at 16:24




            The sorted list of dates is probably the best answer. generate a sorted list at logN then iterate over it once keeping a running count. There might be some other tricky way to do it with a single pass and some interesting custom data structure--but I can't see it (and it would probably still be logN to create your Interesting data structure).
            – Bill K
            Apr 6 at 16:24












            @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
            – Frank
            Apr 6 at 16:27





            @BillK You'll have a hard time generating the list without visiting each element, making that a NlogN. For reference, the "interesting data structure" could simply be a pair of dates/bool (wether it's a birth or a death).
            – Frank
            Apr 6 at 16:27













            Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
            – Bill K
            Apr 6 at 17:43




            Yeah, that's what I meant--logN to create it while it's being iterated over would = NlogN... I didn't say that very clearly, thanks :)
            – Bill K
            Apr 6 at 17:43












            up vote
            0
            down vote













            Nothing wrong with using the HashMap, but…



            … all you actually need to store is the overall change for each year. Not even total births or deaths, just the total change. You can iterate at the end, and (keeping a high water mark) to find the maximum you only need to check when your change for the year is positive.



            Things that might help



            • Sort by birth, and keep a priority queue of deaths.

            • Separate the birth and death, sort both lists.

            Plenty wrong with the question, though



            (the interviewer’s, not your posting here).



            • Should changes be considered to happen at the start of the year?

            • The end?

            • When do you measure?

            • Is it the average number for the year, or the maximum possible? Do any of the births happen before any of the deaths?

            .. and so on. The problem is a little under-specified.






            share|improve this answer

























              up vote
              0
              down vote













              Nothing wrong with using the HashMap, but…



              … all you actually need to store is the overall change for each year. Not even total births or deaths, just the total change. You can iterate at the end, and (keeping a high water mark) to find the maximum you only need to check when your change for the year is positive.



              Things that might help



              • Sort by birth, and keep a priority queue of deaths.

              • Separate the birth and death, sort both lists.

              Plenty wrong with the question, though



              (the interviewer’s, not your posting here).



              • Should changes be considered to happen at the start of the year?

              • The end?

              • When do you measure?

              • Is it the average number for the year, or the maximum possible? Do any of the births happen before any of the deaths?

              .. and so on. The problem is a little under-specified.






              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                Nothing wrong with using the HashMap, but…



                … all you actually need to store is the overall change for each year. Not even total births or deaths, just the total change. You can iterate at the end, and (keeping a high water mark) to find the maximum you only need to check when your change for the year is positive.



                Things that might help



                • Sort by birth, and keep a priority queue of deaths.

                • Separate the birth and death, sort both lists.

                Plenty wrong with the question, though



                (the interviewer’s, not your posting here).



                • Should changes be considered to happen at the start of the year?

                • The end?

                • When do you measure?

                • Is it the average number for the year, or the maximum possible? Do any of the births happen before any of the deaths?

                .. and so on. The problem is a little under-specified.






                share|improve this answer













                Nothing wrong with using the HashMap, but…



                … all you actually need to store is the overall change for each year. Not even total births or deaths, just the total change. You can iterate at the end, and (keeping a high water mark) to find the maximum you only need to check when your change for the year is positive.



                Things that might help



                • Sort by birth, and keep a priority queue of deaths.

                • Separate the birth and death, sort both lists.

                Plenty wrong with the question, though



                (the interviewer’s, not your posting here).



                • Should changes be considered to happen at the start of the year?

                • The end?

                • When do you measure?

                • Is it the average number for the year, or the maximum possible? Do any of the births happen before any of the deaths?

                .. and so on. The problem is a little under-specified.







                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered Apr 7 at 0:41









                Will Crawford

                1112




                1112






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191416%2fintersection-of-the-interval-set%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Chat program with C++ and SFML

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    Will my employers contract hold up in court?