Fastrail08

435. Non Overlapping Intervals(IMPORTANT DEDUCTION)

Jul 27th, 2025 (edited)
771
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.35 KB | None | 0 0
  1. //VISIT THIS for more understanding - https://chatgpt.com/share/6885b96b-4234-8012-a95a-7a1075632caf
  2. class Solution {
  3. public:
  4.     //This question can't be solved using LIS version as written below because of the following reason -
  5.     //AS both axis are dependent on each other
  6.     //end[nextLevel] >= start[currentLevel]
  7.     //The property spans over both the axis simultaneously due to which it is hard to make them independent.
  8.     //INDEPENDENT MEANS -
  9.     //SORT 1 axis (make it monotonic)
  10.     // USE LIS on other (take different monotonic sequence(here increasing) in AXIS 2, when ordered in ABSOLUTE MONOTONIC ORDER of AXIS 1)
  11.     // but the axis here are dependent on each other
  12.  
  13.     /*
  14.     -----I----------------I-------------I----- AXIS 1
  15.           I              I             I
  16.            I            I             I
  17.             I          I             I
  18.              I        I             I
  19.     ----------I------I-------------I----------- AXIS 2
  20.  
  21.  
  22.     If the diagram looks like this in(non overlapping bridges, russian doll envelopes), we consider it a variation of LIS where we apply LIS on 1 axis when BOTH the AXIS are in SORTED IN MONOTONIC ORDER of 1 AXIS.
  23.  
  24.     --------------------------------------------------------------------------------------------
  25.                     [start1]--------------------[end1]
  26.     [s2]--------e[2]                                  [s3]-------------[e3]
  27.                     [s4]----------[e4]                        [s5]-----[e5] [s6]--------------[e6]
  28.  
  29.  
  30.     Here both the axis are represented in a single combined axis from [start] ------[end].
  31.     Which means the both the axis are dependent on each other as they are represented in a single axis
  32.     It is what is present in the question such as non overlapping intervals(LC version), projects (cses), weighted scheduling problem[LC]
  33.  
  34.     here we see a dependency between the axis in the form of a conditional that interleaves both the values such as in Non overlapping intervals question, conditional used =>
  35.     if Current Level included, then jump to a level that satisfies start[nextLevel] >= end[currentLevel]              
  36.    
  37.     [[1,2],[1,3],[2,3],[3,4]] for this test case
  38.    
  39.     LIS VARIATION/AXES INDEPENDENT (Russian doll or Non Overlapping Bridges(GFG))
  40.     The answer would be 4, as all are non overlapping in nature. {[1,2], [1, 3], [2, 3], [3, 4]}
  41.    
  42.     JUMP DP/AXES DEPENDENT(Non Overlapping Intervals(LC), Projects(CSES), Weighted Scheduling Problem(LC))
  43.     The answer would be 3, as 3 are non overlapping in nature {[1,2], [2, 3]. [3, 4]}
  44.    
  45.     Draw Diagram, would be easy to notice.
  46.  
  47.     */
  48.     int getMaxOverlap(int level, vector<vector<int> > &intervals){
  49.         int maxLength = 0;
  50.         bool flag = false;
  51.  
  52.         for(int i = level + 1; i < intervals.size(); i++){
  53.             //indicates the loop ran ATLEAST ONCE
  54.             flag = true;
  55.             //LIS condition, ONLY CALL TO LEVELS THAT ARE VALID
  56.             //VALID LEVELS, any nextLevel that follows the property => END[nextLevel] >= END[level]
  57.             if(intervals[i][1] >= intervals[level][1]){
  58.                 maxLength = max(maxLength, 1 + getMaxOverlap(i, intervals));
  59.             }
  60.         }
  61.         //if loop didn't run, the value of current valid level never got added as it happens inside loop => 1 + recursive call
  62.         // ADD it EXPLCITLY to the maxLength;
  63.         //return flag == true ? maxLength : maxLength + 1;
  64.  
  65.         //OR you could simply return the value of current level, i.e. 1
  66.         // AS there were no further levels which were valid relative to the current level, the maxLength of the chain that can be formed from  range[level, intervals.size() - 1], INCLUDING level is 1 (current level itself is chain of length 1)
  67.        
  68.         return flag == true ? maxLength : 1;
  69.     }
  70.  
  71.     //LIS VERSION
  72.     int eraseOverlapIntervals(vector<vector<int>>& intervals) {
  73.         int n = intervals.size();
  74.         //sort the intervals to remove dependency from start, NO NEED TO TRACK START as they always increase
  75.         //START is always increasing, so start[level + 1] >= start[level], which makes OVERLAP of intervals impossible based on START as they are always increasing/of monotonic nature.
  76.         sort(intervals.begin(), intervals.end());
  77.  
  78.         //USE LIS on END
  79.         //So for END[level] we need to figure what is maximum increasing sequence when ORDERED in INCREASING ORDER of start times.
  80.         //IMPORTANT
  81.         // 2 AXIS where both AXIS work INDEPENDENTLY
  82.  
  83.         // WE SORT THE FIRST AXIS (introduces monotonicity in that axis, ALWAYS INCREASING)
  84.         // WE DO LIS on SECOND AXIS (for monotonic first axis, find maximum length in 2nd AXIS)
  85.         int maxLength = 0;
  86.         //give every interval the chance to be the first in the sequence
  87.         for(int i = 0; i < n; i++){
  88.             maxLength = max(maxLength, getMaxOverlap(i, intervals));
  89.         }
  90.         return n - maxLength;
  91.     }
  92. };
  93.  
  94. /*
  95. //BEST APPROACH TO DO IT (JUMP DP QUESTION)
  96. //JUMP DP QUESTIONS ARE THOSE QUESTIONS WHERE AXES ARE DEPENDENT ON EACH OTHER/CONDITIONAL WRITTEN INCLUDES element //FROM BOTH THE AXES.
  97. //such as start[nextLevel] >= end[currentLevel]
  98. //THEY ARE DIFFERENT FROM LIS BASED QUESTION, where 1 axis is sorted to make it monotonic and on the other AXIS LIS is //applied.
  99.  
  100. class Solution {
  101. public:
  102.  
  103.     //finding the next OPTIMAL start point O(N)
  104.     int findNextLevel(int level, vector<vector<int> > &intervals){
  105.         for(int i = level + 1; i < intervals.size(); i++){
  106.             //next VALID level is the FIRST/CLOSEST level with property start[nextLevel] >= end[level]
  107.             if(intervals[level][1] <= intervals[i][0]){
  108.                 return i;
  109.             }
  110.         }
  111.         //if there is no next valid after current level, return the index = intervals.size(), SIGNIFYING all the intervals have been processed, and it gets CATCHED in the BASE CASE
  112.         return intervals.size();
  113.     }
  114.  
  115.     //O(log(n)) time to find next valid level
  116.     int findNextLevelBS(int level, vector<vector<int> > &intervals){
  117.         int l = level + 1, r = intervals.size() - 1, idx = intervals.size();
  118.         while(l <= r){
  119.             int mid = (l + r) / 2;
  120.             //if the start[mid] >= end[currentLevel], valid level found, save and search for better
  121.             if(intervals[mid][0] >= intervals[level][1]){
  122.                 idx = mid;
  123.                 r = mid - 1;
  124.             }
  125.             else{
  126.                 l = mid + 1;
  127.             }
  128.         }
  129.         //if bs ran, it would return the MOST OPTIMAL level(A level with interval which has a start JUST LARGER than the end of current level), if it didn't run, it would return intervals.size(), signifying that all the intervals that could be processed are already processed, now we reach base case.
  130.         return idx;
  131.     }
  132.  
  133.     int getMaxOverlap(int level, vector<vector<int> > &intervals, vector<int> &memo){
  134.         if(level >= intervals.size()){
  135.             return 0;
  136.         }
  137.         if(memo[level] != -1){
  138.             return memo[level];
  139.         }
  140.         int inc = 0, exc = 0;
  141.         //include the current level, increase chain by 1, move to the next VALID level
  142.         int nextLevel = findNextLevelBS(level, intervals);
  143.         inc = 1 + getMaxOverlap(nextLevel, intervals, memo);
  144.        
  145.         //next level is automatically valid if current excluded as start[level + 1] >= start[level]
  146.         exc = getMaxOverlap(level + 1, intervals, memo);
  147.  
  148.         return memo[level] = max(inc, exc);
  149.     }
  150.  
  151.     int eraseOverlapIntervals(vector<vector<int>>& intervals) {
  152.         int n = intervals.size();
  153.         sort(intervals.begin(), intervals.end());
  154.         //memo key = memo(level) as it is the ONLY variable that is changing, influencing either the base case or transition logic (here base case), and not derivable
  155.         //memo(level) => range of level{0, 1, 2, 3, 4 .......n} => memo[n]
  156.         vector<int> memo(n, -1);
  157.         //ALTHOUGH we are only jumping to VALID LEVELS, still the complexity of code in worst case would be
  158.         //T.C. = O(N*log(N)) and S.C. = O(N)
  159.         //As there can be at max N levels in wors case(all non overlapping) and at each level log(N) work is done
  160.         //So the total complexity would be total unique states * work at each level
  161.         //N * log(N)
  162.         return intervals.size() - getMaxOverlap(0, intervals, memo);
  163.     }
  164. };
  165. */
  166.  
Advertisement
Add Comment
Please, Sign In to add comment