Speed Run to Quant

अब Quizwiz के साथ अपने होमवर्क और परीक्षाओं को एस करें!

Encode and Decode Strings

Encode -> len(s) + '#' + s itself Decode -> use information above to decode

Lowest Common Ancestor BST - "The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself)."

Note that it is a BST. if both p and q val are less than the root recurse to the left if greater recurse to the right else return the root.

Invert Binary Tree - Given the root of a binary tree, invert the tree, and return its root.

Swap left and right then call invert function on both and return root

Valid Perfect Square -- Given a positive integer num, return true if num is a perfect square or false otherwise. A perfect square is an integer that is the square of an integer. In other words, it is the product of some integer with itself.

Use binary search on 1 to num. Trivial from there.

Same Tree (needed to understand subtree of another tree)

if p XOR q return false, if not p and not q return true, and if p.val != q.val return false. return is same tree left and right

Kth Smallest element in a BST - Given the root of a binary search tree, and an integer k, return the kth smallest value (1-indexed) of all the values of the nodes in the tree.

Again note that this is a BST. In order traversal into an array. Or implement recursion iteratively using a stack which is helpful for dynamic memory purposes. While stack is non empty or curr is not empty -> while curr append it and curr = curr.left then when while loop breaks curr is null so reset curr to the pop of the stack and then decrement k check if 0 and then reset curr to right. guaranteed to find answer. IN order traversal is much more straightforward

Binary Tree Maximum Path Sum - A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root. The path sum of a path is the sum of the node's values in the path.

Again think bottom up. Update result and return different value to parent, similar to diameter of a binary tree. Remember left max = max(left, 0) include 0 in case both values are negative. DFS post order hold a global variable in a list. If root is null return 0. compute max path with split and update result if greater, and then return max path sum without split. curPath = leftmax + rightmax + root.val, return root.val + max(left, right)

Diameter of Binary tree - Given the root of a binary tree, return the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root. The length of a path between two nodes is represented by the number of edges between them.

Bottom UP approach (different than normal tree problems). Keep track of the diameter and height of each node. Null trees have a height of -1, while a single node has a height of 0. Height for each node is 1 + max(left height, righthight) and the diameter of each node is right height + left height + 2. HEIGHT is returned to upper nodes, and DIAMETER is only calculated to update the result. Calculate diameter after dfs called on both right and left using left and right, and then return the new height. Bottom up implemented with dfs. so it can just be called on the root since recursively the first path will go all the way to the bottom and be null.

BT Level Order Traversal - Given the root of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level).

Breadth First Search Using Queue (FIFO) - Use deque and pop left or just an array and pop(0) to implement queue. add root to queue if root else return empty list. while q is non empty: create a temporary list, and for the initial size of queue: pop from the queue add to temp, and add its left and rights to the queue if they aren't null. After for loop, add temp to overall output. Once q becomes null and breaks out of while loop return the overall result list of lists

Longest Palindromic Substring - Dynamic Programming Given a string s, return the longest palindromic substring in s.

