├── .gitignore ├── Algorithms ├── Dynamic-Programming │ ├── canSum.py │ └── fibonacci.py └── Loops │ └── nestedLoops.py ├── coding-interview ├── amazon │ └── process-dates.test.js └── meta │ └── rotational-ciphers.test.js ├── coverage ├── clover.xml ├── coverage-final.json ├── lcov-report │ ├── base.css │ ├── block-navigation.js │ ├── favicon.png │ ├── index.html │ ├── prettify.css │ ├── prettify.js │ ├── sort-arrow-sprite.png │ └── sorter.js └── lcov.info ├── data-structures ├── binary-search-trees │ ├── BST-counting-occurrence.test.js │ ├── BST-insertStrings.test.js │ ├── BSTremoveNode.test.js │ ├── BSTsearches.test.js │ ├── insertBST.test.js │ ├── python │ │ └── insertIntoTree.py │ └── traverseBST.test.js ├── binary-trees │ ├── javascript │ │ └── binaryTree.test.js │ └── python │ │ ├── 1-binaryTree.py │ │ ├── 2-traversals.py │ │ └── binarySearchTree.py ├── graphs │ ├── connectCompCount.py │ ├── hasPath.py │ ├── island_count.py │ ├── largestComp.py │ ├── minIslands.py │ ├── shortest_path.py │ ├── traversals_bfs.py │ ├── traversals_dfs.py │ └── undirected_path.py ├── heaps │ ├── Heap.test.js │ └── MinHeap.test.js ├── linked-list │ ├── linkedList.py │ └── singlyLinkedList.test.js ├── queue │ └── ImplementAQueueDs.test.js └── readme.md ├── hackerRank ├── Arrays │ ├── readme.md │ └── reverseIntArr.test.js ├── linkedList │ ├── compareTwoList.js │ ├── compareTwoList.test.js │ ├── cycleDetection.js │ ├── cycleDetection.test.js │ ├── deleteNodeAtPos.js │ ├── deleteNodeAtPos.test.js │ ├── getNodeValue.js │ ├── getNodeValue.test.js │ ├── insertAtHead.js │ ├── insertAtHead.test.js │ ├── insertAtTail.js │ ├── insertAtTail.test.js │ ├── insertIntoDoublyLinkedList.js │ ├── insertNodeAtAGivenPos.js │ ├── insertNodeAtAGivenPos.test.js │ ├── mergePoint.js │ ├── mergeSortedList.js │ ├── printInReverse.js │ ├── printInReverse.test.js │ ├── printLinkedList.js │ ├── printLinkedList.test.js │ ├── readme.md │ ├── reverseDoublyLinkedList.js │ └── reverseDoublyLinkedList.test.js └── readme.md ├── index.js ├── leetcode ├── javascript │ ├── easy │ │ ├── BST-testcase.test.js │ │ ├── arithmetic-progression.test.js │ │ ├── balancedBinaryTree.test.js │ │ ├── bestTimeToBuyAndSellStock.test.js │ │ ├── binarySearch.test.js │ │ ├── contains-duplicates.test.js │ │ ├── contains-dupsII.test.js │ │ ├── diameterBinaryTree.test.js │ │ ├── firstPalindrome.test.js │ │ ├── group-anagrams.test.js │ │ ├── happyNum.test.js │ │ ├── implementStackUsingQueues.test.js │ │ ├── invertBST.test.js │ │ ├── isPalindrome.test.js │ │ ├── isValid.test.js │ │ ├── max-subarray.test.js │ │ ├── maxDiff.test.js │ │ ├── maximumDepthBST.test.js │ │ ├── mergeLinkedList.test.js │ │ ├── minStack.test.js │ │ ├── palindromeLList.test.js │ │ ├── palindromeNum.test.js │ │ ├── product-sign.test.js │ │ ├── removeDupsFromSortedArr.test.js │ │ ├── removeElement.test.js │ │ ├── reverseLinkedList.test.js │ │ ├── romanToInt.test.js │ │ ├── sameTree.test.js │ │ ├── sortArrayByParity.test.js │ │ ├── string-swap.test.js │ │ └── twoSum.test.js │ ├── hard │ │ └── medianOfSortedArr.test.js │ └── medium │ │ ├── 3Sum.test.js │ │ ├── addTwoNumbers.test.js │ │ ├── contains-dupsIII.test.js │ │ ├── designWordDS.test.js │ │ ├── getTargetCopy.test.js │ │ ├── implementTrie.test.js │ │ ├── longestPalindrome.test.js │ │ ├── longestSubstring.test.js │ │ ├── maxOperations.test.js │ │ ├── maxProfitII.test.js │ │ ├── removeDupsInString.test.js │ │ ├── reverseInteger.test.js │ │ ├── subsets.test.js │ │ ├── twoSum-ii.test.js │ │ └── unsortedSubArray.test.js ├── python │ ├── BFS │ │ └── jumpGameIII.py │ ├── bit-manipulation │ │ ├── countingBits.py │ │ ├── hammingWeight.py │ │ ├── reverseBits.py │ │ ├── reverseInt.py │ │ └── sumTwoInt.py │ ├── easy │ │ ├── climbStairs.py │ │ ├── findJudge.py │ │ ├── isAnagram.py │ │ ├── llistIntersection.py │ │ ├── maxProfit.py │ │ ├── mergeSortedArr.py │ │ ├── minCostClimbingStairs.py │ │ ├── removePalindromeSub.py │ │ ├── runningSum.py │ │ ├── test_kthLargest.py │ │ ├── test_lastStoneWeight.py │ │ ├── test_twoSum.py │ │ ├── transposeMatrix.py │ │ ├── twoSum.py │ │ ├── validPalindrome.py │ │ ├── validParentheses.py │ │ └── validPath.py │ ├── greedy │ │ ├── gasStation.py │ │ ├── handsOfStraights.py │ │ ├── jumpGame.py │ │ └── jumpGameII.py │ ├── hard │ │ ├── nQueens.py │ │ ├── nQueensII.py │ │ └── trapWater.py │ ├── linked-list │ │ ├── mergeLists.py │ │ └── reverseLList.py │ ├── medium │ │ ├── characterReplacement.py │ │ ├── combinationSum.py │ │ ├── encodeDecode.py │ │ ├── houseRobber.py │ │ ├── houseRobberII.py │ │ ├── lengthOfLongestSubstring.py │ │ ├── longestCommonSubsequence.py │ │ ├── longestConsecutiveSequence.py │ │ ├── longestPalindromicString.py │ │ ├── maxArea.py │ │ ├── maxAreaIslands.py │ │ ├── maxProfitCooldown.py │ │ ├── maxSubArray.py │ │ ├── maxUniqueSubArray.py │ │ ├── minCostClimbingStairs.py │ │ ├── minDistance.py │ │ ├── minOperations.py │ │ ├── numDecodings.py │ │ ├── numsIslands.py │ │ ├── palindromicSubstring.py │ │ ├── permutation.py │ │ ├── productExceptSelf.py │ │ ├── rangeSumQuery.py │ │ ├── subsets-ii.py │ │ ├── subsets.py │ │ ├── test_KClosest.py │ │ ├── test_KthLargestArr.py │ │ ├── topKFrequent.py │ │ ├── triangle.py │ │ ├── twoSumII.py │ │ ├── uniquePaths.py │ │ └── validSudoku.py │ └── test_sum.py ├── readme.md └── sean-prashad │ ├── Javascript │ ├── 15-binarySearch.test.js │ ├── 16-nextGreatestLetter.test.js │ ├── 17-avgOfLevels.test.js │ ├── 18-minDeptht.test.js │ ├── 19-maxDepth.test.js │ ├── 20-isSameTree.test.js │ ├── 21-pathSum.test.js │ ├── 22-twoSum.test.js │ ├── 23-invertBinaryTree.test.js │ ├── 24-subTree.test.js │ ├── 25-squareSortedArr.test.js │ ├── 26-backSpaceStringCompare.test.js │ ├── 27-majorityElement.test.js │ └── 28-productExceptSelf.test.js │ └── python │ ├── 1-containsDups.py │ ├── 10-palindromeLList.py │ ├── 11-reverseLList.py │ ├── 12-removeLListEl.py │ ├── 13-removeDupsSortedLList.py │ ├── 14-mergeTwoSortedList.py │ ├── 15-binarySearch.py │ ├── 16-nextGreatestLetter.py │ ├── 17-avgOfLevels.py │ ├── 18-minDepth.py │ ├── 19-maxDepth.py │ ├── 2-missingNumber.py │ ├── 20-isSameTree.py │ ├── 21-pathSum.py │ ├── 22-twoSum.py │ ├── 23-invertBinaryTree.py │ ├── 24-subTree.py │ ├── 25-squareSortedArr.py │ ├── 26-backspaceStringCompare.py │ ├── 27-majorityElement.py │ ├── 3-findDisappearedNumbers.py │ ├── 4-singleNumber.py │ ├── 5-climbingStairs.py │ ├── 6-bestTimeToSell.py │ ├── 7-rangeSumQuery.py │ ├── 8-hasCycle.py │ ├── 9-middleLinkedList.py │ └── bonus-linkedlistII.py ├── package-lock.json ├── package.json └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | note.md -------------------------------------------------------------------------------- /Algorithms/Dynamic-Programming/canSum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | https://coderbyte.com/algorithm/subset-sum-problem?stay=true 3 | 4 | The function would always return true unless the target sum is less than the 5 | smallest number in the array, which is quite a clever trick. 6 | ''' 7 | 8 | import unittest 9 | memo = {} 10 | # 0(m * n) - tc | 0(m) - sc 11 | 12 | def canSum(targetSum, nums): 13 | if targetSum in memo: 14 | return memo[targetSum] 15 | if targetSum == 0: 16 | return True 17 | if targetSum < 0: 18 | return False 19 | 20 | for num in nums: 21 | res = targetSum - num 22 | if canSum(res, nums): 23 | memo[targetSum] = True 24 | return True 25 | 26 | memo[targetSum] = False 27 | return False 28 | 29 | def canSumTwo(target, nums): 30 | smallest = min(nums) 31 | if target < smallest: 32 | return False 33 | return True 34 | 35 | print('print statement', canSum(7, [2, 4])) 36 | print('print statement', canSum(7, [2, 3])) 37 | 38 | class Test(unittest.TestCase): 39 | def test_canSum(self): 40 | self.assertEqual(canSum(7, [2, 3]), True) 41 | self.assertEqual(canSum(7, [5, 3, 4, 7]), True) 42 | self.assertEqual(canSum(7, [2, 4]), False) 43 | self.assertEqual(canSum(8, [2, 3, 5]), True) 44 | self.assertEqual(canSum(300, [7, 14]), False) 45 | 46 | if __name__ == "__main__": 47 | unittest.main() -------------------------------------------------------------------------------- /Algorithms/Dynamic-Programming/fibonacci.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | memo = {} 4 | 5 | 6 | def fib(n): 7 | if n < 0: 8 | raise Exception(f"Invalid input: {n}") 9 | 10 | if n == 0: 11 | return 0 12 | 13 | if n == 1: 14 | return 1 15 | 16 | if n in memo: 17 | return memo[n] 18 | 19 | current_fib_number = fib(n - 1) + fib(n - 2) 20 | memo[n] = current_fib_number 21 | 22 | return current_fib_number 23 | 24 | 25 | class Test(unittest.TestCase): 26 | def test_fib(self): 27 | with self.assertRaises(Exception): 28 | fib(-1) 29 | self.assertEqual(fib(9), 34) 30 | self.assertEqual(fib(50), 12586269025) 31 | self.assertEqual(fib(10), 55) 32 | self.assertEqual(fib(0), 0) 33 | self.assertEqual(fib(1), 1) 34 | self.assertEqual(fib(6), 8) 35 | self.assertEqual(fib(37), 24157817) 36 | self.assertEqual(fib(2), 1) 37 | 38 | 39 | if __name__ == "__main__": 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /Algorithms/Loops/nestedLoops.py: -------------------------------------------------------------------------------- 1 | matrix = [ 2 | [1, 2, 3], 3 | [4, 5, 6], 4 | [8, 7, 9], 5 | [-1, -4, 0] 6 | ] 7 | 8 | for i in range(len(matrix)): 9 | for j in range(len(matrix[0])): 10 | print(i, j) 11 | 12 | -------------------------------------------------------------------------------- /coding-interview/amazon/process-dates.test.js: -------------------------------------------------------------------------------- 1 | // This was a coding test by amazon 2 | 3 | describe('process date', () => { 4 | it('converts date string to YYYY-MM-DD format', () => { 5 | expect(processDates([ 6 | '1st Apr 2022', '4th Aug 2001', 7 | '1st Mar 1974', '22nd Jan 2013', 8 | '7th Apr 1904' 9 | ])) 10 | .toEqual([ 11 | '2022-04-01', '2001-08-04', 12 | '1974-03-01', '2013-01-22', 13 | '1904-04-07' 14 | ]); 15 | }); 16 | }); 17 | 18 | const months = [ 19 | 'Jan', 'Feb', 'Mar', 'Apr', 20 | 'May', 'Jun', 'Jul', 'Aug', 21 | 'Sep', 'Oct', 'Nov', 'Dec' 22 | ]; 23 | 24 | const processDates = (dates) => { 25 | let processedDate = []; 26 | let month, day, year; 27 | 28 | for (let date of dates) { 29 | date = date.split(' '); 30 | 31 | for (d of date) { 32 | day = processDay(date[0]); 33 | month = processMonth(date[1]); 34 | year = date[2]; 35 | } 36 | processedDate.push(year + '-' + month + '-' + day); 37 | } 38 | return processedDate; 39 | }; 40 | 41 | const addZero = (value) => { 42 | value = value.toString().split(''); 43 | if (value.length < 2) return '0' + value; 44 | else return value.join(''); 45 | }; 46 | 47 | const processMonth = (month) => { 48 | month = months.indexOf(month) + 1; 49 | return addZero(month); 50 | }; 51 | 52 | const processDay = (day) => { 53 | let value = []; 54 | for (let d of day) { 55 | d = parseInt(d); 56 | if (d) value += d; 57 | } 58 | return addZero(value); 59 | }; -------------------------------------------------------------------------------- /coding-interview/meta/rotational-ciphers.test.js: -------------------------------------------------------------------------------- 1 | /* Run test: npm test ./meta/rotational-ciphers.test.js 2 | 3 | https://www.facebookrecruiting.com/portal/coding_practice_question/?problem_id=238827593802550&ppid=454615229006519&practice_plan=1 4 | 5 | 6 | 0(n) - time | 0(1) - space 7 | */ 8 | 9 | const { ord, ordFrom, isUpper, isLower } = require('js-ord') 10 | 11 | describe('rotational ciphers', () => { 12 | it('encrypts a string by return the third value of every string and number', () => { 13 | expect(rotationalCipher("Zebra-493?", 3)).toBe("Cheud-726?") 14 | expect(rotationalCipher("abcdefghijklmNOPQRSTUVWXYZ0123456789", 39)).toBe("nopqrstuvwxyzABCDEFGHIJKLM9012345678") 15 | }) 16 | }) 17 | 18 | const rotationalCipher = (string, rotation) => { 19 | let cipher = [] 20 | for (let str of string) { 21 | let validChar = str.match(/[a-zA-Z0-9]/g) 22 | 23 | if (str === '0') { 24 | cipher.push(9) 25 | } 26 | else if (Number(str)) { 27 | str = (Number(str) + rotation) % 10 28 | cipher.push(str) 29 | } 30 | else if (validChar && isUpper(str)) { 31 | str = ((ord(str) - ord('A')) + rotation) % 26 32 | cipher.push(ordFrom(ord('A') + str)) 33 | } 34 | else if (validChar && isLower(str)) { 35 | str = ((ord(str) - ord('a')) + rotation) % 26 36 | cipher.push(ordFrom(ord('a') + str)) 37 | } 38 | else { 39 | cipher.push(str) 40 | } 41 | } 42 | 43 | return cipher.join('') 44 | } -------------------------------------------------------------------------------- /coverage/clover.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /coverage/coverage-final.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /coverage/lcov-report/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blossom-babs/Data-structures-and-algorithm/027b4e7a5037a5897789eafebbf828899313feff/coverage/lcov-report/favicon.png -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blossom-babs/Data-structures-and-algorithm/027b4e7a5037a5897789eafebbf828899313feff/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /coverage/lcov.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blossom-babs/Data-structures-and-algorithm/027b4e7a5037a5897789eafebbf828899313feff/coverage/lcov.info -------------------------------------------------------------------------------- /data-structures/binary-search-trees/BST-counting-occurrence.test.js: -------------------------------------------------------------------------------- 1 | //TEST: npm test ./data-structures/binary-search-trees/BST-counting-occurrence.test.js 2 | 3 | describe('#BST count occurrencr', () => { 4 | let bst; 5 | 6 | beforeEach(() => { 7 | bst = new BST() 8 | bst.insertDups(bst.root, 23); bst.insertDups(bst.root, 16) 9 | bst.insertDups(bst.root, 23); bst.insertDups(bst.root, 16) 10 | bst.insertDups(bst.root, 22); bst.insertDups(bst.root, 20); 11 | bst.insertDups(bst.root, 23); bst.insertDups(bst.root, 20); 12 | }) 13 | 14 | it('increases the count of a node key', () => { 15 | expect(bst.root.count).toBe(3) 16 | expect(bst.root.left.right.left.count).toBe(2) 17 | expect(bst.size).toBe(4) 18 | }) 19 | }) 20 | 21 | class Node { 22 | constructor(data) { 23 | this.data = data; 24 | this.count = 1 25 | this.left = this.right = null 26 | } 27 | } 28 | 29 | class BST { 30 | constructor() { 31 | this.root = null 32 | this.size = 0 33 | 34 | } 35 | 36 | insertDups(root, data) { 37 | let newNode = new Node(data) 38 | 39 | if (!root) { 40 | this.root = newNode 41 | this.size++ 42 | return root 43 | } 44 | 45 | if (data === root.data) { 46 | root.count++ 47 | return root 48 | } else if (data < root.data) { 49 | if (!root.left) { 50 | root.left = newNode 51 | this.size++ 52 | } 53 | else this.insertDups(root.left, data) 54 | } else { 55 | if (!root.right) { 56 | root.right = newNode 57 | this.size++ 58 | } 59 | else this.insertDups(root.right, data) 60 | } 61 | return root 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /data-structures/binary-search-trees/BSTremoveNode.test.js: -------------------------------------------------------------------------------- 1 | //TEST: npm test ./data-structures/binary-search-trees/BSTremoveNode.test.js 2 | 3 | const { findMin } = require("./BSTsearches.test"); 4 | const BST = require("./traverseBST.test"); 5 | 6 | 7 | describe('#BST remove node', () => { 8 | let bst; 9 | 10 | beforeEach(() => { 11 | bst = new BST() 12 | bst.insert(bst.root, 23); bst.insert(bst.root, 16) 13 | bst.insert(bst.root, 45); bst.insert(bst.root, 37) 14 | bst.insert(bst.root, 99); bst.insert(bst.root, 3) 15 | bst.insert(bst.root, 22); bst.insert(bst.root, 20); 16 | }) 17 | 18 | it('removes a leaf node', () => { 19 | expect(removeNode(bst.root, 3).left.left).toBe(null) 20 | }) 21 | 22 | it('removes a node with one child', () => { 23 | expect(removeNode(bst.root, 22).left.right.data).toBe(20) 24 | }) 25 | }) 26 | 27 | const removeNode = (root, data) => { 28 | 29 | if (!root) return null 30 | else if (data < root.data) { 31 | root.left = removeNode(root.left, data) 32 | } else if (data > root.data) { 33 | root.right = removeNode(root.right, data) 34 | } else { 35 | if ((!root.left && !root.right)) root = null 36 | else if (!root.left) { 37 | root = root.right 38 | } else if (!root.right) { 39 | root = root.left 40 | } else { 41 | temp = findMin(root.right) 42 | root.data = temp.data 43 | root.right = removeNode(root.right, temp.data) 44 | } 45 | } 46 | 47 | return root 48 | } -------------------------------------------------------------------------------- /data-structures/binary-search-trees/BSTsearches.test.js: -------------------------------------------------------------------------------- 1 | //TEST: npm test ./data-structures/binary-search-trees/BSTsearches.test.js 2 | 3 | const BST = require("./traverseBST.test"); 4 | 5 | 6 | describe('#BST Searches', () => { 7 | let bst; 8 | 9 | beforeEach(() => { 10 | bst = new BST() 11 | bst.insert(bst.root, 23); bst.insert(bst.root, 16) 12 | bst.insert(bst.root, 45); bst.insert(bst.root, 37) 13 | bst.insert(bst.root, 99); bst.insert(bst.root, 3) 14 | bst.insert(bst.root, 22) 15 | }) 16 | 17 | it('find the minimun element in a BST search tree', () => { 18 | expect(findMin(bst.root).data).toBe(3) 19 | }) 20 | 21 | it('find the maximum element in a BST search tree', () => { 22 | expect(findMax(bst.root)).toBe(99) 23 | }) 24 | 25 | it('finds a specific value in the tree', () => { 26 | expect(findVal(bst.root, 45)).toBe(true) 27 | expect(findVal(bst.root, 95)).toBe(null) 28 | }) 29 | }) 30 | 31 | 32 | 33 | const findMin = (root) => { 34 | if (!root) return -1 35 | 36 | else if (root.left) { return findMin(root.left) } 37 | 38 | else return root 39 | } 40 | 41 | const findMax = (root) => { 42 | if (!root) return -1 43 | 44 | else if (root.right) { 45 | return findMax(root.right) 46 | } 47 | 48 | else return root.data 49 | } 50 | 51 | const findVal = (root, data) => { 52 | if (!root) return null 53 | 54 | if (data === root.data) return true 55 | else if (data < root.data) return findVal(root.left, data) 56 | else return findVal(root.right, data) 57 | } 58 | 59 | module.exports = { findMin } -------------------------------------------------------------------------------- /data-structures/binary-search-trees/insertBST.test.js: -------------------------------------------------------------------------------- 1 | //Test: npm test ./data-structures/binary-search-trees/insertBST.test.js 2 | 3 | describe('Binary Search Trees', () => { 4 | let bNode; 5 | 6 | beforeEach(() => { 7 | bNode = new BST() 8 | }) 9 | 10 | it('inserts into a binary search tree', () => { 11 | bNode.insert(4); bNode.insert(3); bNode.insert(5); bNode.insert(2) 12 | expect(bNode.root.data).toBe(4) 13 | expect(bNode.root.left.left.data).toBe(2) 14 | }) 15 | }) 16 | 17 | class BNode { 18 | constructor(data, left, right) { 19 | this.data = data 20 | this.left = left 21 | this.right = right 22 | } 23 | 24 | show() { 25 | return this.data 26 | } 27 | } 28 | 29 | class BST { 30 | constructor() { 31 | this.root = null 32 | } 33 | 34 | // inserts iteratively 35 | insert(data) { 36 | let newNode = new BNode(data, null, null) 37 | 38 | if (!this.root) { 39 | this.root = newNode 40 | } else { 41 | 42 | let current = this.root 43 | let parent; 44 | 45 | while (true) { 46 | parent = current 47 | 48 | if (data < current.data) { 49 | current = current.left 50 | 51 | if (!current) { 52 | parent.left = newNode 53 | break; 54 | } 55 | } else { 56 | current = current.right 57 | 58 | if (!current) { 59 | parent.right = newNode 60 | break; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | module.exports = BNode; -------------------------------------------------------------------------------- /data-structures/binary-search-trees/python/insertIntoTree.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blossom-babs/Data-structures-and-algorithm/027b4e7a5037a5897789eafebbf828899313feff/data-structures/binary-search-trees/python/insertIntoTree.py -------------------------------------------------------------------------------- /data-structures/binary-search-trees/traverseBST.test.js: -------------------------------------------------------------------------------- 1 | 2 | const BNode = require("./insertBST.test"); 3 | 4 | /* There are 4 types of traversal 5 | 6 | 1. inorder traversal 7 | 2. preorder traversal 8 | 3. postorder traversal 9 | 10 | */ 11 | 12 | 13 | // inserting using recursion 14 | class BST { 15 | 16 | constructor() { 17 | this.root = null 18 | } 19 | 20 | inOrder(node) { 21 | if (node) { 22 | this.inOrder(node.left) 23 | console.log(node.data) 24 | this.inOrder(node.right) 25 | } 26 | } 27 | 28 | preOrder(node) { 29 | if (node) { 30 | console.log(node.data) 31 | this.preOrder(node.left) 32 | this.inOrder(node.right) 33 | } 34 | } 35 | 36 | postOrder(node) { 37 | if (node) { 38 | this.postOrder(node.left) 39 | this.postOrder(node.right) 40 | console.log(node.data) 41 | } 42 | } 43 | 44 | insert(root, data) { 45 | let newNode = new BNode(data) 46 | 47 | if (!root) { 48 | this.root = newNode 49 | return root 50 | } 51 | 52 | if (data < root.data) { 53 | if (!root.left) root.left = newNode 54 | else this.insert(root.left, data) 55 | } else { 56 | if (!root.right) root.right = newNode 57 | else this.insert(root.right, data) 58 | } 59 | 60 | return root 61 | } 62 | 63 | 64 | } 65 | 66 | module.exports = BST -------------------------------------------------------------------------------- /data-structures/binary-trees/javascript/binaryTree.test.js: -------------------------------------------------------------------------------- 1 | // create a Node class 2 | 3 | class Node { 4 | constructor(data) { 5 | this.data = data 6 | this.left = null 7 | this.right = null 8 | } 9 | 10 | } 11 | 12 | class BinaryTree { 13 | constructor() { 14 | this.root = null 15 | } 16 | 17 | 18 | insert(root, data) { 19 | let newNode = new Node(data) 20 | 21 | if (root === null) { 22 | this.root = newNode 23 | return root 24 | } 25 | 26 | 27 | if (data < this.root.data) { 28 | if (this.root.left === null) { 29 | this.root.left = newNode 30 | } else { 31 | this.insert(root.left, data) 32 | } 33 | } 34 | 35 | if (data > this.root.data) { 36 | if (this.root.right === null) { 37 | this.root.right = newNode 38 | } else { 39 | this.insert(root.right, data) 40 | } 41 | } 42 | 43 | } 44 | 45 | preorder(root){ 46 | console.log(root.data) 47 | if(root.left) this.preorder(root.left) 48 | if(root.right) this.preorder(root.right) 49 | } 50 | 51 | inorder(root){ 52 | if(root.left) this.preorder(root.left) 53 | console.log(root.data) 54 | if(root.right) this.preorder(root.right) 55 | } 56 | 57 | postorder(root){ 58 | if(root.left) this.preorder(root.left) 59 | if(root.right) this.preorder(root.right) 60 | console.log(root.data) 61 | } 62 | 63 | bfs(root){ 64 | let queue = [root] 65 | 66 | while(queue.length){ 67 | let node = queue.shift() 68 | console.log(node.data) 69 | if(node.left) queue.push(node.left) 70 | if(node.right) queue.push(node.right) 71 | } 72 | } 73 | } 74 | 75 | let tree = new BinaryTree() 76 | tree.insert(tree.root, 10) 77 | tree.insert(tree.root, 2) 78 | tree.insert(tree.root, 20) 79 | // tree.insert(tree.root, 15) 80 | // tree.insert(tree.root, 87) 81 | // tree.insert(tree.root, 7) 82 | // tree.insert(tree.root, 17) 83 | // tree.inorder(tree.root) 84 | tree.bfs(tree.root) -------------------------------------------------------------------------------- /data-structures/binary-trees/python/binarySearchTree.py: -------------------------------------------------------------------------------- 1 | # create a python node 2 | 3 | class Node: 4 | def __init__(self, data): 5 | self.root = data 6 | self.left = None 7 | self.right = None 8 | 9 | def insert(self, data): 10 | if self.root: 11 | if data < self.root: 12 | if self.left is None: 13 | self.left = Node(data) 14 | else: 15 | self.left.insert(data) 16 | if data > self.root: 17 | if self.right is None: 18 | self.right = Node(data) 19 | else: 20 | self.right.insert(data) 21 | 22 | else: 23 | self.root = data 24 | 25 | def inorder(self, root): 26 | res = [] 27 | if root: 28 | res = self.inorder(root.left) 29 | res.append(root.root) 30 | res = res + self.inorder(root.right) 31 | return res 32 | 33 | 34 | 35 | 36 | 37 | ''' 38 | 10 39 | / \ 40 | 2 20 41 | \ / \ 42 | 7 15 87 43 | \ 44 | 17 45 | ''' 46 | 47 | 48 | tree = Node(10) 49 | tree.insert(2) 50 | tree.insert(20) 51 | tree.insert(15) 52 | tree.insert(87) 53 | tree.insert(7) 54 | tree.insert(17) 55 | 56 | print(tree.inorder(tree)) 57 | 58 | -------------------------------------------------------------------------------- /data-structures/graphs/connectCompCount.py: -------------------------------------------------------------------------------- 1 | ''' 2 | source: structy 3 | 4 | CONNECTED COMPONENTS COUNT 5 | 6 | write a function, connectedComponentCount, that takes in the adjacency list of an undirected graph 7 | (that is you need a set to avoid cyclic graphs). 8 | The function should return the number of connected components in the graph. 9 | 10 | test__00: 11 | connectedComponentsCount({ 12 | 0: [8, 1, 5], 13 | 1: [0], 14 | 5: [0, 8], 15 | 8: [0, 5], 16 | 2: [3, 4], 17 | 3: [2, 4], 18 | 4: [3, 2] 19 | }) # 2 20 | ''' 21 | import unittest 22 | # 0(e) tc | 0(n) - sc 23 | 24 | cc = { 25 | 0: [8, 1, 5], 26 | 1: [0], 27 | 5: [0, 8], 28 | 8: [0, 5], 29 | 2: [3, 4], 30 | 3: [2, 4], 31 | 4: [3, 2] 32 | } # 2 33 | 34 | cc_2 = { 35 | 3: [], 36 | 4: [6], 37 | 6: [4,5,7,8], 38 | 8: [6], 39 | 7: [6], 40 | 5: [6], 41 | 1: [2], 42 | 2: [1] 43 | } # 3 44 | 45 | 46 | def connectedComponentsCount(graph): 47 | count, visited = 0, set() 48 | for key in graph: 49 | if dfs(graph, key, visited) == True: 50 | count += 1 51 | return count 52 | 53 | 54 | def dfs(graph, key, visited): 55 | if key in visited: 56 | return False 57 | visited.add(key) 58 | for neighbor in graph[key]: 59 | dfs(graph, neighbor, visited) 60 | return True 61 | 62 | 63 | class Test(unittest.TestCase): 64 | def test_connectComp(self): 65 | self.assertEqual(connectedComponentsCount(cc), 2) 66 | self.assertEqual(connectedComponentsCount(cc_2), 3) 67 | 68 | if __name__ == "__main__": 69 | unittest.main() -------------------------------------------------------------------------------- /data-structures/graphs/traversals_bfs.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Breadth first traversal 3 | ''' 4 | 5 | import collections 6 | 7 | adjacency_list = { 8 | 'a': ['b', 'c'], 9 | 'b': ['d'], 10 | 'c': ['e'], 11 | 'd': ['f'], 12 | 'e': [], 13 | 'f': [] 14 | } 15 | 16 | def dfs(graph, start): 17 | queue = collections.deque([start]) # add the starting item to the queue 18 | while queue: # run this loop until the queue is empty 19 | curr = queue.popleft() # remove the FIRST item in the queue FIFO 20 | print(curr) # print the item 21 | 22 | for item in graph[curr]: # add all the neighbors of the curr item to the queue 23 | queue.append(item) 24 | 25 | dfs(adjacency_list, 'a') -------------------------------------------------------------------------------- /data-structures/graphs/traversals_dfs.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Depth first traversal 3 | ''' 4 | 5 | # Iteratively 6 | adjacency_list = { 7 | 'a': ['b', 'c'], 8 | 'b': ['d'], 9 | 'c': ['e'], 10 | 'd': ['f'], 11 | 'e': [], 12 | 'f': [] 13 | } 14 | 15 | def dfs(graph, start): 16 | stack_ds = [start] # add the starting item to the stack 17 | 18 | while stack_ds: # run this loop until the stack is empty 19 | curr = stack_ds.pop() # remove the last item in the stack LIFO 20 | print(curr) # print the item 21 | 22 | for item in graph[curr]: # add the neighbors of the curr item to the stack 23 | stack_ds.append(item) 24 | 25 | dfs(adjacency_list, 'a') 26 | 27 | # recursively 28 | 29 | def dfs_recursive(graph, start): 30 | print(start) 31 | for item in graph[start]: 32 | dfs_recursive(graph, item) 33 | 34 | dfs_recursive(adjacency_list, 'a') -------------------------------------------------------------------------------- /data-structures/heaps/Heap.test.js: -------------------------------------------------------------------------------- 1 | class Heap { 2 | constructor() { 3 | this.items = [] 4 | this.size = 0 5 | } 6 | swap(idx1, idx2) { 7 | let temp = this.items[idx1] 8 | this.items[idx1] = this.items[idx2] 9 | this.items[idx2] = temp 10 | } 11 | parentIdx(idx) { 12 | return Math.floor((idx - 1) / 2) 13 | } 14 | leftChildIdx(idx) { 15 | return (idx * 2) + 1 16 | } 17 | rightChildIdx(idx) { 18 | return (idx * 2) + 2 19 | } 20 | parent(idx) { 21 | return this.items[this.parentIdx(idx)] 22 | } 23 | leftChild(idx) { 24 | return this.items[this.leftChildIdx(idx)] 25 | } 26 | rightChild(idx) { 27 | return this.items[this.rightChildIdx(idx)] 28 | } 29 | 30 | hasParent(idx) { 31 | return this.parentIdx(idx) >= 0 32 | } 33 | 34 | hasLeftChild(idx){ 35 | return this.leftChildIdx(idx) < this.size 36 | } 37 | 38 | hasRightChild(idx){ 39 | return this.rightChildIdx(idx) < this.size 40 | } 41 | } 42 | 43 | module.exports = Heap 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /data-structures/heaps/MinHeap.test.js: -------------------------------------------------------------------------------- 1 | //TEST: npm test ./data-structures/heaps/MinHeap.test.js 2 | const Heap = require("./Heap.test"); 3 | 4 | describe('#Min-Heap', () => { 5 | let mh; 6 | 7 | beforeEach(() => { 8 | mh = new MinHeap() 9 | mh.insert(1); mh.insert(10); 10 | mh.insert(5); mh.insert(100); 11 | mh.insert(8); 12 | }) 13 | 14 | it('inserts data to heap', () => { 15 | expect(mh.items).toStrictEqual([1, 8, 5, 100, 10]) 16 | expect(mh.items).toHaveLength(5) 17 | }) 18 | 19 | it('removed data from heap', () => { 20 | expect(mh.removeMin()).toBe(5) 21 | }) 22 | }) 23 | 24 | class MinHeap extends Heap { 25 | insert(data) { 26 | this.items[this.size] = data 27 | this.size++ 28 | this.heapifyUp(this.size - 1) 29 | } 30 | 31 | heapifyUp(idx) { 32 | if (this.hasParent(idx) && this.parent(idx) > this.items[idx]) { 33 | this.swap(this.parentIdx(idx), idx) 34 | this.heapifyUp(this.parentIdx, idx) 35 | } 36 | } 37 | 38 | removeMin() { 39 | if (this.size === 0) { 40 | throw new Error('Empty Heap') 41 | } 42 | 43 | let data = this.items[0] 44 | this.items[0] = this.items[this.size - 1] 45 | this.size-- 46 | this.heapifyDown(0) 47 | return data 48 | } 49 | 50 | heapifyDown(idx) { 51 | let smallest = idx 52 | 53 | if (this.hasLeftChild(idx) && this.items[smallest] > this.leftChild(idx)) { 54 | smallest = this.leftChildIdx(idx) 55 | } 56 | 57 | if (this.hasRightChild && this.items[smallest] > this.rightChildIdx(idx)) { 58 | smallest = this.rightChildIdx(idx) 59 | } 60 | 61 | if (smallest !== idx) { 62 | this.swap(idx, smallest) 63 | this.heapifyDown(smallest) 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /data-structures/queue/ImplementAQueueDs.test.js: -------------------------------------------------------------------------------- 1 | // Implement a Queue data structure 2 | // Test: npm test ./data-structures/queue/ImplementAQueueDs.test.js 3 | 4 | describe('Queue', () => { 5 | let queue; 6 | 7 | beforeEach(() => { 8 | queue = new Queue() 9 | }) 10 | 11 | it('adds elemets to a queue', () => { 12 | queue.enqueue(5); queue.enqueue(7); queue.enqueue(8); queue.enqueue(7) 13 | expect(queue.datastore).toStrictEqual([5, 7, 8, 7]) 14 | expect(queue.size).toBe(4) 15 | }) 16 | }) 17 | 18 | class Queue { 19 | constructor() { 20 | this.datastore = [] 21 | this.size = 0 22 | } 23 | 24 | enqueue(data) { 25 | this.datastore[this.datastore.length++] = data 26 | this.size++ 27 | return this.datastore 28 | } 29 | 30 | dequeue() { 31 | this.datastore.splice(0, 1) 32 | this.size-- 33 | return this.datastore 34 | } 35 | 36 | peek() { 37 | return this.datastore[0] 38 | } 39 | 40 | backPeek() { 41 | return this.datastore[this.size - 1] 42 | } 43 | 44 | isEmpty() { 45 | return this.size === 0 46 | } 47 | 48 | display() { 49 | let items = '' 50 | for (let item of this.datastore) { 51 | items += item + '\n' 52 | } 53 | return items 54 | } 55 | } 56 | 57 | // const queue = new Queue() 58 | // queue.enqueue(7) 59 | // queue.enqueue(8) 60 | // queue.enqueue(9) 61 | // console.log( queue) 62 | // queue.dequeue() 63 | // console.log( queue.display()) -------------------------------------------------------------------------------- /data-structures/readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blossom-babs/Data-structures-and-algorithm/027b4e7a5037a5897789eafebbf828899313feff/data-structures/readme.md -------------------------------------------------------------------------------- /hackerRank/Arrays/readme.md: -------------------------------------------------------------------------------- 1 | ## Index of the solution to [Hackkerrank Array challenge](https://www.hackerrank.com/domains/data-structures?filters%5Bsubdomains%5D%5B%5D=arrays) 2 | 3 | | Index | Question | Solution & Test | 4 | | ----- | -------- | --------------- | 5 | | 1. | [Reverse an array of integers](https://www.hackerrank.com/challenges/arrays-ds/problem?isFullScreen=true) | [solution](https://github.com/blossom-babs/Data-structures-and-algorithm/blob/main/hackerRank/Arrays/reverseIntArr.test.js) | -------------------------------------------------------------------------------- /hackerRank/Arrays/reverseIntArr.test.js: -------------------------------------------------------------------------------- 1 | // https://www.hackerrank.com/challenges/arrays-ds/problem?isFullScreen=true 2 | // Test: npm test ./hackerRank/Arrays/reverseIntArr.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('reverse an array of integers', () => { 6 | it('returns an array of reversed integers', () => { 7 | expect(reverseArray([2,5,4])).toStrictEqual([4,5,2]) 8 | expect(reverseArray([0])).toStrictEqual([0]) 9 | }) 10 | }) 11 | 12 | const reverseArray = arr => { 13 | let reversed = [] 14 | 15 | for(let i = arr.length - 1; i >= 0; i--){ 16 | reversed.push(arr[i]) 17 | } 18 | 19 | return reversed 20 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/compareTwoList.js: -------------------------------------------------------------------------------- 1 | /* DAY 8 OF A 10-DAY CODE CHALLENGE WITH SODIQ AYILARA MD 2 | 3 | https://www.hackerrank.com/challenges/compare-two-linked-lists/problem?isFullScreen=true 4 | 5 | Test: npm test ./hackerRank/linkedList/compareTwoList.test.js 6 | */ 7 | 8 | // Complete the CompareLists function below. 9 | 10 | /* 11 | * For your reference: 12 | * 13 | * SinglyLinkedListNode { 14 | * int data; 15 | * SinglyLinkedListNode next; 16 | * } 17 | * 18 | */ 19 | function CompareLists(llist1, llist2) { 20 | let list1 = llist1 21 | let list2 = llist2 22 | 23 | while (list1 && list2) { 24 | if (list1.data === list2.data) { 25 | list1 = list1.next 26 | list2 = list2.next 27 | } else { 28 | return 0 29 | } 30 | } 31 | return list1 || list2 ? 0 : 1 32 | } 33 | 34 | -------------------------------------------------------------------------------- /hackerRank/linkedList/compareTwoList.test.js: -------------------------------------------------------------------------------- 1 | /* Test: npm test ./hackerRank/linkedList/compareTwoList.test.js */ 2 | 3 | describe('compare lists', () => { 4 | 5 | let list, list1, list2 6 | 7 | beforeEach(() => { 8 | list = new SinglyLinkedList() 9 | list1 = new SinglyLinkedList() 10 | list2 = new SinglyLinkedList() 11 | }) 12 | 13 | it('returns 0 if lists are not the same', () => { 14 | list1.insert(10) 15 | list1.insert(20) 16 | list1.insert(30) 17 | list2.insert(10) 18 | list2.insert(20) 19 | expect(list.compare(list1, list2)).toBe(0) 20 | }) 21 | 22 | it('returns 1 if list are the same', () => { 23 | list1.insert(10) 24 | list1.insert(20) 25 | list2.insert(10) 26 | list2.insert(20) 27 | expect(list.compare(list1, list2)).toBe(1) 28 | }) 29 | }) 30 | 31 | class Node { 32 | constructor(data) { 33 | this.data = data 34 | this.next = null 35 | } 36 | } 37 | 38 | class SinglyLinkedList { 39 | insert(data) { 40 | let newNode = new Node(data) 41 | 42 | if (!this.head) { 43 | this.head = newNode 44 | return this.head 45 | } 46 | 47 | let current = this.head 48 | this.head = newNode 49 | this.head.next = current 50 | 51 | return this.head 52 | } 53 | 54 | compare(list1, list2) { 55 | let head1 = list1.head 56 | let head2 = list2.head 57 | 58 | while (head1 && head2) { 59 | if (head1.data !== head2.data) { 60 | return 0 61 | } 62 | head1 = head1.next 63 | head2 = head2.next 64 | } 65 | 66 | return head1 || head2 ? 0 : 1 67 | } 68 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/cycleDetection.js: -------------------------------------------------------------------------------- 1 | // https://www.hackerrank.com/challenges/detect-whether-a-linked-list-contains-a-cycle/problem 2 | // Test: npm test ./hackerRank/linkedList/cycleDetection.test.js 3 | // 0(n) - space | 0(n) - time 4 | 5 | function hasCycle(head){ 6 | let list = head 7 | let hash = new Map() 8 | 9 | while(list){ 10 | if(hash.has(list.data)){return 1} 11 | else { 12 | hash.set(list.data, true) 13 | list = list.next 14 | } 15 | } 16 | return 0 17 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/cycleDetection.test.js: -------------------------------------------------------------------------------- 1 | // https://www.hackerrank.com/challenges/detect-whether-a-linked-list-contains-a-cycle/problem 2 | // Test: npm test ./hackerRank/linkedList/cycleDetection.test.js 3 | // 0(n) - space | 0(n) - time 4 | 5 | describe('cycle detection', () => { 6 | let list; 7 | beforeEach(() => { 8 | list = new SinglyLinkedList() 9 | }) 10 | it('returns 1 if there is a cycle detection', () => { 11 | list.insert(1) 12 | list.insert(-1) 13 | list.insert(1) 14 | let cycle = list.hasCycle() 15 | expect(cycle).toStrictEqual(1) 16 | }) 17 | it('returns 0 if there is no cycle detection', () => { 18 | list.insert(1) 19 | list.insert(2) 20 | list.insert(3) 21 | let cycle = list.hasCycle() 22 | expect(cycle).toStrictEqual(0) 23 | }) 24 | }) 25 | 26 | class Node { 27 | constructor(data) { 28 | this.data = data 29 | this.next = null 30 | } 31 | } 32 | 33 | class SinglyLinkedList { 34 | insert(data) { 35 | let newNode = new Node(data) 36 | if (!this.head) { 37 | this.head = newNode 38 | return this.head 39 | } 40 | let current = this.head 41 | while (current.next) { 42 | current = current.next 43 | } 44 | current.next = newNode 45 | return current 46 | } 47 | 48 | hasCycle() { 49 | let list = this.head 50 | let hash = new Map() 51 | while (list) { 52 | if (hash.has(list.data)) { return 1 } 53 | else { hash.set(list.data, true) } 54 | list = list.next 55 | } 56 | return 0 57 | } 58 | } 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /hackerRank/linkedList/deleteNodeAtPos.js: -------------------------------------------------------------------------------- 1 | /* DAY 5 OF A 10-DAY LINKED LIST CHALLENGE WITH SODIQ AYILARA MD 2 | 3 | https://www.hackerrank.com/challenges/delete-a-node-from-a-linked-list/problem?isFullScreen=true 4 | 5 | Test: npm test ./hackerRank/linkedList/deleteNodeAtPos.test.js 6 | 7 | 0(n) - time | 0(1) - space 8 | */ 9 | 10 | 11 | /* 12 | * Complete the 'deleteNode' function below. 13 | * 14 | * The function is expected to return an INTEGER_SINGLY_LINKED_LIST. 15 | * The function accepts following parameters: 16 | * 1. INTEGER_SINGLY_LINKED_LIST llist 17 | * 2. INTEGER position 18 | */ 19 | 20 | /* 21 | * For your reference: 22 | * 23 | * SinglyLinkedListNode { 24 | * int data; 25 | * SinglyLinkedListNode next; 26 | * } 27 | * 28 | */ 29 | function deleteNode(llist, position) { 30 | let nxt; 31 | 32 | if (position === 0) { 33 | nxt = llist.next 34 | llist = nxt 35 | return llist 36 | } 37 | 38 | let count = 0 39 | let current = llist 40 | 41 | while (current) { 42 | if (count === position - 1) { 43 | nxt = current.next.next 44 | current.next = nxt 45 | } 46 | current = current.next 47 | count++ 48 | } 49 | return llist 50 | } 51 | -------------------------------------------------------------------------------- /hackerRank/linkedList/deleteNodeAtPos.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | TEST: npm test ./hackerRank/linkedList/deleteNodeAtPos.test.js 3 | */ 4 | 5 | describe('delete node', () => { 6 | it('deletes a node at a given position and returns the head', () => { 7 | const list = new SinglyLinkedList() 8 | list.insert(10) 9 | const deleteNode = list.delete(0) 10 | expect(deleteNode).toBe(null) 11 | }) 12 | }) 13 | 14 | class Node{ 15 | constructor(data){ 16 | this.data = data 17 | this.next = null 18 | } 19 | } 20 | 21 | class SinglyLinkedList{ 22 | insert(data){ 23 | let newNode = new Node(data) 24 | 25 | if(!this.head){ 26 | this.head = newNode 27 | return this.head 28 | } 29 | 30 | let current = this.head 31 | 32 | while(current.next){ 33 | current = current.next 34 | } 35 | 36 | current.next = newNode 37 | return current 38 | } 39 | 40 | delete(position){ 41 | let nxt; 42 | 43 | if(position === 0){ 44 | nxt = this.head.next 45 | this.head = nxt 46 | return this.head 47 | } 48 | 49 | let current = this.head 50 | let count = 0 51 | 52 | while(current){ 53 | if(count === position - 1){ 54 | nxt = current.next.next 55 | current.next = nxt 56 | } 57 | current = current.next 58 | count++ 59 | } 60 | return this.head 61 | } 62 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/getNodeValue.js: -------------------------------------------------------------------------------- 1 | // day 10 linked list challenge 2 | //https://www.hackerrank.com/challenges/get-the-value-of-the-node-at-a-specific-position-from-the-tail/problem?isFullScreen=true 3 | /* 4 | * Complete the 'getNode' function below. 5 | * 6 | * The function is expected to return an INTEGER. 7 | * The function accepts following parameters: 8 | * 1. INTEGER_SINGLY_LINKED_LIST llist 9 | * 2. INTEGER positionFromTail 10 | */ 11 | 12 | /* 13 | * For your reference: 14 | * 15 | * SinglyLinkedListNode { 16 | * int data; 17 | * SinglyLinkedListNode next; 18 | * } 19 | * 20 | */ 21 | 22 | // 0(n) - space | 0(n) - time 23 | // Test: npm test ./hackerRank/linkedList/getNodeValue.test.js 24 | 25 | function getNode(llist, positionFromTail) { 26 | let hash = {}; let count = -1; let length = 0 27 | 28 | while (llist) { 29 | count++ 30 | hash[count] = llist.data 31 | length = Math.max(length, count) 32 | llist = llist.next 33 | } 34 | return hash[length - positionFromTail] 35 | } 36 | 37 | -------------------------------------------------------------------------------- /hackerRank/linkedList/getNodeValue.test.js: -------------------------------------------------------------------------------- 1 | //www.hackerrank.com/challenges/get-the-value-of-the-node-at-a-specific-position-from-the-tail/problem?isFullScreen=true 2 | // Test: npm test ./hackerRank/linkedlist/getNodeValue.test.js 3 | 4 | describe('get node value', () => { 5 | it('return the number at the node 3 from the tail position', () => { 6 | const list = new SinglyLinkedList() 7 | list.insert(10) 8 | list.insert(120) 9 | list.insert(30) 10 | list.insert(40) 11 | list.insert(50) 12 | let pos3 = list.getNodeValue(3) 13 | let pos2 = list.getNodeValue(2) 14 | expect(pos3).toBe(120) 15 | expect(pos2).toBe(30) 16 | }) 17 | 18 | }) 19 | 20 | class Node { 21 | constructor(data) { 22 | this.data = data 23 | this.next = null 24 | } 25 | } 26 | 27 | class SinglyLinkedList { 28 | insert(data) { 29 | let newNode = new Node(data) 30 | if (!this.head) { 31 | this.head = newNode 32 | return this.head 33 | } 34 | let current = this.head 35 | while (current.next) { 36 | current = current.next 37 | } 38 | current.next = newNode 39 | return current 40 | } 41 | 42 | getNodeValue(positionFromTail) { 43 | let head = this.head 44 | let hash = {}; let length = 0; let count = -1; 45 | 46 | while (head) { 47 | count++ 48 | hash[count] = head.data 49 | length = Math.max(length, count) 50 | head = head.next 51 | } 52 | 53 | return hash[length - positionFromTail] 54 | } 55 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/insertAtHead.js: -------------------------------------------------------------------------------- 1 | /* https://www.hackerrank.com/challenges/insert-a-node-at-the-head-of-a-linked-list/problem 2 | 3 | complexity analysis 4 | 0(1) - space 5 | 0(1) - time 6 | */ 7 | 8 | 9 | function insertNodeAtHead(head, data) { 10 | if(head === null) return new SinglyLinkedListNode(data) 11 | 12 | let llist = new SinglyLinkedListNode(data) 13 | llist.next = head 14 | return llist 15 | } 16 | -------------------------------------------------------------------------------- /hackerRank/linkedList/insertAtHead.test.js: -------------------------------------------------------------------------------- 1 | //Run test: npm test ./hackerRank/linkedList/insertAtHead.test.js 2 | 3 | 4 | describe('#insertAtHead', () => { 5 | it('inserts node at head of linked list', () => { 6 | const newNode = new SinglyLinkedList() 7 | newNode.insertAtHead(10) 8 | const oldHead = newNode.head 9 | newNode.insertAtHead(20) 10 | expect(newNode.head.data).toBe(20) 11 | expect(oldHead.data).toBe(10) 12 | expect(newNode.size).toBe(2) 13 | }) 14 | }) 15 | 16 | const SinglyLinkedListNode = class { 17 | constructor(nodeData) { 18 | this.data = nodeData; 19 | this.next = null; 20 | } 21 | }; 22 | 23 | const SinglyLinkedList = class { 24 | constructor() { 25 | this.head = null; 26 | this.size = 0 27 | } 28 | 29 | insertAtHead(element) { 30 | const newNode = new SinglyLinkedListNode(element) 31 | newNode.next = this.head 32 | this.head = newNode 33 | this.size++ 34 | } 35 | }; -------------------------------------------------------------------------------- /hackerRank/linkedList/insertAtTail.js: -------------------------------------------------------------------------------- 1 | /* https://www.hackerrank.com/challenges/insert-a-node-at-the-tail-of-a-linked-list/problem 2 | 3 | complexity analysis 4 | 0(n) - time | 0(1) - space 5 | 6 | * For your reference: 7 | * 8 | * SinglyLinkedListNode { 9 | * int data; 10 | * SinglyLinkedListNode next; 11 | * } 12 | * 13 | */ 14 | 15 | function insertAtTail(head) { 16 | let newNode = new SinglyLinkedListNode(head) 17 | 18 | if (!head) { 19 | head = newNode 20 | return head 21 | } 22 | 23 | let current = head 24 | 25 | while (current.next) { 26 | current = current.next 27 | } 28 | 29 | current.next = newNode 30 | return current 31 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/insertAtTail.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | Run test: npm test ./hackerRank/linkedList/insertAtTail.test.js 3 | */ 4 | 5 | describe('insert node at tail', () => { 6 | it('inserts new node at the tail of linked list', () => { 7 | let newNode = new singlyLinkedList() 8 | newNode.insertAtTail(10) 9 | newNode.insertAtTail(20) 10 | expect(newNode.head.next.next.data).toBe(20) 11 | }) 12 | }) 13 | 14 | class Node{ 15 | constructor(data){ 16 | this.data = data 17 | this.next = null 18 | } 19 | } 20 | 21 | class singlyLinkedList{ 22 | constructor(){ 23 | this.head = new Node('head') 24 | } 25 | 26 | insertAtTail(data){ 27 | let newNode = new Node(data) 28 | let currData = this.head 29 | 30 | while(currData !== null){ 31 | if (currData.next === null){ 32 | currData.next = newNode 33 | newNode.next = null 34 | } 35 | currData = currData.next 36 | } 37 | return 2 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /hackerRank/linkedList/insertIntoDoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | //www.hackerrank.com/challenges/insert-a-node-into-a-sorted-doubly-linked-list/problem?isFullScreen=true 2 | // test: npm test ./hackerRank/linkedList/insertIntoDoublyLinkedList.test.js 3 | // 0(1) - space | 0(n) - time 4 | /* 5 | * Complete the 'sortedInsert' function below. 6 | * 7 | * The function is expected to return an INTEGER_DOUBLY_LINKED_LIST. 8 | * The function accepts following parameters: 9 | * 1. INTEGER_DOUBLY_LINKED_LIST llist 10 | * 2. INTEGER data 11 | */ 12 | 13 | /* 14 | * For your reference: 15 | * 16 | * DoublyLinkedListNode { 17 | * int data; 18 | * DoublyLinkedListNode next; 19 | * DoublyLinkedListNode prev; 20 | * } 21 | * 22 | */ 23 | 24 | function sortedInsert(llist, data) { 25 | // Write your code here 26 | let list = llist 27 | let newNode = new DoublyLinkedListNode(data) 28 | 29 | if (!list) { 30 | list = newNode 31 | return list 32 | } 33 | 34 | if (data < list.data) { 35 | list.prev = newNode 36 | newNode.next = list 37 | return newNode 38 | } 39 | 40 | while (list) { 41 | if (data >= list.data && list.next === null) { 42 | list.next = newNode 43 | newNode.prev = list 44 | return llist; 45 | } 46 | if (list.next.data >= data) { 47 | newNode.next = list.next 48 | newNode.prev = list 49 | list.next = newNode 50 | list.next.prev = newNode 51 | return llist 52 | } 53 | 54 | list = list.next 55 | 56 | } 57 | return llist 58 | } 59 | -------------------------------------------------------------------------------- /hackerRank/linkedList/insertNodeAtAGivenPos.js: -------------------------------------------------------------------------------- 1 | /* https://www.hackerrank.com/challenges/insert-a-node-at-a-specific-position-in-a-linked-list/problem?isFullScreen=true 2 | 3 | 0(n) - time | 0(1) - space 4 | 5 | * Complete the 'insertNodeAtPosition' function below. 6 | * 7 | * The function is expected to return an INTEGER_SINGLY_LINKED_LIST. 8 | * The function accepts following parameters: 9 | * 1. INTEGER_SINGLY_LINKED_LIST llist 10 | * 2. INTEGER data 11 | * 3. INTEGER position 12 | */ 13 | 14 | /* 15 | * For your reference: 16 | * 17 | * SinglyLinkedListNode { 18 | * int data; 19 | * SinglyLinkedListNode next; 20 | * } 21 | * 22 | */ 23 | 24 | function insertNodeAtPosition(llist, data, position) { 25 | // Write your code here 26 | let newNode = new SinglyLinkedListNode(data) 27 | 28 | if (position === 0) { 29 | llist = newNode 30 | return llist 31 | } 32 | 33 | let current = llist 34 | let count = 0 35 | 36 | while (current) { 37 | if (count === position - 1) { 38 | let posHolder = current.next 39 | current.next = newNode 40 | newNode.next = posHolder 41 | } 42 | current = current.next 43 | count++ 44 | } 45 | return llist 46 | } 47 | -------------------------------------------------------------------------------- /hackerRank/linkedList/insertNodeAtAGivenPos.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | Run test: npm test ./hackerRank/linkedList/insertNodeAtAGivenPos.test.js 3 | */ 4 | 5 | describe('Insert node at a given position', () => { 6 | it('inserts node at a given position', () => { 7 | let node = new singlyLinkedList() 8 | node.insert(10) 9 | node.insert(20) 10 | let givenPos = node.insertAtPos(30, 1) 11 | expect(givenPos.next.data).toBe(30) 12 | }) 13 | }) 14 | 15 | class Node { 16 | constructor(data) { 17 | this.data = data 18 | this.next = null 19 | } 20 | } 21 | 22 | class singlyLinkedList { 23 | insert(data) { 24 | let newNode = new Node(data) 25 | 26 | if (!this.head) { 27 | this.head = newNode 28 | return this.head 29 | } 30 | 31 | let current = this.head 32 | 33 | while (current.next) { 34 | current = current.next 35 | } 36 | 37 | current.next = newNode 38 | return current 39 | } 40 | insertAtPos(data, position) { 41 | let newNode = new Node(data) 42 | 43 | if (position === 0) { 44 | this.head = newNode 45 | return this.head 46 | } 47 | 48 | let current = this.head 49 | let count = 0 50 | 51 | while (current) { 52 | if (count === position - 1) { 53 | let holder = current.next 54 | current.next = newNode 55 | newNode.next = holder 56 | } 57 | current = current.next 58 | count++ 59 | } 60 | return this.head 61 | } 62 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/mergePoint.js: -------------------------------------------------------------------------------- 1 | //https://www.hackerrank.com/challenges/find-the-merge-point-of-two-joined-linked-lists/problem 2 | // 0(mn) - time | 0(1) - space 3 | // tests: pending 4 | 5 | /* 6 | Find merge point of two linked lists 7 | Note that the head may be 'null' for the empty list. 8 | Node is defined as 9 | var Node = function(data) { 10 | this.data = data; 11 | this.next = null; 12 | } 13 | */ 14 | 15 | // This is a "method-only" submission. 16 | // You only need to complete this method. 17 | 18 | function findMergeNode(headA, headB) { 19 | let m = length(headA) 20 | let n = length(headB) 21 | let list = headB 22 | 23 | 24 | for (let i = 0; i < m; i++) { 25 | headB = list 26 | for (let j = 0; j < n; j++) { 27 | if (headA === headB) { 28 | return headA.data 29 | } else { 30 | 31 | headB = headB.next 32 | 33 | } 34 | } 35 | headA = headA.next 36 | } 37 | } 38 | 39 | function length(head) { 40 | let list = head 41 | let len = 0 42 | while (list) { 43 | len++ 44 | list = list.next 45 | } 46 | return len 47 | } 48 | 49 | -------------------------------------------------------------------------------- /hackerRank/linkedList/mergeSortedList.js: -------------------------------------------------------------------------------- 1 | // DAY 9 OF A 10-DAY LINKED LIST CHALLENGE 2 | 3 | // this question has already been solved during a leetcode practice. 4 | // Find test here: npm test ./leetcode/linked-list/mergeLinkedList.test.js 5 | // 0(n) - t | 0(n) - space 6 | // https://www.hackerrank.com/challenges/merge-two-sorted-linked-lists/problem 7 | 8 | // Complete the mergeLists function below. 9 | 10 | /* 11 | * For your reference: 12 | * 13 | * SinglyLinkedListNode { 14 | * int data; 15 | * SinglyLinkedListNode next; 16 | * } 17 | * 18 | */ 19 | function mergeLists(head1, head2) { 20 | let dummyNode = new SinglyLinkedListNode(0) 21 | let merged = dummyNode 22 | 23 | while (true) { 24 | if (!head1) { 25 | merged.next = head2; 26 | break; 27 | } 28 | if (!head2) { 29 | merged.next = head1; 30 | break; 31 | } 32 | if (head1.data <= head2.data) { 33 | merged.next = head1 34 | head1 = head1.next 35 | } else { 36 | merged.next = head2 37 | head2 = head2.next 38 | } 39 | merged = merged.next 40 | } 41 | return dummyNode.next 42 | } 43 | -------------------------------------------------------------------------------- /hackerRank/linkedList/printInReverse.js: -------------------------------------------------------------------------------- 1 | /* DAY 6 & 7 OF A 10-DAY LINKED LIST CHALLENGE WITH SODIQ AYILARA MD 2 | 3 | https://www.hackerrank.com/challenges/print-the-elements-of-a-linked-list-in-reverse/problem?isFullScreen=true 4 | 5 | Test: npm test ./hackerRank/linkedList/printInReverse.test.js 6 | 7 | 0(n) - time | 0(1) - space 8 | */ 9 | 10 | 11 | /* 12 | * Complete the 'reversePrint' function below. 13 | * 14 | * The function accepts INTEGER_SINGLY_LINKED_LIST llist as parameter. 15 | */ 16 | 17 | /* 18 | * For your reference: 19 | * 20 | * SinglyLinkedListNode { 21 | * int data; 22 | * SinglyLinkedListNode next; 23 | * } 24 | * 25 | */ 26 | 27 | function reversePrint(llist) { 28 | if (llist) { 29 | reversePrint(llist.next) 30 | console.log(llist.data) 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /hackerRank/linkedList/printInReverse.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | TEST: npm test ./hackerRank/linkedList/printInReverse.test.js 3 | */ 4 | 5 | describe('print in reverse', () => { 6 | it('prints the data values of a linked list in reverse', () => { 7 | const list = new SinglyLinkedList() 8 | list.insert(10) 9 | list.insert(20) 10 | list.insert(30) 11 | const reverse = list.reverse() 12 | expect(reverse.data).toBe(30) 13 | expect(reverse.next.data).toBe(20) 14 | expect(reverse.next.next.data).toBe(10) 15 | expect(reverse.next.next.next).toBe(null) 16 | }) 17 | }) 18 | 19 | class Node{ 20 | constructor(data){ 21 | this.data = data 22 | this.next = null 23 | } 24 | } 25 | 26 | class SinglyLinkedList{ 27 | insert(data){ 28 | let newNode = new Node(data) 29 | if(!this.head){ 30 | this.head = newNode 31 | return this.head 32 | } 33 | let current = this.head 34 | while(current.next){ 35 | current = current.next 36 | } 37 | current.next = newNode 38 | return current 39 | } 40 | 41 | reverse(){ 42 | if(this.head){ 43 | let current = this.head 44 | let prev = null 45 | 46 | while(current){ 47 | let nxt = current.next 48 | current.next = prev 49 | prev = current 50 | current = nxt 51 | } 52 | return prev 53 | } 54 | 55 | while(prev){ 56 | console.log(prev.data) 57 | prev = prev.next 58 | } 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /hackerRank/linkedList/printLinkedList.js: -------------------------------------------------------------------------------- 1 | /* https://www.hackerrank.com/challenges/print-the-elements-of-a-linked-list/problem?isFullScreen=true 2 | 3 | complexity anaysis 4 | 0(n) - time 5 | 0(1) - space 6 | */ 7 | 8 | function printLinkedList(head) { 9 | let currEl = head 10 | 11 | while(currEl !== null){ 12 | console.log(currEl.data) 13 | currEl = currEl.next 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/printLinkedList.test.js: -------------------------------------------------------------------------------- 1 | //Run test: npm test ./hackerRank/linkedList/printLinkedList.test.js 2 | 3 | 4 | describe('print the element of a linked list', () => { 5 | it('returns the el in a list', () => { 6 | let list = new LList() 7 | list.insert(2, 'head') 8 | list.insert(16, 2) 9 | list.insert(18, 6) 10 | expect(list.size).toBe(3) 11 | expect(list.head.next.element).toBe(2) 12 | expect(list.display()).toStrictEqual([16, 18]) 13 | }) 14 | }) 15 | 16 | class Node { 17 | constructor(element) { 18 | this.element = element 19 | this.next = null 20 | } 21 | } 22 | 23 | class LList { 24 | constructor() { 25 | this.head = new Node('head') 26 | this.size = 0 27 | } 28 | 29 | find(item) { 30 | let currNode = this.head 31 | while (currNode !== item && currNode.next !== null) { 32 | currNode = currNode.next 33 | } 34 | return currNode 35 | } 36 | 37 | // this function assumes newEl is inserted after item in a linked list 38 | insert(newEl, item) { 39 | let newNode = new Node(newEl) 40 | let current = this.find(item) 41 | if (current.next) { 42 | newNode.next = current.next 43 | } else { 44 | newNode.next = null 45 | } 46 | current.next = newNode 47 | this.size++ 48 | } 49 | 50 | display() { 51 | let currNode = this.head.next 52 | let values = [] 53 | while (currNode !== null && this.size > 1) { 54 | console.log(currNode.next.element) 55 | values.push(currNode.next.element) 56 | currNode = currNode.next 57 | this.size-- 58 | } 59 | return values 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /hackerRank/linkedList/reverseDoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | //https://www.hackerrank.com/challenges/reverse-a-doubly-linked-list/problem?isFullScreen=true 2 | // Test: npm test ./hackerRank/linkedList/reverseDoublyLinkedlist.test.js 3 | // 0(n) - time | 0(n) - space 4 | 5 | 6 | /* 7 | * Complete the 'reverse' function below. 8 | * 9 | * The function is expected to return an INTEGER_DOUBLY_LINKED_LIST. 10 | * The function accepts INTEGER_DOUBLY_LINKED_LIST llist as parameter. 11 | */ 12 | 13 | /* 14 | * For your reference: 15 | * 16 | * DoublyLinkedListNode { 17 | * int data; 18 | * DoublyLinkedListNode next; 19 | * DoublyLinkedListNode prev; 20 | * } 21 | * 22 | */ 23 | 24 | function reverse(llist) { 25 | // Write your code here 26 | let current = llist 27 | if (!current) return; 28 | 29 | let temp = null 30 | 31 | while (current) { 32 | let ptr2 = current.next 33 | current.next = temp 34 | current.prev = ptr2 35 | temp = current 36 | current = ptr2 37 | } 38 | 39 | if (temp) { 40 | llist = temp 41 | } 42 | 43 | return llist 44 | 45 | } -------------------------------------------------------------------------------- /hackerRank/linkedList/reverseDoublyLinkedList.test.js: -------------------------------------------------------------------------------- 1 | //https://www.hackerrank.com/challenges/reverse-a-doubly-linked-list/problem?isFullScreen=true 2 | // Test: npm test ./hackerRank/linkedList/reverseDoublyLinkedlist.test.js 3 | // 0(n) - time | 0(n) - space 4 | 5 | describe('reverse doubly linked list', () => { 6 | it('reverses a doubly linked list in place', () => { 7 | const list = new DoublyLinkedList() 8 | list.insert(10) 9 | list.insert(20) 10 | list.insert(30) 11 | let listReverse = list.reverse() 12 | expect(listReverse.data).toBe(30) 13 | expect(listReverse.prev).toBe(null) 14 | expect(listReverse.next.prev.data).toBe(30) 15 | }) 16 | }) 17 | 18 | class Node { 19 | constructor(data) { 20 | this.data = data; 21 | this.next = null; 22 | this.prev = null; 23 | } 24 | } 25 | 26 | class DoublyLinkedList { 27 | insert(data) { 28 | let newNode = new Node(data) 29 | if (!this.head) { 30 | this.head = newNode 31 | return this.head 32 | } 33 | 34 | let current = this.head 35 | 36 | while (current.next) { 37 | current = current.next 38 | } 39 | 40 | current.next = newNode 41 | return this.head 42 | } 43 | 44 | reverse() { 45 | if (!this.head) return 46 | 47 | let prev = null 48 | let current = this.head 49 | 50 | while (current) { 51 | let nxt = current.next 52 | current.next = prev 53 | current.prev = nxt 54 | prev = current 55 | current = nxt 56 | } 57 | return prev 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /hackerRank/readme.md: -------------------------------------------------------------------------------- 1 | ## Index of solution 2 | 3 | | Index | Topic | Link | 4 | | ----- | -------- | --------------- | 5 | | 1. | [Linked List](https://www.hackerrank.com/domains/data-structures?filters%5Bsubdomains%5D%5B%5D=linked-lists) | [Link](https://github.com/blossom-babs/Data-structures-and-algorithm/blob/main/hackerRank/linkedList) | 6 | | 2. | [Arrays](https://www.hackerrank.com/domains/data-structures?filters%5Bsubdomains%5D%5B%5D=arrays) | [Link](https://github.com/blossom-babs/Data-structures-and-algorithm/blob/main/hackerRank/Arrays) | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | function* generatorFunction() { 2 | index = 0 3 | while (true) { 4 | yield index 5 | index += 1 6 | } 7 | } 8 | 9 | let gen = generatorFunction() 10 | 11 | 12 | for (let value of gen) { 13 | console.log(value) 14 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/arithmetic-progression.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://leetcode.com/problems/can-make-arithmetic-progression-from-sequence/ 3 | 4 | test: npm test ./leetcode/easy/arithmetic-progression.test.js 5 | 6 | complexity analysis 7 | 0(1) space 8 | 0(n) time 9 | */ 10 | 11 | const arithmeticProgression = (arr) => { 12 | arr = arr.sort((a, b) => a - b); 13 | let diff = arr[0] - arr[1]; 14 | for (let i = 1; i < arr.length - 1; i++) { 15 | if (arr[i] - arr[i + 1] !== diff) { 16 | return false; 17 | } 18 | } 19 | return true; 20 | }; 21 | 22 | describe("can array make an arithmetic progression", () => { 23 | it("returns true", () => { 24 | expect(arithmeticProgression([5, 3, 1])).toBe(true); 25 | expect(arithmeticProgression([1, 200])).toBe(true); 26 | expect(arithmeticProgression([-1, -2, -3])).toBe(true); 27 | expect(arithmeticProgression([1, 1, 1])).toBe(true); 28 | }); 29 | it("returns false", () => { 30 | expect(arithmeticProgression([1, 2, 4])).toBe(false); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/balancedBinaryTree.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/balanced-binary-tree/ 2 | // TEST: npm test ./leetcode/easy/balancedBinaryTree.test.js 3 | //0(1) - space | 0(n) - time 4 | 5 | const BST = require("./BST-testcase.test"); 6 | 7 | describe('#Balanced Binary tree', () => { 8 | let bst; 9 | 10 | beforeEach(() => { 11 | bst = new BST() 12 | }) 13 | 14 | it('returns true if tree is balanced', () => { 15 | bst.insert(bst.root, 6); bst.insert(bst.root, 3); 16 | bst.insert(bst.root, 7); bst.insert(bst.root, 2); 17 | bst.insert(bst.root, 5); 18 | expect(balancedBinaryTree(bst.root)).toBe(true) 19 | }) 20 | 21 | 22 | it('returns false if tree is not balanced', () => { 23 | bst.insert(bst.root, 6); bst.insert(bst.root, 5); 24 | bst.insert(bst.root, 7); bst.insert(bst.root, 4); 25 | bst.insert(bst.root, 8); bst.insert(bst.root, 3); 26 | expect(balancedBinaryTree(bst.root)).toBe(false) 27 | }) 28 | 29 | it('returns false if tree is not balanced', () => { 30 | expect(balancedBinaryTree(bst.root)).toBe(true) 31 | }) 32 | }) 33 | 34 | const balancedBinaryTree = root => { 35 | if(!root) return true 36 | 37 | let output = true 38 | 39 | const dfs = root => { 40 | if(!root) return 0 41 | 42 | const left = dfs(root.left) 43 | const right = dfs(root.right) 44 | 45 | if(Math.abs(left - right) > 1) output = false 46 | 47 | return Math.max(left, right) + 1 48 | } 49 | dfs(root) 50 | return output 51 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/bestTimeToBuyAndSellStock.test.js: -------------------------------------------------------------------------------- 1 | /* https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 2 | 3 | Run test: npm test ./leetcode/easy/bestTimeToBuyAndSellStock.test.js 4 | 5 | 0(n) - time | 0(1) - space 6 | */ 7 | 8 | describe('BEST TIME TO BUY AND SELL STOCK', () => { 9 | it('buys low, sells high and returns the maximum profit made', () => { 10 | expect(maxProfit([7, 1, 5, 3, 6])).toBe(5) 11 | expect(maxProfit([7, 6, 4, 3, 1])).toBe(0) 12 | expect(maxProfit([2, 1, 2, 1, 0, 1, 2])).toBe(2) 13 | }) 14 | }) 15 | 16 | const maxProfit = prices => { 17 | let maxProfit = 0 18 | let left = 0 19 | let right = 1 20 | 21 | while (right < prices.length) { 22 | let profit = prices[right] - prices[left] 23 | 24 | if (profit < 0) { 25 | left++ 26 | } else { 27 | right++ 28 | } 29 | 30 | maxProfit = Math.max(maxProfit, profit) 31 | } 32 | return maxProfit 33 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/binarySearch.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/binary-search/ 2 | //Test: npm test ./leetcode/easy/binarySearch.test.js 3 | //0(log n) - time | 0(1) - space 4 | 5 | describe('#binary search', () => { 6 | it('returns the index of a given target', () => { 7 | expect(binarySearch([1, 0, 3, 5, 9, 12], 9)).toBe(4) 8 | expect(binarySearch([1, 0, 3, 5, 9, 12], 2)).toBe(-1) 9 | expect(binarySearch([1], 2)).toBe(-1) 10 | }) 11 | }) 12 | 13 | 14 | const binarySearch = (nums, target) => { 15 | let lower = 0 16 | let upper = nums.length - 1 17 | 18 | while (lower <= upper) { 19 | let mid = lower + Math.floor((upper - lower) / 2) 20 | 21 | if (target === nums[mid]) { 22 | return mid 23 | } 24 | 25 | if (target > nums[mid]) { 26 | lower = mid + 1 27 | } else { 28 | upper = mid - 1 29 | } 30 | } 31 | 32 | return -1 33 | }; -------------------------------------------------------------------------------- /leetcode/javascript/easy/contains-duplicates.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/contains-duplicate/ 2 | //Test: npm test ./leetcode/easy/contains-duplicates.test.js 3 | 4 | 5 | describe('check if arr of integers contains duplicates', () => { 6 | it('returns true if duplicate value is found', () => { 7 | expect(containsDuplicate([1, 2, 3, 1])).toBe(true) 8 | expect(containsDuplicateTwo([1, 1, 1, 3, 3, 4, 3, 2, 4, 2])).toBe(true) 9 | expect(containsDuplicateThree([-1, -1, 1, 2, 3, 4, 5, 5, 1])).toBe(true) 10 | }) 11 | it('returns false if duplicate not found', () => { 12 | expect(containsDuplicate([1, 2, 3, 4])).toBe(false) 13 | expect(containsDuplicateTwo([3, 4])).toBe(false) 14 | expect(containsDuplicateThree([])).toBe(false) 15 | }) 16 | }) 17 | 18 | // April 2022 19 | // 0(n log n) - time | 0(log n) - space (quick sort) 20 | const containsDuplicate = nums => { 21 | nums = nums.sort((a, b) => a - b) 22 | 23 | for (let i = 0; i < nums.length; i++) { 24 | if (nums[i] === nums[i + 1]) return true 25 | } 26 | 27 | return false 28 | } 29 | 30 | //0(n) - time | 0(n) - space 31 | const containsDuplicateTwo = nums => { 32 | let numsTable = {} 33 | let i = 0 34 | 35 | while (i < nums.length) { 36 | if ((nums[i] in numsTable)) { 37 | return true 38 | } 39 | numsTable[nums[i]] = i 40 | i++ 41 | } 42 | return false 43 | } 44 | 45 | // May 20 2022 | 4am wat 46 | // 0(n) - time | 0(n) - space 47 | 48 | const containsDuplicateThree = nums => { 49 | let hash = {} 50 | 51 | for (const num of nums) { 52 | if (hash[num]) return true 53 | hash[num] = 1 54 | } 55 | return false 56 | } 57 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/contains-dupsII.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/contains-duplicate-ii/ 2 | //Test: npm test ./leetcode/easy/contains-dupsII.test.js 3 | 4 | describe('#contains duplicates II', () => { 5 | it('returns true if array contains duplicates and difference of duplicates(index) is less than integer k', () => { 6 | expect(containsNearbyDuplicates([3], 3)).toBe(false) 7 | expect(containsNearbyDuplicates([], 13)).toBe(false) 8 | expect(containsNearbyDuplicates([1, 2, 3, 1], 3)).toBe(true) 9 | expect(containsNearbyDuplicates([1,0,1,1,1], 1)).toBe(true) 10 | expect(containsNearbyDuplicates([1,2,3,1,2,3], 2)).toBe(false) 11 | }) 12 | }) 13 | 14 | 15 | // 0(n) - time | 0(n) - space 16 | containsNearbyDuplicates = (nums, k) => { 17 | let hash = {} 18 | 19 | for (let i = 0; i < nums.length; i++) { 20 | let num = nums[i] 21 | 22 | if (hash.hasOwnProperty(num)) { 23 | let diff = Math.abs(hash[num] - i) 24 | if (diff <= k) return true 25 | } 26 | 27 | hash[num] = i 28 | 29 | } 30 | 31 | return false 32 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/diameterBinaryTree.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/diameter-of-binary-tree/ 2 | // TEST: npm test ./leetcode/easy/diameterBinaryTree.test.js 3 | //0(1) - space | 0(n) - time 4 | 5 | const BST = require("./BST-testcase.test"); 6 | 7 | describe('Diamter of a binary tree', () => { 8 | let bst; 9 | 10 | beforeEach(() => { 11 | bst = new BST() 12 | }) 13 | 14 | it('returns the diamter of a binary tree', () => { 15 | bst.insert(bst.root, 6); bst.insert(bst.root, 3); 16 | bst.insert(bst.root, 7); bst.insert(bst.root, 2); 17 | bst.insert(bst.root, 5); 18 | expect(diameterOfABinaryTree(bst.root)).toBe(3) 19 | }) 20 | 21 | it('returns the diamter of a binary tree', () => { 22 | bst.insert(bst.root, 1); bst.insert(bst.root, 2); 23 | expect(diameterOfABinaryTree(bst.root)).toBe(1) 24 | }) 25 | 26 | it('returns the diamter of a binary tree', () => { 27 | expect(diameterOfABinaryTree(bst.root)).toBe(0) 28 | }) 29 | }) 30 | 31 | const diameterOfABinaryTree = root => { 32 | let res = 0 33 | 34 | const dfs = root => { 35 | if (!root) return -1 36 | 37 | const left = dfs(root.left) 38 | const right = dfs(root.right) 39 | 40 | res = Math.max(res, 2 + left + right) 41 | 42 | return Math.max(left, right) + 1 43 | } 44 | dfs(root) 45 | return res 46 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/firstPalindrome.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/valid-palindrome/ 2 | // Test: npm test ./leetcode/easy/firstPalindrome.test.js 3 | //0(n * k) - time | 0(1) - space 4 | 5 | describe('#first palindrome in an array', () => { 6 | it('returns the first palindrome in an array of strings', () => { 7 | expect(firstPalindrome(["abc","car","ada","racecar","cool"])).toBe('ada') 8 | expect(firstPalindrome(["notapalindrome","racecar"])).toBe('racecar') 9 | expect(firstPalindrome([["def","ghi"]])).toBe('') 10 | }) 11 | }) 12 | 13 | const firstPalindrome = arr => { 14 | for (const word of arr) { 15 | if (validPalindrome(word)) return word 16 | } 17 | 18 | return '' 19 | } 20 | 21 | const validPalindrome = s => { 22 | let l = 0 23 | let r = s.length - 1 24 | while (l < r) { 25 | if (s[l].toLowerCase() !== s[r].toLowerCase()) return false 26 | l++ 27 | r-- 28 | } 29 | return true 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/group-anagrams.test.js: -------------------------------------------------------------------------------- 1 | /* https://leetcode.com/problems/group-anagrams/ 2 | 3 | Test: npm test ./leetcode/arrays/group-anagrams.test.js 4 | 5 | 0(n) - space | 0(m * nlogn) - time 6 | */ 7 | 8 | describe('Group Anagrams', () => { 9 | it('groups anagrams together', () => { 10 | expect(groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"])).toStrictEqual([["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]) 11 | expect(groupAnagrams([" "])).toStrictEqual([[" "]]) 12 | expect(groupAnagrams(["a"])).toStrictEqual([["a"]]) 13 | }) 14 | }) 15 | 16 | const groupAnagrams = strs => { 17 | let hash = {} 18 | 19 | for (let str of strs) { 20 | let sorted = str.split('').sort().join('') 21 | 22 | if (hash[sorted]) { 23 | hash[sorted].push(str) 24 | } else { 25 | hash[sorted] = [str] 26 | } 27 | } 28 | 29 | return Object.values(hash) 30 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/happyNum.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://leetcode.com/problems/happy-number/ 3 | 4 | complexity analysis 5 | 0(n) - space (hashtable was used) 6 | 0(n) - time 7 | */ 8 | 9 | describe('Happy numbers', () => { 10 | it('returns true if number is happy', () =>{ 11 | expect(isHappy(7)).toBe(true) 12 | expect(isHappy(19)).toBe(true) 13 | expect(isHappy(1)).toBe(true) 14 | }) 15 | it('returns false if number is not happy', () =>{ 16 | expect(isHappy(2)).toBe(false) 17 | expect(isHappy(0)).toBe(false) 18 | expect(isHappy(-1)).toBe(false) 19 | }) 20 | }) 21 | 22 | const isHappy = n => { 23 | let numbers = {} 24 | 25 | while (!(n in numbers)) { 26 | if (n === 1) return true 27 | numbers[n] = n 28 | 29 | n = ('' + n).split('').map(num => parseInt(num * num)) 30 | .reduce((curr, prev) => curr + prev) 31 | } 32 | return false 33 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/implementStackUsingQueues.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/implement-stack-using-stacks/submissions/ 2 | // Test: npm test ./leetcode/easy/implementStackUsingQueues.test.js 3 | 4 | describe('Implement stack using queue', () => { 5 | let obk; 6 | 7 | beforeEach(() => { 8 | obj = new MyStack() 9 | obj.push(7); obj.push(8); obj.push(9) 10 | }) 11 | 12 | it('adds element to the end of stack', () => { 13 | expect(obj.stack).toStrictEqual([7, 8,9]) 14 | }) 15 | 16 | it('removed element from the end of stack', () => { 17 | expect(obj.pop()).toStrictEqual(9) 18 | }) 19 | 20 | it('returns the last element in the stack', () => { 21 | expect(obj.top()).toStrictEqual(9) 22 | }) 23 | 24 | it('returns false if the stack is empty', () => { 25 | expect(obj.empty()).toStrictEqual(false) 26 | }) 27 | }) 28 | 29 | 30 | class MyStack { 31 | constructor() { 32 | this.stack = [] 33 | } 34 | 35 | // 0(1) - time && space 36 | push(x) { 37 | return this.stack[this.stack.length++] = x 38 | } 39 | 40 | // 0(n) - time | 0(1) - space 41 | pop() { 42 | for (let i = 0; i < this.stack.length - 1; i++) { 43 | this.stack.push(this.stack.shift()) 44 | } 45 | return this.stack.shift() 46 | } 47 | 48 | // 0(1) - time | 0(1) - space 49 | top() { 50 | return this.stack[this.stack.length - 1] 51 | } 52 | 53 | 54 | empty() { 55 | return this.stack.length === 0 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/invertBST.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/invert-binary-tree/ 2 | // test: npm test ./leetcode/easy/invertBST.test.js 3 | // 0(h) - time | 0(1) - space 4 | 5 | describe('#invert tree', () => { 6 | let bst 7 | beforeEach(() => { 8 | bst = new BST() 9 | bst.insert(bst.root, 4) 10 | bst.insert(bst.root, 2); bst.insert(bst.root, 7); 11 | bst.insert(bst.root, 1); bst.insert(bst.root, 3) 12 | bst.insert(bst.root, 6); bst.insert(bst.root, 9) 13 | }) 14 | 15 | it('expects tree to be inverted', () => { 16 | let invert = bst.invertTree(bst.root) 17 | expect(invert.left.data).toBe(7) 18 | }) 19 | 20 | }) 21 | 22 | class Node { 23 | constructor(data) { 24 | this.data = data 25 | this.left = this.right = null 26 | } 27 | } 28 | 29 | class BST { 30 | constructor() { 31 | this.root = null 32 | } 33 | 34 | insert(root, data) { 35 | let newNode = new Node(data) 36 | if (!root) { 37 | this.root = newNode 38 | return root 39 | } 40 | 41 | if (data < root.data) { 42 | if (!root.left) root.left = newNode 43 | else this.insert(root.left, data) 44 | } else { 45 | if (!root.right) root.right = newNode 46 | else this.insert(root.right, data) 47 | } 48 | } 49 | 50 | invertTree(root) { 51 | if (!root) return root 52 | let temp = root.left 53 | root.left = root.right 54 | root.right = temp 55 | 56 | this.invertTree(root.left) 57 | this.invertTree(root.right) 58 | 59 | return root 60 | } 61 | } 62 | 63 | 64 | const invertTree = (root) => { 65 | if (!root) return root 66 | 67 | let temp = root.left 68 | root.left = root.right 69 | root.right = temp 70 | 71 | invertTree(root.right) 72 | invertTree(root.left) 73 | 74 | return root 75 | }; -------------------------------------------------------------------------------- /leetcode/javascript/easy/isPalindrome.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/valid-palindrome/ 2 | // Test: npm test ./leetcode/easy/isPalindrome.test.js 3 | 4 | describe('is valid palindrome', () => { 5 | it('returns true if phrase is a valid palindrome', () => { 6 | expect(validPalindrome("Don't nod")).toBe(true) 7 | expect(validPalindrome('I did, did I?')).toBe(true) 8 | expect(validPalindrome('Amore roma')).toBe(true) 9 | expect(validPalindrome('A man, a plan, a canal: Panama')).toBe(true) 10 | expect(validPalindrome(' ')).toBe(true) 11 | expect(validPalindrome('aba')).toBe(true) 12 | }) 13 | it('returns false if phrase is not a valid palindrome', () => { 14 | expect(validPalindrome('race a car')).toBe(false) 15 | expect(validPalindrome('Good job')).toBe(false) 16 | }) 17 | }) 18 | 19 | // may 2022 | 0(n) - time | 0(1) - space 20 | const validPalindrome = s => { 21 | let l = 0 22 | let r = s.length - 1 23 | 24 | while (l < r) { 25 | if (isAlphaNum(s[l]) === false) { 26 | l++ 27 | continue 28 | } 29 | 30 | if (isAlphaNum(s[r]) === false) { 31 | r-- 32 | continue 33 | } 34 | 35 | if (s[l].toLowerCase() !== s[r].toLowerCase()) return false 36 | l++ 37 | r-- 38 | } 39 | 40 | return true 41 | } 42 | 43 | const isAlphaNum = str => { 44 | str = str.charCodeAt(0) 45 | return (str >= ('0').charCodeAt(0) && str <= ('9').charCodeAt(0) || 46 | str >= ('a').charCodeAt(0) && str <= ('z').charCodeAt(0) || 47 | str >= ('A').charCodeAt(0) && str <= ('Z').charCodeAt(0)) 48 | } 49 | 50 | // April 2022 51 | // 0(n ^2) - time | 0(n) - space 52 | const isPalindrome = s => { 53 | s = s.replace(/[^a-zA-Z0-9]/g).toLowerCase() 54 | let left = 0 55 | let right = s.length - 1 56 | 57 | while (left < right) { 58 | if (s[left++] !== s[right--]) return false 59 | } 60 | 61 | return true 62 | } 63 | 64 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/isValid.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/valid-parentheses/ 2 | // Test: npm test ./leetcode/medium/isValid.test.js 3 | //0(n) - time | 0(n) - space 4 | 5 | describe('is valid parentheses', () => { 6 | it('expects closing bracket for open bracket', () => { 7 | expect(isValid('([)]')).toBe(false) 8 | expect(isValid('([])]')).toBe(false) 9 | expect(isValid('()[]{}')).toBe(true) 10 | }) 11 | }) 12 | const isValid = (s) => { 13 | let stack = [] 14 | 15 | for (let el of s) { 16 | let prev = stack[stack.length - 1] 17 | 18 | if (prev === '(' && el === ')') { 19 | stack.pop() 20 | } else if (prev === '[' && el === ']') { 21 | stack.pop() 22 | } else if (prev === '{' && el === '}') { 23 | stack.pop() 24 | } else { 25 | stack.push(el) 26 | } 27 | } 28 | 29 | return stack.length === 0 30 | }; -------------------------------------------------------------------------------- /leetcode/javascript/easy/max-subarray.test.js: -------------------------------------------------------------------------------- 1 | /* https://leetcode.com/problems/maximum-subarray/ 2 | Test: npm test ./leetcode/easy/max-subarray.test.js 3 | complexity analysis 0(n) - time | 0(1) -space 4 | */ 5 | 6 | describe('maximum subarray', () => { 7 | it('returns sum of the largest sub array', () => { 8 | expect(maxSubArray([-2,1,-3,4,-1,2,1,-5,4])).toBe(6) 9 | expect(maxSubArray([5,4,-1,7,8])).toBe(23) 10 | expect(maxSubArray([1])).toBe(1) 11 | expect(maxSubArray([-1, -5, 0])).toBe(0) 12 | }) 13 | }) 14 | 15 | const maxSubArray = arr => { 16 | let maxSub = arr[0] 17 | let currSum = 0 18 | 19 | for(let num of arr){ 20 | if (currSum < 0) currSum = 0 21 | currSum += num 22 | maxSub = Math.max(maxSub, currSum) 23 | } 24 | return maxSub 25 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/maxDiff.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/maximum-difference-between-increasing-elements/ 2 | //Test: npm test ./leetcode/easy/maxDiff.test.js 3 | //0(n) - time | 0(1) - space 4 | 5 | describe('#maximum difference of subarray', () => { 6 | it('returns the maximum difference in a subarray', () => { 7 | expect(maximumDifference([7,1,5,4])).toBe(4) 8 | expect(maximumDifference([9,4,3,2])).toBe(-1) 9 | expect(maximumDifference([1,5,2,10])).toBe(9) 10 | expect(maximumDifference([1,5])).toBe(4) 11 | }) 12 | }) 13 | 14 | var maximumDifference = function(nums) { 15 | let l = 0 16 | let r = 1 17 | let max = 0 18 | 19 | while(r < nums.length){ 20 | let diff = nums[r] - nums[l] 21 | 22 | if(diff < 0){ 23 | l++ 24 | } else{ 25 | r++ 26 | } 27 | 28 | max = Math.max(max, diff) 29 | } 30 | 31 | return max > 0 ? max : -1 32 | }; -------------------------------------------------------------------------------- /leetcode/javascript/easy/mergeLinkedList.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/merge-two-sorted-lists/ 2 | // Test: npm test ./leetcode/linked-list/mergeLinkedList.test.js 3 | // 0(n) - time | 0(n) - space 4 | 5 | describe('merge two linked list', () => { 6 | 7 | let list, list1, list2 8 | beforeEach(() => { 9 | list = new SinglyLinkedList() 10 | list1 = new SinglyLinkedList() 11 | list2 = new SinglyLinkedList() 12 | }) 13 | 14 | it('merge sorted linked list', () => { 15 | list1.insert(10) 16 | list1.insert(20) 17 | list1.insert(50) 18 | list1.insert(80) 19 | 20 | list2.insert(10) 21 | list2.insert(20) 22 | list2.insert(30) 23 | 24 | let mergeNodes = list.merge(list1, list2) 25 | expect(mergeNodes.next.next.data).toBe(20) 26 | 27 | }) 28 | }) 29 | 30 | class Node { 31 | constructor(data) { 32 | this.data = data 33 | this.next = null 34 | } 35 | } 36 | 37 | class SinglyLinkedList { 38 | insert(data) { 39 | let newNode = new Node(data) 40 | if (!this.head) { 41 | this.head = newNode 42 | return this.head 43 | } 44 | 45 | let current = this.head 46 | 47 | while (current.next) { 48 | current = current.next 49 | } 50 | current.next = newNode 51 | return current 52 | } 53 | 54 | merge(list1, list2) { 55 | let head1 = list1.head 56 | let head2 = list2.head 57 | 58 | let dummyNode = new Node(0) 59 | let tail = dummyNode 60 | 61 | while (true) { 62 | if (!head1) { 63 | tail.next = head2 64 | break; 65 | } 66 | if (!head2) { 67 | tail.next = head1 68 | break 69 | } 70 | if (head1.data <= head2.data) { 71 | tail.next = head1 72 | head1 = head1.next 73 | } else { 74 | tail.next = head2 75 | head2 = head2.next 76 | } 77 | 78 | tail = tail.next 79 | } 80 | return dummyNode.next 81 | } 82 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/minStack.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/min-stack/ 2 | // Test: npm test ./leetcode/easy/minStack.test.js 3 | // 0(1) - time | 0(n) - space 4 | 5 | describe('#min stack', () => { 6 | let minStack; 7 | 8 | beforeEach(() => { 9 | minStack = new MinStack(); 10 | minStack.push(-2); 11 | minStack.push(0); 12 | minStack.push(-3); 13 | }) 14 | 15 | it('PUSH element to the stack', () => { 16 | expect(minStack.stack).toStrictEqual([[-2, -2], [0, -2], [-3, -3]]) 17 | }) 18 | 19 | it('POP element from the stack', () => { 20 | minStack.pop() 21 | expect(minStack.stack).toStrictEqual([[-2, -2], [0, -2]]) 22 | }) 23 | 24 | it('returns element at the TOP of the stack', () => { 25 | let top = minStack.top() 26 | expect(top).toBe(-3) 27 | }) 28 | 29 | it('returns the MINIMUM value in the stack in constant time', () => { 30 | let min = minStack.getMin() 31 | expect(min).toBe(-3) 32 | }) 33 | }) 34 | 35 | class MinStack { 36 | constructor() { 37 | this.stack = [] 38 | } 39 | 40 | push(val) { 41 | let min = Math.min(val, this.getMin()) 42 | this.stack[this.stack.length++] = [val, min] 43 | } 44 | 45 | pop() { 46 | this.stack.pop() 47 | } 48 | 49 | top() { 50 | return this.peek()[0] 51 | } 52 | 53 | getMin() { 54 | return this.peek()[1] ?? Infinity 55 | } 56 | 57 | peek() { 58 | return this.stack[this.stack.length - 1] || 0 59 | } 60 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/palindromeNum.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/palindrome-number/ 2 | // test: npm test ./leetcode/easy/palindromeNum.test.js 3 | 4 | // FOLLOW UP: can you do it without converting the num to a string 5 | 6 | describe('Palindrome number', () => { 7 | it('returns true if int is a palindrome', () => { 8 | expect(isPalindrome(121)).toBe(true) 9 | expect(isPalindrome(0)).toBe(true) 10 | }) 11 | it('returns false if int is not a palindrome', () => { 12 | expect(isPalindrome(182)).toBe(false) 13 | expect(isPalindrome(-121)).toBe(false) 14 | }) 15 | }) 16 | 17 | const isPalindrome = num => { 18 | if(num < 0) return false 19 | if(num === 0) return true 20 | 21 | let reversed = '' 22 | let newNum = num 23 | let digits = 0 24 | 25 | while(newNum){ 26 | digits = newNum % 10 27 | newNum = Math.round(newNum / 10) 28 | reversed += digits 29 | } 30 | 31 | return parseInt(reversed) === num 32 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/product-sign.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://leetcode.com/problems/sign-of-the-product-of-an-array/ 3 | 4 | Complexity analysis 5 | 0(n) - time 6 | 0(1) - space 7 | */ 8 | 9 | const signFunc = (x) => { 10 | if (x > 0) { 11 | return 1; 12 | } else if (x < 0) { 13 | return -1; 14 | } else { 15 | return 0; 16 | } 17 | }; 18 | 19 | const arraySign = (nums) => { 20 | let product = 1; 21 | 22 | for (let i = 0; i < nums.length; i++) { 23 | product *= nums[i]; 24 | } 25 | 26 | return signFunc(product); 27 | }; 28 | 29 | describe("sign of the product of an array", () => { 30 | it("returns 0 if product is 0", () => { 31 | expect(arraySign([1, 5, 0, 2, -3])).toBe(0); 32 | }); 33 | 34 | it("returns 1 if product is +ve", () => { 35 | expect(arraySign([-1, -2, -3, -4, 3, 2, 1])).toBe(1); 36 | }); 37 | 38 | it("returns -1 if product is -ve", () => { 39 | expect(arraySign([-1, 1, -1, 1, -1])).toBe(-1); 40 | }); 41 | }); 42 | 43 | 44 | const signedArray = (nums) => { 45 | let sign = 1; 46 | 47 | for (let i = 0; i < nums.length; i++) { 48 | if (nums[i] === 0) { 49 | return 0; 50 | } else if (nums[i] < 0) { 51 | sign = -sign; 52 | } 53 | } 54 | 55 | return sign; 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/removeDupsFromSortedArr.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 2 | // Test: npm test ./leetcode/easy/removeDupsFromSortedArr.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('remove duplicates from sorted array', () => { 6 | it('removes duplicates from sorted array in place', () => { 7 | expect(removeDuplicates([1, 1, 2])).toBe(2) 8 | expect(removeDuplicates([1, 1, 2, 3])).toBe(3) 9 | }) 10 | }) 11 | 12 | const removeDuplicates = nums => { 13 | let left = 1 14 | let right = 1 15 | 16 | while (right < nums.length) { 17 | if (nums[right] !== nums[right - 1]) { 18 | nums[left] = nums[right] 19 | left++ 20 | } 21 | right++ 22 | } 23 | return left 24 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/removeElement.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/remove-element/ 2 | // Test: npm test ./leetcode/easy/removeElement.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('remove element', () => { 6 | it('removes the val element occurence in the array', () => { 7 | expect(removeElement([0, 1, 2, 2, 3, 0, 4, 2], 2).nums).toStrictEqual([0, 1, 3, 0, 4, 0, 4, 2]) 8 | expect(removeElement([0, 1, 2, 2, 3, 0, 4, 2], 2).left).toBe(5) 9 | expect(removeElement([], 2)).toBe(0) 10 | }) 11 | }) 12 | 13 | const removeElement = (nums, val) => { 14 | if (nums.length < 1) return 0 15 | 16 | let left = 0 17 | 18 | for (let right = 0; right < nums.length; right++) { 19 | if (nums[right] !== val) { 20 | nums[left] = nums[right] 21 | left++ 22 | } 23 | } 24 | return { nums, left } 25 | }; -------------------------------------------------------------------------------- /leetcode/javascript/easy/reverseLinkedList.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | Test: Run test: npm test ./leetcode/linked-list/reverseLinkedList.test.js 3 | 4 | Source: https://leetcode.com/problems/reverse-linked-list/ 5 | 6 | complexity analysis: 0(n) - time | 0(1) - space 7 | */ 8 | 9 | describe('reverse linked list', () => { 10 | it('reverses a linked list iteratively', () => { 11 | let list = new SinglyLinkedList() 12 | list.insert(10) 13 | list.insert(20) 14 | list.insert(30) 15 | const reverse = list.reverse() 16 | expect(reverse.data).toBe(30) 17 | expect(reverse.next.next.data).toBe(10) 18 | }) 19 | }) 20 | 21 | class Node { 22 | constructor(data) { 23 | this.data = data 24 | this.next = null 25 | } 26 | } 27 | 28 | class SinglyLinkedList { 29 | insert(data) { 30 | let newNode = new Node(data) 31 | if (!this.head) { 32 | this.head = newNode 33 | return this.head 34 | } 35 | 36 | let current = this.head 37 | while (current.next) { 38 | current = current.next 39 | } 40 | current.next = newNode 41 | return current 42 | } 43 | 44 | reverse() { 45 | let prev = null 46 | let curr = this.head 47 | 48 | while (curr) { 49 | let nxt = curr.next 50 | curr.next = prev 51 | prev = curr 52 | curr = nxt 53 | } 54 | return prev 55 | } 56 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/romanToInt.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/roman-to-integer/submissions/ 2 | // Test: npm test ./leetcode/easy/romanToInt.test.js 3 | //0(n) - time | 0(n) -space 4 | 5 | describe('roman to integer', () => { 6 | it('converts roman to integer', () => { 7 | expect(romanToInt('viii')).toBe(8) 8 | expect(romanToInt('mmi')).toBe(2001) 9 | }) 10 | }) 11 | 12 | const romanToInt = (s) => { 13 | s = s.toUpperCase() 14 | const hash = { 15 | I: 1, 16 | V: 5, 17 | X: 10, 18 | L: 50, 19 | C: 100, 20 | D: 500, 21 | M: 1000, 22 | } 23 | 24 | let sum = 0 25 | for (let i = 0; i < s.length; i++) { 26 | let curr = hash[s[i]] 27 | let nxt = hash[s[i + 1]] 28 | if (curr < nxt) { 29 | sum -= curr 30 | } else { 31 | sum += curr 32 | } 33 | } 34 | return sum 35 | }; 36 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/sameTree.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/same-tree/ 2 | // TEST: npm test ./leetcode/easy/sameTree.test.js 3 | 4 | const BST = require("./BST-testcase.test"); 5 | 6 | describe('#Same Tree', () => { 7 | let p, q; 8 | 9 | beforeEach(() => { 10 | p = new BST() 11 | q = new BST() 12 | }) 13 | 14 | it('returns true if trees have the same node and value', () => { 15 | p.insert(p.root, 3); p.insert(p.root, 4); p.insert(p.root, 2) 16 | q.insert(q.root, 3); q.insert(q.root, 4); q.insert(q.root, 2) 17 | expect(sameTree(p.root, q.root)).toBe(true) 18 | }) 19 | 20 | it('returns false if trees do not have the same node and value', () => { 21 | p.insert(p.root, 3); p.insert(p.root, 4); p.insert(p.root, 2) 22 | q.insert(q.root, 3); 23 | expect(sameTree(p.root, q.root)).toBe(false) 24 | }) 25 | 26 | it('returns true if trees are null', () => { 27 | expect(sameTree(p.root, q.root)).toBe(true) 28 | }) 29 | 30 | }) 31 | 32 | const sameTree = (p, q) => { 33 | if(!p && !q) return true 34 | if(!p || !q || p.data !== q.data) return false 35 | return sameTree(p.left, q.left) && sameTree(p.right, q.right) 36 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/sortArrayByParity.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/sort-array-by-parity/ 2 | // Test: npm test ./leetcode/easy/sortArrayByParity.test.js 3 | // 0(n) - time | 0(1) -space 4 | 5 | describe('sort array by parity', () => { 6 | it('odds number comes after even numbers', () => { 7 | expect(sortArrayByParity([1, 0, 3])).toStrictEqual([0, 1, 3]) 8 | expect(sortArrayByParity([0, 1, 2])).toStrictEqual([0, 2, 1]) 9 | expect(sortArrayByParity([1, 3, 2, 4])).toStrictEqual([4, 2, 3, 1]) 10 | }) 11 | }) 12 | 13 | // l = left pointer, r = right poiter 14 | const sortArrayByParity = function (nums) { 15 | let l = 0 16 | let r = nums.length - 1 17 | 18 | 19 | while (l < r) { 20 | if (isEven(nums[l]) && isEven(nums[r])) { 21 | l++ 22 | } 23 | 24 | else if (!isEven(nums[l]) && !isEven(nums[r])) { 25 | r-- 26 | } 27 | 28 | else if (!isEven(nums[l]) && isEven(nums[r])) { 29 | swap(nums, l, r) 30 | l++ 31 | r-- 32 | } 33 | 34 | else { 35 | l++ 36 | r-- 37 | } 38 | 39 | } 40 | 41 | return nums 42 | }; 43 | 44 | const isEven = num => { 45 | return num % 2 === 0 46 | } 47 | 48 | var swap = (arr, s1, s2) => { 49 | [arr[s1], arr[s2]] = [arr[s2], arr[s1]]; 50 | } 51 | -------------------------------------------------------------------------------- /leetcode/javascript/easy/string-swap.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /* 4 | https://leetcode.com/problems/check-if-one-string-swap-can-make-strings-equal/ 5 | 6 | complexity analysis 7 | 0(1) - space 8 | 0(n) - time 9 | */ 10 | 11 | describe('Check if One String Swap Can Make Strings Equal', () => { 12 | it('returns true if it satisfies the condition', () => { 13 | expect(areAlmostEqual('bank', 'kanb')).toBe(true) 14 | expect(areAlmostEqual('attack', 'defend')).toBe(false) 15 | expect(areAlmostEqual('kelb', 'kelb')).toBe(true) 16 | expect(areAlmostEqual('kelb', 'belk')).toBe(true) 17 | expect(areAlmostEqual('aa', 'ac')).toBe(false) 18 | expect(areAlmostEqual('aaz', 'caa')).toBe(false) 19 | }) 20 | }) 21 | 22 | 23 | const areAlmostEqual = (s1, s2) => { 24 | if (s1.length !== s2.length) return false 25 | 26 | let count = 0 27 | let index = [] 28 | 29 | for (let i = 0; i < s1.length; i++) { 30 | if (s1[i] !== s2[i]) { 31 | count++ 32 | index.push(i) 33 | } 34 | } 35 | 36 | let idxOne = index[0] 37 | let idxTwo = index[1] 38 | 39 | if (count > 2 || (s1[idxOne] !== s2[idxTwo] || s1[idxTwo] !== s2[idxOne])) { 40 | return false 41 | } 42 | 43 | return true 44 | } -------------------------------------------------------------------------------- /leetcode/javascript/easy/twoSum.test.js: -------------------------------------------------------------------------------- 1 | describe('two sum', () => { 2 | it('return the indices', () => { 3 | expect(twoSum([2, 7, 11, 15], 9)).toEqual([0, 1]) 4 | expect(twoSum([3, 2, 4], 6)).toEqual([1, 2]) 5 | expect(twoSum([3, 3], 6)).toEqual([0, 1]) 6 | }) 7 | }) 8 | 9 | /* 10 | https://leetcode.com/problems/two-sum/ 11 | 12 | complexity analysis 13 | 0(n) - time 14 | 0(n) - space 15 | */ 16 | 17 | const twoSum = function (nums, target) { 18 | let diff, idx = 0 19 | let map = new Map() 20 | 21 | while (idx < nums.length) { 22 | diff = target - nums[idx] 23 | 24 | if (map.has(diff)) { 25 | return [map.get(diff), idx] 26 | } 27 | map.set(nums[idx], idx) 28 | idx++ 29 | } 30 | 31 | return [] 32 | } 33 | 34 | -------------------------------------------------------------------------------- /leetcode/javascript/hard/medianOfSortedArr.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/median-of-two-sorted-arrays/ 2 | // Test: npm test ./leetcode/hard/medianOfSortedArr.test.js 3 | // 0(m+n) 4 | 5 | describe('median of sorted arrays', () => { 6 | it('returns the media of sorted arrays', () => { 7 | expect(findMedianSortedArrays([1, 2], [3, 4])).toStrictEqual(2.5) 8 | expect(findMedianSortedArrays([], [1])).toStrictEqual(1) 9 | }) 10 | }) 11 | 12 | const findMedianSortedArrays = function (num1, num2) { 13 | let num = num1 14 | 15 | for (let i = 0; i < num2.length; i++) { 16 | num.push(num2[i]) 17 | } 18 | 19 | num = num.sort((a, b) => a - b) 20 | if (num.length === 1) return num[0] 21 | 22 | let mid = Math.floor(num.length / 2) 23 | 24 | if (num.length % 2 === 0) return (num[mid] + num[mid - 1]) / 2 25 | else return num[mid] 26 | }; -------------------------------------------------------------------------------- /leetcode/javascript/medium/3Sum.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/3sum/ 2 | // Test: npm test ./leetcode/medium/3Sum.test.js 3 | // 0(n^2) - time | 0(1) - space 4 | 5 | describe('3 sum', () => { 6 | it('returns possible sum of 3 numbers that sum up to 0', () => { 7 | expect(threeSum([0, 0, 0])).toStrictEqual([[0, 0, 0]]) 8 | expect(threeSum([-2, 2, -2, 0, 0])).toStrictEqual([[-2, 0,2]]) 9 | expect(threeSum([])).toStrictEqual([]) 10 | expect(threeSum([1])).toStrictEqual([]) 11 | expect(threeSum([1, 2, 3])).toStrictEqual([]) 12 | }) 13 | }) 14 | 15 | const threeSum = (nums) => { 16 | if (nums.length < 3) return [] 17 | 18 | nums = nums.sort((a, b) => a - b) 19 | let validSum = [] 20 | 21 | for (let i = 0; i < nums.length; i++) { 22 | if (nums[i] > 0) break 23 | if (i > 0 && nums[i] === nums[i - 1]) 24 | continue 25 | 26 | 27 | let left = i + 1 28 | let right = nums.length - 1 29 | 30 | while (left < right) { 31 | const sum = nums[i] + nums[left] + nums[right] 32 | 33 | if (sum === 0) { 34 | validSum.push([nums[i], nums[left], nums[right]]) 35 | left++ 36 | right-- 37 | while (left < right && nums[left] === nums[left - 1]) { 38 | left++ 39 | } 40 | } else if (sum < 0) { 41 | left++ 42 | } else { 43 | right-- 44 | } 45 | } 46 | } 47 | return validSum 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /leetcode/javascript/medium/contains-dupsIII.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('#contains duplicates III', () => { 3 | it('returns true if array contains duplicates, diff of duplicates(index) <= k && diff of nums <= t', () => { 4 | expect(containsNearbyAlmostDuplicate([3], 3, 0)).toBe(false) 5 | expect(containsNearbyAlmostDuplicate([], 1, 3)).toBe(false) 6 | expect(containsNearbyAlmostDuplicate([1, 2, 3, 1], 3, 0)).toBe(true) 7 | expect(containsNearbyAlmostDuplicate([1,0,1,1,1], 1, 2)).toBe(true) 8 | expect(containsNearbyAlmostDuplicate([1,5,9,1,5,9], 2, 3)).toBe(false) 9 | expect(containsNearbyAlmostDuplicate([-1, -2, 0, 5,-2], 3, 4)).toBe(true) 10 | }) 11 | }) 12 | 13 | var containsNearbyAlmostDuplicate = function(nums, k, t) { 14 | const buckets = new Map(); 15 | const w = t + 1; 16 | 17 | for(let i = 0; i < nums.length; i++){ 18 | const idx = Math.floor(nums[i] / w) 19 | 20 | if(buckets.has(idx)){ 21 | return true 22 | } 23 | 24 | if(buckets.has(idx - 1) && Math.abs(nums[i] - buckets.get(idx - 1)) < w){ 25 | return true 26 | } 27 | 28 | if(buckets.has(idx + 1) && Math.abs(nums[i] - buckets.get(idx + 1)) < w){ 29 | return true 30 | } 31 | 32 | buckets.set(idx, nums[i]) 33 | 34 | if(i >= k){ 35 | const idxOfBucket2Remove = Math.floor(nums[i-k] / w) 36 | 37 | buckets.delete(idxOfBucket2Remove) 38 | } 39 | } 40 | 41 | return false; 42 | }; 43 | 44 | const containsNearbyAlmostDuplicate = (nums, k, t) => { 45 | let map = new Map() 46 | 47 | for(let i=0; i { 10 | let obj 11 | 12 | beforeEach(() => { 13 | obj = new WordDictionary() 14 | obj.addWord('bad'); obj.addWord('mad'); 15 | obj.addWord('dad'); 16 | }) 17 | 18 | it('returns true if word is found in the dictionary', () => { 19 | expect(obj.search('pad')).toBe(false) 20 | expect(obj.search('bad')).toBe(true) 21 | expect(obj.search('.ad')).toBe(true) 22 | expect(obj.search('b..')).toBe(true) 23 | }) 24 | }) 25 | 26 | class WordDictionary { 27 | constructor() { 28 | this.root = {} 29 | } 30 | 31 | addWord(word) { 32 | let node = this.root 33 | 34 | for (const char of word) { 35 | if (!node[char]) node[char] = {} 36 | 37 | node = node[char] 38 | } 39 | node.isEnd = true 40 | } 41 | 42 | 43 | search(word) { 44 | 45 | const dfs = (i, node) => { 46 | 47 | if (i === word.length) { 48 | return node.isEnd || false 49 | } 50 | 51 | const char = word[i] 52 | 53 | if (char === ".") { 54 | 55 | for (const c of Object.keys(node)) { 56 | return (dfs(i + 1, node[c])) || false 57 | } 58 | 59 | } else { 60 | if (!node[char]) return false 61 | return dfs(i + 1, node[char]) 62 | } 63 | 64 | 65 | } 66 | return dfs(0, this.root) 67 | } 68 | 69 | } 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /leetcode/javascript/medium/getTargetCopy.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/find-a-corresponding-node-of-a-binary-tree-in-a-clone-of-that-tree/ 2 | // TEST: npm test ./leetcode/medium/getTargetCopy.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | const BST = require("../easy/BST-testcase.test"); 6 | 7 | describe('#Get target copy from a cloned BT', () => { 8 | let p, q; 9 | 10 | beforeEach(() => { 11 | p = new BST() 12 | p.insert(p.root, 60); p.insert(p.root, 10) 13 | p.insert(p.root, 40); p.insert(p.root, 70) 14 | p.insert(p.root, 20); p.insert(p.root, 5) 15 | q = p.copy() 16 | }) 17 | 18 | it('returns the target in the cloned tree', () => { 19 | expect(getTargetCopy(p.root, q, 20).data).toBe(20) 20 | expect(getTargetCopy(p.root, q, 60).data).toBe(60) 21 | }) 22 | }) 23 | 24 | 25 | 26 | const getTargetCopy = (original, cloned, target) => { 27 | if (!original || !cloned) return 28 | const dfs = (original, copy) => { 29 | if (!original) return 30 | 31 | if (original.data === target) return copy // in leetcode playground, compare the original node, not just the target. This will cover the edge case of duplicate values 32 | 33 | let left = dfs(original.left, copy.left) 34 | let right = dfs(original.right, copy.right) 35 | 36 | return left || right 37 | } 38 | 39 | return dfs(original, cloned) 40 | } -------------------------------------------------------------------------------- /leetcode/javascript/medium/implementTrie.test.js: -------------------------------------------------------------------------------- 1 | //TEST: npm test ./leetcode/medium/implementTrie.test.js 2 | 3 | describe('#Implement Trie Data structure', () => { 4 | let myTrie; 5 | 6 | beforeEach(() => { 7 | myTrie = new Trie() 8 | myTrie.insert('gorilla'); myTrie.insert('gotham'); myTrie.insert('boo'); 9 | }) 10 | 11 | it('inserts string into trie', () => { 12 | expect(myTrie.root.g).toBeDefined() 13 | expect(myTrie.root.n).toBeUndefined() 14 | }) 15 | 16 | it('searches for string in trie', () => { 17 | expect(myTrie.search('golang')).toEqual(false) 18 | expect(myTrie.search('boo')).toEqual(true) 19 | }) 20 | 21 | it('finds prefix of string in trie', () => { 22 | expect(myTrie.startsWith('go')).toEqual(true) 23 | expect(myTrie.startsWith('boom')).toEqual(false) 24 | }) 25 | }) 26 | 27 | class Trie { 28 | constructor() { 29 | this.root = {} 30 | } 31 | 32 | insert(word) { 33 | let node = this.root 34 | 35 | for (const char of word) { 36 | if (!node[char]) { 37 | node[char] = {} 38 | } 39 | node = node[char] 40 | } 41 | node.isEnd = true 42 | } 43 | 44 | search(word) { 45 | let node = this.root 46 | 47 | for (const char of word) { 48 | if (!node[char]) return false 49 | node = node[char] 50 | } 51 | 52 | return node.isEnd || false 53 | } 54 | 55 | startsWith(prefix) { 56 | let node = this.root 57 | 58 | for (const char of prefix) { 59 | if (!node[char]) return false 60 | node = node[char] 61 | } 62 | 63 | return true 64 | } 65 | } -------------------------------------------------------------------------------- /leetcode/javascript/medium/longestSubstring.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/longest-substring-without-repeating-characters/ 2 | // Test: npm test ./leetcode/medium/longestSubstring.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('longest substring without returning characters', () => { 6 | it('returns the count of the longest substring', () => { 7 | expect(lengthOfLongestSubstring('abcd08=ab')).toBe(7) 8 | expect(lengthOfLongestSubstring('wikew')).toBe(4) 9 | }) 10 | }) 11 | 12 | const lengthOfLongestSubstring = str => { 13 | let max = 0 14 | let left = 0 15 | let set = new Set() 16 | 17 | for (let right = 0; right < str.length; right++) { 18 | while (set.has(str[right])) { 19 | set.delete(str[left]) 20 | left++ 21 | } 22 | 23 | set.add(str[right]) 24 | max = Math.max(max, right - left + 1) 25 | } 26 | return max 27 | }; -------------------------------------------------------------------------------- /leetcode/javascript/medium/maxOperations.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/max-number-of-k-sum-pairs 2 | // Test: npm test ./leetcode/medium/maxOperations.test.js 3 | 4 | describe('max operation', () => { 5 | it('returns the number of possible sums for k', () =>{ 6 | expect(maxOperationsTwo([2,5,4,4,1,3,4,4,1,4,4,1,2,1,2,2,3,2,4,2], 3)).toBe(4) 7 | expect(maxOperations([3,1,3,4,3], 6)).toBe(1) 8 | expect(maxOperations([], 2)).toBe(0) 9 | }) 10 | }) 11 | 12 | // 0(n) - time | 0(n) - space 13 | const maxOperations = (nums, k) => { 14 | let map = new Map() 15 | let count = 0 16 | 17 | for (let n of nums){ 18 | let diff = k - n 19 | 20 | if(diff > 0 && map.get(diff) > 0){ 21 | count++ 22 | map.set(diff, map.get(diff) - 1) 23 | } else{ 24 | map.set(n, (map.get(n) || 0) + 1) 25 | } 26 | } 27 | 28 | return count 29 | } 30 | 31 | // 0(nlogn) - time | 0(1) - space 32 | const maxOperationsTwo = (nums, k) => { 33 | nums = nums.sort((a,b) => a - b) 34 | 35 | let left = 0 36 | let right = nums.length - 1 37 | let count = 0 38 | 39 | while(left < right){ 40 | if (nums[left] + nums[right] < k) left++ 41 | else if (nums[left] + nums[right] > k) right-- 42 | else{ 43 | left++ 44 | right-- 45 | count++ 46 | } 47 | } 48 | 49 | return count 50 | }; -------------------------------------------------------------------------------- /leetcode/javascript/medium/maxProfitII.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 2 | // Test: npm test ./leetcode/medium/maxProfitII.test.js 3 | //0(n) - time | 0(1) - space 4 | 5 | describe('#max profit', () => { 6 | it('returns the max profit from buying and selling stocks', () => { 7 | expect(maxProfit([7,1,5,3,6,4])).toBe(7) 8 | expect(maxProfit([1,2,3,4,5])).toBe(4) 9 | expect(maxProfit([7,6,4,3,1])).toBe(0) 10 | expect(maxProfit([])).toBe(0) 11 | expect(maxProfit([0, -1, 4, 5])).toBe(6) 12 | }) 13 | }) 14 | 15 | const maxProfit = nums => { 16 | let profit = 0 17 | 18 | for(let i = 0; i < nums.length; i++){ 19 | if(nums[i + 1] > nums[i]){ 20 | profit += (nums[i + 1] - nums[i]) 21 | } 22 | } 23 | 24 | return profit 25 | } -------------------------------------------------------------------------------- /leetcode/javascript/medium/reverseInteger.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/reverse-integer/ 2 | // test: npm test ./leetcode/medium/reverseInteger.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('reverse 2 bit integer', () => { 6 | it('expects to reverse 32 bit integer', () => { 7 | expect(reverse(120)).toBe(21) 8 | expect(reverse(-123)).toBe(-321) 9 | }) 10 | it('expects to return 0 for integers larger or less than 32 bit', () => { 11 | expect(reverse(1534236469)).toBe(0) 12 | expect(reverse(-(2**31))).toBe(0) 13 | }) 14 | }) 15 | 16 | const reverse = x => { 17 | let res = 0 18 | let sign = Math.sign(x) 19 | let min = -(2**31) 20 | let max = (2**31) - 1 21 | 22 | console.log({min, max}) 23 | console.log(Math.floor(max / 10)) 24 | 25 | if(sign === -1){ 26 | x = x * sign 27 | } 28 | 29 | 30 | while(x){ 31 | let digit = x % 10 32 | x = Math.floor(x/10) 33 | 34 | if (res > Math.floor(max/10) || res === Math.floor(max/10) && digit >= max % 10){ return 0} 35 | if (res < Math.floor(min/10) || res === Math.floor(min/10) && digit <= min % 10) { return 0 } 36 | 37 | res = (res * 10) + digit 38 | } 39 | 40 | return res*sign 41 | } 42 | 43 | -------------------------------------------------------------------------------- /leetcode/javascript/medium/subsets.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/subsets/ 2 | //Test: npm test ./leetcode/medium/subsets.test.js 3 | //0(n * 2^n) - time | 0(n) - space 4 | 5 | describe('#subsets', () => { 6 | it('returns the subsets of a given array', () => { 7 | expect(subsets([1, 2, 3])).toStrictEqual([[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]) 8 | expect(subsets([0])).toStrictEqual([[0], []]) 9 | }) 10 | }) 11 | 12 | const subsets = nums => { 13 | let res = [] 14 | let subsets = [] 15 | 16 | const dfs = i => { 17 | if (i >= nums.length) { 18 | res.push([...subsets]) 19 | return 20 | } 21 | 22 | subsets.push(nums[i]) 23 | dfs(i + 1) 24 | 25 | subsets.pop() 26 | dfs(i + 1) 27 | } 28 | dfs(0) 29 | return res 30 | } -------------------------------------------------------------------------------- /leetcode/javascript/medium/twoSum-ii.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 2 | // npm test ./leetcode/medium/twoSum-ii.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('Two sum II: 1-indexed array', () => { 6 | it('returns the indices of numbers that sum up to target', () =>{ 7 | expect(twoSum([2, 7, 11, 15], 9)).toStrictEqual([1, 2]) 8 | expect(twoSum([2, 3, 4], 6)).toStrictEqual([1, 3]) 9 | expect(twoSum([3, 3, 4, 9, 8], 12)).toStrictEqual([3, 5]) 10 | }) 11 | }) 12 | 13 | /* 14 | complexity analysis 15 | */ 16 | 17 | const twoSum = (numbers, target) => { 18 | let left = 0 19 | let right = numbers.length - 1 20 | 21 | while (left < right){ 22 | let sum = numbers[left] + numbers[right] 23 | 24 | if(sum > target) right-- 25 | else if (sum < target) left++ 26 | else return [left+1, right+1] 27 | } 28 | } -------------------------------------------------------------------------------- /leetcode/javascript/medium/unsortedSubArray.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/shortest-unsorted-continuous-subarray/ 2 | // Test: npm test ./leetcode/medium/unsortedSubArray.test.js 3 | // 0(n) - time | 0(1) - space 4 | 5 | describe('unsorted sub array', () => { 6 | it('returns the length of unsorted subarray', () => { 7 | expect(findUnsortedSubarray([4, 6, 3, 2, 7, 5, 8])).toBe(6) 8 | expect(findUnsortedSubarray([1, 3, 2, 4, 5])).toBe(2) 9 | expect(findUnsortedSubarray([])).toBe(0) 10 | }) 11 | }) 12 | 13 | 14 | const findUnsortedSubarray = function (nums) { 15 | let start = 0 16 | let end = nums.length - 1 17 | 18 | while (start + 1 < nums.length && nums[start] <= nums[start + 1]) start++ 19 | 20 | while (end - 1 >= 0 && nums[end] >= nums[end - 1]) end-- 21 | 22 | if (start === nums.length - 1) return 0 23 | 24 | let min = +Infinity 25 | let max = -Infinity 26 | 27 | for (let i = start; i <= end; i++) { 28 | min = Math.min(min, nums[i]) 29 | max = Math.max(max, nums[i]) 30 | } 31 | while (start - 1 >= 0 && nums[start - 1] > min) start-- 32 | 33 | while (end + 1 <= nums.length && nums[end + 1] < max) end++ 34 | 35 | return end - start + 1 36 | } 37 | -------------------------------------------------------------------------------- /leetcode/python/BFS/jumpGameIII.py: -------------------------------------------------------------------------------- 1 | from typing import Deque, List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/jump-game-iii/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | 10 | class Solution: 11 | def canReach(self, arr: List[int], start: int) -> bool: 12 | queue = Deque([start]) 13 | visited = set() 14 | 15 | while queue: 16 | idx = queue.popleft() 17 | 18 | if idx in visited: 19 | continue 20 | visited.add(idx) 21 | 22 | if arr[idx] == 0: 23 | return True 24 | else: 25 | if idx - arr[idx] >= 0: 26 | queue.append(idx - arr[idx]) 27 | if idx + arr[idx] < len(arr): 28 | queue.append(idx + arr[idx]) 29 | return False 30 | 31 | class Test(unittest.TestCase): 32 | def test_canReach(self): 33 | self.assertEqual(Solution.canReach(self, [3,0,2,1,2], 2), False) 34 | self.assertEqual(Solution.canReach(self, [4,2,3,0,3,1,2], 5), True) 35 | 36 | if __name__ == "__main__": 37 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/bit-manipulation/countingBits.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/counting-bits/ 6 | 0(n log n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def countBitsDp(self, n:int) -> List[int]: 11 | dp = [0] * (n + 1) 12 | offset = 1 13 | 14 | for i in range(1, n + 1): 15 | if offset * 2 == i: 16 | offset = i 17 | dp[i] = 1 + dp[i - offset] 18 | return dp 19 | 20 | def countBits(self, n: int) -> List[int]: 21 | ans = [] 22 | 23 | for i in range(n + 1): 24 | convertToBin = bin(i) 25 | ans.append(convertToBin.count('1')) 26 | return ans 27 | 28 | class Test(unittest.TestCase): 29 | def test_countBits(self): 30 | self.assertEqual(Solution.countBits(self, 2), [0,1,1]) 31 | self.assertEqual(Solution.countBits(self, 5), [0,1,1,2,1,2]) 32 | 33 | def test_countBitsDP(self): 34 | self.assertEqual(Solution.countBits(self, 1), [0,1]) 35 | self.assertEqual(Solution.countBits(self, 0), [0]) 36 | 37 | 38 | if __name__ == "__main__": 39 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/bit-manipulation/hammingWeight.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/number-of-1-bits/ 5 | 0(1) - tc | 0(1) - sc 6 | ''' 7 | 8 | class Solution: 9 | def hammingWeight(self, n) -> int: 10 | n = int(n) 11 | count = 0 12 | while n: 13 | count += n % 2 14 | n = n // 2 15 | return count 16 | 17 | def hammingWeightTwo(self, n) -> int: 18 | n = int(n) 19 | print(n) 20 | count = 0 21 | while n: 22 | if n & 1: 23 | count += 1 24 | n = n >> 1 25 | return count 26 | 27 | 28 | -------------------------------------------------------------------------------- /leetcode/python/bit-manipulation/reverseBits.py: -------------------------------------------------------------------------------- 1 | ''' 2 | https://leetcode.com/problems/reverse-bits/ 3 | 0(1) - tc & sc 4 | ''' 5 | 6 | class Solution: 7 | def reverseBits(self, n: int) -> int: 8 | pos = 31 9 | rvd = 0 10 | 11 | while pos >= 0 and n: 12 | if n & 1: 13 | rvd = rvd | (1 << pos) 14 | n >>= 1 15 | pos -= 1 16 | return rvd 17 | 18 | -------------------------------------------------------------------------------- /leetcode/python/bit-manipulation/reverseInt.py: -------------------------------------------------------------------------------- 1 | import math, unittest 2 | 3 | class Solution: 4 | def reverse(self, x: int) -> int: 5 | MIN = -2147483648 6 | MAX = 2147483647 7 | res = 0 8 | 9 | while x: 10 | digit = int(math.fmod(x, 10)) 11 | x = int(x / 10) 12 | 13 | if (res > MAX // 10 or (res == MAX // 10 and digit >= MAX % 10)): 14 | return 0 15 | 16 | if (res < MIN // 10 or (res == MIN // 10 and digit <= MIN % 10)): 17 | return 0 18 | 19 | res = (res * 10) + digit 20 | 21 | return res 22 | 23 | class Test(unittest.TestCase): 24 | def test_reverse(self): 25 | self.assertEqual(Solution.reverse(self, -123), -321) 26 | self.assertEqual(Solution.reverse(self, 1534236469), 0) 27 | 28 | if __name__ == "__main__": 29 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/bit-manipulation/sumTwoInt.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/sum-of-two-integers/ 5 | 0(1) - tc & sc 6 | ''' 7 | 8 | class Solution: 9 | def getSum(self, a: int, b: int) -> int: 10 | def add(a, b): 11 | if not a or not b: 12 | return a or b 13 | return add(a^b, (a & b) << 1) 14 | if a * b < 0: 15 | if a > 0: 16 | return self.getSum(b, a) 17 | if add(~a, 1) == b: 18 | return 0 19 | if add(~a, 1) < b: 20 | return add(~add(add(~a, 1), add(~b, 1)), 1) 21 | return add(a, b) 22 | 23 | class Test(unittest.TestCase): 24 | def test_getSum(self): 25 | self.assertEqual(Solution.getSum(self, 2, 3), 5) 26 | self.assertEqual(Solution.getSum(self, 1, 2), 3) 27 | 28 | if __name__ == "__main__": 29 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/climbStairs.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/climbing-stairs/ 5 | 0(n) - TC | 0(n) - SC 6 | ''' 7 | 8 | def climbStairs(n) -> int: 9 | one, two = 1, 1 10 | 11 | for i in range (n - 1): 12 | temp = one 13 | one = one + two 14 | two = temp 15 | 16 | return one 17 | 18 | def climbStairsRecursive(n) -> int: 19 | memo = {} 20 | 21 | def recurse(n): 22 | if n in memo: 23 | return memo[n] 24 | if n == 1: 25 | return 1 26 | if n == 2: 27 | return 2 28 | memo[n] = recurse(n - 1) + recurse(n - 2) 29 | return memo[n] 30 | 31 | return recurse(n) 32 | 33 | print(climbStairsRecursive(38)) 34 | class Test(unittest.TestCase): 35 | def test_climbStairs(self): 36 | self.assertEqual(climbStairsRecursive(2), 2) 37 | self.assertEqual(climbStairsRecursive(3), 3) 38 | self.assertEqual(climbStairsRecursive(5), 8) 39 | self.assertEqual(climbStairsRecursive(38), 63245986) 40 | 41 | 42 | if __name__ == "__main__": 43 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/findJudge.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | ''' 4 | https://leetcode.com/problems/find-the-town-judge/ 5 | 0(n) - sc | 0(n) -tc 6 | ''' 7 | 8 | def trustJudge(n, trust:List[List[int]]) -> int: 9 | trust_board = [0] * (n + 1) 10 | 11 | for person1, person2 in trust: 12 | trust_board[person2] += 1 13 | trust_board[person1] -= 1 14 | 15 | for i in range(1, n + 1): 16 | if trust_board[i] == n - 1: 17 | return i 18 | return -1 19 | 20 | 21 | print(trustJudge(3, [[1,2], [2,3]])) -------------------------------------------------------------------------------- /leetcode/python/easy/isAnagram.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/valid-anagram/ 5 | ''' 6 | 7 | #0(n log n) - tc & sc 8 | class Solution: 9 | def isAnagram(self, s: str, t: str) -> bool: 10 | def sortStr(letter): 11 | letter = sorted(letter) 12 | newLetter = ''.join(letter) 13 | return newLetter 14 | 15 | return sortStr(s) == sortStr(t) 16 | 17 | #0(s + t) - tc & sc 18 | class SolutionTwo: 19 | def isAnagram(self, s: str, t: str) -> bool: 20 | if len(s) != len(t): 21 | return False 22 | countS, countT = {}, {} 23 | 24 | for i in range(len(s)): 25 | countS[s[i]] = 1 + countS.get(s[i], 0) 26 | countT[t[i]] = 1 + countT.get(t[i], 0) 27 | 28 | for c in countS: 29 | if countS[c] != countT.get(c, 0): 30 | return False 31 | return True 32 | 33 | class Test(unittest.TestCase): 34 | def test_solutionOne(self): 35 | self.assertEqual(Solution.isAnagram(self, 'anagram', 'nagaram'), True) 36 | self.assertEqual(Solution.isAnagram(self, 'rat', 'car'), False) 37 | self.assertEqual(Solution.isAnagram(self, 'rat', 'ca'), False) 38 | self.assertEqual(Solution.isAnagram(self, '', ''), True) 39 | self.assertEqual(Solution.isAnagram(self, '', 'b'), False) 40 | self.assertEqual(Solution.isAnagram(self, ' ', ' '), True) 41 | 42 | def test_solutionTwo(self): 43 | self.assertEqual(SolutionTwo.isAnagram(self, 'anagram', 'nagaram'), True) 44 | self.assertEqual(SolutionTwo.isAnagram(self, 'rat', 'car'), False) 45 | self.assertEqual(SolutionTwo.isAnagram(self, 'rat', 'ca'), False) 46 | self.assertEqual(SolutionTwo.isAnagram(self, '', ''), True) 47 | self.assertEqual(SolutionTwo.isAnagram(self, '', 'b'), False) 48 | self.assertEqual(SolutionTwo.isAnagram(self, ' ', ' '), True) 49 | 50 | if __name__ == "__main__": 51 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/maxProfit.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | class Solution: 10 | def maxProfit(self, nums: List[int]) -> int: 11 | left, right = 0, 1 12 | profit = 0 13 | 14 | while right < len(nums): 15 | if nums[right] < nums[left]: 16 | left += 1 17 | else: 18 | profit = max(profit, nums[right] - nums[left]) 19 | right += 1 20 | return profit 21 | 22 | class Test(unittest.TestCase): 23 | def test_maxProfit(self): 24 | self.assertEqual(Solution.maxProfit(self, [7,1,5,3,6,4]), 5) 25 | self.assertEqual(Solution.maxProfit(self, [7,6,4,3,1]), 0) 26 | self.assertEqual(Solution.maxProfit(self, [1]), 0) 27 | self.assertEqual(Solution.maxProfit(self, [1, 1]), 0) 28 | self.assertEqual(Solution.maxProfit(self, [0, 1]), 1) 29 | self.assertEqual(Solution.maxProfit(self, []), 0) 30 | 31 | if __name__ == "__main__": 32 | unittest.main() 33 | -------------------------------------------------------------------------------- /leetcode/python/easy/mergeSortedArr.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/merge-sorted-array/ 6 | 0(n + m) - TC | 0(1) - SC 7 | ''' 8 | 9 | def merge(nums1:List[int], nums2:List[int], m:int, n:int) -> None: 10 | last = m + n - 1 11 | 12 | while m > 0 and n > 0: 13 | if nums1[m - 1] > nums2[n - 1]: 14 | nums1[last] = nums1[m - 1] 15 | m -= 1 16 | else: 17 | nums1[last] = nums2[n - 1] 18 | n -= 1 19 | last -= 1 20 | 21 | 22 | while n > 0: 23 | nums1[last] = nums2[n - 1] 24 | n -= 1 25 | last -= 1 26 | 27 | return nums1 28 | 29 | 30 | class Test(unittest.TestCase): 31 | def test_merge(self): 32 | fn = merge([1, 2, 3, 0, 0, 0], [2,5,6], 3, 3) 33 | self.assertEqual(fn, [1, 2,2,3,5,6]) 34 | 35 | 36 | if __name__ == '__main__': 37 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/minCostClimbingStairs.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/min-cost-climbing-stairs/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def minCostClimbingStairs(self, cost: List[int]) -> int: 11 | cost.append(0) 12 | 13 | for i in range(len(cost) - 3, -1, -1): 14 | cost[i] += min(cost[i + 1], cost[i + 2]) 15 | 16 | return min(cost[0], cost[1]) 17 | 18 | class Test(unittest.TestCase): 19 | def test_minCost(self): 20 | self.assertEqual(Solution.minCostClimbingStairs(self, [10,15,20]), 15) 21 | self.assertEqual(Solution.minCostClimbingStairs(self, [1,100,1,1,1,100,1,1,100,1]), 6) 22 | 23 | if __name__ == "__main__": 24 | unittest.main() 25 | -------------------------------------------------------------------------------- /leetcode/python/easy/removePalindromeSub.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/remove-palindromic-subsequences/ 5 | 0(n) - TC | 0(1) - SC 6 | ''' 7 | 8 | def removePalindromeSub(str) -> int: 9 | i, j = 0, len(str) - 1 10 | 11 | while i < j: 12 | if str[i] != str[j]: 13 | return 2 14 | i += 1 15 | j -= 1 16 | return 1 17 | 18 | class Test(unittest.TestCase): 19 | def test_solution(self): 20 | self.assertEqual(removePalindromeSub('baabb'), 2) 21 | self.assertEqual(removePalindromeSub("bbaabaaa"), 2) 22 | self.assertEqual(removePalindromeSub('ababa'), 1) 23 | 24 | if __name__ == "__main__": 25 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/runningSum.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | """ 5 | https://leetcode.com/problems/running-sum-of-1d-array/ 6 | 0(n) - TC | 0(1) - SC 7 | """ 8 | 9 | def runningSum(nums:List[int]) -> List[int]: 10 | for i in range(1, len(nums)): 11 | nums[i] = nums[i] + nums[i - 1] 12 | 13 | return nums 14 | 15 | 16 | class Test(unittest.TestCase): 17 | def test_runningSum(self): 18 | self.assertEqual(runningSum([1,1,1,2,2,3]), [1,2,3,5,7,10]) 19 | self.assertEqual(runningSum([]), []) 20 | self.assertEqual(runningSum([1]), [1]) 21 | self.assertEqual(runningSum([-1, 1, 2]), [-1, 0, 2]) 22 | 23 | 24 | if __name__ == "__main__": 25 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/test_kthLargest.py: -------------------------------------------------------------------------------- 1 | import unittest, heapq 2 | from pip import List 3 | 4 | """ 5 | https://leetcode.com/problems/kth-largest-element-in-a-stream/ 6 | 0(n log k) - TC | 0(1) - space 7 | """ 8 | 9 | class KthLargest: 10 | def __init__(self, k:int, nums: List[int]): 11 | self.minHeap = nums 12 | self.k = k 13 | heapq.heapify(self.minHeap) 14 | while len(self.minHeap) > k: 15 | heapq.heappop(self.minHeap) 16 | 17 | def add(self, val:int) -> int: 18 | heapq.heappush(self.minHeap, val) 19 | if len(self.minHeap) > self.k: 20 | heapq.heappop(self.minHeap) 21 | return self.minHeap[0] 22 | 23 | class TestKthLargest(unittest.TestCase): 24 | def test_kthLargest(self): 25 | heap = KthLargest(3, [4,5,8,2]) 26 | result = heap.add(3) 27 | self.assertEqual(result, 4) 28 | 29 | if __name__ == "__main__": 30 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/test_twoSum.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | 5 | class Solution: 6 | def twoSum(self, nums:List[int], target:int )->int: 7 | hash = {} 8 | i = 0 9 | 10 | while i < len(nums): 11 | diff = target - nums[i] 12 | if diff in hash: 13 | return [hash[diff], i] 14 | hash[nums[i]] = i 15 | i += 1 16 | 17 | 18 | class TestTwoSum(unittest.TestCase): 19 | def test_twoSum(self): 20 | result = Solution.twoSum(self, [2,7,11,15], 9) 21 | result_two = Solution.twoSum(self, [3,2,4], 6) 22 | self.assertEqual(result, [0,1]) 23 | self.assertEqual(result_two, [1,2]) 24 | 25 | if __name__ == "__main__": 26 | unittest.main() 27 | 28 | -------------------------------------------------------------------------------- /leetcode/python/easy/transposeMatrix.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | """ 5 | https://leetcode.com/problems/transpose-matrix/ 6 | 0(R * C) TC | SC - rows * cols of given matrix 7 | """ 8 | 9 | class Solution: 10 | def transpose(self, matrix:List[List[int]]) -> List[List[int]]: 11 | rows, cols = len(matrix), len(matrix[0]) 12 | transposed = [] 13 | 14 | for i in range(rows): 15 | transposed.append([]) 16 | for j in range(cols): 17 | transposed[i].append(matrix[j][i]) 18 | 19 | return transposed 20 | 21 | class TestTranspose(unittest.TestCase): 22 | def test_transpose(self): 23 | sol = Solution.transpose(self, [[2, 4, -1], [-10, 5, 11], [18, -7, 6]]) 24 | self.assertEqual(sol, [[2, -10, 18], [4, 5, -7], [-1, 11, 6]]) 25 | 26 | if __name__ == "__main__": 27 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/twoSum.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | Leetcode 1: https://leetcode.com/problems/two-sum/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def twoSum(self, nums: List[int], target: int) -> List[int]: 11 | store = {} 12 | for i in range(len(nums)): 13 | diff = target - nums[i] 14 | if diff in store: 15 | return [store[diff], i] 16 | store[nums[i]] = i 17 | 18 | 19 | class Test(unittest.TestCase): 20 | def test_twoSum(self): 21 | self.assertEqual(Solution.twoSum(self, [3, 3], 6), [0, 1]) 22 | self.assertEqual(Solution.twoSum(self, [2,7,11,15], 9), [0, 1]) 23 | self.assertEqual(Solution.twoSum(self, [3,2,4], 6), [1, 2]) 24 | 25 | 26 | if __name__ == "__main__": 27 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/validPalindrome.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/valid-palindrome/ 5 | 0(n) - tc | 0(1) - sc 6 | ''' 7 | 8 | class Solution: 9 | def isPalindrome(self, s: str) -> bool: 10 | s = s.lower().replace(' ', '') 11 | l, r = 0, len(s) - 1 12 | 13 | 14 | while l < r: 15 | if not s[l].isalnum(): 16 | l += 1 17 | continue 18 | if not s[r].isalnum(): 19 | r -= 1 20 | continue 21 | if s[l] != s[r]: 22 | return False 23 | l += 1 24 | r -= 1 25 | return True 26 | 27 | class Test(unittest.TestCase): 28 | def test_validPalindrom(self): 29 | self.assertEqual(Solution.isPalindrome(self, "A man, a plan, a canal: Panama"), True) 30 | self.assertEqual(Solution.isPalindrome(self, ",."), True) 31 | self.assertEqual(Solution.isPalindrome(self, "race a car"), False) 32 | self.assertEqual(Solution.isPalindrome(self, " "), True) 33 | 34 | if __name__ == "__main__": 35 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/easy/validParentheses.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/valid-parentheses/ 5 | 0(n) - tc & 0(n) - sc 6 | ''' 7 | class Solution: 8 | def isValid(self, s: str) -> bool: 9 | stack = [] 10 | 11 | for item in s: 12 | lastItem = stack and stack[-1] 13 | if lastItem == "(" and item == ")": 14 | stack.pop() 15 | elif lastItem == "[" and item == "]": 16 | stack.pop() 17 | elif lastItem == "{" and item == "}": 18 | stack.pop() 19 | else: 20 | stack.append(item) 21 | return len(stack) == 0 22 | 23 | class Test(unittest.TestCase): 24 | def test_isValid(self): 25 | self.assertEqual(Solution.isValid(self, '([])'), True) 26 | self.assertEqual(Solution.isValid(self, '([)]'), False) 27 | self.assertEqual(Solution.isValid(self, '()[]{}'), True) 28 | 29 | if __name__ == "__main__": 30 | unittest.main() 31 | 32 | -------------------------------------------------------------------------------- /leetcode/python/easy/validPath.py: -------------------------------------------------------------------------------- 1 | 2 | #Input: n = 6, edges = [[0,1],[0,2],[3,5],[5,4],[4,3]], source = 0, 3 | 4 | def vp(n, edges): 5 | adjacencyList = [[] for _ in range(n)] 6 | for node1, node2 in edges: 7 | adjacencyList[node1].append(node2) 8 | adjacencyList[node2].append(node1) 9 | print(adjacencyList) 10 | 11 | vp(6, [[0,1],[0,2],[3,5],[5,4],[4,3]]) -------------------------------------------------------------------------------- /leetcode/python/greedy/gasStation.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/gas-station/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | 10 | class Solution: 11 | def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: 12 | if sum(gas) < sum(cost): 13 | return -1 14 | 15 | total, res = 0, 0 16 | 17 | for i in range(len(gas)): 18 | total += (gas[i] - cost[i]) 19 | 20 | if total < 0: 21 | total = 0 22 | res = i + 1 23 | return res 24 | 25 | 26 | class Test(unittest.TestCase): 27 | def test_canCompleteCircuit(self): 28 | self.assertEqual(Solution.canCompleteCircuit(self, [2, 3, 4], [3, 4, 3]), -1) 29 | self.assertEqual(Solution.canCompleteCircuit(self, [1,2,3,4,5], [3,4,5,1,2]), 4) 30 | 31 | 32 | if __name__ == "__main": 33 | unittest.main() 34 | -------------------------------------------------------------------------------- /leetcode/python/greedy/handsOfStraights.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest, heapq 3 | 4 | ''' 5 | https://leetcode.com/problems/hand-of-straights/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def isNStraightHand(self, hand: List[int], groupSize: int) -> bool: 11 | if len(hand) % groupSize != 0: 12 | return False 13 | 14 | count = {} 15 | for n in hand: 16 | count[n] = 1 + count.get(n, 0) 17 | 18 | minHeap = list(count.keys()) 19 | heapq.heapify(minHeap) 20 | 21 | while minHeap: 22 | minVal = minHeap[0] 23 | 24 | for num in range(minVal, minVal + groupSize): 25 | if num not in count: 26 | return False 27 | count[num] -= 1 28 | 29 | if count[num] == 0: 30 | if num != minHeap[0]: 31 | return False 32 | heapq.heappop(minHeap) 33 | return True 34 | 35 | class Test(unittest.TestCase): 36 | def test_isNStraightHand(self): 37 | self.assertEqual(Solution.isNStraightHand(self, [1, 0], 3), False) 38 | self.assertEqual(Solution.isNStraightHand(self, [8, 10, 12], 3), False) 39 | self.assertEqual(Solution.isNStraightHand(self, [1,2,3,6,2,3,4,7,8], 3), True) 40 | self.assertEqual(Solution.isNStraightHand(self, [1,2,3,4,5], 4), False) 41 | 42 | if __name__ == "__main__": 43 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/greedy/jumpGame.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | Medium 6 | https://leetcode.com/problems/jump-game/ 7 | 0(n) - tc | 0(1) - sc 8 | ''' 9 | 10 | class Solution: 11 | def canJump(self, nums: List[int]) -> bool: 12 | goal = len(nums) - 1 13 | 14 | for i in range(len(nums) -1, -1, -1): 15 | if i + nums[i] >= goal: 16 | goal = i 17 | return True if goal == 0 else False 18 | 19 | class Test(unittest.TestCase): 20 | def test_canJump(self): 21 | self.assertEqual(Solution.canJump(self, [2,3,1,1,4]), True) 22 | self.assertEqual(Solution.canJump(self, [3,2,1,0,4]), False) 23 | 24 | if __name__ == "__main__": 25 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/greedy/jumpGameII.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/jump-game-ii/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | class Solution: 10 | def jump(self, nums: List[int]) -> int: 11 | res = 0 12 | l = r = 0 13 | 14 | while r < len(nums) - 1: 15 | farthest = 0 16 | for i in range(l, r + 1): 17 | farthest = max(farthest, i + nums[i]) 18 | l = r + 1 19 | r = farthest 20 | res += 1 21 | return res 22 | 23 | class Test(unittest.TestCase): 24 | def test_jump(self): 25 | self.assertEqual(Solution.jump(self, [2,3,1,1,4]), 2) 26 | self.assertEqual(Solution.jump(self, [2,3,0,1,4]), 2) 27 | 28 | if __name__ == "__main__": 29 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/hard/nQueens.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/n-queens/ 6 | 0(2 ^ N) - TC | 0(N ^ 2) - SC 7 | ''' 8 | 9 | class Solution: 10 | def solveNQueens(self, n: int) -> List[List[str]]: 11 | col = set() 12 | posDiag = set() 13 | negDiag = set() 14 | 15 | res = [] 16 | board = [["."] * n for i in range(n)] 17 | 18 | def backtrack(r): 19 | if r == n: 20 | copy = ["".join(row) for row in board] 21 | res.append(copy) 22 | return 23 | 24 | for c in range(n): 25 | if c in col or (r + c) in posDiag or (r - c) in negDiag: 26 | continue 27 | 28 | col.add(c) 29 | posDiag.add(r + c) 30 | negDiag.add(r - c) 31 | board[r][c] = "Q" 32 | 33 | backtrack(r + 1) 34 | 35 | col.remove(c) 36 | posDiag.remove( r + c) 37 | negDiag.remove(r - c) 38 | board[r][c] = "." 39 | 40 | backtrack(0) 41 | return res 42 | 43 | 44 | class TestSolution(unittest.TestCase): 45 | def test_solveNQueens(self): 46 | self.assertEqual(Solution.solveNQueens(self, 4), [[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]) 47 | self.assertEqual(Solution.solveNQueens(self, 1), [["Q"]]) 48 | 49 | 50 | if __name__ == "__main__": 51 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/hard/nQueensII.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/n-queens-ii/ 6 | 0(2 ^ N) - TC | 0(N ^ 2) - SC 7 | ''' 8 | class Solution: 9 | def solveNQueens(self, n: int) -> List[List[str]]: 10 | col = set() 11 | posDiag = set() 12 | negDiag = set() 13 | 14 | res = [] 15 | board = [["."] * n for i in range(n)] 16 | 17 | def backtrack(r): 18 | if r == n: 19 | copy = ["".join(row) for row in board] 20 | res.append(copy) 21 | return 22 | 23 | for c in range(n): 24 | if c in col or (r + c) in posDiag or (r - c) in negDiag: 25 | continue 26 | 27 | col.add(c) 28 | posDiag.add(r + c) 29 | negDiag.add(r - c) 30 | board[r][c] = "Q" 31 | 32 | backtrack(r + 1) 33 | 34 | col.remove(c) 35 | posDiag.remove( r + c) 36 | negDiag.remove(r - c) 37 | board[r][c] = "." 38 | 39 | backtrack(0) 40 | return len(res) 41 | 42 | 43 | class TestSolution(unittest.TestCase): 44 | def test_solveNQueens(self): 45 | self.assertEqual(Solution.solveNQueens(self, 4), 2) 46 | self.assertEqual(Solution.solveNQueens(self, 1), 1) 47 | 48 | 49 | if __name__ == "__main__": 50 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/hard/trapWater.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/trapping-rain-water/ 6 | 0(n) - tc & 0(1) - sc 7 | ''' 8 | 9 | def trap(height:List[int]) -> int: 10 | if not height: return 0 11 | 12 | l, r = 0, len(height) - 1 13 | leftMax, rightMax = height[l], height[r] 14 | res = 0 15 | 16 | while l < r: 17 | if leftMax <= rightMax: 18 | l += 1 19 | leftMax = max(leftMax, height[l]) 20 | res += leftMax - height[l] 21 | else: 22 | r -= 1 23 | rightMax = max(rightMax, height[r]) 24 | res += rightMax - height[r] 25 | 26 | return res 27 | 28 | class Test(unittest.TestCase): 29 | def test_trap(self): 30 | self.assertEqual(trap([]), 0) 31 | self.assertEqual(trap([0,1,0,2,1,0,1,3,2,1,2,1]), 6) 32 | self.assertEqual(trap([4,2,0,3,2,5]), 9) 33 | 34 | if __name__ == "__main__": 35 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/linked-list/mergeLists.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | from typing import Optional 3 | 4 | 5 | class ListNode: 6 | def __init__(self, val=0, next=None): 7 | self.val = val 8 | self.next = next 9 | 10 | ''' 11 | https://leetcode.com/problems/merge-two-sorted-lists/ 12 | 0(n) - tc | 0(n) - sc 13 | ''' 14 | 15 | class Solution: 16 | def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: 17 | dummy = ListNode() 18 | tail = dummy 19 | 20 | while True: 21 | if not list1: 22 | tail.next = list2 23 | break 24 | elif not list2: 25 | tail.next = list1 26 | break 27 | elif list1.val <= list2.val: 28 | tail.next = list1 29 | list1 = list1.next 30 | else: 31 | tail.next = list2 32 | list2 = list2.next 33 | tail = tail.next 34 | return dummy.next 35 | -------------------------------------------------------------------------------- /leetcode/python/linked-list/reverseLList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | from typing import Optional 3 | 4 | 5 | class ListNode: 6 | def __init__(self, val=0, next=None): 7 | self.val = val 8 | self.next = next 9 | 10 | 11 | ''' 12 | https://leetcode.com/problems/reverse-linked-list 13 | ''' 14 | 15 | 16 | class Solution: 17 | # 0(n) - tc | 0(n) - sc 18 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 19 | def reverse(curr, prev): 20 | if curr is None: 21 | return prev 22 | else: 23 | nxt = curr.next 24 | curr.next = prev 25 | return reverse(nxt, curr) 26 | return reverse(head, None) 27 | 28 | # iterative 0(n) - tc | 0(1) - sc 29 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 30 | prev, curr = None, head 31 | while curr: 32 | temp = curr.next 33 | curr.next = prev 34 | prev = curr 35 | curr = temp 36 | return prev 37 | -------------------------------------------------------------------------------- /leetcode/python/medium/characterReplacement.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/longest-repeating-character-replacement/ 5 | 0(n) - tc & 0(n) - sc 6 | ''' 7 | 8 | def characterReplacement(s:str, k:int) -> int: 9 | l, res = 0, 0 10 | count = {} 11 | 12 | for r in range(len(s)): 13 | count[s[r]] = 1 + count.get(s[r], 0) 14 | while (r - l + 1) - max(count.values()) > k: 15 | count[s[l]] -= 1 16 | l += 1 17 | res = max(res, r - l + 1) 18 | return res 19 | 20 | class Test(unittest.TestCase): 21 | def test_characterReplacement(self): 22 | self.assertEqual(characterReplacement('ABAB', 2), 4) 23 | self.assertEqual(characterReplacement('AABABBA', 1), 4) 24 | 25 | if __name__ == "__main__": 26 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/combinationSum.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | """ 5 | https://leetcode.com/problems/combination-sum/ 6 | """ 7 | 8 | class Solution: 9 | def combinationSum(self, candidates:List[int], target:int) -> List[List[int]]: 10 | res = [] 11 | 12 | def dfs(i, cur, total): 13 | if total == target: 14 | res.append(cur.copy()) 15 | return 16 | 17 | if i >= len(candidates) or total > target: 18 | return 19 | 20 | cur.append(candidates[i]) 21 | dfs(i, cur, total + candidates[i]) 22 | cur.pop() 23 | dfs(i + 1, cur, total) 24 | 25 | dfs(0, [], 0) 26 | return res 27 | 28 | 29 | class TestCombination(unittest.TestCase): 30 | def test_combinationSum(self): 31 | one = Solution.combinationSum(self, [2,3,6,7], 7) 32 | two = Solution.combinationSum(self, [2,3,5], 8) 33 | three = Solution.combinationSum(self, [2], 1) 34 | 35 | self.assertEqual(one, [[2,2,3],[7]]) 36 | self.assertEqual(two, [[2,2,2,2],[2,3,3],[3,5]]) 37 | self.assertEqual(three, []) 38 | 39 | if __name__ == "__main__": 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /leetcode/python/medium/encodeDecode.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | """ 5 | https://leetcode.com/problems/encode-and-decode-strings/ 6 | """ 7 | 8 | class Solution: 9 | """ 10 | @param: list of strings 11 | @return: encode string of list to a single string 12 | 0(n) - tc | o(1) - sc 13 | """ 14 | 15 | def encode(self, strs:List[str]) -> str: 16 | res = "" 17 | for s in strs: 18 | res += str(len(s)) + "#" + s 19 | return res 20 | 21 | """ 22 | @param: string 23 | @return: decides a single string to a list of strings 24 | 0(n) - tc | o(1) - sc 25 | """ 26 | 27 | def decode(self, str:str) -> List[str]: 28 | res, i = [], 0 29 | 30 | while i < len(str): 31 | j = i 32 | while str[j] != '#': 33 | j += 1 34 | length = int(str[i:j]) 35 | res.append(str[j + 1: j + 1 + length]) 36 | i = j + 1 + length 37 | 38 | return res 39 | 40 | class Test(unittest.TestCase): 41 | def test_solution(self): 42 | self.assertEqual(Solution.encode(self, ["Church", "go"]), "6#Church2#go") 43 | self.assertEqual(Solution.decode(self, "6#Church2#go"), ["Church", "go"]) 44 | 45 | if __name__ == "__main__": 46 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/houseRobber.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/house-robber/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | def rob(nums:List[int]) -> int: 10 | rob1, rob2 = 0, 0 11 | 12 | for n in nums: 13 | temp = max(n + rob1, rob2) 14 | rob1 = rob2 15 | rob2 = temp 16 | return rob2 17 | 18 | class Test(unittest.TestCase): 19 | def test_rob(self): 20 | self.assertEqual(rob([1, 2, 3, 1]), 4) 21 | self.assertEqual(rob([1, 2]), 2) 22 | self.assertEqual(rob([2, 7, 9, 3, 1]), 12) 23 | 24 | if __name__ == "__main__": 25 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/houseRobberII.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/house-robber/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def rob(self, nums: List[int]) -> int: 11 | def helper(nums): 12 | rob1, rob2 = 0, 0 13 | 14 | for n in nums: 15 | newRob = max(rob1 + n, rob2) 16 | rob1 = rob2 17 | rob2 = newRob 18 | return rob2 19 | return max(nums[0], helper(nums[1:]), helper(nums[:-1])) 20 | 21 | 22 | class Test(unittest.TestCase): 23 | def test_rob(self): 24 | self.assertEqual(Solution.rob(self, [2, 3, 2]), 3) 25 | self.assertEqual(Solution.rob(self, [1, 2, 3]), 3) 26 | self.assertEqual(Solution.rob(self, [1, 2, 3, 1]), 4) 27 | 28 | 29 | if __name__ == "__main__": 30 | unittest.main() 31 | -------------------------------------------------------------------------------- /leetcode/python/medium/lengthOfLongestSubstring.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/longest-substring-without-repeating-characters/ 5 | 0(n) - TC | 0(n) - SC 6 | ''' 7 | 8 | def lengthOfLongestSubstring(s:str) -> int: 9 | l, res, charSet = 0, 0, set() 10 | 11 | for r in range(len(s)): 12 | while s[r] in charSet: 13 | charSet.remove(s[l]) 14 | l += 1 15 | charSet.add(s[r]) 16 | res = max(res, r - l + 1) 17 | 18 | return res 19 | 20 | #solution 2 21 | 22 | def lengthOfLongestSubstring(s): 23 | res, count, hash = 0, 0, set() 24 | 25 | for i in range(len(s)): 26 | while s[i] in hash: 27 | hash.pop() 28 | count -= 1 29 | 30 | hash.add(s[i]) 31 | count += 1 32 | res = max(count, res) 33 | 34 | return res 35 | 36 | class Test(unittest.TestCase): 37 | def test_solution(self): 38 | self.assertEqual(lengthOfLongestSubstring(""), 0) 39 | self.assertEqual(lengthOfLongestSubstring(" "), 1) 40 | self.assertEqual(lengthOfLongestSubstring("dvdf"), 3) 41 | 42 | if __name__ == "__main__": 43 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/longestCommonSubsequence.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/longest-common-subsequence/ 5 | 0(mn) - tc | 0(mn) - sc 6 | ''' 7 | 8 | class Solution: 9 | def longestCommonSubsequence(self, text1: str, text2: str) -> int: 10 | dp = [[0 for j in range(len(text2) + 1)] for i in range(len(text1) + 1)] 11 | 12 | for i in range(len(text1) -1, -1, -1): 13 | for j in range(len(text2) -1, -1, -1): 14 | if text1[i] == text2[j]: 15 | dp[i][j] = 1 + dp[i + 1][j + 1] 16 | else: 17 | dp[i][j] = max(dp[i][j + 1], dp[i + 1][j]) 18 | return dp[0][0] 19 | 20 | 21 | class Test(unittest.TestCase): 22 | def test_lcs(self): 23 | self.assertEqual(Solution.longestCommonSubsequence(self, 'abcde', 'ace'), 3) 24 | self.assertEqual(Solution.longestCommonSubsequence(self, 'abc', 'abc'), 3) 25 | self.assertEqual(Solution.longestCommonSubsequence(self, 'abc', 'def'), 0) 26 | self.assertEqual(Solution.longestCommonSubsequence(self, 'abc', ''), 0) 27 | self.assertEqual(Solution.longestCommonSubsequence(self, '', 'def'), 0) 28 | self.assertEqual(Solution.longestCommonSubsequence(self, '', ''), 0) 29 | self.assertEqual(Solution.longestCommonSubsequence(self, ' ', ' '), 1) 30 | 31 | if __name__ == "__main__": 32 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/longestConsecutiveSequence.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/longest-consecutive-sequence/ 6 | 0(n) tc & sc 7 | ''' 8 | 9 | def consecutiveSeq(nums:List[int]) -> int: 10 | numsSet = set(nums) 11 | longest = 0 12 | 13 | for n in nums: 14 | if (n - 1) not in numsSet: 15 | length = 0 16 | while (n + length) in numsSet: 17 | length += 1 18 | longest = max(longest, length) 19 | 20 | return longest 21 | 22 | class Test(unittest.TestCase): 23 | def test_consecutiveSeq(self): 24 | self.assertEqual(consecutiveSeq([100,4,200,1,3,2]), 4) 25 | self.assertEqual(consecutiveSeq([0,3,7,2,5,8,4,6,0,1]), 9) 26 | 27 | 28 | if __name__ == "__main__": 29 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/longestPalindromicString.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/longest-palindromic-substring/ 5 | 0(n) - tc | 0(1) - sc 6 | ''' 7 | 8 | class Solution: 9 | def longestPalindrome(self, s: str) -> str: 10 | res = "" 11 | resLen = 0 12 | 13 | for i in range(len(s)): 14 | # odd length 15 | l, r = i, i 16 | 17 | while l >= 0 and r < len(s) and s[l] == s[r]: 18 | if (r - l + 1) > resLen: 19 | res = s[l:r+1] 20 | resLen = r - l + 1 21 | l -= 1 22 | r += 1 23 | 24 | # even length 25 | l, r = i, i + 1 26 | while l >= 0 and r < len(s) and s[l] == s[r]: 27 | if(r - l + 1) > resLen: 28 | res = s[l:r+1] 29 | resLen = r - l + 1 30 | l -= 1 31 | r += 1 32 | return res 33 | 34 | class Test(unittest.TestCase): 35 | def test_longestPalindrome(self): 36 | self.assertEqual(Solution.longestPalindrome(self, 'babad'), 'bab') 37 | self.assertEqual(Solution.longestPalindrome(self, 'cbbd'), 'bb') 38 | self.assertEqual(Solution.longestPalindrome(self, 'b'), 'b') 39 | 40 | if __name__ == "__main__": 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /leetcode/python/medium/maxArea.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/container-with-most-water/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | def maxArea(height:List[int]) -> int: 10 | res, l, r = 0, 0, len(height) - 1 11 | 12 | while l < r: 13 | res = max(res, (r - l) * min(height[l], height[r])) 14 | if height[l] <= height[r]: 15 | l += 1 16 | else: 17 | r -= 1 18 | 19 | return res 20 | 21 | class Test(unittest.TestCase): 22 | def test_maxArea(self): 23 | self.assertEqual(maxArea([1,8,6,2,5,4,8,3,7]), 49) 24 | self.assertEqual(maxArea([1,1]), 1) 25 | self.assertEqual(maxArea([5,4,8,3,7]), 20) 26 | 27 | 28 | if __name__ == "__main__": 29 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/maxAreaIslands.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | class Solution: 5 | def maxAreaOfIsland(self, grid: List[List[int]]) -> int: 6 | ROWS, COLS = len(grid), len(grid[0]) 7 | visited = set() 8 | 9 | def dfs(r, c): 10 | if (r < 0 or r == ROWS or c < 0 or c == COLS or grid[r][c] == 0 or (r, c) in visited): 11 | return 0 12 | visited.add((r, c)) 13 | return 1 + dfs(r + 1, c) + dfs(r - 1, c) + dfs(r, c + 1) + dfs(r, c - 1) 14 | 15 | area = 0 16 | 17 | for r in range(ROWS): 18 | for c in range(COLS): 19 | area = max(area, dfs(r, c)) 20 | return area 21 | 22 | grid_one= [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]] 23 | grid_two = [[0,0,0,0,0,0,0,0]] 24 | 25 | class Test(unittest.TestCase): 26 | def test_maxAreaOfIslands(self): 27 | self.assertEqual(Solution.maxAreaOfIsland(self, grid_one), 6) 28 | self.assertEqual(Solution.maxAreaOfIsland(self, grid_two), 0) 29 | 30 | if __name__ == "__main__": 31 | unittest.main() 32 | -------------------------------------------------------------------------------- /leetcode/python/medium/maxProfitCooldown.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def maxProfit(self, prices: List[int]) -> int: 11 | dp = {} 12 | 13 | def dfs(i, canBuy): 14 | if i >= len(prices): 15 | return 0 16 | if (i, canBuy) in dp: 17 | return dp[(i, canBuy)] 18 | 19 | if canBuy: 20 | buy = dfs(i + 1, not canBuy) - prices[i] 21 | cooldown = dfs(i + 1, canBuy) 22 | dp[(i, canBuy)] = max(buy, cooldown) 23 | else: 24 | sell = dfs(i + 2, not canBuy) + prices[i] 25 | cooldown = dfs(i + 1, canBuy) 26 | dp[(i, canBuy)] = max(sell, cooldown) 27 | return dp[(i, canBuy)] 28 | 29 | return dfs(0, True) 30 | 31 | class Test(unittest.TestCase): 32 | def test_maxProfit(self): 33 | self.assertEqual(Solution.maxProfit(self, [1,2,3,0,2]), 3) 34 | self.assertEqual(Solution.maxProfit(self, [1]), 0) 35 | 36 | if __name__ == "__main__": 37 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/maxSubArray.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from typing import List 3 | 4 | ''' 5 | https://leetcode.com/problems/maximum-subarray/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | class Solution: 10 | def maxSubArray(self, nums: List[int]) -> int: 11 | res = nums[0] 12 | currSum = 0 13 | 14 | for num in nums: 15 | currSum += num 16 | res = max(res, currSum) 17 | if currSum < 0: 18 | currSum = 0 19 | 20 | return res 21 | 22 | 23 | class Test(unittest.TestCase): 24 | def test_maxSubArray(self): 25 | self.assertEqual(Solution.maxSubArray(self, [-1]), -1) 26 | self.assertEqual(Solution.maxSubArray(self, [1]), 1) 27 | self.assertEqual(Solution.maxSubArray(self, [-2,1,-3,4,-1,2,1,-5,4]), 6) 28 | self.assertEqual(Solution.maxSubArray(self, [5,4,-1,7,8]), 23) 29 | 30 | if __name__ == "__main__": 31 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/maxUniqueSubArray.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/maximum-erasure-value/ 6 | 0(n) - tc & sc 7 | ''' 8 | 9 | def maximumUniqueSubArray(nums:List[int]) -> int: 10 | l, total, sum = 0, 0, 0 11 | hash = set() 12 | 13 | for r in range(len(nums)): 14 | while nums[r] in hash: 15 | hash.remove(nums[l]) 16 | sum -= nums[l] 17 | l += 1 18 | 19 | hash.add(nums[r]) 20 | sum += nums[r] 21 | total = max(total, sum) 22 | 23 | return total 24 | 25 | 26 | class Test(unittest.TestCase): 27 | def test_maxUniqueSubArray(self): 28 | self.assertEqual(maximumUniqueSubArray([4,2,4,5,6]), 17) 29 | self.assertEqual(maximumUniqueSubArray([5,2,1,2,5,2,1,2,5]), 8) 30 | 31 | 32 | if __name__ == "__main__": 33 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/minCostClimbingStairs.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/min-cost-climbing-stairs/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | def minCostClimbingStairs(cost:List[List[int]]) -> int: 10 | cost.append(0) 11 | for i in range(len(cost) - 3, -1, -1): 12 | cost[i] += min(cost[i + 1], cost[i + 2]) 13 | return min(cost[0], cost[1]) 14 | 15 | class Test(unittest.TestCase): 16 | def test_minCostClimbingStairs(self): 17 | self.assertEqual(minCostClimbingStairs([10, 15, 20]), 15) 18 | self.assertEqual(minCostClimbingStairs([1,100,1,1,1,100,1,1,100,1]), 6) 19 | 20 | if __name__ == "__main__": 21 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/minDistance.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/delete-operation-for-two-strings/ 5 | 0(m + n) - tc | 0(min(m + n)) - sc 6 | ''' 7 | 8 | def minDistance(word1:str, word2:str) -> int: 9 | if len(word1) > len(word2): 10 | word2, word1 = word1, word2 11 | 12 | m, n = len(word1), len(word2) 13 | prev = [0] * (m + 1) 14 | 15 | for i in range(n-1, -1, -1): 16 | curr = [0] * (m + 1) 17 | for j in range(m-1, -1, -1): 18 | if word1[j] == word2[i]: 19 | curr[j] = 1 + prev[j + 1] 20 | else: 21 | curr[j] = max(curr[j + 1], prev[j]) 22 | prev = curr 23 | 24 | return m + n - 2 * prev[0] 25 | 26 | class Test(unittest.TestCase): 27 | def test_minDistance(self): 28 | self.assertEqual(minDistance('sea', 'eat'),2) 29 | self.assertEqual(minDistance('sea', 'cap'),0) 30 | self.assertEqual(minDistance('leetcode', 'etco'),4) 31 | 32 | if __name__ == "__main__": 33 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/minOperations.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | class Solution: 10 | def minOperations(self, nums: List[int], x: int) -> int: 11 | total, n = sum(nums), len(nums) 12 | target = total - x 13 | maxLen = -1 14 | left, currSum = 0, 0 15 | 16 | for right, num in enumerate(nums): 17 | currSum += num 18 | 19 | while currSum > target and left <= right: 20 | currSum -= nums[left] 21 | left += 1 22 | 23 | if currSum == target: 24 | maxLen = max(maxLen, right - left + 1) 25 | 26 | return n - maxLen if maxLen != -1 else - 1 27 | 28 | class Test(unittest.TestCase): 29 | def test_minOperations(self): 30 | self.assertEqual(Solution.minOperations(self, [1,1,4,2,3], 5), 2) 31 | self.assertEqual(Solution.minOperations(self, [5,6,7,8,9], 4), -1) 32 | self.assertEqual(Solution.minOperations(self, [3,2,20,1,1,3], 10), 5) 33 | self.assertEqual(Solution.minOperations(self, [6016,5483,541,4325,8149,3515,7865,2209,9623,9763,4052,6540,2123,2074,765,7520,4941,5290,5868,6150,6006,6077,2856,7826,9119], 34 | 31841), 6) 35 | 36 | if __name__ == "__main__": 37 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/numDecodings.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/decode-ways/ 5 | 0(n) - tc | 0(n) - sc 6 | ''' 7 | 8 | class Solution: 9 | def numDecodings(self, s: str) -> int: 10 | dp = {len(s): 1} 11 | 12 | def dfs(i): 13 | if i in dp: 14 | return dp[i] 15 | if s[i] == "0": 16 | return 0 17 | 18 | res = dfs(i + 1) 19 | if (i + 1 < len(s) and (s[i] == "1" or s[i] == "2" and s[i + 1] in "0123456")): 20 | res += dfs(i + 2) 21 | dp[i] = res 22 | return res 23 | return dfs(0) 24 | 25 | class Test(unittest.TestCase): 26 | def test_numDecodings(self): 27 | self.assertEqual(Solution.numDecodings(self, "12"), 2) 28 | self.assertEqual(Solution.numDecodings(self, "226"), 3) 29 | self.assertEqual(Solution.numDecodings(self, "06"), 0) 30 | 31 | if __name__ == "__main__": 32 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/palindromicSubstring.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/palindromic-substrings/ 5 | 0(n) - tc | 0(1) - sc 6 | ''' 7 | 8 | class Solution: 9 | def countSubstrings(self, s: str) -> int: 10 | resLen = 0 11 | 12 | for i in range(len(s)): 13 | l, r = i, i 14 | 15 | while l >= 0 and r < len(s) and s[l] == s[r]: 16 | resLen += 1 17 | l -= 1 18 | r += 1 19 | 20 | # even numbers 21 | l, r = i, i + 1 22 | while l >= 0 and r < len(s) and s[l] == s[r]: 23 | resLen += 1 24 | l -= 1 25 | r += 1 26 | return resLen 27 | 28 | class Test(unittest.TestCase): 29 | def test_countSubstrings(self): 30 | self.assertEqual(Solution.countSubstrings(self, 'abc'), 3) 31 | self.assertEqual(Solution.countSubstrings(self, 'aaa'), 6) 32 | self.assertEqual(Solution.countSubstrings(self, 'aa'), 3) 33 | self.assertEqual(Solution.countSubstrings(self, 'a'), 1) 34 | self.assertEqual(Solution.countSubstrings(self, ''), 0) 35 | self.assertEqual(Solution.countSubstrings(self, ' '), 1) 36 | 37 | if __name__ == "__main__": 38 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/permutation.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | """ 5 | https://leetcode.com/problems/permutations/ 6 | 0(n) - SC | 0(2^n) - TC 7 | """ 8 | 9 | def permute(nums:List[int]) -> List[List[int]]: 10 | res = [] 11 | 12 | if (len(nums)) == 1: 13 | return [nums[:]] 14 | 15 | for i in range (len(nums)): 16 | n = nums.pop(0) 17 | perms = permute(nums) 18 | 19 | for perm in perms: 20 | perm.append(n) 21 | 22 | res.extend(perms) 23 | nums.append(n) 24 | 25 | return res 26 | 27 | class TestPermutation(unittest.TestCase): 28 | def test_permute(self): 29 | one = permute([1,2,3]) 30 | two = permute([1]) 31 | three = permute([0, 1]) 32 | 33 | self.assertEqual(one, [[3, 2, 1], [2, 3, 1], [1, 3, 2], [3, 1, 2], [2, 1, 3], [1, 2, 3]]) 34 | self.assertEqual(two, [[1]]) 35 | self.assertEqual(three, [[1, 0], [0, 1]]) 36 | 37 | if __name__ == "__main__": 38 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/productExceptSelf.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/product-of-array-except-self/ 6 | 0(n) - TC | 0(1) - SC (the output array does not count as extra space) 7 | ''' 8 | 9 | def productExceptSelf(nums:List[int]) -> List[int]: 10 | res = [1] * len(nums) 11 | prefix = 1 12 | 13 | for i in range (len(nums)): 14 | res[i] = prefix 15 | prefix *= nums[i] 16 | 17 | postfix = 1 18 | 19 | for i in range(len(nums) - 1, -1, -1): 20 | res[i] *= postfix 21 | postfix *= nums[i] 22 | 23 | return res 24 | 25 | 26 | class Test(unittest.TestCase): 27 | def test_productExceptSelf(self): 28 | self.assertEqual(productExceptSelf([1,2,3,4]), [24, 12, 8, 6]) 29 | self.assertEqual(productExceptSelf([-1,1,0,-3,3]), [0, 0, 9, 0, 0]) 30 | 31 | 32 | if __name__ == "__main__": 33 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/rangeSumQuery.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | """ 3 | https://leetcode.com/problems/range-sum-query-2d-immutable/ 4 | """ 5 | 6 | class NumMatrix: 7 | 8 | def __init__(self, matrix: List[List[int]]): 9 | rows, cols = len(matrix), len(matrix[0]) 10 | self.sumMath = [[0] * (cols + 1) for r in range (rows + 1)] 11 | 12 | for r in range(rows): 13 | prefix = 0 14 | for c in range(cols): 15 | prefix += matrix[r][c] 16 | above = self.sumMath[r][c + 1] 17 | self.sumMath[r + 1][c + 1] = prefix + above 18 | 19 | 20 | def sumRegion(self, r1: int, c1: int, r2: int, c2: int) -> int: 21 | r1, c1, r2, c2 = r1 + 1, c1 + 1, r2 + 1, c2 + 1 22 | 23 | bottomRight = self.sumMath[r2][c2] 24 | above = self.sumMath[r1 - 1][c2] 25 | left = self.sumMath[r2][c1 - 1] 26 | topLeft = self.sumMath[r1 - 1][c1 - 1] 27 | 28 | return bottomRight - above - left + topLeft 29 | -------------------------------------------------------------------------------- /leetcode/python/medium/subsets-ii.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | def subsetsWithDup(nums:List[int]) -> List[List[int]]: 5 | res, subset = [], [] 6 | 7 | def backtrack(i): 8 | if i >= len(nums): 9 | res.append(subset[::]) 10 | return 11 | 12 | subset.append(nums[i]) 13 | backtrack(i + 1) 14 | subset.pop() 15 | 16 | while i + 1 < len(nums) and nums[i] == nums [i + 1]: 17 | i += 1 18 | 19 | backtrack(i + 1) 20 | 21 | backtrack(0) 22 | return res 23 | 24 | class Test(unittest.TestCase): 25 | def test_subsetWithDup(self): 26 | self.assertEqual(subsetsWithDup([1, 2, 2]), [[1, 2, 2], [1, 2], [1], [2, 2], [2], []]) 27 | self.assertEqual(subsetsWithDup([0]), [[0], []]) 28 | 29 | if __name__ == "__main__": 30 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/subsets.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/subsets/ 6 | 0(n * 2^n) - TC | 0(n) - SC 7 | ''' 8 | 9 | def subsets(nums: List[int]) -> List[List[int]]: 10 | res, subset = [], [] 11 | 12 | def backtrack(i): 13 | if i >= len(nums): 14 | res.append(subset[::]) 15 | return 16 | 17 | subset.append(nums[i]) 18 | backtrack(i + 1) 19 | 20 | subset.pop() 21 | backtrack(i + 1) 22 | 23 | backtrack(0) 24 | return res 25 | 26 | class Test(unittest.TestCase): 27 | def test_subset(self): 28 | self.assertEqual(subsets([1, 2, 3]), [[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]) 29 | self.assertEqual(subsets([1]), [[1], []]) 30 | 31 | 32 | if __name__ == '__main__': 33 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/test_KClosest.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | from typing import List 3 | import unittest 4 | 5 | """ 6 | https://leetcode.com/problems/k-closest-points-to-origin/ 7 | 0(k log n) - TC | 0(n) - SC 8 | """ 9 | 10 | class Solution: 11 | def KClosest(self, points:List[List[int]], k:int) -> List[List[int]]: 12 | minHeap = [] 13 | 14 | for x,y in points: 15 | dist = (x**2) + (y**2) 16 | minHeap.append([dist, x, y]) 17 | 18 | heapq.heapify(minHeap) 19 | res = [] 20 | 21 | while k > 0: 22 | dist, x, y = heapq.heappop(minHeap) 23 | res.append([x,y]) 24 | k -= 1 25 | 26 | return res 27 | 28 | class TestKClosest(unittest.TestCase): 29 | def test_KClosest(self): 30 | points = [[1,3],[-2,2]] 31 | points_two = [[3,3],[5,-1],[-2,4]] 32 | k = 1 33 | k_two = 2 34 | result = Solution.KClosest(self, points, k) 35 | result_two = Solution.KClosest(self, points_two, k_two) 36 | self.assertEqual(result, [[-2, 2]]) 37 | self.assertEqual(result_two, [[3,3],[-2,4]]) 38 | 39 | if __name__ == '__main__': 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /leetcode/python/medium/test_KthLargestArr.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | from typing import List 3 | import unittest 4 | 5 | """ 6 | https://leetcode.com/problems/kth-largest-element-in-an-array/ 7 | """ 8 | class Solution: 9 | """ 10 | sort method 11 | 0(n log n) - TC | 0(n) - SC 12 | """ 13 | def KthLargestArr(self, nums: List[int], k: int) -> int: 14 | nums.sort() 15 | idx = len(nums) - k 16 | return nums[idx] 17 | 18 | """ 19 | Heap method 20 | 0(k log n) - TC | 0(1) - SC 21 | """ 22 | def KthLargestHeap(self, nums: List[int], k: int) -> int: 23 | heapq.heapify(nums) 24 | while len(nums) > k: 25 | heapq.heappop(nums) 26 | return nums[0] 27 | 28 | 29 | class TestKthLargestArr(unittest.TestCase): 30 | def test_kthLargest(self): 31 | nums = [3, 2, 3, 1, 2, 4, 5, 5, 6] 32 | res = Solution.KthLargestArr(self, nums, 4) 33 | res_two = Solution.KthLargestHeap(self, [3, 2, 1, 5, 6, 4], 2) 34 | self.assertEqual(res, 4) 35 | self.assertEqual(res_two, 5) 36 | 37 | 38 | if __name__ == "__main__": 39 | unittest.main() 40 | -------------------------------------------------------------------------------- /leetcode/python/medium/topKFrequent.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | from typing import List 3 | import unittest 4 | 5 | """ 6 | https://leetcode.com/problems/top-k-frequent-elements/ 7 | """ 8 | 9 | class Solution: 10 | """ 11 | Heap method 12 | 0(k log n) - TC | 0(n) - SC 13 | """ 14 | def topKFrequent(self, nums: List[int], k: int) -> List[int]: 15 | count = {} 16 | minHeap = [] 17 | res = [] 18 | 19 | # Count each number in the nums array 20 | for n in nums: 21 | count[n] = 1 + count.get(n, 0) 22 | 23 | # Add the (num, count to the heap) 24 | for n, c in count.items(): 25 | heapq.heappush(minHeap, (c, n)) 26 | if len(minHeap) > k: 27 | heapq.heappop(minHeap) 28 | 29 | # append the numbers with k occurence to res 30 | for c, n in minHeap: 31 | res.append(n) 32 | 33 | return res 34 | 35 | """ 36 | Bucket sort 37 | 0(n) - TC | 0(n) - SC 38 | """ 39 | 40 | def topKFrequentBucket(self, nums:List[int], k:int) -> List[int]: 41 | count = {} 42 | freq = [[] for i in range (len (nums) + 1)] 43 | 44 | for n in nums: 45 | count[n] = 1 + count.get(n, 0) 46 | 47 | for n, c in count.items(): 48 | freq[c].append(n) 49 | 50 | res = [] 51 | for i in range(len(freq) -1, 0, -1): 52 | for n in freq[i]: 53 | res.append(n) 54 | if len(res) == k: 55 | return res 56 | 57 | 58 | class TestTopK(unittest.TestCase): 59 | def test_topK(self): 60 | data = Solution.topKFrequent(self, [5,5,5,5,6,6,6,7], 2) 61 | self.assertEqual(data, [6,5]) 62 | 63 | def test_topKBucket(self): 64 | data = Solution.topKFrequentBucket(self, [2,2,2,3,3], 1) 65 | self.assertEqual(data, [2]) 66 | 67 | if __name__ == "__main__": 68 | unittest.main() 69 | -------------------------------------------------------------------------------- /leetcode/python/medium/triangle.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/triangle/ 6 | 0(n) - sc | 0(2 ^ n) - tc 7 | ''' 8 | 9 | def minTotal(triangle:List[List[int]]) -> int: 10 | dp = [0] * (len(triangle) + 1) 11 | 12 | for row in triangle[::-1]: 13 | for i, n in enumerate(row): 14 | dp[i] = n + min(dp[i], dp[i + 1]) 15 | 16 | return dp[0] 17 | 18 | 19 | class Test(unittest.TestCase): 20 | def test_minTotal(self): 21 | self.assertEqual(minTotal([[-1],[2,3],[1,-1,-3]]), -1) 22 | self.assertEqual(minTotal([[2],[3,4],[6,5,7],[4,1,8,3]]), 11) 23 | self.assertEqual(minTotal([[-10]]), -10) 24 | 25 | if __name__ == "__main__": 26 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/twoSumII.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | def TwoSumII(nums, target) -> List[int]: 5 | i, j = 0, len(nums) - 1 6 | 7 | while i < j: 8 | sum = nums[i] + nums[j] 9 | 10 | if sum == target: 11 | return [i + 1, j + 1] 12 | elif sum < target: 13 | i += 1 14 | else: 15 | j -= 1 16 | 17 | 18 | class Test(unittest.TestCase): 19 | def test_TwoSumII(self): 20 | self.assertEqual(TwoSumII([2,3,5,7,11], 9), [1, 4]) 21 | self.assertEqual(TwoSumII([0, -1], -1), [1, 2]) 22 | 23 | 24 | if __name__ == "__main__": 25 | unittest.main() -------------------------------------------------------------------------------- /leetcode/python/medium/uniquePaths.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | ''' 4 | https://leetcode.com/problems/unique-paths/ 5 | 0(m * n) - tc | 0(m + n) - sc 6 | ''' 7 | 8 | def uniquePaths(m: int, n: int) -> int: 9 | def memoPath(m, n, memo={}): 10 | key = (m, n) 11 | if key in memo: 12 | return memo[key] 13 | if m == 1 and n == 1: 14 | return 1 15 | if m == 0 or n == 0: 16 | return 0 17 | 18 | memo[key] = (memoPath(m - 1, n) + memoPath(m, n - 1)) 19 | return memo[key] 20 | 21 | return memoPath(m, n) 22 | 23 | 24 | class Test(unittest.TestCase): 25 | def test_uniquePaths(self): 26 | self.assertEqual(uniquePaths(3,7), 28) 27 | self.assertEqual(uniquePaths(2,3), 3) 28 | self.assertEqual(uniquePaths(3, 3), 6) 29 | self.assertEqual(uniquePaths(18, 18), 2333606220 ) 30 | 31 | if __name__ == "__main__": 32 | unittest.main() 33 | 34 | -------------------------------------------------------------------------------- /leetcode/python/test_sum.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | def my_sum(nums): 4 | total = 0 5 | for n in nums: 6 | total += n 7 | return total 8 | 9 | class TestSum(unittest.TestCase): 10 | def test_sum(self): 11 | """ 12 | test that the sum of the list is correct 13 | """ 14 | data = [1,2,3] 15 | result = my_sum(data) 16 | self.assertEqual(result, 6, "should be 6") 17 | 18 | def test_sum_input(self): 19 | """ 20 | test that the input is truthy 21 | """ 22 | data = [2,4,6] 23 | result = my_sum(data) 24 | self.assertTrue(result) 25 | 26 | if __name__ == "__main__": 27 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/15-binarySearch.test.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/binary-search/ 2 | // Test: npm test ./sean-prashad/Javascript/15-binarySearch.test.js 3 | // 0(log n) - time | 0(1) - space 4 | 5 | describe('#binary search', () => { 6 | it('returns the index of a given target', () => { 7 | expect(binarySearch([1, 0, 3, 5, 9, 12], 9)).toBe(4) 8 | expect(binarySearch([1, 0, 3, 5, 9, 12], 2)).toBe(-1) 9 | expect(binarySearch([1], 2)).toBe(-1) 10 | }) 11 | }) 12 | 13 | 14 | const binarySearch = (nums, target) => { 15 | let lower = 0 16 | let upper = nums.length - 1 17 | 18 | while (lower <= upper) { 19 | let mid = Math.floor((upper + lower) / 2) 20 | 21 | if (target === nums[mid]) { 22 | return mid 23 | } 24 | 25 | if (nums[mid] > target) { 26 | upper = mid - 1 27 | } else { 28 | lower = mid + 1 29 | } 30 | } 31 | 32 | return -1 33 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/16-nextGreatestLetter.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[]} letters 3 | * @param {character} target 4 | * @return {character} 5 | */ 6 | 7 | // https://leetcode.com/problems/find-smallest-letter-greater-than-target 8 | // Test: npm test ./sean-prashad/Javascript/16-nextGreatestLetter.test.js 9 | // 0(log n) - time | 0(1) - space 10 | 11 | describe('#nextGreatestLetter', () => { 12 | it('returns the Smallest Letter Greater Than Target', () => { 13 | expect(nextGreatestLetter(["c", "f", "j"], "a")).toBe("c") 14 | expect(nextGreatestLetter(["c", "f", "j"], "c")).toBe("f") 15 | expect(nextGreatestLetter(["c", "f", "j"], "d")).toBe("f") 16 | expect(nextGreatestLetter(["c", "f", "j"], "j")).toBe("c") 17 | }) 18 | }) 19 | 20 | 21 | 22 | var nextGreatestLetter = function(letters, target) { 23 | let [left, right] = [0, letters.length - 1] 24 | 25 | if (target < letters[left] || target >= letters[right]){ 26 | return letters[0] 27 | } 28 | 29 | while (left < right){ 30 | let mid = Math.floor((left + right) / 2) 31 | 32 | if (letters[mid] > target){ 33 | right = mid 34 | } else{ 35 | left = mid + 1 36 | } 37 | } 38 | 39 | return letters[right] 40 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/17-avgOfLevels.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[]} 12 | */ 13 | 14 | // 0(n) - TC | 0(N) - SC 15 | var averageOfLevels = function(root) { 16 | let res = [] 17 | let queue = [root] 18 | 19 | while(queue.length){ 20 | let total = 0 21 | queueLen = queue.length 22 | 23 | for(let i = 0; i < queueLen; i++){ 24 | node = queue.shift() 25 | total += node.val 26 | 27 | if(node.left) queue.push(node.left) 28 | if(node.right) queue.push(node.right) 29 | } 30 | res.push(total / queueLen) 31 | } 32 | return res 33 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/18-minDeptht.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | 14 | var minDepth = function (root) { 15 | if (root == null) return 0 16 | 17 | if (root.right == null && root.left == null) return 1 18 | 19 | if (root.right == null) { 20 | return 1 + minDepth(root.left) 21 | } 22 | 23 | if (root.left == null) { 24 | return 1 + minDepth(root.right) 25 | } 26 | 27 | return 1 + Math.min(minDepth(root.right), minDepth(root.left)) 28 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/19-maxDepth.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | var maxDepth = function(root) { 14 | if(root == null) return 0 15 | 16 | if (root.left == null && root.right == null) return 1 17 | 18 | if(root.left == null){ 19 | return 1 + maxDepth(root.right) 20 | } 21 | 22 | if(root.right == null){ 23 | return 1 + maxDepth(root.left) 24 | } 25 | 26 | return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)) 27 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/20-isSameTree.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} p 11 | * @param {TreeNode} q 12 | * @return {boolean} 13 | */ 14 | // https://leetcode.com/problems/same-tree/ 15 | // BFS - O(N) - TC & SC 16 | var isSameTree = function (p, q) { 17 | const queue = [[p, q]] 18 | 19 | while (queue.length) { 20 | const [p, q] = queue.shift() 21 | 22 | if (!p && !q) continue 23 | if (!p || !q) return false 24 | if (p.val !== q.val) return false 25 | 26 | if (p && q) { 27 | queue.push([p.right, q.right]) 28 | queue.push([p.left, q.left]) 29 | } 30 | 31 | } 32 | return true 33 | }; 34 | 35 | // Recursive DFS 0(N) - TC & SC 36 | var isSameTree = function (p, q) { 37 | if (!p && !q) return true 38 | if (!p || !q) return false 39 | if (p.val !== q.val) return false 40 | 41 | return isSameTree(p.left, q.left) && 42 | isSameTree(p.right, q.right) 43 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/21-pathSum.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @param {number} targetSum 12 | * @return {boolean} 13 | */ 14 | var hasPathSum = function(root, sum) { 15 | if(root === null) return false 16 | 17 | if (root.left === null && root.right === null && root.val === sum) return true 18 | 19 | return (hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val)) 20 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/22-twoSum.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | 7 | // npm test ./leetcode/sean-prashad/javascript/22-twoSum.test.js", 8 | // https://leetcode.com/problems/two-sum/ 9 | // 0(n) - time | 0(n) - space 10 | 11 | const twoSum = function (nums, target) { 12 | let hash = {} 13 | 14 | for (let i = 0; i <= nums.length; i++) { 15 | let diff = target - nums[i] 16 | 17 | if (diff in hash) return [i, hash[diff]] 18 | hash[nums[i]] = i 19 | } 20 | } 21 | 22 | describe('#Two Sum', () => { 23 | it('returns the indices of values that sum up to a target', () => { 24 | expect(twoSum([2, 7, 11, 15], 9)).toStrictEqual([1, 0]) 25 | expect(twoSum([3, 2, 4], 6)).toStrictEqual([2, 1]) 26 | expect(twoSum([3, 3], 6)).toStrictEqual([1, 0]) 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/23-invertBinaryTree.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {TreeNode} 12 | */ 13 | 14 | // 0(n) - time | 0(n) - space 15 | // https://leetcode.com/problems/invert-binary-tree/ 16 | 17 | const invertTree = function(root) { 18 | if(!root) return root 19 | 20 | let temp = root.left 21 | root.left = root.right 22 | root.right = temp 23 | 24 | invertTree(root.right) 25 | invertTree(root.left) 26 | 27 | return root 28 | }; -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/24-subTree.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @param {TreeNode} subRoot 12 | * @return {boolean} 13 | */ 14 | 15 | // https://leetcode.com/problems/subtree-of-another-tree/ 16 | // 0(r * s) - tc | 0(r * s) - sc 17 | 18 | 19 | var isSubtree = function(root, subRoot) { 20 | if (subRoot && !root) return false 21 | 22 | if (isMatch(root, subRoot)) return true 23 | 24 | return (isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)) 25 | 26 | }; 27 | 28 | const isMatch = function(r, s){ 29 | if (r && s) { 30 | return (r.val === s.val && isMatch(r.left, s.left) && isMatch(r.right, s.right)) 31 | } 32 | if(!r && s) return false 33 | if(r && !s) return false 34 | if(!r && !s) return true 35 | } -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/25-squareSortedArr.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | 6 | // https://leetcode.com/problems/squares-of-a-sorted-array/ 7 | // 0(n) - tc | 0(n) - sc 8 | 9 | 10 | const sortedSquares = function(nums) { 11 | let res = [] 12 | let [l, r] = [0, nums.length - 1] 13 | 14 | while (l <= r){ 15 | let [left, right] = [nums[l], nums[r]] 16 | 17 | if (Math.abs(right) > Math.abs(left)){ 18 | res.unshift(right * right) 19 | r-- 20 | } else{ 21 | res.unshift(left * left) 22 | l++ 23 | } 24 | } 25 | return res 26 | }; 27 | 28 | describe('#Squares of sorted Array', () => { 29 | it('returns the sorted value of the values in the array', () => { 30 | expect(sortedSquares([-4,-1,0,3,10])).toStrictEqual( [0,1,9,16,100]) 31 | expect(sortedSquares([-7,-3,2,3,11])).toStrictEqual([4,9,9,49,121]) 32 | expect(sortedSquares([-4,-1,3,10])).toStrictEqual([1,9,16,100]) 33 | expect(sortedSquares([1, 2, 3, 4])).toStrictEqual([1,4,9,16]) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/27-majorityElement.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/majority-element 2 | 3 | /** 4 | * @param {number[]} nums 5 | * @return {number} 6 | */ 7 | 8 | // 0(n) - TC | 0(n) - SC 9 | const majorityElement = function (nums) { 10 | const map = {} 11 | let [maxCount, res] = [0, 0] 12 | 13 | for (let i = 0; i < nums.length; i++) { 14 | map[nums[i]] = map[nums[i]] + 1 || 1 15 | 16 | if (map[nums[i]] > maxCount) { 17 | res = nums[i] 18 | maxCount = map[nums[i]] 19 | } 20 | } 21 | 22 | return res 23 | }; 24 | 25 | const majorityElementBoyer = function (nums) { 26 | let [res, maxCount] = [0, 0] 27 | 28 | for (let num of nums) { 29 | if (maxCount === 0) { 30 | res = num 31 | } 32 | 33 | maxCount += num === res ? 1 : -1 34 | } 35 | 36 | return res 37 | }; 38 | 39 | describe('#Majority Element', () => { 40 | describe('it returns the element that occurs more than half the length in the array', () => { 41 | 42 | it('function 1', () => { 43 | expect(majorityElement([2, 2, 1, 1, 1, 2, 2])).toBe(2) 44 | expect(majorityElement([2, 1, 1, 1, 1, 2, 2])).toBe(1) 45 | expect(majorityElement([2, 3, 1, 2, 2, 2, 2])).toBe(2) 46 | }) 47 | 48 | it('function 2', () => { 49 | expect(majorityElementBoyer([2, 2, 1, 1, 1, 2, 2])).toBe(2) 50 | expect(majorityElementBoyer([2, 1, 1, 1, 1, 2, 2])).toBe(1) 51 | expect(majorityElementBoyer([2, 3, 1, 2, 2, 2, 2])).toBe(2) 52 | }) 53 | }) 54 | }) 55 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/Javascript/28-productExceptSelf.test.js: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/problems/product-of-array-except-self/ 2 | 3 | // brute force 4 | const productExceptSelfB = (nums) => { 5 | const N = nums.length 6 | let prod = new Array(N) 7 | 8 | for (let i = 0; i < N; i++) { 9 | let prodExclCurr = 1 10 | 11 | for (let j = 0; j < N; j++) { 12 | if (i == j) continue 13 | 14 | prodExclCurr *= nums[j] 15 | } 16 | prod[i] = prodExclCurr 17 | } 18 | 19 | return prod 20 | }; 21 | 22 | describe('#Product of Array Except Self', () => { 23 | describe('it returns the product of elements in the array except its self', () => { 24 | 25 | test('brute force', () => { 26 | expect(productExceptSelfB([1, 2, 3, 4])).toStrictEqual([24, 12, 8, 6]) 27 | // expect(productExceptSelfB([-1, 1, 0, -3, 3])).toStrictEqual([-0, 0, 9, -0, 0]) 28 | expect(productExceptSelfB([5, 2, 8, 4, 5])).toStrictEqual([320, 800, 200, 400, 320]) 29 | expect(productExceptSelfB([1, 0, 4, 3, 5])).toStrictEqual([0, 60, 0, 0, 0]) 30 | expect(productExceptSelfB([1, 1, 1, 1])).toStrictEqual([1, 1, 1, 1]) 31 | expect(productExceptSelfB([0, 4, 0, 3])).toStrictEqual([0, 0, 0, 0]) 32 | }) 33 | 34 | 35 | }) 36 | }) 37 | 38 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/1-containsDups.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/contains-duplicate/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | class Solution: 10 | def containsDuplicate(self, nums: List[int]) -> bool: 11 | storage = set() 12 | 13 | for num in nums: 14 | if num in storage: 15 | return True 16 | storage.add(num) 17 | 18 | return False 19 | 20 | class Test(unittest.TestCase): 21 | def test_containsDuplicate(self): 22 | self.assertEqual(Solution.containsDuplicate(self, [1,1,1,3,3,4,3,2,4,2]), True) 23 | self.assertEqual(Solution.containsDuplicate(self, [1,1]), True) 24 | self.assertEqual(Solution.containsDuplicate(self, [1,2]), False) 25 | self.assertEqual(Solution.containsDuplicate(self, []), False) 26 | self.assertEqual(Solution.containsDuplicate(self, [1]), False) 27 | self.assertEqual(Solution.containsDuplicate(self, [-1, 2, 3, 4]), False) 28 | self.assertEqual(Solution.containsDuplicate(self, [-1, 2, 3, -1]), True) 29 | 30 | if __name__ == "__main__": 31 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/10-palindromeLList.py: -------------------------------------------------------------------------------- 1 | ''' 2 | https://leetcode.com/problems/palindrome-linked-list/ 3 | ''' 4 | # Definition for singly-linked list. 5 | class ListNode: 6 | def __init__(self, val=0, next=None): 7 | self.val = val 8 | self.next = next 9 | class Solution: 10 | def isPalindrome(self, head:ListNode) -> bool: 11 | llist = [] 12 | 13 | while head: 14 | llist.append(head.val) 15 | head = head.next 16 | 17 | left = 0 18 | right = len(llist) - 1 19 | 20 | while left < right: 21 | # print(llist[left], llist[right]) 22 | if llist[left] != llist[right]: 23 | return False 24 | left += 1 25 | right -= 1 26 | return True 27 | 28 | 29 | # 0(n) - tc | 0(n) - sc 30 | class Solution: 31 | def isPalindrome(self, head: ListNode) -> bool: 32 | slow, fast = head, head 33 | 34 | #find the middle of the linked list 35 | while fast and fast.next: 36 | slow = slow.next 37 | fast = fast.next.next 38 | 39 | # reverse the middle of the linked list from the slow pointer 40 | prev = None 41 | while slow: 42 | temp = slow.next 43 | slow.next = prev 44 | prev = slow 45 | slow = temp 46 | 47 | # find palindrom 48 | left, right = head, prev 49 | while right: 50 | if left.val != right.val: 51 | return False 52 | left = left.next 53 | right = right.next 54 | 55 | return True 56 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/11-reverseLList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | from typing import Optional 3 | 4 | 5 | class ListNode: 6 | def __init__(self, val=0, next=None): 7 | self.val = val 8 | self.next = next 9 | 10 | 11 | ''' 12 | https://leetcode.com/problems/reverse-linked-list 13 | ''' 14 | 15 | 16 | class Solution: 17 | # 0(n) - tc | 0(n) - sc 18 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 19 | def reverse(curr, prev): 20 | if curr is None: return prev 21 | 22 | nxt = curr.next 23 | curr.next = prev 24 | return reverse(nxt, curr) 25 | return reverse(head, None) 26 | 27 | # iterative 0(n) - tc | 0(1) - sc 28 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 29 | prev, curr = None, head 30 | while curr: 31 | temp = curr.next 32 | curr.next = prev 33 | prev = curr 34 | curr = temp 35 | return prev 36 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/12-removeLListEl.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | from typing import Optional 3 | 4 | 5 | class ListNode: 6 | def __init__(self, val=0, next=None): 7 | self.val = val 8 | self.next = next 9 | 10 | class Solution: 11 | # create a dummy node 12 | # update its pointers using prev 13 | # 0(n) - TC | 0(n) - SC 14 | def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]: 15 | dummy = ListNode(next=head) 16 | prev, curr = dummy, head 17 | 18 | while curr: 19 | nxt = curr.next 20 | 21 | if curr.val == val: 22 | prev.next = nxt 23 | else: 24 | prev = curr 25 | 26 | curr = nxt 27 | return dummy.next 28 | 29 | 30 | # recursive solution - 0(n) - TC | 0(n) - sc 31 | def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]: 32 | if head is None: return None 33 | nxt = self.removeElements(head.next, val) 34 | if head.val == val: 35 | head = nxt 36 | else: 37 | head.next = nxt 38 | return head 39 | 40 | # solution 1 pointer - 0(n) - tc | 0(n) - sc 41 | def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]: 42 | dummy = cur = ListNode() 43 | dummy.next = head 44 | while cur.next: 45 | if cur.next.val == val: 46 | cur.next = cur.next.next 47 | else: 48 | cur = cur.next 49 | return dummy.next 50 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/13-removeDupsSortedLList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode: 3 | def __init__(self, val=0, next=None): 4 | self.val = val 5 | self.next = next 6 | from typing import Optional 7 | 8 | ''' 9 | https://leetcode.com/problems/remove-duplicates-from-sorted-list/ 10 | ''' 11 | 12 | class Solution: 13 | #0(n) - tc | 0(1) - sc 14 | def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: 15 | curr = head 16 | 17 | while curr and curr.next: 18 | if curr.val == curr.next.val: 19 | curr.next = curr.next.next 20 | continue 21 | curr = curr.next 22 | 23 | return head 24 | 25 | # Question: Do you understand the difference between the above method and this? 26 | # 0(n) - tc | 0(1) - sc 27 | def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: 28 | curr = head 29 | 30 | while curr: 31 | while curr.next and curr.val == curr.next.val: 32 | curr.next = curr.next.next 33 | 34 | curr = curr.next 35 | 36 | return head 37 | 38 | # two pointer + set method 39 | # 0(n) - tc | 0(1) - sc 40 | def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: 41 | if not head: return head 42 | prev, curr = head, head.next 43 | dups = set() 44 | dups.add(prev.val) 45 | 46 | while curr: 47 | if curr.val in dups: 48 | prev.next = curr.next 49 | else: 50 | dups.add(curr.val) 51 | prev = curr 52 | 53 | curr = curr.next 54 | 55 | return head 56 | 57 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/14-mergeTwoSortedList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | from typing import Optional 3 | 4 | ''' 5 | https://leetcode.com/problems/merge-two-sorted-lists/submissions/ 6 | ''' 7 | # 0(m + n) - TC 8 | 9 | class ListNode: 10 | def __init__(self, val=0, next=None): 11 | self.val = val 12 | self.next = next 13 | 14 | 15 | class Solution: 16 | # recursive 17 | # 0(n) - SC 18 | def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: 19 | def merge(l1, l2): 20 | if not l1: 21 | return l2 22 | if not l2: 23 | return l1 24 | 25 | if l1.val <= l2.val: 26 | l1.next = merge(l1.next, l2) 27 | return l1 28 | else: 29 | l2.next = merge(l1, l2.next) 30 | return l2 31 | return merge(list1, list2) 32 | 33 | # iterative 34 | # 0(1) - SC 35 | def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: 36 | dummy = ListNode() 37 | tail = dummy 38 | 39 | while True: 40 | if not list1: 41 | tail.next = list2 42 | break 43 | elif not list2: 44 | tail.next = list1 45 | break 46 | elif list1.val <= list2.val: 47 | tail.next = list1 48 | list1 = list1.next 49 | else: 50 | tail.next = list2 51 | list2 = list2.next 52 | tail = tail.next 53 | return dummy.next 54 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/15-binarySearch.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/binary-search/submissions/ 2 | # 0(log n) - TC | 0(1) - SC 3 | from typing import List 4 | import unittest 5 | 6 | 7 | class Solution: 8 | def search(self, nums: List[int], target: int) -> int: 9 | lower, upper = 0, len(nums) - 1 10 | 11 | while lower <= upper: 12 | mid = (upper + lower) // 2 13 | if nums[mid] == target: 14 | return mid 15 | elif nums[mid] > target: 16 | upper = mid - 1 17 | else: 18 | lower = mid + 1 19 | 20 | return -1 21 | 22 | class Test(unittest.TestCase): 23 | def test_search(self): 24 | self.assertEqual(Solution.search(self, [-1,0,3,5,9,12], 9), 4) 25 | self.assertEqual(Solution.search(self, [-1,0,3,5,9,12], 2), -1) 26 | 27 | if __name__ == "__main__": 28 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/16-nextGreatestLetter.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | # https://leetcode.com/problems/find-smallest-letter-greater-than-target 5 | # 0(log n) - TC | 0(1) - SC 6 | class Solution: 7 | def nextGreatestLetter(self, letters: List[str], target: str) -> str: 8 | lower, upper = 0, len(letters) - 1 9 | 10 | if target < letters[lower] or target >= letters[upper]: return letters[0] 11 | 12 | while lower < upper: 13 | mid = (upper + lower) // 2 14 | 15 | if letters[mid] > target: 16 | upper = mid 17 | else: 18 | lower = mid + 1 19 | 20 | return letters[upper]; 21 | 22 | class Test(unittest.TestCase): 23 | def test_nextGreatestLetter(self): 24 | self.assertEqual(Solution.nextGreatestLetter(self, ['c', 'f', 'j'], 'a'), 'c') 25 | self.assertEqual(Solution.nextGreatestLetter(self, ['c', 'f', 'j'], 'c'), 'f') 26 | self.assertEqual(Solution.nextGreatestLetter(self, ['c', 'f', 'j'], 'd'), 'f') 27 | self.assertEqual(Solution.nextGreatestLetter(self, ['c', 'f', 'j'], 'j'), 'c') 28 | 29 | 30 | if __name__ == "__main__": 31 | unittest.main() 32 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/17-avgOfLevels.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # 0(n) - TC | 0(N) - SC 3 | 4 | from typing import Collection, List 5 | class TreeNode: 6 | def __init__(self, val=0, left=None, right=None): 7 | self.val = val 8 | self.left = left 9 | self.right = right 10 | 11 | class Solution: 12 | def averageOfLevels(self, root: TreeNode) -> List[float]: 13 | res = [] 14 | queue = Collection.deque() 15 | queue.append(root) 16 | 17 | while queue: 18 | total = 0 19 | queueLen = len(queue) 20 | 21 | for _ in range(queueLen): 22 | node = queue.popleft() 23 | total += node.val 24 | if node.left: queue.append(node.left) 25 | if node.right: queue.append(node.right) 26 | 27 | res.append(total / queueLen) 28 | 29 | return res 30 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/18-minDepth.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | 8 | class Solution: 9 | def minDepth(self, root: TreeNode) -> int: 10 | if root is None: return 0 11 | leftDepth = self.minDepth(root.left) 12 | rightDepth = self.minDepth(root.right) 13 | 14 | if root.left is None and root.right is None: return 1 15 | 16 | if root.left is None: return rightDepth + 1 17 | 18 | if root.right is None: return leftDepth + 1 19 | 20 | return min(leftDepth, rightDepth) + 1 21 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/19-maxDepth.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | class Solution: 8 | def maxDepth(self, root: TreeNode) -> int: 9 | if root is None: return 0 10 | 11 | leftDepth = self.maxDepth(root.left) 12 | 13 | rightDepth = self.maxDepth(root.right) 14 | 15 | if root.left is None and root.right is None: return 1 16 | 17 | if root.left is None: return rightDepth + 1 18 | 19 | if root.right is None: return leftDepth + 1 20 | 21 | return max(leftDepth, rightDepth) + 1 22 | 23 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/20-isSameTree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | 8 | # Bfs 0(N) - TC | SC 9 | # https://leetcode.com/problems/same-tree/ 10 | 11 | 12 | class Solution: 13 | def isSameTree(self, p: TreeNode, q: TreeNode) -> bool: 14 | queue = [(p, q)] 15 | 16 | while queue: 17 | node1, node2 = queue.pop(0) 18 | 19 | if not node1 and not node2: 20 | continue 21 | elif not node1 or not node2: 22 | return False 23 | else: 24 | if node1.val != node2.val: 25 | return False 26 | queue.append((node1.left, node2.left)) 27 | queue.append((node1.right, node2.right)) 28 | return True 29 | 30 | # Dfs 31 | def isSameTree(self, p: TreeNode, q: TreeNode) -> bool: 32 | node1, node2 = p, q 33 | 34 | if not node1 and not node2: 35 | return True 36 | if not node1 or not node2: 37 | return False 38 | 39 | if node1.val != node2.val: 40 | return False 41 | return (self.isSameTree(node1.left, node2.left) and self.isSameTree(node1.right, node2.right)) 42 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/21-pathSum.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | from typing import Optional 8 | 9 | 10 | class Solution: 11 | def hasPathSum(self, root: Optional[TreeNode], tsum: int) -> bool: 12 | if not root: return False 13 | 14 | if not root.left and not root.right: 15 | if tsum == root.val: return True 16 | 17 | return (self.hasPathSum(root.left, tsum - root.val) or 18 | self.hasPathSum(root.right, tsum - root.val)) 19 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/22-twoSum.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | # https://leetcode.com/problems/two-sum/ 5 | # 0(n) - time | 0(n) - space 6 | class Solution: 7 | def twoSum(self, nums: List[int], target: int) -> List[int]: 8 | hash = {} 9 | 10 | for i in range(len(nums)): 11 | diff = target - nums[i] 12 | 13 | if diff in hash: 14 | return [i, hash[diff]] 15 | hash[nums[i]] = i 16 | 17 | class Test(unittest.TestCase): 18 | def test_twoSum(self): 19 | self.assertEqual(Solution.twoSum(self, [2,7,11,15], 9), [1, 0]) 20 | self.assertEqual(Solution.twoSum(self, [3,2,4], 6), [2, 1]) 21 | self.assertEqual(Solution.twoSum(self, [3, 3], 6), [1, 0]) 22 | 23 | if __name__ == "__main__": 24 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/23-invertBinaryTree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | from typing import Optional 3 | 4 | 5 | class TreeNode: 6 | def __init__(self, val=0, left=None, right=None): 7 | self.val = val 8 | self.left = left 9 | self.right = right 10 | 11 | # 0(n) - time | 0(n) - space 12 | # https://leetcode.com/problems/invert-binary-tree/ 13 | 14 | class Solution: 15 | def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: 16 | if not root: return root 17 | 18 | tmp = root.left 19 | root.left = root.right 20 | root.right = tmp 21 | 22 | self.invertTree(root.left) 23 | self.invertTree(root.right) 24 | 25 | return root -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/24-subTree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | class TreeNode: 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | from typing import Optional 8 | 9 | # https://leetcode.com/problems/subtree-of-another-tree/ 10 | # 0(r * s) - tc | 0(r * s) - sc 11 | 12 | class Solution: 13 | def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: 14 | if subRoot and not root: return False 15 | if self.isMatch(root, subRoot): return True 16 | 17 | return (self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)) 18 | 19 | 20 | def isMatch(self, r, s): 21 | if r and s: 22 | return r.val == s.val and self.isMatch(r.left, s.left) and self.isMatch(r.right, s.right) 23 | return r is s 24 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/25-squareSortedArr.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest, collections 3 | 4 | # https://leetcode.com/problems/squares-of-a-sorted-array/ 5 | # 0(n) - tc | 0(n) - sc 6 | 7 | class Solution: 8 | def sortedSquares(self, nums: List[int]) -> List[int]: 9 | res = collections.deque() 10 | l, r = 0, len(nums) - 1 11 | 12 | while l <= r: 13 | 14 | left, right = nums[l], nums[r] 15 | 16 | if abs(right) > abs(left): 17 | res.appendleft(right * right) 18 | r -= 1 19 | else: 20 | res.appendleft(left * left) 21 | l += 1 22 | 23 | return list(res) 24 | 25 | 26 | class Test(unittest.TestCase): 27 | def test_sortedSquare(self): 28 | self.assertEqual(Solution.sortedSquares(self, [-4,-1,0,3,10]), [0,1,9,16,100]) 29 | self.assertEqual(Solution.sortedSquares(self, [-7,-3,2,3,11]), [4,9,9,49,121]) 30 | self.assertEqual(Solution.sortedSquares(self, [-4,-1,3,10]), [1,9,16,100]) 31 | self.assertEqual(Solution.sortedSquares(self, [1, 2, 3, 4]), [1,4,9,16]) 32 | 33 | if __name__ == "__main__": 34 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/26-backspaceStringCompare.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | # https://leetcode.com/problems/backspace-string-compare/solutions/?orderBy=most_votes&languageTags=javascript&topicTags=two-pointers 4 | # 0(n) - TC | 0(1) - SC 5 | 6 | class Solution: 7 | def backspaceCompare(self, s: str, t: str) -> bool: 8 | sLen = len(s) - 1 9 | tLen = len(t) - 1 10 | 11 | sSkip, tSkip = 0, 0 12 | sNew, tNew = '', '' 13 | 14 | while(sLen >= 0 or tLen >= 0): 15 | while(sLen >= 0): 16 | if s[sLen] == '#': 17 | sSkip += 1 18 | elif sSkip > 0: 19 | sSkip -= 1 20 | else: 21 | sNew += s[sLen] 22 | sLen -= 1 23 | 24 | while tLen >= 0: 25 | if t[tLen] == '#': 26 | tSkip += 1 27 | elif tSkip > 0: 28 | tSkip -= 1 29 | else: 30 | tNew += t[tLen] 31 | tLen -= 1 32 | 33 | return tNew == sNew 34 | 35 | class Test(unittest.TestCase): 36 | def test_backspaceCompare(self): 37 | self.assertEqual(Solution.backspaceCompare(self, 'ab#cd#', 'ac#d#c'), True) 38 | self.assertEqual(Solution.backspaceCompare(self, "ab#c", 'ad#c'), True) 39 | self.assertEqual(Solution.backspaceCompare(self, "ab##", 'c#d#'), True) 40 | self.assertEqual(Solution.backspaceCompare(self, 'a#c', 'b'), False) 41 | 42 | if __name__ == "__main__": 43 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/27-majorityElement.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blossom-babs/Data-structures-and-algorithm/027b4e7a5037a5897789eafebbf828899313feff/leetcode/sean-prashad/python/27-majorityElement.py -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/3-findDisappearedNumbers.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/ 6 | ''' 7 | 8 | class Solution: 9 | # 0(n) - tc | 0(n) - sc 10 | def findDisappearedNumbers1(self, nums: List[int]) -> List[int]: 11 | numsSet, res = set(nums), [] 12 | 13 | for i in range(1, len(nums) + 1): 14 | if i not in numsSet: 15 | res.append(i) 16 | return res 17 | 18 | # 0(n) - tc | 0(1) - sc 19 | def findDisappearedNumbers2(self, nums: List[int]) -> List[int]: 20 | i = 0 21 | res = [] 22 | 23 | while i < len(nums): 24 | j = nums[i] - 1 25 | 26 | if nums[i] != nums[j]: 27 | nums[i], nums[j] = nums[j], nums[i] 28 | else: 29 | i += 1 30 | 31 | for i in range(len(nums) + 1): 32 | if i < len(nums) and i + 1 != nums[i]: 33 | res.append(i + 1) 34 | return res 35 | 36 | class Test(unittest.TestCase): 37 | def test_disappearedNum(self): 38 | self.assertEqual(Solution.findDisappearedNumbers1(self, [1, 1]), [2]) 39 | self.assertEqual(Solution.findDisappearedNumbers1(self, [4,3,2,7,8,2,3,1]), [5, 6]) 40 | 41 | def test_disappearedNum2(self): 42 | self.assertEqual(Solution.findDisappearedNumbers2(self, [1, 1]), [2]) 43 | self.assertEqual(Solution.findDisappearedNumbers2(self, [4,3,2,7,8,2,3,1]), [5, 6]) 44 | 45 | 46 | if __name__ == "__main__": 47 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/5-climbingStairs.py: -------------------------------------------------------------------------------- 1 | ''' 2 | https://leetcode.com/problems/climbing-stairs/ 3 | ''' 4 | import unittest 5 | 6 | 7 | class Solution: 8 | #0(n) - tc | 0(n) - sc 9 | def climbStairs(self, n: int) -> int: 10 | count = [1, 2] 11 | 12 | for i in range(2, n): 13 | count.append((n - 1) + (n - 2)) 14 | return count[n - 1] 15 | 16 | #0(2^n) - tc | 0(n) - sc 17 | def climbStairsRecurse(self, n: int) -> int: 18 | memo = {} 19 | 20 | def recurse(n): 21 | if n in memo: 22 | return memo[n] 23 | if n == 1: 24 | return 1 25 | if n == 2: 26 | return 2 27 | memo[n] = recurse(n - 1) + recurse(n - 2) 28 | return memo[n] 29 | 30 | return recurse(n) 31 | 32 | 33 | class Test(unittest.TestCase): 34 | def test_climbingStairs(self): 35 | self.assertEqual(Solution.climbStairs(self, 2), 2) 36 | self.assertEqual(Solution.climbStairs(self, 3), 3) 37 | self.assertEqual(Solution.climbStairs(self, 1), 1) 38 | 39 | def test_climbingStairsRecurse(self): 40 | self.assertEqual(Solution.climbStairsRecurse(self, 2), 2) 41 | self.assertEqual(Solution.climbStairsRecurse(self, 3), 3) 42 | self.assertEqual(Solution.climbStairsRecurse(self, 1), 1) 43 | 44 | if __name__ == "__main__": 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/6-bestTimeToSell.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 6 | 0(n) - tc | 0(1) - sc 7 | ''' 8 | 9 | class Solution: 10 | def maxProfit(self, prices: List[int]) -> int: 11 | buy, sell = 0, 1 12 | profit = 0 13 | 14 | while sell < len(prices): 15 | sale = prices[sell] - prices[buy] 16 | 17 | if sale < 0: 18 | buy += 1 19 | else: 20 | profit = max(profit, sale) 21 | sell += 1 22 | return profit 23 | 24 | 25 | class Test(unittest.TestCase): 26 | def test_maxProfit(self): 27 | self.assertEqual(Solution.maxProfit(self, [7,1,5,3,6,4]), 5) 28 | self.assertEqual(Solution.maxProfit(self, [7,4,5,3,6,4]), 3) 29 | self.assertEqual(Solution.maxProfit(self, [7,6,4,3,1]), 0) 30 | 31 | if __name__ == "__main__": 32 | unittest.main() -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/7-rangeSumQuery.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import unittest 3 | 4 | ''' 5 | https://leetcode.com/problems/range-sum-query-immutable/ 6 | 0(n) - tc | 0(n) - sc 7 | ''' 8 | 9 | # prefix sum 10 | class NumArray: 11 | 12 | def __init__(self, nums: List[int]): 13 | self.nums = [0] 14 | for num in nums: 15 | self.nums.append(self.nums[-1] + num) 16 | 17 | 18 | def sumRange(self, left: int, right: int) -> int: 19 | return self.nums[right + 1] - self.nums[left] 20 | 21 | # Brute force 22 | class NumArray: 23 | 24 | def __init__(self, nums: List[int]): 25 | self.nums = nums 26 | 27 | 28 | def sumRange(self, left: int, right: int) -> int: 29 | return sum(self.nums[left: right + 1]) 30 | 31 | 32 | 33 | class Test(unittest.TestCase): 34 | def test_NumArray(self): 35 | NumArray.__init__(self, [-2, 0, 3, -5, 2, -1]) 36 | param = NumArray.sumRange(self, 0, 2) 37 | param2 = NumArray.sumRange(self, 2, 5) 38 | param3 = NumArray.sumRange(self, 0, 5) 39 | self.assertEqual(param, 1) 40 | self.assertEqual(param2, -1) 41 | self.assertEqual(param3, -3) 42 | 43 | 44 | if __name__ == "__main__": 45 | unittest.main() 46 | 47 | # Your NumArray object will be instantiated and called as such: 48 | # obj = NumArray(nums) 49 | # param_1 = obj.sumRange(left,right) 50 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/8-hasCycle.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode: 3 | def __init__(self, x): 4 | self.val = x 5 | self.next = None 6 | 7 | from typing import Optional 8 | 9 | ''' 10 | https://leetcode.com/problems/linked-list-cycle/ 11 | ''' 12 | 13 | # Set patter 14 | # 0(n) - tc | 0(n) - sc 15 | class Solution: 16 | def hasCycle(self, head: Optional[ListNode]) -> bool: 17 | cycle = set() 18 | while head: 19 | if head in cycle: 20 | return True 21 | cycle.add(head) 22 | head = head.next 23 | return False 24 | 25 | 26 | # Floyd's cycle detection algorithm 27 | # 0(n) - TC | 0(1) - SC 28 | class Solution: 29 | def hasCycle(self, head: Optional[ListNode]) -> bool: 30 | slow = fast = head 31 | 32 | while fast and fast.next: 33 | slow = slow.next 34 | fast = fast.next.next 35 | 36 | if slow == fast: 37 | return True 38 | return False 39 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/9-middleLinkedList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | class ListNode: 3 | def __init__(self, val=0, next=None): 4 | self.val = val 5 | self.next = next 6 | from typing import Optional 7 | 8 | ''' 9 | https://leetcode.com/problems/middle-of-the-linked-list/ 10 | ''' 11 | 12 | # 0(n) - tc | 0(1) - sc 13 | class Solution: 14 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]: 15 | slow = fast = head 16 | while fast and fast.next: 17 | fast = fast.next.next 18 | slow = slow.next 19 | return slow 20 | 21 | 22 | # Brute force approach 23 | # 0(n ^ 2) - TC | 0(1) - sc 24 | class Solution: 25 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]: 26 | listLen = 0 27 | temp = head 28 | 29 | while temp: 30 | listLen += 1 31 | temp = temp.next 32 | 33 | mid = listLen // 2 34 | pos = 0 35 | 36 | 37 | while head: 38 | if pos == mid: 39 | return head 40 | head = head.next 41 | pos += 1 42 | -------------------------------------------------------------------------------- /leetcode/sean-prashad/python/bonus-linkedlistII.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | from typing import Optional 3 | 4 | 5 | class ListNode: 6 | def __init__(self, x): 7 | self.val = x 8 | self.next = None 9 | 10 | 11 | ''' 12 | https://leetcode.com/problems/linked-list-cycle-ii/submissions/ 13 | ''' 14 | 15 | # set solution 16 | # 0(n) - tc | 0(n) - sc 17 | 18 | 19 | class Solution: 20 | def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: 21 | hash = set() 22 | current = head 23 | 24 | while current: 25 | if current in hash: 26 | return current 27 | hash.add(current) 28 | current = current.next 29 | 30 | return None 31 | 32 | 33 | class Solution: 34 | def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: 35 | slow = fast = pointer = head 36 | 37 | while fast and fast.next: 38 | slow = slow.next 39 | fast = fast.next.next 40 | 41 | if fast == slow: 42 | slow = head 43 | while slow != fast: 44 | slow = slow.next 45 | fast = fast.next 46 | return slow 47 | 48 | return None 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data-structure-and-algorithms", 3 | "version": "1.0.0", 4 | "description": "This repository holds solutions to my solutions to data structures and algorithmic problems.", 5 | "main": "", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "start": "clear && npm test ./leetcode/sean-prashad/javascript/28-productExceptSelf.test.js", 9 | "start-js-tree": "clear && node ./data-structures/binary-trees/javascript/createNodeClass.test.js", 10 | "run-py": "clear && python ./data-structures/binary-trees/python/1-createNodeClass.py" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/blossom-babs/leetcode-challenges.git" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/blossom-babs/leetcode-challenges/issues" 21 | }, 22 | "homepage": "https://github.com/blossom-babs/leetcode-challenges#readme", 23 | "devDependencies": { 24 | "@types/jest": "^27.4.1", 25 | "jest": "^27.5.1" 26 | }, 27 | "dependencies": { 28 | "js-ord": "^4.1.1" 29 | } 30 | } --------------------------------------------------------------------------------