Skip to content

Commit 10e31cf

Browse files
committed
update
1 parent 815e883 commit 10e31cf

12 files changed

+1060
-17
lines changed

first-missing-positive.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* First Missing Positive
3+
*
4+
* Given an unsorted integer array, find the smallest missing positive integer.
5+
*
6+
* Example 1:
7+
*
8+
* Input: [1,2,0]
9+
* Output: 3
10+
*
11+
* Example 2:
12+
*
13+
* Input: [3,4,-1,1]
14+
* Output: 2
15+
*
16+
* Example 3:
17+
*
18+
* Input: [7,8,9,11,12]
19+
* Output: 1
20+
*
21+
* Note:
22+
*
23+
* Your algorithm should run in O(n) time and uses constant extra space.
24+
*/
25+
26+
27+
/**
28+
* First Missing Positive
29+
* @param {number[]} nums
30+
* @return {number}
31+
* @time complexity: O(n)
32+
* @space complexity: O(1)
33+
*/
34+
function firstMissingPositive(nums) {
35+
const contains = new Set();
36+
let num = 1;
37+
38+
for (let n of nums) {
39+
contains.add(n);
40+
}
41+
42+
while (true) {
43+
if (!contains.has(num)) {
44+
return num;
45+
}
46+
num++;
47+
}
48+
}
49+
50+
/**
51+
* First Missing Positive
52+
* @param {number[]} nums
53+
* @return {number}
54+
* @time complexity: O(n)
55+
* @space complexity: O(1)
56+
*/
57+
function firstMissingPositiveUsingSort(nums) {
58+
let num = 1;
59+
60+
nums.sort((a, b) => a - b);
61+
62+
for (let n of nums) {
63+
if (n === num) {
64+
num++;
65+
} else if (n > num) {
66+
return num;
67+
}
68+
}
69+
70+
return num;
71+
}
72+
73+
const assert = require('chai').assert;
74+
75+
describe('First Missing Positive', () => {
76+
77+
it('should return 3 when [1,2,0] is given', () => {
78+
assert.strictEqual(firstMissingPositive([1,2,0]), 3);
79+
});
80+
81+
it('should return 2 when [3,4,-1,1] is given', () => {
82+
assert.strictEqual(firstMissingPositive([3,4,-1,1]), 2);
83+
});
84+
85+
it('should return 1 when [7,8,9,11,12] is given', () => {
86+
assert.strictEqual(firstMissingPositive([7,8,9,11,12]), 1);
87+
});
88+
89+
});
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Lowest Common Ancestor of a Binary Tree
3+
*
4+
* Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
5+
*
6+
* According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
7+
*
8+
* Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
9+
*
10+
* 3
11+
* / \
12+
* 5 1
13+
* / \ / \
14+
* 6 2 0 8
15+
* / \
16+
* 7 4
17+
*
18+
* Example 1:
19+
*
20+
* Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
21+
* Output: 3
22+
* Explanation: The LCA of nodes 5 and 1 is 3.
23+
*
24+
* Example 2:
25+
*
26+
* Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
27+
* Output: 5
28+
* Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
29+
*
30+
* Note:
31+
*
32+
* All of the nodes' values will be unique.
33+
* p and q are different and both values will exist in the binary tree.
34+
*/
35+
36+
/**
37+
* Definition for a binary tree node.
38+
*/
39+
function TreeNode(val) {
40+
this.val = val;
41+
this.left = this.right = null;
42+
}
43+
44+
/**
45+
* @param {TreeNode} root
46+
* @param {TreeNode} p
47+
* @param {TreeNode} q
48+
* @return {TreeNode}
49+
* @time complexity: O(n) where n is the number of nodes
50+
* @space complexity: O(n) utilized by recursion stack
51+
*/
52+
var lowestCommonAncestor = function(root, p, q) {
53+
if (!root || root.val === p.val || root.val === q.val) {
54+
return root;
55+
}
56+
57+
const left = lowestCommonAncestor(root.left, p, q);
58+
const right = lowestCommonAncestor(root.right, p, q);
59+
60+
if (!left) {
61+
return right;
62+
}
63+
64+
if (!right) {
65+
return left;
66+
}
67+
68+
return root;
69+
};
70+
71+
72+
const assert = require('chai').assert;
73+
74+
describe('Lowest Common Ancestor of a Binary Tree', () => {
75+
let tree;
76+
77+
before(() => {
78+
tree = arrayToTree([3,5,1,6,2,0,8,null,null,7,4]);
79+
80+
function arrayToTree(arr, root = null, index = 0) {
81+
if (index < arr.length) {
82+
root = new TreeNode(arr[index]);
83+
84+
root.left = arrayToTree(arr, root.left, 2 * index + 1);
85+
root.right = arrayToTree(arr, root.right, 2 * index + 2);
86+
}
87+
return root;
88+
}
89+
});
90+
91+
it('should return node with value of 3', () => {
92+
const result = lowestCommonAncestor(tree, new TreeNode(5), new TreeNode(1));
93+
assert.strictEqual(result.val, 3);
94+
});
95+
96+
it('should return node with value of 5', () => {
97+
const result = lowestCommonAncestor(tree, new TreeNode(5), new TreeNode(4));
98+
assert.strictEqual(result.val, 5);
99+
});
100+
101+
});
102+
103+

