Skip to content

Commit a355db0

Browse files
committed
Add Max Sub Array Test
1 parent c51d205 commit a355db0

File tree

2 files changed

+100
-90
lines changed

2 files changed

+100
-90
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import findMaxSubarr, { bruteForce, random, transformArr } from "./maxSubarr";
2+
3+
describe("Max Sub Arr test", () => {
4+
const SIZE = 1000;
5+
const MAX = 100;
6+
const N = 100;
7+
test("using random arr to check if D&C and BF obtain the same result", () => {
8+
for (let i = 0; i < N; i++) {
9+
// create arr with len=SIZE and random values in range [0,MAX)
10+
const arr = Array.from({ length: SIZE }, () => random(MAX));
11+
const [buy, sell, sum] = bruteForce(arr);
12+
const [low, high, val] = findMaxSubarr(transformArr(arr));
13+
expect(val).toBe(sum);
14+
}
15+
});
16+
});

src/divide-and-conquer/maxSubarr.ts

Lines changed: 84 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,90 @@
11
// 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) {
6210
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;
7011
sell = j;
12+
max = sum;
7113
}
7214
}
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;
9280
}
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

Comments
 (0)