1+ /**
2+ * Solves the Weighted Interval Scheduling problem.
3+ *
4+ * Given intervals with start time, end time, and profit,
5+ * returns the maximum profit such that no intervals overlap.
6+ *
7+ * Uses Dynamic Programming + Binary Search.
8+ *
9+ * Time Complexity: O(n log n)
10+ * Space Complexity: O(n)
11+ *
12+ * @param {{start:number, end:number, profit:number}[] } intervals
13+ * @returns {number }
14+ */
15+
16+ const weightedIntervalScheduling = ( intervals ) => {
17+ if ( ! Array . isArray ( intervals ) ) {
18+ throw new Error ( 'Input must be an array of intervals' )
19+ }
20+
21+ if ( intervals . length === 0 ) return 0
22+
23+ // Sort intervals by end time
24+ intervals . sort ( ( a , b ) => a . end - b . end )
25+
26+ const n = intervals . length
27+ const dp = Array ( n ) . fill ( 0 )
28+
29+ dp [ 0 ] = intervals [ 0 ] . profit
30+
31+ // Binary search to find last non-overlapping interval
32+ const findLastNonOverlapping = ( index ) => {
33+ let left = 0
34+ let right = index - 1
35+
36+ while ( left <= right ) {
37+ const mid = Math . floor ( ( left + right ) / 2 )
38+
39+ if ( intervals [ mid ] . end <= intervals [ index ] . start ) {
40+ if ( intervals [ mid + 1 ] ?. end <= intervals [ index ] . start ) {
41+ left = mid + 1
42+ } else {
43+ return mid
44+ }
45+ } else {
46+ right = mid - 1
47+ }
48+ }
49+
50+ return - 1
51+ }
52+
53+ for ( let i = 1 ; i < n ; i ++ ) {
54+ let includeProfit = intervals [ i ] . profit
55+ const lastIndex = findLastNonOverlapping ( i )
56+
57+ if ( lastIndex !== - 1 ) {
58+ includeProfit += dp [ lastIndex ]
59+ }
60+
61+ dp [ i ] = Math . max ( dp [ i - 1 ] , includeProfit )
62+ }
63+
64+ return dp [ n - 1 ]
65+ }
66+
67+ export { weightedIntervalScheduling }
0 commit comments