Brute force approach (odd and even length substrings for every character runs as O(N^3), so we should utilize dynamic programming to optimize. dp[i][j] = whether the substring from index i to j is a palindrome or not. Expand from center is O(N^2), or use Manacher's algorithm which is O(N). Only works for odd lengths, for even lengths, insert a # at the starts and in-between every character. EXPAND FROM MIDDLE(outside for loop for each character, and then each character will have to separate while loops: one that considers odd length and one that considers even length. IF END - START + 1 > maxLength, update the maxStart and maxEnd indices and then decrement the start and increment the end pointers.

Top K Frequent Elements

Bucket Sort -- Hashmap for frequencies. create an array that is indexed by the frequency and has a value that is the list of numbers that have that frequency. use the for k,v in items. The size of this bucket list will be len(nums) because at the most extreme case every value will be the same and will exist at a frequency that is the size of the array. Make sure to offset by one for this problem. Then start adding to result vector starting from the back of this new array of arrays and only add k values to output then break. Can easily be solved with sorted input but this will be O(nlogn), we want O(n).

Minimum Window Substring - Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "".

Can use the concept of "matches" just as in permutation in string, or utilize the "have/need" approach. If we get the correct number of char value matches aka matches == targetMatches (depending on implementation), move left ptr to optimize. 1. Fill map with char frequency like usual of t. Move R until a valid window is found, and then optimize with t. Target matches is initially the length of t. decrement differences map no matter what and if is now 0 or is still positive, decrement matches (if it becomes negative that's ok it just means we will have duplicates when optimizing) 2a. while target matches is 0 optimize (aka increment the difference and if it becomes positive that means there is now a value in t that is not present within our new window of s, so we increment difference and target matches. 2b. Keep track of minLenght and starting Index to return substr at end. 3. Note that values in the map become negative because we have them in the bank meaning we can have duplicates so we need to account for duplicates when optimizing. THE MAP REPRESENTS THE CHARActer differences between t and s, and holds the requirement for t, that's why the map should be called something like tCnt.

Find the duplicate number - Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive. There is only one repeated number in nums, return this repeated number. You must solve the problem without modifying the array nums and uses only constant extra space.

Can't use hash set or sorting because it needs to be constant space. Linked list cycle, Floyd's cycle detection algorithm. 1. Consider each index of array to be a node and consider that the values in array are pointers to its "next" node given by the index. each value in array contains the index of array that it points to. Before cycle, in cycle, returning back to start of cycle. 1. Tortoise and hare to find cycle, and then keep incrementing at start and at that position found until they equal again, because that will 100% be the beginning of the cycle. Floyd = tortoise and hare modified. Fast will at least one full loop before the intersection point, and the mathematical proof is that p = x. PART 1: slow, fast = 0, 0 -> while True, slow = nums[slow] fast = nums[nums[fast]] advance by 2 in linked list, if slow = fast break. PART 2. slow2 is start slow is slow1 increment both by doing slow = nums[slow] break and return either slow1 or slow2 once slow1 = slow2 because both are mapping to the same index. 0 is fs not in cycle, because it is just an index, and not included in range.

ZigZag Conversion - The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R And then read line by line: "PAHNAPLSIIGYIR" Write the code that will take a string and make this conversion given a number of rows: string convert(string s, int numRows);

Jump length to get to to next character in row (# rows - 1) * 2 == jump length for first row. For the second row, we want to jump what we jumped the row before, - 2 (because of symmetry). For the last row, we reset to the jump length that we were at at the start. The way to implement this is to have an outside for loop for each number of rows. Then, another for loop that will construct each row that starts at the beginning index of each row and is incremented by the magic increment formula (2 * (#rows - 1). Add this to result string. Now if we are in an in between row, add in the i + increment - 2*r where r is that row number. Then the result string is fully constructed. Make sure to check that i + increment - 2*r is in bounds before adding it to the result string

Trapping Rainwater (hard lc, but v simple genius solution)

LR Pointers for O(1) memory, O(n) time: L is first index and R is last index. The maximum amount of water that can be trapped is determined by the minimum of the maxLeft and maxRight pointers (which are altered every iteration) - value in array. Move whichever pointer has the smaller respective max value (since we want to find window with water in it) and add the one with smaller max value to result res += min(maxL, maxR) - height[l/r]

Container with most water - You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]). Find two lines that together with the x-axis form a container, such that the container contains the most water. Return the maximum amount of water a container can store.

LR pointers for O(n). L is at 0 and R is at max index. area is determined by minimum of values of l and r ptrs. simply calculate the area, update max, and if l pointer points to the smaller value move that ptr if not mov right pointer. Remember we want to find max area, so why would we want to change a ptr that has a higher height when trying to find the max area? Keep the ptr that has a higher height and move the smaller one to optimize.

Find Median In Data Stream

Max Heap and Min Heap (priority queue) O(logN) - 1. Add to small heap to ensure it is not empty 2. Check if max of small heap <= min of large heap. 3. If not, move max in small heap to large heap. 4. Check if heap sizes are are uneven (off by more than 1). If true, move respective max and min to other heap to maintain size. Python, only does minHeaps, can work around by *-1 or using C++ where maxHeaps are supported by default. priority_queue<int, vector<int>, greater<int>> higher; for min heap. When finding median if one of the sizes is greater return the top of that one else return the tops added together / 2.

Find Minimum in Rotated Sorted Array --Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become: [4,5,6,7,0,1,2] if it was rotated 4 times. [0,1,2,4,5,6,7] if it was rotated 7 times. Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]]. Given the sorted rotated array nums of unique elements, return the minimum element of this array. You must write an algorithm that runs in O(log n) time.

Perform binary search on the indices. Keep track of current minimum which is initialized to float("inf") and then is updated to the min of current minimum and the nums[mid] where mid the binary search middle index. If the middle index points to a value that is greater than the high index, then that means the minimum exists on the right side of the array **update**. else the minimum exists on the LHS, therefore **update**. Then return the min(currMin, nums[low]) After the final iteration. Pretty much just going through the entire array and updating the solution. The last statement just ensures that the last iteration didn't actually produce the minimum which is why we have to return nums[low].

Task Scheduler - Priority Heap and Queue - Given a characters array tasks, representing the tasks a CPU needs to do, where each letter represents a different task. Tasks could be done in any order. Each task is done in one unit of time. For each unit of time, the CPU could complete either one task or just be idle. However, there is a non-negative integer n that represents the cooldown period between two same tasks (the same letter in the array), that is that there must be at least n units of time between any two same tasks. Return the least number of units of times that the CPU will take to finish all the given tasks.

