Skip to content

Commit 64a4a4f

Browse files
chore(lab): add new exercises
* chore(lab): critial routers exercise * solve the problem but with repetitions * 🔧 chore (lab): solve the problem * --wip-- [skip ci] * --wip-- [skip ci] * feat(lab): integer to words * feat(lab): improve algo to cover corner cases * chore(lab): alien dictionary exercise * chore(lab): sum exercises added * new exercise * using dijkstra algorithm * new exercises * update exercises * new exercise * solution * 🔧 chore eslint
1 parent bcc81b4 commit 64a4a4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+11752
-5974
lines changed

.eslintrc.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ module.exports = {
1515

1616
// https://eslint.org/docs/rules/no-plusplus
1717
// allows unary operators ++ and -- in the afterthought (final expression) of a for loop.
18-
'no-plusplus': [2,{'allowForLoopAfterthoughts': true}],
18+
'no-plusplus': [0,{'allowForLoopAfterthoughts': true}],
19+
'no-continue': [0],
1920

2021
// Allow for..of
2122
'no-restricted-syntax': [0,'ForOfStatement'],

lab/exercises/10-mixed/2sum-1.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
/**
3+
* Given a SORTED array and a target, return the indices of the 2 number that sum up target
4+
*
5+
* @param {number[]} nums
6+
* @param {numer} target
7+
* @returns
8+
*
9+
* @runtime O(n)
10+
*/
11+
functiontwoSum(nums,target){
12+
constlen=nums.length-1;
13+
letlo=0;
14+
lethi=len;
15+
16+
while(lo<hi&&hi>0&&lo<len){
17+
constsum=nums[lo]+nums[hi];
18+
if(sum===target){
19+
return[lo,hi];
20+
}
21+
if(sum>target){
22+
hi--;
23+
}else{
24+
lo++;
25+
}
26+
}
27+
28+
return[];
29+
}
30+
31+
module.exports=twoSum;

lab/exercises/10-mixed/2sum.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
/**
3+
* Given an array and a target, return the indices of the 2 number that sum up target
4+
*
5+
* @param {number[]} nums
6+
* @param {numer} target
7+
* @returns
8+
*
9+
* @runtime O(n)
10+
*/
11+
functiontwoSum(nums,target){
12+
constmap=newMap();
13+
14+
for(leti=0;i<nums.length;i++){
15+
constdiff=target-nums[i];
16+
if(map.has(diff)){
17+
return[map.get(diff),i];
18+
}
19+
map.set(nums[i],i);
20+
}
21+
22+
return[];
23+
}
24+
25+
module.exports=twoSum;

lab/exercises/10-mixed/2sum.spec.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
constfn=require('./2sum');
2+
3+
describe('2 sum',()=>{
4+
it('should work',()=>{
5+
expect(fn([-1,0,1],0)).toEqual(expect.arrayContaining([0,2]));
6+
});
7+
8+
it('should work',()=>{
9+
expect(fn([2,7,11,15],9)).toEqual([0,1]);
10+
});
11+
12+
it('should work',()=>{
13+
expect(fn([2,7,11,15],18)).toEqual([1,2]);
14+
});
15+
16+
it('should be empty',()=>{
17+
expect(fn([2,7,11,15],1)).toEqual([]);
18+
});
19+
20+
it('should should work with non-sorted',()=>{
21+
expect(fn([3,2,4],6)).toEqual([1,2]);
22+
});
23+
});

lab/exercises/10-mixed/3sum-1.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number[][]}
4+
*
5+
* @runtime O(n^3)
6+
*/
7+
functionthreeSum(nums){
8+
constans=newSet();
9+
10+
for(leti=0;i<nums.length;i++){
11+
for(letj=i+1;j<nums.length;j++){
12+
for(letk=j+1;k<nums.length;k++){
13+
if(nums[i]+nums[j]+nums[k]===0){
14+
ans.add(JSON.stringify([nums[i],nums[j],nums[k]].sort()));
15+
}
16+
}
17+
}
18+
}
19+
20+
returnArray.from(ans).map((s)=>JSON.parse(s));
21+
}
22+
23+
module.exports=threeSum;
24+
25+
// Given an array find the unique triplets elements that sum zero.
26+
27+
// Brute force: O(n^3)
28+
// Using twoSum: O(n^2)
29+
//