merge-two-sorted-lists.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* Merge Two Sorted Lists
3+
* Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
4+
*
5+
* Example:
6+
*
7+
* Input: 1->2->4, 1->3->4
8+
* Output: 1->1->2->3->4->4
9+
*/
10+
11+
/**
12+
* Definition for singly-linked list.
13+
*/
14+
function ListNode(val) {
15+
this.val = val;
16+
this.next = null;
17+
}
18+
19+
/**
20+
* Merge Two Sorted Lists
21+
* @param {ListNode} l1
22+
* @param {ListNode} l2
23+
* @return {ListNode}
24+
* @time complexity: O(n + m)
25+
* where n and m are the size of l1 and l2 respectively
26+
* @space complexity: O(1)
27+
* not allocating extra memory space instead reference to existing list node
28+
*/
29+
function mergeTwoLists(l1, l2) {
30+
if (!l1) {
31+
return l2;
32+
}
33+
34+
if (!l2) {
35+
return l1;
36+
}
37+
38+
const dummy = new ListNode();
39+
let curr = dummy;
40+
41+
while (l1 || l2) {
42+
if (!l1 || (l2 && l2.val < l1.val)) {
43+
curr.next = l2;
44+
l2 = l2.next;
45+
} else {
46+
curr.next = l1;
47+
l1 = l1.next;
48+
}
49+
curr = curr.next;
50+
}
51+
52+
return dummy.next;
53+
};
54+
55+
const assert = require('chai').assert;
56+
57+
58+
function toList(arr) {
59+
const dummy = new ListNode();
60+
let curr = dummy;
61+
62+
for (let n of arr) {
63+
curr.next = new ListNode(n);
64+
curr = curr.next;
65+
}
66+
67+
return dummy.next;
68+
}
69+
70+
function toArray(list) {
71+
const arr = [];
72+
73+
while (list) {
74+
arr.push(list.val);
75+
list = list.next;
76+
}
77+
78+
return arr;
79+
}
80+
81+
describe('Merge Two Sorted Lists', () => {
82+
it('should return sorted list', () => {
83+
const l1 = toList([1, 2, 4]);
84+
const l2 = toList([1, 3, 4]);
85+
const result = mergeTwoLists(l1, l2);
86+
assert.deepEqual(toArray(result), [1, 1, 2, 3, 4, 4]);
87+
});
88+
it('should return l1 list when l2 is empty', () => {
89+
const l1 = toList([1]);
90+
const l2 = toList([]);
91+
const result = mergeTwoLists(l1, l2);
92+
assert.deepEqual(toArray(result), [1]);
93+
});
94+
it('should return l2 list when l1 is empty', () => {
95+
const l1 = toList([]);
96+
const l2 = toList([1]);
97+
const result = mergeTwoLists(l1, l2);
98+
assert.deepEqual(toArray(result), [1]);
99+
});
100+
it('should return empty list', () => {
101+
const l1 = toList([]);
102+
const l2 = toList([]);
103+
const result = mergeTwoLists(l1, l2);
104+
assert.deepEqual(toArray(result), []);
105+
});
106+
});

palindrome-number.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Palindrome Number
3+
*
4+
* Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.
5+
*
6+
* Example 1:
7+
*
8+
* Input: 121
9+
* Output: true
10+
*
11+
* Example 2:
12+
*
13+
* Input: -121
14+
* Output: false
15+
* Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
16+
*
17+
* Example 3:
18+
*
19+
* Input: 10
20+
* Output: false
21+
* Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
22+
*
23+
* Follow up:
24+
*
25+
* Coud you solve it without converting the integer to a string?
26+
*/
27+
28+
/**
29+
* Palindrome Number
30+
* @param {number} x
31+
* @return {boolean}
32+
* @time complexity: O(log x) because we are dividing x by 10 in each iteration
33+
* @space complexity: O(1)
34+
*/
35+
function isPalindromeNumber(x) {
36+
// Negative number and positive number with trailing zero (except zero itself)
37+
// are not palindrome number
38+
if(x < 0 || (x % 10 == 0 && x != 0)) {
39+
return false;
40+
}
41+
42+
let reverted = 0;
43+
44+
while (x > reverted) {
45+
reverted = reverted * 10 + x % 10; // Push digits one position forward and add last digit that pop from x
46+
x = Math.floor(x / 10); // Only keep integer, so discards decimal points
47+
}
48+
49+
// When the length of x is an odd number, remove the last digit (reverted / 10)
50+
// The middle digit doesn't matter in palindrome
51+
return x === reverted || x === Math.floor(reverted / 10);
52+
};
53+
54+
const assert = require('chai').assert;
55+
56+
describe('Palindrome Number', () => {
57+
58+
it('should return true', () => {
59+
assert.strictEqual(isPalindromeNumber(121), true);
60+
});
61+
62+
it('should return false if it is an nagative number', () => {
63+
assert.strictEqual(isPalindromeNumber(-123), false);
64+
});
65+
66+
it('should return false if the number ends with zero', () => {
67+
assert.strictEqual(isPalindromeNumber(10), false);
68+
});
69+
70+
});

0 commit comments

Comments
 (0)