Process the more frequent task first. Always process the more frequent character if it is available to use (in maxheap). To check if a value becomes available to us, use a queue. Use a MAXHEAP + QUEUE. The items that are added to the queue are the items that require idle time. Add to QUEUE a pair (-current val, curTime + idleTime). While maxHeap OR queue, there are still things to process, so increment the time. if the maxheap is not empty, pop from it, add one (using negatives) , and if not 0, add to q. After, check if the time is equal to the time that is stored on the top of the maxHeap and if it is it can be safely popped from the queue and added back to the maxHeap. Return the time at the end.

Reorder list - L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → ...

Reverse the back half of the list by performing reverse linked list after doing the tortoise and hare approach, and then alternate into output. As an alternative to alternating with isp1Turn and switching every time, it is possible to merge the two together using neetcodes solution. Pretty much set the second ptr to the end, and while the second and first: set temporary values to their actual next values, and then readjust their actual temporary values. (diagonal)The slow pointers next value must be set to NULL.

Longest Repeating Character Replacement - You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most ktimes. Return the length of the longest substring containing the same letter you can get after performing the above operations.

Sliding window expand window if we can change the character. Shift window left if the requirement is to change more than k characters in order to make a longer substring with the most frequent letter from count hashmap. 1. increment frequency in count. 2. Keep track of max frequency of same letter. 3. IF AVAILABLE WINDOW - MAXF > K UPDATE LEFT POINTER AND subtract from frequency in map. 4. Always ensure we are updating a valid result, aka res = max(res, r - l + 1). Window can only get longer or stay the same. BY default increment in map right after start of the for loop (right ptr) similar to minimum window substring and permutation in string I think

Longest Substring Without Repeating Characters Given a string s, find the length of the longest substring without repeating characters.

Sliding window technically O(n) worst case is 2*O(n). 1. If char not in set, expand and update result. 2. Else, erase left char from set and contract (l++). Must be IF ELSE. Also use a hash set for O(1). Don't do bs array thing.

Asteroid Collision -- find out the state of asteroids after collision. Input [5,10,-5] Output [5,10] because 5 and 10 will never meet and 10 and -5 will collide

Stack O(n): for each asteroid, while stack is not empty and current asteroid is negative and top of stack is positive, handle each case and break only on explosion or if the absolute value of the incoming negative asteroid is less than the top of the stack in which case it will be destroyed. Can be implemented with for -> while else. or by doing for -> while + if where if has the case whether or not we should append based on whether or not the new asteroid should be added to stack (only if it has absolute value greater than the top and is negative or is positive while the top is positive). This is v specific, v simple to implement. (neetcode sets the asteroid a to 0 if its a perf collision)

Valid Palindrome

Two pointers, if a non alphanumeric character is found skip over it, and then compare the lowercase version of each ptr

Permutation in String - Given two strings s1 and s2, return true if s2 contains a permutation of s1, or falseotherwise. In other words, return true if one of s1's permutations is the substring of s2.

Utilize the concept of "matches" allocate hash map for s1 and alternative window of s2 depending on the values of these matches. 1. IF s1's length > s2's length, s2 can't possibly contain a permutation of s1, so therefore return false. 2. count1, count2 are arrays that contain the frequency of characters in s1 and s2 respectively, and before main iteration through s2 keep track of the current amount of matches in terms of frequency of characters(0-25 for each letter). 3. go through s2, but already considered the first len(s1) elements of s2 initially so change starting index accordingly. 3a. If we get matches == 26, immediately return true. 3b. THE WINDOW WILL ALWAYS BE OF SIZE of S1, since we are only considering the different possible permutations of s1 that could be present in s2. 3c. Increment count2 of the right character and if it is now equal to count1 of same character, increment matches. If we take a new char in count2 that already had a frequency == count1 aka count 2 = count1 + 1, we are escaping a match so decrement count. Do the same thing with left pointer and increment it. 4. Return matches == 26. Note that count2 holds the total frequency of characters ONLY for the window that we are considering and not the entire s2 string.

Merge Two Sorted Lists You are given the heads of two sorted linked lists list1 and list2. Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists. Return the head of the merged linked list.

4 steps that need to be checked. 1. If either list is NULL we want to return the other one. 2. Figure out what the head of the list should be (which one is less). 3. set a curr = head, While both lists are not NULL, the next value in current will be whichever is less (Most of the code, the structure is made to be from curr). 4. If one of the lists is NULL and not the other, we want to append the other to the curr-> next. Obviously if this is all successful return Head. MAKE SURE TO INCREMENT PTR IN LIST AKA LIST1 = list1.next every time we update something. WITH DUMMY NODE as head, we only do 3 and 4 and can skip 1 and 2, and return dummy.next, because we don't know what the start of the list is originally