lab/exercises/10-mixed/3sum-2.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number[][]}
4+
*
5+
* @runtime O(n^2)
6+
* @space O(n)
7+
*/
8+
constthreeSum=function(nums){
9+
constarray=nums.reduce((acc,n,i)=>{// O(n^2)
10+
if(i>nums.length-2)returnacc;
11+
constpartial=twoSum(nums,-n,i+1);
12+
constres=partial.map((p)=>[n, ...p]);
13+
// console.log({i, n, partial, res, acc})
14+
returnacc.concat(res);
15+
},[]);
16+
17+
// remove dups
18+
constset=array.reduce((acc,n)=>{
19+
conststr=n.sort((a,b)=>a-b).toString();
20+
returnacc.add(str);
21+
},newSet());
22+
23+
// convert to array of nums
24+
return[...set].map((a)=>a.split(',').map((n)=>+n));
25+
};
26+
27+
functiontwoSum(nums,target,start){// O(n)
28+
constans=[];
29+
constmap=newMap();
30+
31+
for(leti=start;i<nums.length;i++){
32+
if(map.has(target-nums[i])){
33+
ans.push([target-nums[i],nums[i]]);
34+
}
35+
map.set(nums[i],i);
36+
}
37+
38+
returnans;
39+
}
40+
41+
module.exports=threeSum;
42+
43+
// Given an array find the unique triplets elements that sum zero.
44+
45+
// Brute force: O(n^3)
46+
// Using twoSum: O(n^2)
47+
//

lab/exercises/10-mixed/3sum.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number[][]}
4+
*
5+
* @runtime O(n^2) and skips duplicates
6+
* @space O(1)
7+
*/
8+
functionthreeSum(nums){
9+
constans=[];
10+
11+
nums.sort((a,b)=>a-b);// sort: O(n log n)
12+
13+
for(leti=0;i<nums.length-2;i++){// O(n^2)
14+
if(i>0&&nums[i-1]===nums[i])continue;// skip duplicates
15+
16+
letlo=i+1;
17+
lethi=nums.length-1;
18+
19+
while(lo<hi){
20+
constsum=nums[i]+nums[lo]+nums[hi];
21+
if(sum===0){
22+
ans.push([nums[i],nums[lo],nums[hi]]);
23+
// console.log([nums[i], nums[lo], nums[hi]]);
24+
lo++;
25+
hi--;
26+
while(lo<hi&&nums[lo-1]===nums[lo])lo++;// skip duplicates
27+
while(lo<hi&&nums[hi+1]===nums[hi])hi--;// skip duplicates
28+
}elseif(sum<0){
29+
lo++;
30+
while(lo<hi&&nums[lo-1]===nums[lo])lo++;// skip duplicates
31+
}else{
32+
hi--;
33+
while(lo<hi&&nums[hi+1]===nums[hi])hi--;// skip duplicates
34+
}
35+
}
36+
}
37+
38+
returnans;
39+
}
40+
41+
module.exports=threeSum;
42+
43+
// Given an array find the unique triplets elements that sum zero.
44+
45+
// Brute force: O(n^3)
46+
// Using twoSum: O(n^2)
47+
//

