1
1
// Returns the day to buy, to sell and the sum
2
- const bruteForce = ( arr : number [ ] ) : [ number , number , number ] => {
3
- let sum , buy :number , sell :number ;
4
- let max = Number . NEGATIVE_INFINITY ;
5
- for ( let i = 0 ; i < arr . length ; i ++ ) {
6
- for ( let j = i + 1 ; j < arr . length ; j ++ ) {
7
- // buy in day i and sell in day j
8
- sum = arr [ j ] - arr [ i ] ;
9
- if ( sum > max ) {
10
- buy = i ;
11
- sell = j ;
12
- max = sum ;
13
- }
14
- }
15
- }
16
- return [ buy ! , sell ! , max ] ;
17
- } ;
18
-
19
- // Return an new arr, where arr[i] = arr[i] - arr[i-1]
20
- const transformArr = ( arr :number [ ] ) => {
21
- const ret = arr . map ( ( e , i ) => {
22
- return e - arr [ i - 1 ] ;
23
- } ) ;
24
- return ret . slice ( 1 ) ;
25
- } ;
26
-
27
- // Returns the indeces and the sum of vals of one max sub arr
28
- const findMaxSubarr = ( arr :number [ ] , low = 0 , high = arr . length - 1 ) :[ number , number , number ] => {
29
- // one element
30
- if ( low === high ) {
31
- return [ low , high , arr [ low ] ] ;
32
- }
33
- const mid = Math . floor ( ( high + low ) / 2 ) ;
34
- const [ leftLow , leftHigh , leftSum ] = findMaxSubarr ( arr , low , mid ) ;
35
- const [ rightLow , rightHigh , rightSum ] = findMaxSubarr ( arr , mid + 1 , high ) ;
36
- const [ crossLow , crossHigh , crossSum ] = findMaxCrossSubarr (
37
- arr ,
38
- low ,
39
- mid ,
40
- high
41
- ) ;
42
- if ( leftSum >= rightSum && leftSum >= crossSum ! ) {
43
- return [ leftLow , leftHigh , leftSum ] ;
44
- } else if ( rightSum >= leftSum && rightSum >= crossSum ! ) {
45
- return [ rightLow , rightHigh , rightSum ] ;
46
- }
47
- return [ crossLow ! , crossHigh ! , crossSum ! ] ;
48
- } ;
49
-
50
- // Returns max sum crossing mid
51
- // where this subarr starts (buy) and where it ends
52
- const findMaxCrossSubarr = ( arr :number [ ] , low : number , mid : number , high : number ) :[ number , number , number ] => {
53
- let leftSum = Number . NEGATIVE_INFINITY ;
54
- let rightSum = Number . NEGATIVE_INFINITY ;
55
- let sum = 0 ;
56
- let buy : number , sell : number
57
- // we need to start in mid because this subarr MUST contain mid
58
- for ( let i = mid ; i > low - 1 ; i -- ) {
59
- sum += arr [ i ] ;
60
- if ( sum > leftSum ) {
61
- leftSum = sum ;
2
+ export const bruteForce = ( arr : number [ ] ) : [ number , number , number ] => {
3
+ let sum , buy : number , sell : number ;
4
+ let max = Number . NEGATIVE_INFINITY ;
5
+ for ( let i = 0 ; i < arr . length ; i ++ ) {
6
+ for ( let j = i + 1 ; j < arr . length ; j ++ ) {
7
+ // buy in day i and sell in day j
8
+ sum = arr [ j ] - arr [ i ] ;
9
+ if ( sum > max ) {
62
10
buy = i ;
63
- }
64
- }
65
- sum = 0 ;
66
- for ( let j = mid + 1 ; j < high + 1 ; j ++ ) {
67
- sum += arr [ j ] ;
68
- if ( sum > rightSum ) {
69
- rightSum = sum ;
70
11
sell = j ;
12
+ max = sum ;
71
13
}
72
14
}
73
- return [ buy ! , sell ! , leftSum + rightSum ] ;
74
- } ;
75
-
76
- // Returns a random number between [0,max)
77
- const random = ( max : number ) => {
78
- return Math . floor ( Math . random ( ) * max ) ;
79
- } ;
80
-
81
- // Prints false if any test fails
82
- // size: len of arr
83
- // max: val max allowed
84
- // n: numer of times to test
85
- const testMaxSubarr = ( size : number , max : number , n : number ) : void => {
86
- for ( let i = 0 ; i < n ; i ++ ) {
87
- // create arr with len=size and random values in range [0,max)
88
- const arr = Array . from ( { length : size } , ( ) => random ( max ) ) ;
89
- const [ buy , sell , sum ] = bruteForce ( arr ) ;
90
- const [ low , high , val ] = findMaxSubarr ( transformArr ( arr ) ) ;
91
- console . assert ( sum === val ) ;
15
+ }
16
+ return [ buy ! , sell ! , max ] ;
17
+ } ;
18
+
19
+ // Return an new arr, where arr[i] = arr[i] - arr[i-1]
20
+ export const transformArr = ( arr : number [ ] ) => {
21
+ const ret = arr . map ( ( e , i ) => {
22
+ return e - arr [ i - 1 ] ;
23
+ } ) ;
24
+ return ret . slice ( 1 ) ;
25
+ } ;
26
+
27
+ // Returns the indeces and the sum of vals of one max sub arr
28
+ const findMaxSubarr = (
29
+ arr : number [ ] ,
30
+ low = 0 ,
31
+ high = arr . length - 1
32
+ ) : [ number , number , number ] => {
33
+ // one element
34
+ if ( low === high ) {
35
+ return [ low , high , arr [ low ] ] ;
36
+ }
37
+ const mid = Math . floor ( ( high + low ) / 2 ) ;
38
+ const [ leftLow , leftHigh , leftSum ] = findMaxSubarr ( arr , low , mid ) ;
39
+ const [ rightLow , rightHigh , rightSum ] = findMaxSubarr ( arr , mid + 1 , high ) ;
40
+ const [ crossLow , crossHigh , crossSum ] = findMaxCrossSubarr (
41
+ arr ,
42
+ low ,
43
+ mid ,
44
+ high
45
+ ) ;
46
+ if ( leftSum >= rightSum && leftSum >= crossSum ! ) {
47
+ return [ leftLow , leftHigh , leftSum ] ;
48
+ } else if ( rightSum >= leftSum && rightSum >= crossSum ! ) {
49
+ return [ rightLow , rightHigh , rightSum ] ;
50
+ }
51
+ return [ crossLow ! , crossHigh ! , crossSum ! ] ;
52
+ } ;
53
+
54
+ // Returns max sum crossing mid
55
+ // where this subarr starts (buy) and where it ends
56
+ const findMaxCrossSubarr = (
57
+ arr : number [ ] ,
58
+ low : number ,
59
+ mid : number ,
60
+ high : number
61
+ ) : [ number , number , number ] => {
62
+ let leftSum = Number . NEGATIVE_INFINITY ;
63
+ let rightSum = Number . NEGATIVE_INFINITY ;
64
+ let sum = 0 ;
65
+ let buy : number , sell : number ;
66
+ // we need to start in mid because this subarr MUST contain mid
67
+ for ( let i = mid ; i > low - 1 ; i -- ) {
68
+ sum += arr [ i ] ;
69
+ if ( sum > leftSum ) {
70
+ leftSum = sum ;
71
+ buy = i ;
72
+ }
73
+ }
74
+ sum = 0 ;
75
+ for ( let j = mid + 1 ; j < high + 1 ; j ++ ) {
76
+ sum += arr [ j ] ;
77
+ if ( sum > rightSum ) {
78
+ rightSum = sum ;
79
+ sell = j ;
92
80
}
93
- } ;
94
-
95
- testMaxSubarr ( 1000 , 100 , 100 )
96
- export { }
81
+ }
82
+ return [ buy ! , sell ! , leftSum + rightSum ] ;
83
+ } ;
84
+
85
+ // Returns a random number between [0,max)
86
+ export const random = ( max : number ) => {
87
+ return Math . floor ( Math . random ( ) * max ) ;
88
+ } ;
89
+
90
+ export default findMaxSubarr ;
0 commit comments