Can place flowers? - You have a long flowerbed in which some of the plots are planted, and some are not. However, flowers cannot be planted in adjacent plots. Given an integer array flowerbed containing 0's and 1's, where 0 means empty and 1 means not empty, and an integer n, return if n new flowers can be planted in the flowerbed without violating the no-adjacent-flowers rule.

Add 0 to the front and back of flowerbed, since they are technically accessible spots. [0, flowerbed, 0]. Use list.insert(index, value) in python. Alg is O(N) from here. Set a ticker that resets when 1 is or when 0 is found and ticker is already at 2 (since 3 in a row means u can place). Only increment ticker if value is 0 and make sure that is executed AFTER checking whether or not it is 2 already since 5 open 0's means we can put 2 flowers in. We don't need 6 open spots for 2 flowers. Or do neetcodes plant flower solution that does l[I] == 0 and l[I+1] == 0 and l[I-1] == 0 then setting l[I] = 1, decrementing n, PLANTING l[I] = 1, and returning whether or not n is less than 0 (aka all the flowers are planted)

Median of Two Sorted Arrays - Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Binary Search - Ensure len(A) < len(B) by swapping. Take sum of both lengths and // 2. This will be the size of the left partition. Take LR ptrs on start, end of smaller array, find the mid, and then that will be the left partition for the first array. Half - mid1 will be the size of the left partition on the 2nd larger array. If the last val in left partition of second is greater than first val in right partition of first or vice versa aka (X), then pointers will be adjusted. Once correct left partition is found, return min(start of right partition on array 1, start of right partition on array 2) if odd total length else do a+b/2 where a is max(Aleft, Bleft) and b is min(Aright, Bright). Do while true since l could = r and we are actually looking at both array when doing binary search. I, j = mid(A), mid(B). Both I and j could be out of bounds. if I < 0 Aleft = -inf else A[I]. If I+1 > len(A), Aright = +inf else A[I+1]. If j < 0, Bleft same as Aleft w j, if J+1>lenB Bright same Aright w j. Note off by one errors when calculating the right bounds for the left partitions of A and B.

Arranging Coins -- You have n coins and you want to build a staircase with these coins. The staircase consists of k rows where the ith row has exactly i coins. The last row of the staircase may be incomplete. Given the integer n, return the number of complete rows of the staircase you will build.

Binary search on n. Use the sum from 1 to n formula (we proved this by induction in week 1 of math 61)

Longest Increasing Subsequence - Dynamic Programming Given a sequence of numbers, find the length of the longest increasing subsequence (it does not have to be contiguous or unique).

By default, every individual number has a longest increasing subsequence of 1, since its just a number, so dp = [1] * len for every index i, and then for index j in up until I, if nums[I] > nums[j] it has the potential for updating the longest increasing subsequence, so dp[I] = max(dp[I], dp[j] + 1). After this O(N^2), return the maximum of the dp array

Car Fleet - There are n cars going to the same destination along a one-lane road. The destination is target miles away. You are given two integer array position and speed, both of length n, where position[i] is the position of the ith car and speed[i] is the speed of the ith car (in miles per hour). A car can never pass another car ahead of it, but it can catch up to it and drive bumper to bumper at the same speed. The faster car will slow down to match the slower car's speed. The distance between these two cars is ignored (i.e., they are assumed to have the same position). A car fleet is some non-empty set of cars driving at the same position and same speed. Note that a single car is also a car fleet.

Create a list of pairs of position and speed and sort them in reverse order by position. Create a stack, which holds the total time to reach the end. Add rightmost car to stack, and then argue whether the next Car should be added to stack. It should only be added to the stack if it finishes strictly AFTER the car on the top of the stack. Be default, add to stack and then remove it if the condition doesn't hold. That's pretty much it, and the length of the stack will hold the total number of car fleets.

Min cost for tickets - dynamic programming [3]

DFS function will take in the index as the parameter, and it is also the value that will be cached. BASE: if index is out of bounds return 0. default of cache[I] = float("inf"). use zip to iterate through [1.3.7] and costs at the same time. While loop -> let j = index. WHILE J < LEN(DAYS) AND DAYS[J} < DAYS[I]+ DAY_pass_value, j++. Must use a dp right away. and let dp[I] just be that guy. FOR LOOPS RETURN AFTER DONE EXECUTING NOT WITHIN FOR LOOP.

Minimum cost of climbing stairs - Dynamic Programming