lab/exercises/10-mixed/3sum.spec.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
constfn=require('./3sum');
2+
3+
describe('3 Sum',()=>{
4+
it('should work',()=>{
5+
expect(fn([-1,0,1,2,-1,4])).toEqual(expect.arrayContaining([
6+
expect.arrayContaining([-1,0,1]),
7+
expect.arrayContaining([-1,2,-1]),
8+
]));
9+
});
10+
11+
it('should work',()=>{
12+
constactual=fn([-2,0,1,1,2]);
13+
expect(actual.length).toEqual(2);
14+
expect(actual).toEqual(expect.arrayContaining([
15+
expect.arrayContaining([-2,0,2]),
16+
expect.arrayContaining([-2,1,1]),
17+
]));
18+
});
19+
20+
it('should work',()=>{
21+
constactual=fn([-2,-4,-2,-2,0,1,2,2,2,3,3,4,4,6,6]);
22+
expect(actual.length).toEqual(6);
23+
expect(actual).toEqual(expect.arrayContaining([
24+
expect.arrayContaining([-4,-2,6]),
25+
expect.arrayContaining([-4,0,4]),
26+
expect.arrayContaining([-4,1,3]),
27+
expect.arrayContaining([-4,2,2]),
28+
expect.arrayContaining([-2,-2,4]),
29+
expect.arrayContaining([-2,0,2]),
30+
]));
31+
});
32+
33+
it('should work with many zeros',()=>{
34+
constactual=fn(Array(5).fill(0));
35+
expect(actual.length).toEqual(1);
36+
expect(JSON.stringify(actual)).toEqual('[[0,0,0]]');// jest negative zero workaround
37+
});
38+
39+
it('should work with large arrays',()=>{
40+
constactual=fn(Array(3000).fill(0));
41+
expect(actual.length).toEqual(1);
42+
expect(JSON.stringify(actual)).toEqual('[[0,0,0]]');
43+
});
44+
});
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
2+
/**
3+
* Add nodes and edges into a graph using adjacency list
4+
*
5+
* @class Graph
6+
*/
7+
classGraph{
8+
constructor(){
9+
this.nodes=newMap();
10+
}
11+
12+
// add node or directed edge
13+
add(node1,node2){
14+
// console.log({node1, node2})
15+
constadj=this.nodes.has(node1) ? this.nodes.get(node1) : newSet();
16+
if(node2)adj.add(node2);
17+
this.nodes.set(node1,adj);
18+
}
19+
}
20+
21+
/**
22+
* DFS + tarjan for loop detection
23+
*
24+
* @param {Graph} g
25+
* @param {Map} node
26+
* @param {Set} set
27+
* @param {Map} [parent=null]
28+
* @param {Map} [grouping=new Map()]
29+
* @param {number} [depth=0]
30+
* @returns {boolean} true if has a loop, false otherwise
31+
*/
32+
functionhasLoopOrAddToSet(g,node,set,parent=null,grouping=newMap(),depth=0){
33+
if(set.has(node))set.delete(node);
34+
set.add(node);
35+
grouping.set(node,depth);
36+
37+
// console.log({node, adjs: g.nodes.get(node)});
38+
39+
for(constadjofg.nodes.get(node)){
40+
// if (adj === parent) continue; // only for indirected graph
41+
42+
if(!grouping.has(adj)){
43+
if(hasLoopOrAddToSet(g,adj,set,node,grouping,depth+1))returntrue;
44+
}
45+
46+
constminGroup=Math.min(grouping.get(adj),grouping.get(node));
47+
grouping.set(node,minGroup);
48+
49+
if(grouping.get(adj)===grouping.get(node))returntrue;
50+
}
51+
}
52+
53+
54+
/**
55+
* Find the order of the alien alphabet given a list of words on lexicographical order.
56+
*
57+
* @param {string[]} words
58+
* @return {string} The alien alphabet order.
59+
*/
60+
functionalienOrder(words){
61+
constg=newGraph();
62+
if(!words||words.length<2)returnwords&&words.join('');
63+
64+
for(leti=1;i<words.length;i++){// O(n) * O(k)
65+
constw1=words[i-1];
66+
constw2=words[i];
67+
letj=0;
68+
69+
while(j<w1.length&&j<w2.length&&w1[j]===w2[j]){// O(k), k = max word length
70+
g.add(w1[j++]);
71+
}
72+
73+
if(j===w2.length&&w1.length>w2.length){
74+
return'';// shorter words should come first.
75+
}
76+
77+
if(w1[j])g.add(w1[j],w2[j]);
78+
[...w1.slice(j)].forEach((n)=>g.add(n));
79+
[...w2.slice(j)].forEach((n)=>g.add(n));
80+
}
81+
82+
// console.log({ g: JSON.stringify(g) });
83+
// console.log({ g: g.nodes });
84+
85+
constset=newSet();
86+
for(const[node]ofg.nodes){// O(?)
87+
if(hasLoopOrAddToSet(g,node,set)){// DFS: O(E + V), V: total unique letters
88+
return'';
89+
}
90+
}
91+
92+
return[...set].join('');
93+
}
94+
95+
module.exports=alienOrder;
96+
97+
// Find the order of the alien alphabet given a list of words on lexicographical order.
98+
99+
// take words in pair, and build a dependency graph.
100+
// skip while w1.char === w2.char
101+
// add the first diff chars as a adj nodes
102+
// add each letter as a node in the graph.
103+
104+
// find the order of the alien alph
105+
// iterate over each node
106+
// dfs + tarjan to detect loops
107+
// add each visited node to a set
108+
// if there’s a loop return ‘’
109+
// return set

0 commit comments

Comments
 (0)
close