DFS: Base cases: if index is 0 or 1 return that value. If index is less than 0 return 0. Return cost[index] + min(minCost(index -1), minCost(index - 2)). Return the min(dfs(len - 1), dfs(len-2))

Remove K Digits

Monotonically Increasing stack. 1. for each num pop from stack if stack is not empty and next value happens to be less than the top of the stack, pop from stack and decrement k because this is because we want increasing order. After for loop, if k is still not 0, do stack = stack[:len(stack) - k) in case the input is in increasing order. Then "".join the stack and return if the stack is non empty. If it is empty, then return "0"

Subtree of another tree - Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and falseotherwise. A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node's descendants. The tree tree could also be considered as a subtree of itself.

If subRoot is NULL, ALWAYS return true. If subroot and root is null, return false. Return true if its the same tree using same tree helper function (another lc prob) else return try left or right w same subroot.

2 sum

If u can't do this go f yourself. Hash map value -> index. If target - nums[I] in map add to output otherwise just add to hash map

Daily Temperatures - Given an array of integers temperatures represents the daily temperatures, return an array answersuch that answer[i] is the number of days you have to wait after the ith day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0 instead.

Monotonic Decreasing Stack (temperature, index) O(N) - While larger value found pop from stack and add index diff to output until not larger. Now the temperature will be less than or equal to the top of the stack after while loop exits, so append it to the stack. Stack will store [val, index].

Time Based Key-Value Store - Design a time-based key-value data structure that can store multiple values for the same key at different time stamps and retrieve the key's value at a certain timestamp. Implement the TimeMap class: TimeMap() Initializes the object of the data structure. void set(String key, String value, int timestamp) Stores the key key with the value value at the given time timestamp. String get(String key, int timestamp) Returns a value such that set was called previously, with timestamp_prev <= timestamp. If there are multiple such values, it returns the value associated with the largest timestamp_prev. If there are no values, it returns "".

Hash map (obviously) keys are the keys, while the value to this hash map is a list of lists -> [[val1, timestamp1], [val2, ts2], ...] which is a pair. If the timestamp doesn't exist, return the value associated with the most recent timestamp in the map less than input timestamp. ALL THE TIMESTAMPS ARE STRICTLY INCREASING. meaning we don't have to sort the timestamps in each key value pair, so we can search in O(logN) using binary search as opposed to a linear scan or sorting. BS on the list of values. if the second value in pair is less than or equal to timestamp, it is valid so the first value must be set equal to the result. If the 2nd value in pair is greater than the timestamp, then indeed it is invalid, so we only want to adjust pointers and not update the result.

LRU Cache - RUCache(int capacity) Initialize the LRU cache with positive size capacity. int get(int key) Return the value of the key if the key exists, otherwise return -1. void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.

Hash map key : ptr to node. L and R are the dummy Nodes that create the inherent structure of the solution. L.next ptr is LRU and R.prev ptr is MRU. Implement a doubly linked list in order to keep track of ordering of nodes and Lrus. (not circuraly, but could be). Get rid of lru when we try to put in a key not in hashmap and size of hash map (double linked list) is at capacity. Make sure to update the pointer in the value of the hash map. SETUP: Node struct -> key, val, prev = None, next = None. In LRU class, initialize the capacity, the hash table, and dummy LR ptrs to None, and make sure they are connected. GET(key): if key is in cache return it and before call remove helper function followed by insert helper function. We first want to remove the node and then add it to the most recent spot afterwards. REMOVE(node): removes the node from the linked list. prev.next is next and next.prev is prev INSERT(node): Adds node to the end of linked list (aka right most spot is one after mru). This must be in the middle of end and dummy node right. Adjust ptrs accordingly because it is a middle value (inserting means MRU). PUT: If key already exists remove it. Allocate new space for node and add to cache and then call insert to insert into mru of linked list. Then if over capacity, remove the lru from both linked list and cache. Lot of steps, must follow exactly.

Hand of Straights -- Alice has some number of cards and she wants to rearrange the cards into groups so that each group is of size groupSize, and consists of groupSize consecutive cards. Given an integer array hand where hand[i] is the value written on the ith card and an integer groupSize, return true if she can rearrange the cards, or false otherwise.

Hash map or Hashmap + minHeap: First check if hand length is divisible by groupSize by default. Hashmap count -> frequency. And create a minHeap from the keys in this hash map. and then while heap is not empty find the top of the minHeap (first) and go until group size and return false if count is 0 or doesn't exist in map, decrement, and then if the count is now 0 we already used it so it can be evicted from count. IF THE COUNT IS 0, CHECK IF THE MIN VALUE IN HEAP IS THE SAME AS tHAT VALUE, IF NOT< THERE IS A HOLE AND WE MUST RETURN FALSE, OTHERWISE SIMPLY EVICT FOR COUNT 0 CASE. IMPORTANT: if using while loop and map, make sure u take the minimum key that exists as starting value, this kind of makes the min heap solution 10x better tho lol. Literally same alg as just using while min heap and popping and starting with top of min heap and popping from min heap if the value in map is 0 and not the top of min heap

Valid Sudoku

Hash sets, compound data structures, map box index using // 3. Use hash map, with key as row column or in the case of the box row/3, col/3 and value -> is a hash set. Also kinda complicated in python collections.defaultdict(set). If board[r][c] is empty continue to next iteration. or do 2d true false arrays which make more sense and to get a unique index for boxes do (r//3)*3 + (c//3). If a value in any of these true false arrays that function as hash sets are already true (meaning value already existed and there is a duplicated) return false else make all the row col and box hash sets true. This is O(9^2) at worst case.

Delete and Earn -- Dynamic programming -- You are given an integer array nums. You want to maximize the number of points you get by performing the following operation any number of times: Pick any nums[i] and delete it to earn nums[i] points. Afterwards, you must delete every element equal to nums[i] - 1 and every element equal to nums[i] + 1. Return the maximum number of points you can earn by applying the above operation some number of times.

House robber modified. Sort the input array, count frequency into a hash map, and then create a new array that has values only equal to the keys of this count hashmap. dp array will represent the max we can get until that index of the non duplicate array. return dp[len - 1]. For each value in the non duplicate array, we are going to take the maximum of including it (ie multiplying val w corresponding value in hashmap) + previous value if not one less, and previous value. Only need to keep track of two previous values, earn1 and earn2 = 0, 0. FOR LOOP: curEarn = nums[I] * count, set temp = earn2. and then set that equal to earn1 after earn2 is recomputed. Earn2 is recomputed based on the if statement that check if value is equal to 1 + previous value. If that is the case, earn2 must be reset to the max of earn2 and earn1 + curEarn (I, e we have a choice to take it). If its more than 1 + previous value, it only makes sense to add it to earn2 itself. So earn2+=curEarn. RETURN EARN2

Last Stone Weight - You are given an array of integers stones where stones[i] is the weight of the ith stone. We are playing a game with the stones. On each turn, we choose the heaviest two stones and smash them together. Suppose the heaviest two stones have weights x and y with x <= y. The result of this smash is: If x == y, both stones are destroyed, and If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x. At the end of the game, there is at most one stone left.

Implement maxHeap in python by multiplying every value by -1 at the start. while the maxH is non empty, if the length of it is 1 return the top of the heap but if not pop the top two values and if the first is strictly less than the second push the difference back onto the heap. If the while loop exits, it means we should return 0.

Remove Nth node from end of list. - Given the head of a linked list, remove the nth node from the end of the list and return its head.

LR pointers, where the left ptr is initially the dummy and the right ptr is initially the head. We need to use a dummy node because actually want to have access to the node before the one we want to delete so it is possible for us to delete it. The right ptr is moved to the right n times, so then we can keep incrementing until the node before nth from end node to the end. Basically a fixed sliding window to find a ptr that is able to delete the node. ALWAYS RETURN DUMMY>NEXT

4 sum

Let recursion simulate the iteration. We are generalizing for "k-sum" at this point. 1. Identify output vectors and sort the input . 2. Recursion (non base case) 3. Check Duplicates. 4. Two sum II (true base case when k == 2). kSum will take 3 parameters: k, start, and target. Within the non base case, we need to go through every value in nums until LEN(NUMS) - K + 1!! because we only want to consider up until that point as starting values for the rest of its children (aka a parent waits until a child is 18 and then the child can deal w problems, the parent doesn't need to take care of entire thing) with the same start value (this is kind of like a backtracking problem). # decrement k, change target, try next start value. BEFORE ACTUALLY CALLING Recursive function, add potential values to output array, and pop them from the output array after they finish so we can try the next value (backtracking) also don't forget to check duplicates. Can arbitrarily choose to increment left ptr

Sliding Window Maximum - You are given an array of integers nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.

MONOTONICALLY DECREASING QUEUE (queue is always in decreasing order) - The key is to use the deque data structure where you can add and pop elements from both the front and the back of the data structure O(1). Sliding window is a fixed size, but we want to first establish that size and then move from there (grow then shift). THE DEQUE STORES INDICES 1. Start LR ptrs both = 0. 2. While through array (R < len) 3. While the deque is non empty and the top of the deque is less than the next value, pop from the deque. We want to pop smaller values from the deque because it definitely won't be the maximum. 4. append r pointer to deque 5. If the l pointer is greater than the index that points to the maximum value in deque (aka deque[0])(this means that maximum value in the deque has left the window. then we know we are out of bounds and can pop from the left of the deque using popLeft. 6. Now its finally ok to add to output and adjust pointers + setup edge case. 7. We will only increment left pointer and add leftmost value to output once the window is valid, aka r + 1 >= k. 8. increment right pointer. The explanation is long, code is simple af.

Kth Largest Element in a stream - Design a class to find the kth largest element in a stream. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Min Heap of size K - this is so the Kth largest will be on top. Anything smaller than k will not be placed on the heap (will be added and then popped with while loop), but things larger than k will be placed onto the heap because it will potentially change the Kth largest element. before in constructor, pop from mishap while size > k. After adding to heap, if the heap size is greater than K, pop so that the kth largest is on top.

132 pattern - Given an array of n integers nums, a 132 pattern is a subsequence of three integers nums[i], nums[j] and nums[k] such that i < j < k and nums[i] < nums[k] < nums[j]. Return true if there is a 132 pattern in nums, otherwise, return false.

Monotonically decreasing stack O(N), O(N)-- Stack will add values if the next value is less than the top, otherwise we will pop from the stack until this condition is true. The stack will also need to keep track of the minimum value that came before it for each value in the input array in order to find a valid solution for the problem so satisfy I < j < k s.t arr[I] <arr[k]<arr[j]. STACK Will CONTAIN PAIR, NUM AND MIN LEFT VAL. update min value when new value is added to stack. The basic idea is that we want the largest value on the stack so we can find a high enough j value since it must be the greatest. We can pop to get obtain this value. 1. Initially, minVal = nums[0] 2. for 3. while stack and top of stack is less than or equal to current value In array pop 4. if stack is now non empty and next value is less than top of stack (guaranteed by first condition) and is greater than minimum value to the left of the top of the stack [-1][1](PROBLEM CONDITION) Return true. 5. append to stack with current minimum, and then update current minimum. MIN VALUE LEFT SU

Reverse linked list

Move the chains diagonally, first by next = cur.next, cur.next = prev, etc.... return prev because cur will be null. Basic idea is to save a temporary ptr to the next value before flipping the direction of pointers

Merge K sorted lists - You are given an array of k linked-lists lists, each linked-list is sorted in ascending order. Merge all the linked-lists into one sorted linked-list and return it.

My solution O(K*N) time. Merge the first and the last lists and put into first, remove last, and repeat. Use solution to merge two lists. If not lists return None. NEETCODE O(logK * N). While len lists > 1, make a temporary variable for merged lists, for I in range(0, len, +2), merge the two adjacent lists and then append them to temproy variable, when the for loop exits update lists w temporary variable for exit while loop condition. Note that the second list may be out of bound so if I +1 > len lists set l2 = None. Important Note: If there are no lists, return None. (weird edge case) at first.

Add two numbers - You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself.

My solution involved adding and then reversing linked list but ended up being very convoluted. Here is Neetcodes solution: Edge Case station. Instead of while both lists are not NULL, we GO until EITHER list is STILL ALIVE (non null), If one of the lists is NULL, we assume it to still have a value of 0. then do normal elementary right to left addition. Remember 8 + 7 edge case, because there are no nodes left but still need to carry. WHILE L1 OR L2 OR CARRY: if l1 is not null v1 = l1.val else 0 same with l2, carry is total sum // 10 and val is total sum % 10, increment ptrs if non null else leave ptrs as None. Return dummy.next

Copy List w Random Pointer - A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null. Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list.

My solution: 1. Set a dummy node to copy list 2. Two data sctructures: 2a. Array of pointers to index into new pointers of new list to set random values. 2b. Hash map ptr->index of old list as to keep track of ptr/network orientation when adding in random values. 3. Go through the list and set p.next = the value of the old one, add ptr to hash map with index and append p to the index->ptr array of new copied list, increment curr(old map ptr) and p(new map ptr). 4. Assume last value is Null, so after loop finishes set, add Null to the hash map at index n, and add append Null to the array. 5. reset ptrs and go through list again this time adding random ptrs setting p.random = randArr[idxHashMap[curr.random]], 6. Return dummy.next. NEETCODE: Simply create a hashmap mapping old list to new list, and then copying each value, way easier lmao. Create new node and add to hash map in first while loop, and then add next and random values in second while loop. Main diff - neetcode does random and next together, I do random separate and next and val together.

Koko Eating Bananas (binary search) - Koko loves to eat bananas. There are n piles of bananas, the ith pile has piles[i] bananas. The guards have gone and will come back in h hours. Koko can decide her bananas-per-hour eating speed of k. Each hour, she chooses some pile of bananas and eats k bananas from that pile. If the pile has less than k bananas, she eats all of them instead and will not eat any more bananas during this hour. Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return. Return the minimum integer k such that she can eat all the bananas within h hours.

O(P*log(max(P)) -> L, R = 1, max(PILES) Run BINARY SEARCH on this range. 2. Mid is r + l // 2. 3. for each value in piles, divide it by k using / and then use math.ceil because we want to round up. Add these together and then determine if its less than the required rate or greater. Keep doing binary search to optimize, and return it. USE <= FOR BINARY SEARCH, not just <. You can ONLY update the output (minK) if the total time or sum <= required hours h given in parameter. During this case u also do r = k - 1. The else case is technically invalid so we have to update left pointer l = k + 1 to search for a valid value of k in a more likely window.

3 sum

O(n^2). Sort the input. Make sure to skip over duplicate values in outer for loop right away. if nums[k] ever becomes greater than 0 this means that we have already considered all values that will ever add to 0 so we can break. then two sum II with two pointers I = k+ 1, j = Len(nums) - 1. Move ptrs accordingly. DONT FORGET TO CONSIDER OTHER TRIPLETS WITH STARTING VALUE POINTED TO BY K. After adding to output, increment and decrement I and j respectively and check if its duplicate to previous value and while it is a duplicate keep incrementing/decrementing until we get completely different values for both not just one. WHY BOTH NOT JUST ONE? - Well, if we change one and keep to the same?? GUESS WHAT BY BASIC LOGIC THE SUM ISNT 0 anymore, alg will still work if one is only changed because sum won't be 0 lol.

Construct Binary Tree from Preorder and Inorder Traversal - Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and inorder is the inorder traversal of the same tree, construct and return the binary tree.

The first value in the pre order array is the head. Find the head in the in order array, and everything to left of the head in the inorder array will be partitioned to left and the size will be noted for recursively processing and popping from both arrays. BASE CASE: If either of the arrays are empty, simply return a null node. Root = preorder[0], mid = inorder.index(preorder[0]). root.left = buildTree(preorder[1:mid+1], inorder[:mid], root.right = buildTree(preorder[mid+1:], inorder[mid+1:] return root

Best Time to buy and sell stock with cooldown - You are given an array prices where prices[i] is the price of a given stock on the ith day. Find the maximum profit you can achieve. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times) with the following restrictions: After you sell your stock, you cannot buy stock on the next day (i.e., cooldown one day). Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

The index into the memo is (index, isBuying). Use neetcodes tree type solution things to reason it out. Do bottom up aka start at index 0 and have the base case be for when the index >= len.

Reverse Nodes in a K Group - Given the head of a linked list, reverse the nodes of the list k at a time, and return the modified list. k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as it is. You may not alter the values in the list's nodes, only nodes themselves may be changed.

The story of the New Years dog, rip Vinny. First hard I ever solved, efficiently too. I like my solution better than neetcode's. Create a reverse helper function that returns the new head and the next value it points to. Save the pointer to the first node. first go through k nodes and if it becomes null then return the original head and then NULL as second. Then once its determined that the nodes will fit into a K group, go ahead and reverse the linked list, setting old head.next = curr and then returning prev as the new head and also returning the old head. Then outside, use a dummy node because we don't know exactly what the head node will be at first. curr = dummy. While curr, curr.next, next = what's returned when calling reverse on curr.next, k. then set curr to the next value that's returned from helper, and then once that exits returns dummy.next

Linked List Cycle - Given head, the head of a linked list, determine if the linked list has a cycle in it. There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to. Note that pos is not passed as a parameter. Return true if there is a cycle in the linked list. Otherwise, return false.

Tortoise and hare. CHECK IF FAST = SLOW AFTER INCREMENTING FAST AND SLOW IN WHILE LOOP, aka make sure they don't equal each other on first iteration.

Best time to buy and sell stock I ou are given an array prices where prices[i] is the price of a given stock on the ith day. You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.

go through prices and update minprice and maxDifference. Two pointer solution: just point the left pointer to the minPrce

Validate BST: Implement a function to check if a binary tree is a binary search tree

helper(node, left, right) if node is null ret true if left and right not in between bounds return false. return helper(node.left, left, node.val) and helper(node.right, node.val, right) => return helper(root, -inf, +inf)

Maximum depth of Binary tree - Given the root of a binary tree, return its maximum depth. A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

if null 0 return 1 + max(recurse(left), recurse(right))


संबंधित स्टडी सेट्स

Biology Quiz 1 - Microbial Taxonomy and Fungi

View Set

Florida 4-40 Customer Representative (CIR) License - English

View Set

Techniques for Creating Suspense In Writing

View Set

CompTIA A+ Core 1: Installing Hardware & Display Components

View Set