├── ADT └── hashing.py ├── README.md ├── Grokk-Algos ├── a.out ├── ch04 ├── ch04.cpp ├── ch04.rs └── ch04.py ├── Algos_and_DS___Other_Notes.pdf ├── LinkedList ├── geeks │ ├── Linkedlist.png │ ├── Linked-List-Loop.gif │ ├── Linkedlist_deletion.png │ ├── Linkedlist_find_length.png │ ├── Linkedlist_insert_last.png │ ├── Linkedlist_insert_middle.png │ ├── Linkedlist_insert_at_start.png │ ├── notes.md │ ├── Part3.ipynb │ ├── Part2.ipynb │ └── Part1.ipynb ├── .ipynb_checkpoints │ ├── Part3-checkpoint.ipynb │ ├── Part2-checkpoint.ipynb │ └── Part1-checkpoint.ipynb ├── palindrom.py ├── reverseList.py ├── LinkedListCycle.py ├── FlattenDoublyLinkedList.py ├── IntersactionTwoLList.py ├── removedElement.py ├── AddTwoNumbers.py ├── oddEvenElements.py ├── LinkedListCycle2.py ├── RotateList.py ├── MergeTwoSortedLists.py ├── removeNthNodeEnd.py ├── practice.py ├── lc_notes.md └── DesignLinkedList.py ├── Testings ├── __pycache__ │ └── test_deque_speed.cpython-38-pytest-6.2.1.pyc └── test_deque_speed.py ├── august ├── day1.py ├── day2.py ├── day11.py ├── day3.py ├── test.py ├── day6.java ├── day4.py ├── day9.py └── day5.py ├── november ├── noboring.sql ├── validSquare.py ├── flipping.py └── permutation.py ├── Arrays ├── SquaresSortedArray.py ├── sortedSq.java ├── heightChecker.java ├── moveZeroes.java ├── sortArrayByParity.java ├── findDisappearedNums.java ├── replaceElement.java ├── thirdMax.java ├── mountainarray.java └── removeDups.java ├── codesignal ├── rotateImage.py ├── firstDuplicate.py └── firstNotRepeatingChar.py ├── september ├── day4.py ├── getNoZero.py ├── unique_email.py ├── baseball.py ├── delete_node.py ├── candies.py ├── chips.py ├── day3.py ├── checkIfExists.java ├── day11.java ├── day2.py ├── findLuck.java ├── day10.java ├── nextGreaterElement.java └── day9.java ├── October └── flipping.py ├── BinaryTree ├── constructBinaryTree.py ├── maxDepth.py ├── IsSymmetric.py ├── levelOrder.py ├── SimilarLeafs.py ├── targetSum.py ├── AllTraversals.py ├── notes.md └── BinarySearchTree │ └── BST.py ├── practical_solutions.py ├── Stack_Queue ├── notes.md └── CircularQueue.py ├── binary_search.py ├── DataStructures └── LinkedList.py ├── CHECKLIST.md ├── Leetcode_Question_Categories_and_Approaches_2020.html └── sorts.py /ADT/hashing.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LeetCoding 2 | Collection of LeetCode coding challenges #LeetCoding 3 | -------------------------------------------------------------------------------- /Grokk-Algos/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/Grokk-Algos/a.out -------------------------------------------------------------------------------- /Grokk-Algos/ch04: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/Grokk-Algos/ch04 -------------------------------------------------------------------------------- /Algos_and_DS___Other_Notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/Algos_and_DS___Other_Notes.pdf -------------------------------------------------------------------------------- /LinkedList/geeks/Linkedlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linkedlist.png -------------------------------------------------------------------------------- /LinkedList/geeks/Linked-List-Loop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linked-List-Loop.gif -------------------------------------------------------------------------------- /LinkedList/geeks/Linkedlist_deletion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linkedlist_deletion.png -------------------------------------------------------------------------------- /LinkedList/geeks/Linkedlist_find_length.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linkedlist_find_length.png -------------------------------------------------------------------------------- /LinkedList/geeks/Linkedlist_insert_last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linkedlist_insert_last.png -------------------------------------------------------------------------------- /LinkedList/.ipynb_checkpoints/Part3-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 4 6 | } 7 | -------------------------------------------------------------------------------- /LinkedList/geeks/Linkedlist_insert_middle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linkedlist_insert_middle.png -------------------------------------------------------------------------------- /LinkedList/geeks/Linkedlist_insert_at_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/LinkedList/geeks/Linkedlist_insert_at_start.png -------------------------------------------------------------------------------- /Testings/__pycache__/test_deque_speed.cpython-38-pytest-6.2.1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bexxmodd/LeetCoding/master/Testings/__pycache__/test_deque_speed.cpython-38-pytest-6.2.1.pyc -------------------------------------------------------------------------------- /august/day1.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def detectCapitalUse(self, word: str) -> bool: 3 | if word == word.lower() or word == word.upper() or word == word.title(): 4 | return True -------------------------------------------------------------------------------- /november/noboring.sql: -------------------------------------------------------------------------------- 1 | /* https://leetcode.com/problems/not-boring-movies/submissions/ */ 2 | 3 | SELECT * FROM cinema 4 | WHERE (id % 2 != 0) AND description != "boring"; 5 | ORDER BY rating DESC; -------------------------------------------------------------------------------- /Arrays/SquaresSortedArray.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/fun-with-arrays/523/conclusion/3574/ 2 | 3 | def sortedSquares(self, nums: List[int]) -> List[int]: 4 | sq_sorted = [i*i for i in nums] 5 | return sorted(sq_sorted) -------------------------------------------------------------------------------- /codesignal/rotateImage.py: -------------------------------------------------------------------------------- 1 | # https://app.codesignal.com/interview-practice/task/5A8jwLGcEpTPyyjTB 2 | 3 | def rotateImage(a): 4 | pass 5 | 6 | 7 | print(rotateImage([[1, 2, 3], 8 | [3, 5, 6], 9 | [7, 8, 9]])) -------------------------------------------------------------------------------- /september/day4.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def partitionLabels(self, S: str) -> list: 3 | labels = [] 4 | 5 | [ord(char) - 97 for char in raw_input('Write Text: ').lower()] 6 | 7 | sol = Solution() 8 | print(sol.partitionLabels("ababcbacadefegdehijhklij")) -------------------------------------------------------------------------------- /november/validSquare.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/challenge/card/november-leetcoding-challenge/565/week-2-november-8th-november-14th/3527/ 2 | import math 3 | 4 | class Solution: 5 | def validSquare(self, p1: list, p2: list, p3: list, p4: list) -> bool: 6 | pass 7 | 8 | def distance(self, p1: list, p2: list) -> boolean: 9 | return [p2[0] - p1[0], p2[1] - p1[1]] -------------------------------------------------------------------------------- /October/flipping.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/challenge/card/november-leetcoding-challenge/565/week-2-november-8th-november-14th/3526/ 2 | 3 | class Solution: 4 | def flipAndInvertImage(self, A: list) -> list: 5 | result = [] 6 | for row in A: 7 | row.reverse() 8 | image = [1 if i == 0 in row else 0 for i in row] 9 | result.append(image) 10 | return result -------------------------------------------------------------------------------- /november/flipping.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/challenge/card/november-leetcoding-challenge/565/week-2-november-8th-november-14th/3526/ 2 | 3 | class Solution: 4 | def flipAndInvertImage(self, A: list) -> list: 5 | result = [] 6 | for row in A: 7 | row.reverse() 8 | image = [1 if i == 0 in row else i ==1 for i in row] 9 | result.append(image) 10 | return result -------------------------------------------------------------------------------- /august/day2.py: -------------------------------------------------------------------------------- 1 | class MyHashSet: 2 | 3 | def __init__(self): 4 | self.values = [] 5 | 6 | def add(self, key): 7 | if key not in self.values: 8 | self.values.append(key) 9 | 10 | def remove(self, key): 11 | if key in self.values: 12 | self.values.remove(key) 13 | 14 | def contains(self, key): 15 | if key in self.values: 16 | return True 17 | -------------------------------------------------------------------------------- /codesignal/firstDuplicate.py: -------------------------------------------------------------------------------- 1 | # https://app.codesignal.com/interview-practice/task/pMvymcahZ8dY4g75q 2 | 3 | def firstDuplicate(a: list) -> int: 4 | duplicates = set() 5 | for i in a: 6 | if i in duplicates: 7 | return i 8 | else: 9 | duplicates.add(i) 10 | return -1 11 | 12 | 13 | print(firstDuplicate([2,1,3,4,3,2])) 14 | print(firstDuplicate([2,4,3,5])) 15 | print(firstDuplicate([2,2])) -------------------------------------------------------------------------------- /BinaryTree/constructBinaryTree.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/data-structure-tree/133/conclusion/942/ 2 | 3 | # Definition for a binary tree node. 4 | # class TreeNode: 5 | # def __init__(self, val=0, left=None, right=None): 6 | # self.val = val 7 | # self.left = left 8 | # self.right = right 9 | class Solution: 10 | def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: 11 | pass -------------------------------------------------------------------------------- /august/day11.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | 3 | def hIndex(self, citations): 4 | citations.sort() 5 | n = len(citations) 6 | for i in range(n): 7 | print(i) 8 | if citations[i] >= (n-i): 9 | print(citations[i]) 10 | return n-i 11 | return 0 12 | 13 | 14 | 15 | 16 | sss = [11, 15, 15, 22, 3, 5, 0, 22] 17 | obj = Solution() 18 | print(obj.hIndex(sss)) -------------------------------------------------------------------------------- /august/day3.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | 3 | def isPalindrome(self, s: str) -> bool: 4 | # Extract only alphanumerics from the string 5 | alphas = "".join([i.lower() for i in s if i.isalnum())]) 6 | return alphas == alphas[::-1] 7 | 8 | 9 | S = Solution() 10 | print(S.isPalindrome("A man, a plan, a canal: Panama")) 11 | print(S.isPalindrome("race a car")) 12 | print(S.isPalindrome("")) 13 | print(S.isPalindrome("baab")) 14 | print(S.isPalindrome("0P")) -------------------------------------------------------------------------------- /august/test.py: -------------------------------------------------------------------------------- 1 | def findShortestSubArray(nums) -> int: 2 | C = {} 3 | for i, n in enumerate(nums): 4 | if n in C: 5 | C[n].append(i) 6 | else: 7 | C[n] = [i] 8 | print(C) 9 | M = max([len(i) for i in C.values()]) 10 | print(M) 11 | return min([i[-1]-i[0] for i in C.values() if len(i) == M]) + 1 12 | 13 | 14 | print(findShortestSubArray([1,2,2,3,1,4,2])) 15 | print() 16 | print(findShortestSubArray([1,2,2,3,1])) 17 | -------------------------------------------------------------------------------- /codesignal/firstNotRepeatingChar.py: -------------------------------------------------------------------------------- 1 | # https://app.codesignal.com/interview-practice/task/uX5iLwhc6L5ckSyNC 2 | 3 | def firstNotRepeatingCharacter(s): 4 | for char in s: 5 | print(f'char:{char} s.index:{s.index(char)} == s.rindex:{s.rindex(char)}') 6 | if s.index(char) == s.rindex(char): 7 | return char 8 | return '_' 9 | 10 | 11 | print(firstNotRepeatingCharacter('abacabad')) # c 12 | print(firstNotRepeatingCharacter('abacabaabacaba')) # _ -------------------------------------------------------------------------------- /september/getNoZero.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/convert-integer-to-the-sum-of-two-no-zero-integers/ 2 | 3 | def getNoZeroIntegers(n: int) -> list: 4 | result = [0] * 2 5 | for i in range(0, n + 1): 6 | if str(i).count('0') == 0: 7 | remainder = n - i 8 | if str(remainder).count('0') == 0: 9 | result[0] = i 10 | result[1] = remainder 11 | return result 12 | 13 | print(getNoZeroIntegers(1010)) # [11, 999] -------------------------------------------------------------------------------- /august/day6.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Solution { 4 | public List findDuplicates(int[] nums) { 5 | 6 | List listOfNumbers = new ArrayList<>(); 7 | int[] duplicates = new int[nums.length]; 8 | for (int i = 0; i < nums.length; i++) { 9 | if (duplicates[nums[i] - 1] == 0) { 10 | duplicates[nums[i] - 1] = 1; 11 | } else { 12 | listOfNumbers.add(nums[i]); 13 | } 14 | } 15 | return listOfNumbers; 16 | } 17 | } -------------------------------------------------------------------------------- /BinaryTree/maxDepth.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/data-structure-tree/17/solve-problems-recursively/535/ 2 | 3 | # Definition for a binary tree node. 4 | class TreeNode: 5 | def __init__(self, val=0, left=None, right=None): 6 | self.val = val 7 | self.left = left 8 | self.right = right 9 | 10 | class Solution: 11 | 12 | def maxDepth(self, root: TreeNode) -> int: 13 | if not root: 14 | return 0 15 | 16 | return 1 + max(self.maxDepth(root.left), 17 | self.maxDepth(root.right)) -------------------------------------------------------------------------------- /practical_solutions.py: -------------------------------------------------------------------------------- 1 | def findShortestSubArray(nums): 2 | min_length = 0 3 | degree = 0 4 | count = {} 5 | first_seen = {} 6 | for i, n in enumerate(nums): 7 | if n not in first_seen: 8 | first_seen[n] = i 9 | count[n] = count.get(n, 0) + 1 10 | if count[n] > degree: 11 | degree = count[n] 12 | min_length = (i - first_seen[n]) + 1 13 | elif count[n] == degree: 14 | min_length = min(min_length, (i - first_seen[n]) + 1) 15 | return min_length 16 | 17 | print(findShortestSubArray([1,2,2,3,1,4,2]) -------------------------------------------------------------------------------- /Stack_Queue/notes.md: -------------------------------------------------------------------------------- 1 | # QUEUE - First-in-First-Out (FIFO) 2 | 3 | In a FIFO data structure, the first element added to the queue will be processed first: 4 | 5 | 1. *Enqueue*: A new element is added at the end of the Queue 6 | 2. *Dequeue*: The first element in the queue is removed. 7 | 8 | Efficient way to use Queue is to use a circular queue. We can use a fixed-size array and two pointers for tail and head. The goal is to reuse the wasted storage. 9 | 10 | ## Queue and BFS 11 | 12 | One common application Breadth-First Search (BFS) is to find the shortest path from the root node to the target node. -------------------------------------------------------------------------------- /september/unique_email.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numUniqueEmails(self, emails) -> int: 3 | dictionary = set() 4 | for email in emails: 5 | name, domain = email.split("@") 6 | wild_card = name.split("+")[0] 7 | new_name = ''.join(st for st in wild_card.split('.')) 8 | combined_name = new_name + '@' + domain 9 | dictionary.add(combined_name) 10 | return len(dictionary) 11 | 12 | 13 | s = Solution() 14 | print(s.numUniqueEmails(["test.email+alex@leetcode.com","test.e.mail+bob.cathy@leetcode.com","testemail+david@lee.tcode.com"])) -------------------------------------------------------------------------------- /binary_search.py: -------------------------------------------------------------------------------- 1 | def binary_search(data: list[int], 2 | target: int, 3 | low: int, 4 | high: int) -> int: 5 | if low > high: 6 | return -1 7 | else: 8 | mid = int((low + high) / 2) 9 | if target == data[mid]: 10 | return mid 11 | elif target < data[mid]: 12 | return binary_search(data, target, low, mid-1) 13 | else: 14 | return binary_search(data, target, mid+1, high) 15 | 16 | 17 | arr = [2, 3, 12, 5, 1, 9, 32 ,52, 45] 18 | arr.sort() 19 | print(binary_search(arr, 9, 0, len(arr))) 20 | -------------------------------------------------------------------------------- /august/day4.py: -------------------------------------------------------------------------------- 1 | # Given an integer (signed 32 bits), write a function to check whether it is a power of 4. 2 | 3 | import math 4 | 5 | class Solution: 6 | 7 | def isPowerOfFour(self, num: int) -> bool: 8 | if num <= 0: 9 | return False 10 | result = math.log(num, 4) 11 | return result.real.is_integer() 12 | 13 | 14 | # Test 15 | sol = Solution() 16 | print(sol.isPowerOfFour(16)) 17 | print(sol.isPowerOfFour(64)) 18 | print(sol.isPowerOfFour(-2147483648)) 19 | print(sol.isPowerOfFour(81)) 20 | print(sol.isPowerOfFour(0)) 21 | print(sol.isPowerOfFour(1)) 22 | print(sol.isPowerOfFour(4)) 23 | print(sol.isPowerOfFour(-81)) -------------------------------------------------------------------------------- /september/baseball.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://leetcode.com/problems/baseball-game/ 3 | 4 | """ 5 | 6 | class Solution(object): 7 | def calPoints(self, ops): 8 | stack = [] 9 | for op in ops: 10 | if op == '+': 11 | stack.append(stack[-1] + stack[-2]) 12 | elif op == 'C': 13 | stack.pop() 14 | elif op == 'D': 15 | stack.append(2 * stack[-1]) 16 | else: 17 | stack.append(int(op)) 18 | 19 | return sum(stack) 20 | 21 | sol = Solution() 22 | print(sol.calPoints(["5","2","C","D","+"])) 23 | print(sol.calPoints(["5","-2","4","C","D","9","+","+"])) -------------------------------------------------------------------------------- /LinkedList/palindrom.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/219/classic-problems/1209/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, val=0, next=None): 6 | # self.val = val 7 | # self.next = next 8 | 9 | class Solution: 10 | def isPalindrome(self, head: ListNode) -> bool: 11 | values = [] 12 | current = head 13 | while current: 14 | # Append values of the linked list to regular list 15 | values.append(current.val) 16 | current = current.next 17 | # Check if current list and reversed list are equal 18 | return values == values[::-1] 19 | -------------------------------------------------------------------------------- /LinkedList/reverseList.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/219/classic-problems/1205/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, val=0, next=None): 6 | # self.val = val 7 | # self.next = next 8 | 9 | class Solution: 10 | def reverseList(self, head: ListNode) -> ListNode: 11 | if head is None or head.next is None: 12 | return head 13 | 14 | current = head.next 15 | prev = head 16 | while current: 17 | nex = current.next 18 | current.next = prev 19 | prev = current 20 | current = nex 21 | head = prev 22 | return head -------------------------------------------------------------------------------- /Arrays/sortedSq.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/511/in-place-operations/3261/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] A = {-4,-1,0,3,10}; 9 | 10 | int[] Sol = Solution.sortedSquares(A); 11 | for (Integer a: Sol) { 12 | System.out.print(a + ", "); 13 | } 14 | } 15 | } 16 | 17 | class Solution { 18 | public static int[] sortedSquares(int[] A) { 19 | int[] sortedSq = new int[A.length]; 20 | 21 | for (int i = 0; i < A.length; i++) { 22 | sortedSq[i] = A[i] * A[i]; 23 | } 24 | Arrays.sort(sortedSq); 25 | return sortedSq; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /september/delete_node.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://leetcode.com/problems/delete-node-in-a-linked-list/ 3 | 4 | Example: 5 | 6 | Input: head = [4,5,1,9], n = 1 7 | Output: [4,5,9] 8 | Explanation: You are given the third node with value 1, the linked list should become 4 -> 5 -> 9 after calling your function. 9 | """ 10 | 11 | # class ListNode: 12 | # def __init__(self, x): 13 | # self.val = x 14 | # self.next = None 15 | 16 | class Solution: 17 | def deleteNode(self, node): 18 | """ 19 | :type node: ListNode 20 | :rtype: void Do not return anything, modify node in-place instead. 21 | """ 22 | if node.next is not None: 23 | node.val, node.next = node.next.val, node.next.next 24 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/214/two-pointer-technique/1212/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, x): 6 | # self.val = x 7 | # self.next = None 8 | 9 | class Solution: 10 | def hasCycle(self, head: ListNode) -> bool: 11 | if head is None: 12 | return False 13 | fast_node = head 14 | current = head 15 | while current: 16 | if fast_node.next is None or fast_node.next.next is None: 17 | return False 18 | current = current.next 19 | fast_node = fast_node.next.next 20 | if current == fast_node: 21 | return True -------------------------------------------------------------------------------- /september/candies.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def distributeCandies(self, 3 | candies: int, 4 | num_people: int) -> list: 5 | people = [0] * num_people 6 | people[0] = 1 7 | candz = candies 8 | while True: 9 | for i in range(len(people)): 10 | if candz <= 0: 11 | break 12 | people[i] = people[i - 1] + 1 13 | candz -= people[i] 14 | print(people, candz) 15 | if candz < 0: 16 | break 17 | return people 18 | 19 | if __name__ == '__main__': 20 | sol = Solution() 21 | print(sol.distributeCandies(7, 4)) 22 | print(sol.distributeCandies(10, 3)) 23 | -------------------------------------------------------------------------------- /august/day9.py: -------------------------------------------------------------------------------- 1 | def orangesRotting(grid) -> int: 2 | x, y = 0, 0 3 | matrix_size = len(grid) * len(grid[0]) 4 | oranges = [] 5 | minutes = 0 6 | count = 0 7 | for i in range(len(grid)): 8 | for j in range(len(grid[i])): 9 | if grid[i][j] == 2: 10 | x, y = i, j 11 | if grid[i][j] == 1: 12 | oranges.append([i, j]) 13 | 14 | while (count < matrix_size): 15 | x_copy, y_copy = x, y 16 | if x == 0: 17 | if grid[x + 1][y] == 1: 18 | grid[x + 1][y] = 2 19 | x += 1 20 | minutes += 1 21 | if grid[x - 1] 22 | print(minutes) 23 | 24 | 25 | orangesRotting([[2,1,1],[1,1,0],[0,1,1]]) 26 | orangesRotting([[2,1,1],[0,1,1],[1,0,1]]) 27 | orangesRotting([0,2]) -------------------------------------------------------------------------------- /Arrays/heightChecker.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/523/conclusion/3228/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] A = {1,1,4,2,1,3}; 9 | 10 | System.out.println(Solution.heightChecker(A)); 11 | } 12 | } 13 | 14 | class Solution { 15 | public static int heightChecker(int[] heights) { 16 | int[] sortedHeights = new int[heights.length]; 17 | sortedHeights = Arrays.copyOf(heights, heights.length); 18 | Arrays.sort(sortedHeights); 19 | 20 | int diff = 0; 21 | for (int i = 0; i < heights.length; i++) { 22 | if (heights[i] != sortedHeights[i]) { 23 | diff++; 24 | } 25 | } 26 | return diff; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /september/chips.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://leetcode.com/problems/minimum-cost-to-move-chips-to-the-same-position/ 3 | """ 4 | 5 | class Solution: 6 | 7 | def minCostToMoveChips(self, position) -> int: 8 | table = dict() 9 | for i in position: 10 | if i not in table: 11 | table[i] = 1 12 | else: 13 | table[i] += 1 14 | moving_towards = 0 15 | for i in table: 16 | if table[i] > moving_towards: 17 | moving_towards = table[i] 18 | 19 | for i in table: 20 | if table[i] > moving_towards: 21 | diff = table[i] - moving_towards 22 | 23 | 24 | 25 | 26 | s = Solution() 27 | print('[1,2,3] -->', s.minCostToMoveChips([1,2,3])) 28 | print('[2,2,2,3,3] --> ', s.minCostToMoveChips([2,2,2,3,3])) -------------------------------------------------------------------------------- /BinaryTree/IsSymmetric.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/data-structure-tree/17/solve-problems-recursively/536/ 2 | 3 | # Definition for a binary tree node. 4 | class TreeNode: 5 | def __init__(self, val=0, left=None, right=None): 6 | self.val = val 7 | self.left = left 8 | self.right = right 9 | 10 | class Solution: 11 | def isSymmetric(self, root: TreeNode) -> bool: 12 | if not root: 13 | return False 14 | return self.is_symmetric(root.left, root.right) 15 | 16 | def is_symmetric(self, a: TreeNode, b: TreeNode) -> bool: 17 | if not a and not b: 18 | return True 19 | if not a or not b: 20 | return False 21 | return (a.val == b.val) \ 22 | and self.is_symmetric(a.left, b.right) \ 23 | and self.is_symmetric(a.right, b.left) 24 | 25 | 26 | -------------------------------------------------------------------------------- /Arrays/moveZeroes.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/move-zeroes/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] nums = {0,1,0,3,12}; // 5 9 | 10 | Solution.moveZeroes(nums); 11 | for (Integer s: nums) { 12 | System.out.print(s + ", "); 13 | } 14 | } 15 | } 16 | 17 | class Solution { 18 | public static void moveZeroes(int[] nums) { 19 | int lastNonZeroIndex = 0; 20 | 21 | // Append all non zero elements in the last non 22 | // zero place 23 | for (int i = 0; i < nums.length; i++) { 24 | if (nums[i] != 0) { 25 | nums[lastNonZeroIndex++] = nums[i]; 26 | } 27 | } 28 | // Fill the remaining places with zeros 29 | for (int i = lastNonZeroIndex; i < nums.length; i++) { 30 | nums[i] = 0; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LinkedList/FlattenDoublyLinkedList.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/213/conclusion/1225/ 2 | 3 | # Definition for a Node. 4 | # class Node: 5 | # def __init__(self, val, prev, next, child): 6 | # self.val = val 7 | # self.prev = prev 8 | # self.next = next 9 | # self.child = child 10 | from collections import deque 11 | 12 | class Solution: 13 | def flatten(self, head: 'Node') -> 'Node': 14 | tmp = head 15 | stack = deque() 16 | while head: 17 | if head.child: 18 | if head.next: stack.appendleft(head.next) 19 | head.next = head.child 20 | head.next.prev = head 21 | head.child = None 22 | elif head.next is None and len(stack) > 0: 23 | head.next = stack.popleft() 24 | head.next.prev = head 25 | head = head.next 26 | return tmp 27 | -------------------------------------------------------------------------------- /LinkedList/IntersactionTwoLList.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/214/two-pointer-technique/1215/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, x): 6 | # self.val = x 7 | # self.next = None 8 | 9 | class Solution: 10 | def getIntersectionNode( 11 | self, headA: ListNode, headB: ListNode) -> ListNode: 12 | d = {} 13 | curA = headA 14 | curB = headB 15 | 16 | # Add first linked list nodes in dict 17 | while curA: 18 | if curA in d: 19 | continue 20 | else: 21 | d[curA] = curA.val 22 | curA = curA.next 23 | 24 | # Traverse through the second llist 25 | # if nodes are equal that's your intersaction node 26 | while curB: 27 | if curB in d: 28 | return curB 29 | else: 30 | curB = curB.next 31 | 32 | return None 33 | -------------------------------------------------------------------------------- /LinkedList/removedElement.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/219/classic-problems/1207/ 2 | 3 | # Definition for singly-linked list. 4 | class ListNode: 5 | def __init__(self, val=0, next=None): 6 | self.val = val 7 | self.next = next 8 | 9 | class Solution: 10 | def removeElements(self, head: ListNode, val: int) -> ListNode: 11 | # Create a dummy Nodw who's next node is current head 12 | dummy = ListNode(next=head) 13 | prev = dummy 14 | current = dummy.next 15 | while current: 16 | # if current equals value remove node 17 | # by linking its next to previous' next 18 | if current.val == val: 19 | prev.next = current.next 20 | 21 | # if value is not equal current node move 22 | # both curr and prev to the next 23 | else: 24 | prev = prev.next 25 | current = current.next 26 | return dummy.next -------------------------------------------------------------------------------- /BinaryTree/levelOrder.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/data-structure-tree/134/traverse-a-tree/931/ 2 | 3 | # Definition for a binary tree node. 4 | class TreeNode: 5 | def __init__(self, val=0, left=None, right=None): 6 | self.val = val 7 | self.left = left 8 | self.right = right 9 | 10 | from collections import deque 11 | 12 | class Solution: 13 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 14 | values = [] 15 | if not root: 16 | return values 17 | 18 | queue = deque([root]) 19 | while queue: 20 | current_level = [] 21 | for i in range(len(queue)): 22 | node = queue.popleft() # top node in queue 23 | if node.left: 24 | queue.append(node.left) 25 | if node.right: 26 | queue.append(node.right) 27 | current_level.append(node.val) 28 | values.append(current_level) 29 | return values -------------------------------------------------------------------------------- /Arrays/sortArrayByParity.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/511/in-place-operations/3260/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] A = {3,1,2,4}; // 5 9 | 10 | int[] Sol = Solution.sortArrayByParity(A); 11 | for (Integer a: Sol) { 12 | System.out.print(a + ", "); 13 | } 14 | } 15 | } 16 | 17 | class Solution { 18 | public static int[] sortArrayByParity(int[] A) { 19 | int[] sorted = new int[A.length]; 20 | int evenPointer = 0; 21 | int oddPointer = A.length - 1; 22 | 23 | for (int i = 0; i < A.length; i++) { 24 | // Append evens from the start 25 | // Evens from the ned 26 | if (A[i] % 2 == 0) { 27 | sorted[evenPointer++] = A[i]; 28 | } else { 29 | sorted[oddPointer--] = A[i]; 30 | } 31 | } 32 | return sorted; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Grokk-Algos/ch04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | concept Comparable = requires (T a, T b) { a < b; b < a; }; 8 | 9 | template 10 | int binary_search(int target, std::vector& array) { 11 | if (array.empty()) 12 | return -1; 13 | int mid = array.size() / 2; 14 | if (array[mid] == target) 15 | return mid; 16 | else if (array[mid] < target) { 17 | std::vector sub(array.begin(), array.begin() + mid); 18 | return binary_search(target, sub); 19 | } else { 20 | std::vector sub(array.begin() + mid, array.end()); 21 | return binary_search(target, sub); 22 | } 23 | } 24 | 25 | int main() { 26 | std::vector vec{}; 27 | vec.push_back(1); 28 | vec.push_back(2); 29 | vec.push_back(3); 30 | vec.push_back(4); 31 | vec.push_back(6); 32 | vec.push_back(8); 33 | std::cout << binary_search(3, vec) << std::endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Arrays/findDisappearedNums.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/523/conclusion/3270/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] A = {4,3,2,7,8,2,3,1}; 9 | int[] B = {5, 2, 2}; 10 | 11 | System.out.println(Solution.findDisappearedNumbers(A)); // [5, 6] 12 | // System.out.println(Solution.findDisappearedNumbers(B)); // 5 13 | } 14 | } 15 | 16 | class Solution { 17 | public static List findDisappearedNumbers(int[] nums) { 18 | List disaps = new ArrayList<>(); 19 | 20 | for (int i = 0; i < nums.length; i++) { 21 | int val = Math.abs(nums[i]) - 1; 22 | if (nums[val] > 0) { 23 | nums[val] = -nums[val]; 24 | } 25 | } 26 | for (int i = 0; i < nums.length; i++) { 27 | if (nums[i] > 0) { 28 | disaps.add(i + 1); 29 | } 30 | } 31 | return disaps; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LinkedList/AddTwoNumbers.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/213/conclusion/1228/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, val=0, next=None): 6 | # self.val = val 7 | # self.next = next 8 | 9 | class Solution: 10 | def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: 11 | tmp = ListNode() 12 | curr = tmp 13 | first = l1 14 | second = l2 15 | carry = 0 16 | while first or second: 17 | x = 0 18 | y = 0 19 | if first: 20 | x = first.val 21 | if second: 22 | y = second.val 23 | total = x + y + carry 24 | carry = total // 10 25 | curr.next = ListNode(total % 10) 26 | curr = curr.next 27 | if first: 28 | first = first.next 29 | if second: 30 | second = second.next 31 | if carry > 0: 32 | curr.next = ListNode(carry) 33 | return tmp.next -------------------------------------------------------------------------------- /BinaryTree/SimilarLeafs.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/leaf-similar-trees/ 2 | 3 | # Definition for a binary tree node. 4 | # class TreeNode: 5 | # def __init__(self, val=0, left=None, right=None): 6 | # self.val = val 7 | # self.left = left 8 | # self.right = right 9 | 10 | from collections import deque 11 | 12 | class Solution: 13 | def leafSimilar(self, root1: TreeNode, root2: TreeNode) -> bool: 14 | values1, values2 = [], [] 15 | self.dfs(root1, values1) 16 | self.dfs(root2, values2) 17 | return values1 == values2 18 | 19 | def dfs(self, p: TreeNode, values: list): 20 | stack = deque() 21 | stack.append(p) 22 | while stack: 23 | curr = stack.pop() 24 | if self.is_leaf(curr): 25 | values.append(curr.val) 26 | if curr.left: 27 | stack.append(curr.left) 28 | if curr.right: 29 | stack.append(curr.right) 30 | 31 | def is_leaf(self, p: TreeNode) -> bool: 32 | return not p.left and not p.right -------------------------------------------------------------------------------- /september/day3.py: -------------------------------------------------------------------------------- 1 | """Given a non-empty string check if it can be constructed by taking a substring 2 | of it and appending multiple copies of the substring together. You may assume the given 3 | string consists of lowercase English letters only and its length will not exceed 10000. 4 | 5 | Example 1: 6 | 7 | Input: "abab" 8 | Output: True 9 | Explanation: It's the substring "ab" twice. 10 | """ 11 | 12 | class Solution: 13 | 14 | def repeatedSubstringPattern(self, s: str) -> bool: 15 | n = len(s) 16 | if n == 1: return False 17 | 18 | for i in range(1, n): 19 | if n % i == 0: 20 | if s == s[:i] * (n // i): 21 | return True 22 | return False 23 | 24 | 25 | 26 | sol = Solution() 27 | print(sol.repeatedSubstringPattern("abab")) # True 28 | print(sol.repeatedSubstringPattern("aba")) # False 29 | print(sol.repeatedSubstringPattern("ababba")) # False 30 | print(sol.repeatedSubstringPattern("abcabcabcabc")) # True 31 | 32 | 33 | # print(f"s[:{i}] --> {s[:i]} * {n} // {i} --> {n // i} will equal: {s[:i] * (n // i)}") -------------------------------------------------------------------------------- /november/permutation.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/challenge/card/november-leetcoding-challenge/565/week-2-november-8th-november-14th/3528/ 2 | class Solution: 3 | 4 | def permuteUnique(self, nums: List[int]) -> List[List[int]]: 5 | results = [] 6 | 7 | def backtrack(comb, counter): 8 | if len(comb) == len(nums): 9 | # make a deep copy of the resulting permutation, 10 | # since the permutation would be backtracked later. 11 | results.append(list(comb)) 12 | return 13 | 14 | for num in counter: 15 | if counter[num] > 0: 16 | # add this number into the current combination 17 | comb.append(num) 18 | counter[num] -= 1 19 | # continue the exploration 20 | backtrack(comb, counter) 21 | # revert the choice for the next exploration 22 | comb.pop() 23 | counter[num] += 1 24 | 25 | backtrack([], Counter(nums)) 26 | 27 | return results -------------------------------------------------------------------------------- /BinaryTree/targetSum.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/data-structure-tree/17/solve-problems-recursively/537/ 2 | 3 | # Definition for a binary tree node. 4 | # class TreeNode: 5 | # def __init__(self, val=0, left=None, right=None): 6 | # self.val = val 7 | # self.left = left 8 | # self.right = right 9 | 10 | from collections import deque 11 | 12 | class Solution: 13 | # DFS with stack 14 | def hasPathSum(self, root: TreeNode, targetSum: int) -> bool: 15 | if not root: 16 | return False 17 | stack = deque() 18 | stack.appendleft((root, root.val)) 19 | while stack: 20 | curr, value = stack.popleft() 21 | if self.is_leaf(curr) and value == targetSum: 22 | return True 23 | if curr.left: 24 | stack.appendleft((curr.left, value+curr.left.val)) 25 | if curr.right: 26 | stack.appendleft((curr.right, value+curr.right.val)) 27 | return False 28 | 29 | def is_leaf(self, p: TreeNode) -> bool: 30 | return not p.left and not p.right 31 | 32 | -------------------------------------------------------------------------------- /LinkedList/oddEvenElements.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/219/classic-problems/1208/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, val=0, next=None): 6 | # self.val = val 7 | # self.next = next 8 | 9 | class Solution: 10 | def oddEvenList(self, head: ListNode) -> ListNode: 11 | # Sanity check 12 | if head is None or head.next is None: 13 | return head 14 | 15 | # First node will be start of a linked list with odd nodes 16 | # Second node will start a linked list with even nodes 17 | odds, evens = head, head.next 18 | 19 | # Keep track of head of the evens as it will be attached 20 | # to the linked list with odd nodes 21 | evens_head = evens 22 | 23 | while evens and evens.next: 24 | odds.next = evens.next 25 | odds = odds.next 26 | evens.next = odds.next 27 | evens = evens.next 28 | 29 | # Attach the head of evens to the tail of odds 30 | odds.next = evens_head 31 | return head -------------------------------------------------------------------------------- /Arrays/replaceElement.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/511/in-place-operations/3259/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] arr = {17,18,5,4,6,1}; 9 | 10 | for (Integer i: Solution.replaceElements(arr)) { 11 | System.out.print(">"); 12 | System.out.print(i + ", "); 13 | } 14 | } 15 | } 16 | 17 | class Solution { 18 | public static int[] replaceElements(int[] arr) { 19 | int maxValue = arr[arr.length - 1]; 20 | for (int i = arr.length - 1; i >= 0; i--) { 21 | // Put current value in a temp value 22 | int temp = arr[i]; 23 | 24 | // assign to current value max value encountered before 25 | arr[i] = maxValue; 26 | 27 | // If temp/current value > max value, this becomes max value 28 | if (temp > maxValue) { 29 | maxValue = temp; 30 | } 31 | } 32 | // replace last number with -1 33 | arr[arr.length - 1] = -1; 34 | return arr; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle2.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/214/two-pointer-technique/1214/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, x): 6 | # self.val = x 7 | # self.next = None 8 | ''' 9 | This method uses Floyd's Algorithm to detect 10 | the first node where the cycle starts. 11 | ''' 12 | 13 | class Solution: 14 | 15 | def detectCycle(self, head: ListNode) -> ListNode: 16 | """Detects if we have a cycle""" 17 | fast = slow = head 18 | while fast and fast.next: 19 | fast = fast.next.next 20 | slow = slow.next 21 | if fast == slow: 22 | return self.find_cycle_start(head, fast) 23 | return None 24 | 25 | def find_cycle_start(self, head, intersect): 26 | """Finds the Node where a cycle starts""" 27 | while True: 28 | # check first, then move pointers 29 | if head == intersect: 30 | return head 31 | 32 | head = head.next 33 | intersect = intersect.next 34 | return None -------------------------------------------------------------------------------- /LinkedList/RotateList.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/213/conclusion/1295/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, val=0, next=None): 6 | # self.val = val 7 | # self.next = next 8 | 9 | class Solution: 10 | def rotateRight(self, head: ListNode, k: int) -> ListNode: 11 | if not head: return head 12 | tail = head 13 | 14 | # Calculate length but start with 1 as the loop'll 15 | # stop just before the last value in the linked list 16 | length = 1 17 | while tail.next: 18 | length += 1 19 | tail = tail.next 20 | 21 | # Check if the k exceeds the number of nodes no 22 | # no need to run extra cycle 23 | k %= length 24 | if k == 0: return head 25 | 26 | # New head will start from length - k 27 | start_pointer = length - k 28 | tail.next = head 29 | while start_pointer > 0: 30 | tail = tail.next 31 | start_pointer -= 1 32 | 33 | new_head = tail.next 34 | tail.next = None 35 | return new_head -------------------------------------------------------------------------------- /september/checkIfExists.java: -------------------------------------------------------------------------------- 1 | /* https://leetcode.com/explore/learn/card/fun-with-arrays/527/searching-for-items-in-an-array/3250/ */ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] arr = {10,2,5,3}; 9 | int[] arr2 = {7,1,14,11}; 10 | int[] arr3 = {3,1,7,11}; 11 | int[] arr4 = {-10,12,-20,-8,15}; 12 | int[] arr5 = {-2,0,10,-19,4,6,-8}; 13 | 14 | System.out.println(Solution.checkIfExist(arr)); 15 | System.out.println(Solution.checkIfExist(arr2)); 16 | System.out.println(Solution.checkIfExist(arr3)); 17 | System.out.println(Solution.checkIfExist(arr4)); 18 | System.out.println(Solution.checkIfExist(arr5)); 19 | } 20 | } 21 | 22 | class Solution { 23 | 24 | public static boolean checkIfExist(int[] arr) { 25 | 26 | for (int i = 0; i < arr.length ; i++) { 27 | for (int j = 0; j < arr.length; j++) { 28 | if (arr[i] == arr[j] * 2 29 | && i != j) { 30 | return true; 31 | } 32 | } 33 | } 34 | return false; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LinkedList/MergeTwoSortedLists.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/213/conclusion/1227/ 2 | 3 | # Definition for singly-linked list. 4 | # class ListNode: 5 | # def __init__(self, val=0, next=None): 6 | # self.val = val 7 | # self.next = next 8 | 9 | class Solution: 10 | def rotateRight(self, head: ListNode, k: int) -> ListNode: 11 | if not head: return head 12 | tail = head 13 | 14 | # Calculate length but start with 1 as the loop'll 15 | # stop just before the last value in the linked list 16 | length = 1 17 | while tail.next: 18 | length += 1 19 | tail = tail.next 20 | 21 | # Check if the k exceeds the number of nodes no 22 | # no need to run extra cycle 23 | k %= length 24 | if k == 0: return head 25 | 26 | # New head will start from length - k 27 | start_pointer = length - k 28 | tail.next = head 29 | while start_pointer > 0: 30 | tail = tail.next 31 | start_pointer -= 1 32 | 33 | new_head = tail.next 34 | tail.next = None 35 | return new_head -------------------------------------------------------------------------------- /Arrays/thirdMax.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/523/conclusion/3231/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] A = {2, 2, 3, 1}; 9 | int[] B = {5, 2, 2}; 10 | int[] J = {3, 2, 1}; 11 | int[] C = {1, 2, 2, 5, 3, 1}; 12 | 13 | System.out.println(Solution.thirdMax(A)); // 1 14 | System.out.println(Solution.thirdMax(B)); // 5 15 | System.out.println(Solution.thirdMax(J)); // 1 16 | System.out.println(Solution.thirdMax(C)); // 2 17 | } 18 | } 19 | 20 | class Solution { 21 | public static int thirdMax(int[] nums) { 22 | if (nums.length < 3) { 23 | return Math.max(nums[0], nums[1]); 24 | } 25 | Arrays.sort(nums); 26 | int thirdMax = 0; 27 | int counter = 1; 28 | for (int i = nums.length - 2; i >= 0; i--) { 29 | if (nums[i] < nums[i + 1]) { 30 | thirdMax = nums[i]; 31 | counter++; 32 | } 33 | if (counter == 3) { 34 | return thirdMax; 35 | } 36 | } 37 | return nums[nums.length - 1]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /september/day11.java: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/explore/challenge/card/september-leetcoding-challenge/555/week-2-september-8th-september-14th/3456/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] nums1 = {2, 3, -2, 4}; 9 | System.out.println(Solution.maxProduct(nums1)); 10 | 11 | int[] nums2 = {-2, 0, -1}; 12 | System.out.println(Solution.maxProduct(nums2)); 13 | } 14 | } 15 | 16 | class Solution { 17 | public static int maxProduct(int[] nums) { 18 | int[] max = new int[nums.length]; 19 | int[] min = new int[nums.length]; 20 | 21 | max[0] = min[0] = nums[0]; 22 | int result = nums[0]; 23 | 24 | for (int i = 1; i < nums.length; i++) { 25 | if (nums[i] > 0) { 26 | max[i] = Math.max(nums[i], max[i - 1] * nums[i]); 27 | min[i] = Math.min(nums[i], min[i - 1] * nums[i]); 28 | } else { 29 | max[i] = Math.max(nums[i], min[i - 1] * nums[i]); 30 | min[i] = Math.min(nums[i], max[i - 1] * nums[i]); 31 | } 32 | 33 | if (max[i] > result) { 34 | result = max[i]; 35 | } 36 | } 37 | return result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /september/day2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of integers, find out whether there are 3 | two distinct indices i and j in the array such that the 4 | absolute difference between nums[i] and nums[j] is at most t 5 | and the absolute difference between i and j is at most k. 6 | 7 | 8 | Example 1: 9 | 10 | Input: nums = [1,2,3,1], k = 3, t = 0 11 | Output: true 12 | """ 13 | 14 | class Solution: 15 | def containsNearbyAlmostDuplicate(self, nums: list, k: int, t: int) -> bool: 16 | if t == 0 and len(nums) == len(set(nums)): 17 | return False 18 | for i in range(len(nums)): 19 | for j in range(i + 1, i + k + 1): 20 | if j >= len(nums): 21 | break 22 | if abs(nums[i] - nums[j]) <= t: 23 | return True 24 | return False 25 | 26 | # Test solution 27 | s = Solution() 28 | print(s.containsNearbyAlmostDuplicate(nums = [1,2,3,1], k = 3, t = 0)) 29 | print(s.containsNearbyAlmostDuplicate(nums = [1,0,1,1], k = 1, t = 2)) 30 | print(s.containsNearbyAlmostDuplicate(nums = [1,5,9,1,5,9], k = 2, t = 3)) 31 | print(s.containsNearbyAlmostDuplicate(nums = [-1, -1], k = 1, t = -1)) 32 | print(s.containsNearbyAlmostDuplicate(nums = [1, 2, 3, 1], k = 3, t = 0)) 33 | print(s.containsNearbyAlmostDuplicate(nums = [-3, 3], k = 2, t = 4)) 34 | -------------------------------------------------------------------------------- /september/findLuck.java: -------------------------------------------------------------------------------- 1 | /* https://leetcode.com/problems/find-lucky-integer-in-an-array/ */ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] arr1 = {2,2,3,4}; 9 | int[] arr2 = {1,2,2,3,3,3}; 10 | int[] arr3 = {2,2,2,3,3}; 11 | int[] arr4 = {1,2,2,3,3,3,4}; 12 | List arrays = new ArrayList<>(); 13 | arrays.add(arr1); 14 | arrays.add(arr2); 15 | arrays.add(arr3); 16 | arrays.add(arr4); 17 | for (int[] a: arrays) { 18 | System.out.println(Solution.findLucky(a)); 19 | } 20 | } 21 | } 22 | 23 | class Solution { 24 | 25 | public static int findLucky(int[] arr) { 26 | int lucky = -1; 27 | HashMap numbers = new HashMap<>(); 28 | for (Integer i: arr) { 29 | if (numbers.containsKey(i)) { 30 | numbers.put(i, numbers.get(i) + 1); 31 | } else { 32 | numbers.put(i, 1); 33 | } 34 | } 35 | 36 | for (int key: numbers.keySet()) { 37 | System.out.println("key: " + key + " value: " + numbers.get(key)); 38 | if (key == numbers.get(key) 39 | && key > lucky) { 40 | lucky = key; 41 | } 42 | } 43 | return lucky; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Arrays/mountainarray.java: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/valid-mountain-array/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] arr = {2,1}; 9 | int[] arr2 = {3,5,5}; 10 | int[] arr3 = {0,3,2,1}; 11 | int[] arr4 = {-10,12,-20,-8,15}; 12 | int[] arr5 = {-2,0,10,-19,4,6,-8}; 13 | int[] arr6 = {1,3,4,5,6,4,3,1}; 14 | 15 | System.out.println(Solution.validMountainArray(arr)); 16 | System.out.println(Solution.validMountainArray(arr2)); 17 | System.out.println(Solution.validMountainArray(arr3)); 18 | System.out.println(Solution.validMountainArray(arr4)); 19 | System.out.println(Solution.validMountainArray(arr5)); 20 | System.out.println(Solution.validMountainArray(arr6)); 21 | } 22 | } 23 | 24 | class Solution { 25 | public static boolean validMountainArray(int[] A) { 26 | // check if A has a valid length 27 | int N = A.length; 28 | int i = 0; 29 | 30 | // walk up 31 | while (i + 1 < N && A[i] < A[i + 1]) { 32 | i++; 33 | } 34 | 35 | // peak can't be first of last 36 | if (i == 0 || i == N - 1) { 37 | return false; 38 | } 39 | 40 | // walk down 41 | while (i + 1 < N && A[i] > A[i + 1]) { 42 | i++; 43 | } 44 | 45 | return i == N - 1; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LinkedList/removeNthNodeEnd.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/linked-list/214/two-pointer-technique/1296/ 2 | 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 | 10 | class Solution: 11 | def removeNthFromEnd( 12 | self, head: ListNode, n: int) -> ListNode: 13 | if head is None: 14 | return None 15 | 16 | size = self.get_size(head) 17 | if n > size or n < -1 or size == 1: 18 | return None 19 | 20 | # As we have size the nth node from the back will be 21 | # (size - n + 1)th node from the start 22 | # remove 1 as the index starts from 0 23 | index = size - n 24 | curr = head 25 | 26 | # Remove if the nth node ends up being head 27 | if index == 0: 28 | curr = curr.next 29 | return curr 30 | 31 | # Iterate until we reach nth node 32 | for i in range(index - 1): 33 | curr = curr.next 34 | 35 | # Remove nth node 36 | curr.next = curr.next.next 37 | return head 38 | 39 | def get_size(self, head: ListNode) -> int: 40 | if head is None: 41 | return None 42 | size = 0 43 | tmp = head 44 | while tmp: 45 | tmp = tmp.next 46 | size += 1 47 | return size -------------------------------------------------------------------------------- /Stack_Queue/CircularQueue.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/queue-stack/228/first-in-first-out-data-structure/1337/ 2 | 3 | class MyCircularQueue: 4 | 5 | def __init__(self, k: int): 6 | self.queue = [None] * k 7 | self.head = None 8 | self.tail = None 9 | self.size = 0 10 | 11 | def enQueue(self, value: int) -> bool: 12 | if self.size == len(self.queue): 13 | return False 14 | 15 | 16 | 17 | def deQueue(self) -> bool: 18 | pass 19 | 20 | def Front(self) -> int: 21 | if self.head: 22 | return self.head 23 | else: 24 | return -1 25 | 26 | def Rear(self) -> int: 27 | if self.tail: 28 | return self.tail 29 | else: 30 | return -1 31 | 32 | def isEmpty(self) -> bool: 33 | return not self.head 34 | 35 | def isFull(self) -> bool: 36 | return self.size == len(self.queue) 37 | 38 | 39 | # Your MyCircularQueue object will be instantiated and called as such: 40 | myCircularQueue = MyCircularQueue(3) 41 | myCircularQueue.enQueue(1) # return True 42 | myCircularQueue.enQueue(2) # return True 43 | myCircularQueue.enQueue(3) # return True 44 | myCircularQueue.enQueue(4) # return False 45 | myCircularQueue.Rear() # return 3 46 | myCircularQueue.isFull() # return True 47 | myCircularQueue.deQueue() # return True 48 | myCircularQueue.enQueue(4) # return True 49 | myCircularQueue.Rear() # return 4 -------------------------------------------------------------------------------- /september/day10.java: -------------------------------------------------------------------------------- 1 | //https://leetcode.com/explore/challenge/card/september-leetcoding-challenge/555/week-2-september-8th-september-14th/3455/ 2 | 3 | 4 | public class Main { 5 | 6 | public static void main(String[] args) { 7 | String secret = "1807"; 8 | String guess = "7810"; 9 | System.out.println(Solution.getHint(secret, guess)); 10 | 11 | String secret1 = "1123"; 12 | String guess1 = "0111"; 13 | System.out.println(Solution.getHint(secret1, guess1)); 14 | 15 | String secret2 = "1122"; 16 | String guess2 = "2211"; 17 | System.out.println(Solution.getHint(secret2, guess2)); 18 | } 19 | } 20 | 21 | class Solution { 22 | public static String getHint(String secret, String guess) { 23 | int[] counts = new int[10]; 24 | int bulls = 0; 25 | int cows = 0; 26 | 27 | for (int i = 0; i < secret.length(); i++) { 28 | counts[secret.charAt(i) - 48]++; 29 | if (guess.charAt(i) == secret.charAt(i)) { 30 | bulls++; 31 | counts[secret.charAt(i) - 48]--; 32 | } 33 | } 34 | 35 | for (int i = 0; i < secret.length(); i++) { 36 | if (guess.charAt(i) != secret.charAt(i) 37 | && counts[guess.charAt(i) - 48] > 0) { 38 | cows++; 39 | counts[guess.charAt(i) - 48]--; 40 | } 41 | } 42 | return bulls + "A" + cows + "B"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DataStructures/LinkedList.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | 3 | def __init__(self, data: int): 4 | self.data = data 5 | self.next = None; 6 | 7 | class LinkedList: 8 | 9 | def __init__(self): 10 | self.head = None 11 | 12 | def append(self, data: int) -> None: 13 | # If List is empty we setup data as the head 14 | if self.head == None: 15 | self.head = Node(data) 16 | return 17 | # If List is not empty, add data and update next 18 | current = self.head 19 | while current.next != None: 20 | current = current.next 21 | current.next = Node(data) 22 | 23 | def prepand(self, data: int) -> None: 24 | newHead = Node(data) 25 | newHead.next = self.head 26 | self.head = newHead 27 | 28 | def delete_with_value(self, data: int) -> None: 29 | if self.head == None: 30 | return 31 | if self.head.data == data: 32 | self.head = self.head.next 33 | return 34 | current = self.head 35 | while current.next != None: 36 | if current.next.data == data: 37 | current.next = current.next.next 38 | return 39 | current = current.next 40 | 41 | def count_nodes(self) -> int: 42 | count = 0 43 | current = self.head 44 | while self.next != None: 45 | current = current.next 46 | count += 1 47 | return count 48 | 49 | 50 | -------------------------------------------------------------------------------- /Grokk-Algos/ch04.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use std::cmp::PartialOrd; 3 | 4 | fn binary_search(target: T, arr: &[T]) -> Option 5 | where 6 | T: PartialEq + PartialOrd + Debug 7 | { 8 | if arr.is_empty() { return None } 9 | 10 | let mid: usize = arr.len() / 2; 11 | if arr[mid] == target { return Some(mid) } 12 | 13 | if target < arr[mid] { 14 | return binary_search(target, &arr[0..mid]); 15 | } else { 16 | return binary_search(target, &arr[mid..arr.len()]); 17 | } 18 | } 19 | 20 | fn qsort(arr: &Vec) -> Vec 21 | where 22 | T: PartialEq + PartialOrd + Debug + Clone 23 | { 24 | // base case 25 | if arr.len() < 2 { 26 | return arr.clone() 27 | } else if arr.len() == 2 { 28 | if arr[0] < arr[1] { 29 | return arr.clone() 30 | } else { 31 | return vec![arr[1].clone(), arr[0].clone()] 32 | } 33 | } 34 | let mut left: Vec = vec![]; 35 | let mut right: Vec = vec![]; 36 | for i in 0..arr.len() { 37 | if arr[i] < arr[0] { 38 | left.push(arr[i].clone()); 39 | } else { 40 | right.push(arr[i].clone()) 41 | } 42 | } 43 | left.push(arr[0].clone()); 44 | left.extend(right); 45 | return qsort(&left) 46 | } 47 | 48 | fn main() { 49 | let v_ = vec![1, 3, 5, 6, 8, 9, 13, 15]; 50 | println!("{:?} is at index: {:?}", 3, binary_search(3, &v_)); 51 | 52 | let v_2 = vec![7, 1, 5, 3, 6, 9, 2]; 53 | println!("Sorted: {:?}", qsort(&v_2)); 54 | } 55 | -------------------------------------------------------------------------------- /BinaryTree/AllTraversals.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/explore/learn/card/data-structure-tree/134/traverse-a-tree/928/ 2 | 3 | Definition for a binary tree node. 4 | class TreeNode: 5 | def __init__(self, val=0, left=None, right=None): 6 | self.val = val 7 | self.left = left 8 | self.right = right 9 | 10 | class Solution: 11 | def preorderTraversal(self, root: TreeNode) -> List[int]: 12 | if not root: 13 | return root 14 | values = [] 15 | self.preorder_traversal(root, values) 16 | return values 17 | 18 | 19 | def preorder_traversal(self, p: TreeNode, values: List[int]): 20 | if p: 21 | values.append(p.val) 22 | 23 | self.preorder_traversal(p.left, values) 24 | self.preorder_traversal(p.right, values) 25 | 26 | def inorderTraversal(self, root: TreeNode) -> List[int]: 27 | values = [] 28 | self.inorder_traversal(root, values) 29 | return values 30 | 31 | 32 | def inorder_traversal(self, p: TreeNode, values: List[int]): 33 | if p: 34 | self.inorder_traversal(p.left, values) 35 | values.append(p.val) 36 | self.inorder_traversal(p.right, values) 37 | 38 | def postorderTraversal(self, root: TreeNode) -> List[int]: 39 | values = [] 40 | self.postorder_traversal(root, values) 41 | return values 42 | 43 | def postorder_traversal(self, p: TreeNode, values: List[int]): 44 | if p: 45 | self.postorder_traversal(p.left, values) 46 | self.postorder_traversal(p.right, values) 47 | values.append(p.val) 48 | -------------------------------------------------------------------------------- /LinkedList/geeks/notes.md: -------------------------------------------------------------------------------- 1 | Each node in a singly-linked list contains not only the value but also a reference field to link to the next node. 2 | By this way, the singly-linked list organizes all the nodes in a sequence. 3 | 4 | Here is an example of a singly-linked list: 5 | ![example](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/12/screen-shot-2018-04-12-at-152754.png) 6 | 7 | ``` 8 | class SinglyListNode { 9 | int val; 10 | SinglyListNode next; 11 | SinglyListNode(int x) { val = x; } 12 | } 13 | ``` 14 | 15 | If we want to add a new value after a given node `prev` we should: 16 | 1. Initialize a new node `cur` with the given value; 17 | ![first](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/26/screen-shot-2018-04-25-at-163224.png) 18 | 19 | 2. Link the "next" field of `cur` to `prev`'s next node next 20 | ![second](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/26/screen-shot-2018-04-25-at-163234.png) 21 | 22 | 3. Link the "next" field in `prev` to `cur` 23 | ![third](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/26/screen-shot-2018-04-25-at-163243.png) 24 | 25 | example: 26 | Let's insert a new value 9 after the second node 6. 27 | 28 | We will first initialize a new node with value 9. 29 | Then link node 9 to node 15. 30 | Finally, link node 6 to node 9. 31 | 32 | After insertion, our linked list will look like this: 33 | ![exampleNodes](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/12/screen-shot-2018-04-12-at-154238.png) 34 | 35 | As we know, we use the head node head to represent the whole list. 36 | 37 | So it is essential to update head when adding a new node at the beginning of the list. 38 | 39 | 1. Initialize a new node `cur`; 40 | 2. Link the new node to our original head node `head`. 41 | 3. Assign `cur` to `head`. 42 | 43 | 44 | -------------------------------------------------------------------------------- /Arrays/removeDups.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/learn/card/fun-with-arrays/511/in-place-operations/3258/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int[] nums = {0,0,1,1,1,2,2,3,3,4}; // 5 9 | int[] nums1 = {1,1,2}; // 2 10 | 11 | System.out.println(Solution.removeDuplicates(nums)); 12 | // System.out.println(Solution.removeDuplicates(nums1)); 13 | } 14 | } 15 | 16 | class Solution { 17 | public static int removeDuplicates(int[] nums) { 18 | // Check for edge cases. 19 | if (nums == null) { 20 | return 0; 21 | } 22 | 23 | // Use the two pointer technique to remove the duplicates in-place. 24 | // The first element shouldn't be touched; it's already in its correct place. 25 | int writePointer = 1; 26 | // Go through each element in the Array. 27 | for (int readPointer = 1; readPointer < nums.length; readPointer++) { 28 | // If the current element we're reading is *different* to the previous 29 | // element... 30 | if (nums[readPointer] != nums[readPointer - 1]) { 31 | System.out.println("Read: " + nums[readPointer] + " previous: " + nums[readPointer - 1] + " write: " + nums[writePointer]); 32 | // Copy it into the next position at the front, tracked by writePointer. 33 | nums[writePointer] = nums[readPointer]; 34 | // And we need to now increment writePointer, because the next element 35 | // should be written one space over. 36 | writePointer++; 37 | } 38 | } 39 | // This turns out to be the correct length value. 40 | return writePointer; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /august/day5.py: -------------------------------------------------------------------------------- 1 | """ 2 | Design a data structure that supports the following two operations: 3 | 4 | void addWord(word) 5 | bool search(word) 6 | search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter. 7 | """ 8 | 9 | from collections import defaultdict 10 | 11 | class WordDictionary: 12 | 13 | def __init__(self): 14 | """ 15 | Initialize your data structure here. 16 | """ 17 | self.index = {} 18 | self.words = defaultdict(list) 19 | 20 | 21 | def addWord(self, word: str) -> None: 22 | """ 23 | Adds a word into the data structure. 24 | """ 25 | self.index[word] = True 26 | self.words[len(word)].append(word) 27 | 28 | 29 | def search(self, word: str) -> bool: 30 | """ 31 | Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. 32 | """ 33 | if word in self.index: 34 | return True 35 | if len(word) not in self.words: 36 | return False 37 | if word == '.' * len(word): 38 | return True 39 | for i in self.words[len(word)]: 40 | if self._comparison_(word, i): 41 | return True 42 | return False 43 | 44 | def _comparison_(self, word, compare): 45 | for j, k in zip(word, compare): 46 | if j != k and j != '.': 47 | return False 48 | return True 49 | 50 | 51 | # Your WordDictionary object will be instantiated and called as such: 52 | obj = WordDictionary() 53 | obj.addWord("bad") 54 | obj.addWord("dad") 55 | obj.addWord("dad") 56 | obj.addWord("mad") 57 | print(obj.search("pad")) # false 58 | print(obj.search("bad")) # true 59 | print(obj.search(".at")) # false 60 | obj.addWord('bat') 61 | print(obj.search('.at')) # true 62 | print(obj.search("b..")) # true -------------------------------------------------------------------------------- /september/nextGreaterElement.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/next-greater-element-i/submissions/ 2 | 3 | import java.util.*; 4 | 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | // Test case #1 9 | int[] nums1 = {4, 1, 2}; 10 | int[] nums2 = {1, 3, 4, 2}; 11 | int[] sol1 = Solution.nextGreaterElement(nums1, nums2); 12 | for (Integer i: sol1) { 13 | System.out.print(i + ", "); 14 | } 15 | 16 | // Test case #2 17 | System.out.println(); 18 | int[] nums3 = {2, 4}; 19 | int[] nums4 = {1, 2, 3, 4}; 20 | int[] sol2 = Solution.nextGreaterElement(nums3, nums4); 21 | for (Integer i: sol2) { 22 | System.out.print(i + ", "); 23 | } 24 | 25 | // Test case #3 26 | System.out.println(); 27 | int[] nums5 = {1, 3, 5, 2, 4}; 28 | int[] nums6 = {6, 5, 4, 3, 2, 1, 7}; 29 | int[] sol3 = Solution.nextGreaterElement(nums5, nums6); 30 | for (Integer i: sol3) { 31 | System.out.print(i + ", "); 32 | } 33 | } 34 | } 35 | 36 | class Solution { 37 | public static int[] nextGreaterElement(int[] nums1, int[] nums2) { 38 | int[] nextGreats = new int[nums1.length]; 39 | for (int i = 0; i < nums1.length; i++) { 40 | for (int j = 0; j < nums2.length - 1; j++) { 41 | if (nums1[i] == nums2[j]) { 42 | for (int k = j + 1; k < nums2.length; k++) { 43 | if (nums1[i] < nums2[k]) { 44 | nextGreats[i] = nums2[k]; 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | // If we did not find next great value fill with -1 51 | if (nextGreats[i] == 0) { 52 | nextGreats[i] = -1; 53 | } 54 | } 55 | return nextGreats; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /september/day9.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/explore/challenge/card/september-leetcoding-challenge/555/week-2-september-8th-september-14th/3454/ 2 | // Compare Version Numbers 3 | 4 | import java.util.*; 5 | 6 | public class Main { 7 | 8 | public static void main(String[] args) { 9 | String version1 = "1.0.1"; 10 | String version2 = "1"; 11 | System.out.println(Solution.compareVersion(version1, version2)); // 1 12 | 13 | version1 = "7.5.2.4"; 14 | version2 = "7.5.3"; 15 | System.out.println(Solution.compareVersion(version1, version2)); // -1 16 | 17 | version1 = "1.0"; 18 | version2 = "1.0.0"; 19 | System.out.println(Solution.compareVersion(version1, version2)); // 0 20 | 21 | version1 = "1.01"; 22 | version2 = "1.001"; 23 | System.out.println(Solution.compareVersion(version1, version2)); // 0 24 | } 25 | } 26 | 27 | class Solution { 28 | public static int compareVersion(String version1, String version2) { 29 | String[] ver1 = version1.split("\\."); 30 | String[] ver2 = version2.split("\\."); 31 | int size = ver1.length; 32 | if (ver2.length < size) { 33 | size = ver2.length; 34 | } 35 | for (int i = 0; i < size; i++) { 36 | int v1 = Integer.parseInt(ver1[i]); 37 | int v2 = Integer.parseInt(ver2[i]); 38 | if (v1 > v2) { 39 | return 1; 40 | } else if (v1 < v2) { 41 | return -1; 42 | } 43 | } 44 | // Check if the extra digit at the end exists and is > 0 45 | if (ver1.length > ver2.length) { 46 | int last = Integer.parseInt(ver1[ver1.length - 1]); 47 | if (last > 0) { 48 | return 1; 49 | } 50 | } 51 | if (ver1.length < ver2.length) { 52 | int last = Integer.parseInt(ver2[ver2.length - 1]); 53 | if (last > 0) { 54 | return -1; 55 | } 56 | } 57 | return 0; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /CHECKLIST.md: -------------------------------------------------------------------------------- 1 | # Sorting Algorithms 2 | 3 | ${\bf InsertionSort(A)}$ 4 | $\\n \leftarrow A.length$; 5 | $\\\quad$ $for$ $i \leftarrow$ $0..n - 1$ 6 | $\\\qquad$ $value \leftarrow A[i]$; 7 | $\\\qquad$ $hole \leftarrow i$; 8 | $\\\quad$ $while$ $hole > 0$ $and$ $A[hole - 1] > value$ 9 | $\\\qquad$ $A[hole] \leftarrow A[hole - 1]$; 10 | $\\\qquad$ $hole \leftarrow hole - 1$; 11 | $\\\quad$ $A[hole] \leftarrow value$; 12 | 13 |
14 | 15 | ------------------- 16 | ${\bf BubbleSort(A)}$ 17 | $\\n \leftarrow A.length$; 18 | $\\$ $for$ $i \leftarrow$ $0..n - 1$; 19 | $\\\quad$ $flag \leftarrow 0$; 20 | $\\\quad$ $for$ $j \leftarrow$ $0..n - 2 - i$; 21 | $\\\qquad$ $if A[i] > A[j + 1]$ 22 | $\\\qquad\quad$ $swap(A[j], A[j + 1])$; 23 | $\\\qquad\quad$ $flag \leftarrow 1$; 24 | $\\\quad$ $if$ $\neg flag$ $break$; 25 | 26 |
27 | 28 | ------------------- 29 | ${\bf MergeSort(A)}$ 30 | $\\n \leftarrow A.length$; 31 | $\\ if n < 2$ 32 | $\\\quad return$ 33 | $\\ mid \leftarrow n \div 2$; 34 | $\\ left \leftarrow A[0:mid]$; 35 | $\\ right \leftarrow A[mid: n - 1]$; 36 | $\\ \textit{\textbf{Merge(left, right, A)}}$; 37 | 38 | 39 | ${\bf Merge(L,R,A)}$ 40 | $\\ i \leftarrow 0$; 41 | $\\ j \leftarrow 0$; 42 | $\\ k \leftarrow 0$; 43 | $\\ while$ $i < L.length$ and $j < R.length$ 44 | $\\\quad if$ $L[i] \le R[i]$ 45 | $\\\qquad A[k] \leftarrow L[i]$; 46 | $\\\qquad i \leftarrow i + 1$; 47 | $\\\quad else$ 48 | $\\\qquad A[k] \leftarrow R[j]$; 49 | $\\\qquad j \leftarrow j + 1$; 50 | $\\\quad k \leftarrow k + 1$; 51 | $\\ while$ $i < L.length$ 52 | $\\\quad A[k] \leftarrow L[i]$; 53 | $\\\quad i \leftarrow i + 1$; 54 | $\\\quad k \leftarrow k + 1$; 55 | $\\ while$ $j < R.length$ 56 | $\\\quad A[k] \leftarrow L[j]$; 57 | $\\\quad j \leftarrow j + 1$; 58 | $\\\quad k \leftarrow k + 1$; 59 | 60 |
61 | 62 | ------------------- 63 | 64 | ${\bf Quick Sort(A, start, end)}$ 65 | $\\ if$ $start < end$ 66 | $\\\quad pivotIndex \leftarrow \textit{\textbf{Partition}}(A, start, end)$; 67 | $\\\quad \textit{\textbf{QuickSort}}(A, start, pivotIndex - 1)$; 68 | $\\\quad \textit{\textbf{QuickSort}}(A, pivotIndex + 1, end)$; 69 | 70 | 71 | ${\bf Partition(A, start, end)}$ 72 | $\\ pivotValue \leftarrow A[end]$; 73 | $\\ pivotIndex \leftarrow start$; 74 | $\\ for$ $i \leftarrow start \ldots end - 1$ 75 | $\\\quad if$ $A[i] \le pivotValue$ 76 | $\\\qquad \textit{\textbf{Swap}}(A[i], A[pivotIndex])$; 77 | $\\\qquad pivotIndex \leftarrow pivotIndex + 1$; 78 | $\\ \textit{\textbf{Swap}}(A[pivotIndex], A[end])$; 79 | -------------------------------------------------------------------------------- /LinkedList/practice.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | 3 | def __init__(self, val): 4 | self.val = val 5 | self.next = None 6 | 7 | class MyLinkedList: 8 | 9 | def __init__(self): 10 | """ 11 | Initialize your data structure here. 12 | """ 13 | self.val = None 14 | 15 | def __str__(self) -> str: 16 | linkedlist = '' 17 | tmp = self.val 18 | while tmp: 19 | linkedlist += str(tmp.val) + " -> " 20 | tmp = tmp.next 21 | return linkedlist + 'null' 22 | 23 | def get(self, index: int) -> int: 24 | """ 25 | Get the value of the index-th node in the linked list. 26 | If the index is invalid, return -1. 27 | """ 28 | pass 29 | 30 | def addAtHead(self, val: int) -> None: 31 | """ 32 | Add a node of value val before the first element of the linked list. 33 | After the insertion, the new node will be the first node of the linked list. 34 | """ 35 | new_node = Node(val) 36 | new_node.next = self.val 37 | self.val = new_node 38 | 39 | def addAtTail(self, val: int) -> None: 40 | """ 41 | Append a node of value val to the last element of the linked list. 42 | """ 43 | new_node = Node(val) 44 | if self.val is None: 45 | self.val = new_node 46 | return 47 | 48 | last = self.val 49 | while last.next: 50 | last = last.next 51 | last.next = new_node 52 | 53 | def addAtIndex(self, index: int, val: int) -> None: 54 | """ 55 | Add a node of value val before the index-th node in the linked list. 56 | If index equals to the length of linked list, the node will be 57 | appended to the end of linked list. If index is greater than the length, 58 | the node will not be inserted. 59 | """ 60 | pass 61 | 62 | 63 | def deleteAtIndex(self, index: int) -> None: 64 | """ 65 | Delete the index-th node in the linked list, if the index is valid. 66 | """ 67 | pass 68 | 69 | if __name__ == '__main__': 70 | # Your MyLinkedList object will be instantiated and called as such: 71 | obj = MyLinkedList() 72 | obj.addAtHead(10) 73 | obj.addAtHead(112) 74 | param_1 = obj.get(2) 75 | print(param_1) 76 | obj.addAtHead(1) 77 | obj.addAtTail(2) 78 | obj.addAtIndex(1, 3) 79 | print(obj) 80 | obj.deleteAtIndex(1) -------------------------------------------------------------------------------- /LinkedList/lc_notes.md: -------------------------------------------------------------------------------- 1 | # Two-Pointer in Linked List 2 | 3 | To detect a cycle we need to do use pointers one going faster than other and if they catch up we have a cycle: 4 | 5 | 1. If there is no cycle, the fast pointer will stop at the end of the linked list. 6 | 7 | 2. If there is a cycle, the fast pointer will eventually meet with the slow pointer. 8 | 9 | What is a proper speed of two pointers?: 10 | 11 | - Slow pointer -> one step at a time 12 | - Fast pointer -> two step at a time 13 | - If the length of the cycle is $M$, after $M$ iterations the fast pointer will move one more cycle and catch up with slow pointer. 14 | 15 | - If you want to return the node at which cycle starts have to use Floyd's Algorithm: 16 | - Move one pointer back to head and traverse until they meet. 17 | 18 | - If you want to find the node at which two linked lists meet: 19 | - Use dict to store Nodes of the first linked list 20 | - traverse through the second linked list and if the value is in dict return the node 21 | 22 | ## Tips 23 | 24 | 1. Always examine if the node is null before you call the `next` 25 | 2. Carefully define the end conditions of your loop to avoid endless loop and null-point error. 26 | 27 | ------ 28 | 29 | # Classic Problems 30 | 31 | ## Reverse Linked List 32 | 33 | Iterate the nodes in original order and change the direction of next towards the previous node. For example if we have `23 -> 6 -> 15 -> null`: 34 | We move the next node of the `6` as `23` then we move next node of `15` as `6` and next node of `23` as `null` this way we get `null <- 23 <- 6 <- 15`. 35 | 36 | ## Sort by putting odd nodes first then put even nodes next 37 | 38 | - This can be done first putting the odd nodes in a linked list and the even nodes in another. 39 | - Then link the evenList to the of the oddList 40 | - We need to track head and tail of each linked list 41 | 42 | ----- 43 | 44 | # Doubly Linked List 45 | 46 | Doubly linked list in addition to the `next` has one more reference field known as `prev`. This field allows to reference previous node. 47 | 48 | Just like in a singly linked list: 49 | 50 | 1. We can't acces a random position in O(1). 51 | 2. We have to traverse from the head to get ith node we want. 52 | 3. Worst case time complexity will be O(n). 53 | 54 | ### Adding a node 55 | 56 | The process of inserting a node `current` can be divided into two steps: 57 | 58 | 1. Link `current` with `prev`, where `next` is the original next node of `prev`. 59 | 2. Re-link the `prev` and `next` with `current`. 60 | 61 | -------------------------------------------------------------------------------- /BinaryTree/notes.md: -------------------------------------------------------------------------------- 1 | # Binary Tree 2 | 3 | Each node of the tree will have a root value and a list of references to other nodes which are called child nodes. From graph view, a tree can also be defined as a directed acyclic graph which has $N$ nodes and $N-1$ edges. 4 | 5 | Binary tree can have at most two children (left and right). 6 | 7 | ## Breadth-First Traversal (level-Order) 8 | 9 | Level-order traversal is to traverse the tree level by level. 10 | 11 | Breadth-First Search is an algorithm to traverse or search in data structures like a tree or a graph. 12 | 13 | - The algorithm starts with a root node and visit the node itself first. 14 | - Then traverse its neighbors, traverse its second level neighbors, traverse its third level neighbors, so on and so forth. 15 | 16 | When we do breadth-first search in a tree, the order of the nodes we visited is in level order. Typically, we use a `queue` to help us to do BFS. 17 | 18 | we can solve a tree problem recursively using a top-down approach or using a bottom-up approach 19 | 20 | ## Top-Down Recursion 21 | 22 | "Top-down" means that in each recursive call, we will visit the node first to come up with some values, and pass these values to its children when calling the function recursively. So the **top-down** solution can be considered as a kind of preorder traversal. 23 | 24 | ``` 25 | def top_down(root, params): 26 | 1. return specific value for null node 27 | 2. update the answer if needed // answer <-- params 28 | 3. left_ans = top_down(root.left, left_params) // left_params <-- root.val, params 29 | 4. right_ans = top_down(root.right, right_params) // right_params <-- root.val, params 30 | 5. return the answer if needed // answer <-- left_ans, right_ans 31 | ``` 32 | 33 | When you meet a tree problem, ask yourself two questions: Can you determine some parameters to help the node know its answer? Can you use these parameters and the value of the node itself to determine what should be the parameters passed to its children? If the answers are both yes, try to solve this problem using a "top-down" recursive solution. 34 | 35 | 36 | ### Check if Tree is Symmetric 37 | 38 | A tree is symmetric if the left subtree is a mirror reflection of the right subtree. Two trees are a mirror of each other if: 39 | 40 | 1. Their two roots have the same values 41 | 2. The right subtree of each tree is a mirror reflection of the left subtree of the other tree. 42 | 43 | ``` 44 | def is_mirror(node1, node2): 45 | if not node1 and not node2 46 | return true; 47 | if not node1 or not node2 48 | return false; 49 | return node1.value == node2.value 50 | and is_mirror(node1.right, node2.left) 51 | and is_mirror(node1.left, node2.right) 52 | ``` 53 | 54 | This has time complexity of `O(n)` because we traverse the entire tree once. -------------------------------------------------------------------------------- /Grokk-Algos/ch04.py: -------------------------------------------------------------------------------- 1 | from typing import List, TypeVar 2 | 3 | T = TypeVar('T') 4 | 5 | def rec_sum(nums: List[int]) -> int: 6 | if not nums: 7 | return 0 8 | elif len(nums) == 1: 9 | return nums[0] 10 | return nums[0] + rec_sum(nums[1:]) 11 | 12 | def elem_count(nums: List[int]) -> int: 13 | if not nums: 14 | return 0 15 | else: 16 | return 1 + elem_count(nums[1:]) 17 | 18 | def max_val(nums: List[int]) -> int: 19 | if len(nums) == 2: 20 | return nums[0] if nums[0] > nums[1] else nums[1] 21 | sub_max= max_val(nums[1:]) 22 | return nums[0] if nums[0] > sub_max else sub_max 23 | 24 | def binary_search(x: int, nums: List[int]) -> int: 25 | mid = len(nums) // 2 26 | if not nums: 27 | return None 28 | if nums[mid] == x: 29 | return x 30 | return binary_search(x, nums[mid:]) if x > nums[mid] else binary_search(x, nums[:mid]) 31 | 32 | 33 | ############################################################################### 34 | ################################ QUICK SORT ################################### 35 | ############################################################################### 36 | 37 | def qsort(array: List[T]) -> List[T]: 38 | # base case 39 | if len(array) < 2: 40 | return array 41 | 42 | left = [] 43 | right = [] 44 | for item in array[1:]: 45 | if item <= array[0]: 46 | left.append(item) 47 | else: 48 | right.append(item) 49 | return qsort(left) + [array[0]] + qsort(right) 50 | 51 | 52 | ############################################################################### 53 | ########################### BREADTH FIRST SEARCH ############################## 54 | ############################################################################### 55 | 56 | from collections import deque 57 | from typing import TypeVar 58 | 59 | T = TypeVar('T') 60 | 61 | def bfs(start: T, target: T, graph) -> int: 62 | depth = 0 63 | frontier = deque() 64 | frontier.appendleft(graph[start]) 65 | visited = set() 66 | while frontier: 67 | current = frontier.pop() 68 | if current == target: 69 | return depth 70 | for child in current.neighbors(): 71 | if child not in visited: 72 | frontier.appendleft(graph[current]) 73 | return -1 74 | 75 | 76 | 77 | 78 | if __name__ == '__main__': 79 | print(rec_sum([1, 5, 3, 6, 9, 2])) 80 | print(elem_count([1, 5, 3, 6, 9, 2])) 81 | print(max_val([1, 5, 3, 6, 9, 2])) 82 | print(binary_search(3, [1, 3, 5, 6, 8, 9])) 83 | print(qsort([7, 1, 5, 3, 6, 9, 2])) 84 | 85 | morning = { 86 | 'shower': ('wake up'), 87 | 'wake up': ('shower', 'brush teeth'), 88 | 'brush teeth': ('wake up', 'eat breakfast'), 89 | 'eat breakfast': ('brush teeth') 90 | } 91 | print(bfs('wake up', 'eat breakfast', morning)) 92 | 93 | -------------------------------------------------------------------------------- /Testings/test_deque_speed.py: -------------------------------------------------------------------------------- 1 | """ 2 | Testing the runtime speed for lists and deque append, appendleft and pop 3 | """ 4 | 5 | import time 6 | from collections import deque 7 | 8 | def deque_speed_append(rounds: list) -> dict: 9 | results = {} 10 | for i in rounds: 11 | q = deque() 12 | start = time.time_ns() 13 | for n in range(i): 14 | q.append(n) 15 | end = time.time_ns() 16 | results[i] = end - start 17 | return results 18 | 19 | def deque_speed_appendleft(rounds: list) -> dict: 20 | results = {} 21 | for i in rounds: 22 | q = deque() 23 | start = time.time_ns() 24 | for n in range(i): 25 | q.appendleft(n) 26 | end = time.time_ns() 27 | results[i] = end - start 28 | return results 29 | 30 | def list_append_speed(rounds: list) -> dict: 31 | results = {} 32 | for i in rounds: 33 | s = [] 34 | start = time.time_ns() 35 | for n in range(i): 36 | s.append(n) 37 | end = time.time_ns() 38 | results[i] = end - start 39 | return results 40 | 41 | def deque_speed_pop(rounds: list) -> dict: 42 | results = {} 43 | for i in rounds: 44 | q = deque(m for m in range(i)) 45 | start = time.time_ns() 46 | for n in range(i): 47 | q.pop() 48 | end = time.time_ns() 49 | results[i] = end - start 50 | return results 51 | 52 | def deque_speed_popleft(rounds: list) -> dict: 53 | results = {} 54 | for i in rounds: 55 | q = deque(m for m in range(i)) 56 | start = time.time_ns() 57 | for n in range(i): 58 | q.popleft() 59 | end = time.time_ns() 60 | results[i] = end - start 61 | return results 62 | 63 | def list_speed_pop(rounds: list) -> dict: 64 | results = {} 65 | for i in rounds: 66 | s = [m for m in range(i)] 67 | start = time.time_ns() 68 | for n in range(i): 69 | s.pop() 70 | end = time.time_ns() 71 | results[i] = end - start 72 | return results 73 | 74 | def list_comprehension(rounds: list) -> dict: 75 | results = {} 76 | for i in rounds: 77 | s = [] 78 | start = time.time_ns() 79 | s.append(n for n in range(i)) 80 | end = time.time_ns() 81 | results[i] = end - start 82 | return results 83 | 84 | if __name__ == '__main__': 85 | print(f'deque append\t\t{deque_speed_append([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 86 | print(f'deque appendleft\t{deque_speed_appendleft([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 87 | print(f'list append\t\t{deque_speed_append([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 88 | print('--------------------------------------') 89 | print(f'list comprehension\t{list_comprehension([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 90 | print('--------------------------------------') 91 | print(f'deque pop\t\t{deque_speed_pop([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 92 | print(f'deque popleft\t{deque_speed_popleft([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 93 | print(f'list pop\t\t{list_speed_pop([100, 1000, 10000, 100000, 1000000, 10000000, 100000000])}') 94 | 95 | 96 | -------------------------------------------------------------------------------- /BinaryTree/BinarySearchTree/BST.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | 3 | def __init__(self, val) -> None: 4 | self.value = val 5 | self.left_child = None 6 | self.right_child = None 7 | 8 | def __eq__(self, other) -> bool: 9 | if isinstance(other, Node): 10 | return self.value == other.val \ 11 | and self.left_child == other.left_child \ 12 | and self.right_child == other.right_child 13 | 14 | 15 | class BinarySearchTree: 16 | 17 | def __init__(self) -> None: 18 | self.root = None 19 | 20 | def contains(self, val) -> bool: 21 | return self.__contains(self.root, val) 22 | 23 | def __contains(self, n: Node, val) -> bool: 24 | if not n: 25 | return False; 26 | 27 | if n.value == val: 28 | return True 29 | elif n.value > val: 30 | return self.__contains(n.left_child, val) 31 | else: 32 | return self.__contains(n.right_child, val) 33 | 34 | def add(self, val) -> bool: 35 | if not val: 36 | return False 37 | if not self.root: 38 | self.root = Node(val) 39 | return True 40 | return self.__add(self.root, val) 41 | 42 | def __add(self, n: Node, val) -> bool: 43 | if not n or not val: 44 | return False 45 | if n.value == val: 46 | return False # same value can't be added twice 47 | elif n.value > val: 48 | if not n.left_child: 49 | n.left_child = Node(val) 50 | return True 51 | else: 52 | return self.__add(n.left_child, val) 53 | else: 54 | if not n.right_child: 55 | n.right_child = Node(val) 56 | return True 57 | else: 58 | return self.__add(n.right_child, val) 59 | 60 | def remove(self, val) -> bool: 61 | return self.__remove(root, None, val) 62 | 63 | def __remove(self, n: Node, parent, val) -> bool: 64 | if not n: return False 65 | 66 | if n.value > val: 67 | return remove(n.left_child, n, val) 68 | elif n.value == val: 69 | return remove(n.right_child, n, val) 70 | else: 71 | if not n.left_child and not n.right_child: 72 | n.value = max_value(n.left_child) 73 | self.__remove(n.left_child, n, n.value) 74 | elif not parent: 75 | if n.left_child: self.root = n.left_child 76 | else: self.root = n.right_child 77 | elif parent.left_child == n: 78 | if n.left_child: parent.left_child = n.left_child 79 | else: parent.left_child = n.right_child 80 | else: 81 | if n.left_child: parent.right_child = n.left_child 82 | else: parent.right_child = n.right_child 83 | return True 84 | 85 | def max_value(self, n: Node): 86 | if not n.right_child: 87 | return n.value 88 | else: 89 | return self.max_value(n.right_child) 90 | 91 | if __name__ == '__main__': 92 | bst1 = BinarySearchTree() 93 | bst1.add(7) 94 | bst1.add(3) 95 | bst1.add(5) 96 | bst1.add(8) 97 | 98 | bst2 = BinarySearchTree() 99 | bst1.add(7) 100 | bst2.add(3) 101 | bst2.add(5) 102 | bst2.add(9) 103 | 104 | print(bst1 == bst2) -------------------------------------------------------------------------------- /Leetcode_Question_Categories_and_Approaches_2020.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Filebin 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 |
28 | File download 29 |
30 |
31 |
32 |
33 |

34 | 35 |

36 |
File name
37 |
Leetcode_Question_Categories_and_Approaches_2020.pdf
38 |
File size
39 |
106 kB
40 |
Content type
41 |
application/pdf
42 |
Uploaded
43 |
4 days ago
44 |
45 | 46 |

47 |
48 |
49 | 50 | 61 |
62 |
63 |
64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /LinkedList/DesignLinkedList.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | 3 | def __init__(self, val): 4 | self.val = val 5 | self.next = None 6 | 7 | class MyLinkedList: 8 | 9 | def __init__(self): 10 | """ 11 | Initialize your data structure here. 12 | """ 13 | self.val = None 14 | self.size = 0 15 | 16 | def __str__(self): 17 | string = "" 18 | tmp = self.val 19 | while tmp: 20 | string += f'{tmp.val} -> ' 21 | tmp = tmp.next 22 | return string 23 | 24 | def get(self, index: int) -> int: 25 | """ 26 | Get the value of the index-th node in the linked list. 27 | If the index is invalid, return -1. 28 | """ 29 | if index < 0: 30 | return -1 31 | 32 | tmp = self.val 33 | pointer = 0 34 | while tmp is not None: 35 | if pointer == index: 36 | return tmp.val 37 | tmp = tmp.next 38 | pointer += 1 39 | return -1 40 | 41 | 42 | def addAtHead(self, val: int) -> None: 43 | """ 44 | Add a node of value val before the first element of the linked list. 45 | After the insertion, the new node will be the first node of the linked list. 46 | """ 47 | new_node = Node(val) 48 | new_node.next = self.val 49 | self.val = new_node 50 | self.size += 1 51 | 52 | def addAtTail(self, val: int) -> None: 53 | """ 54 | Append a node of value val to the last element of the linked list. 55 | """ 56 | new_node = Node(val) 57 | if self.val is None: 58 | self.val = new_node 59 | 60 | tmp = self.val 61 | while tmp.next: 62 | tmp = tmp.next 63 | tmp.next = new_node 64 | self.size += 1 65 | 66 | 67 | def addAtIndex(self, index: int, val: int) -> None: 68 | """ 69 | Add a node of value val before the index-th node in the linked list. 70 | If index equals to the length of linked list, the node will be 71 | appended to the end of linked list. If index is greater 72 | than the length, the node will not be inserted. 73 | """ 74 | if index < 0 or index > self.size: 75 | return 76 | elif index == 0: 77 | self.addAtHead(val) 78 | self.size += 1 79 | else: 80 | new_node = Node(val) 81 | current = self.val 82 | for i in range(1, index): 83 | current = current.next 84 | new_node.next = current.next 85 | current.next = new_node 86 | self.size += 1 87 | 88 | 89 | def deleteAtIndex(self, index: int) -> None: 90 | """ 91 | Delete the index-th node in the linked list, if the index is valid. 92 | """ 93 | if index < 0 or index >= self.size or self.val is None: 94 | return 95 | elif index == 0: 96 | self.val = self.val.next 97 | self.size -= 1 98 | else: 99 | current = self.val 100 | for i in range(index - 1): 101 | current = current.next 102 | current.next = current.next.next 103 | self.size -= 1 104 | 105 | 106 | # Your MyLinkedList object will be instantiated and called as such: 107 | myLinkedList = MyLinkedList() 108 | myLinkedList.addAtHead(1) 109 | myLinkedList.addAtTail(3) 110 | myLinkedList.addAtIndex(1, 2) 111 | print(myLinkedList.get(1)) 112 | print(myLinkedList) 113 | myLinkedList.deleteAtIndex(0) 114 | print(myLinkedList) 115 | print(myLinkedList.get(0)) 116 | -------------------------------------------------------------------------------- /sorts.py: -------------------------------------------------------------------------------- 1 | import random 2 | from typing import List, TypeVar 3 | 4 | T = TypeVar('T') 5 | 6 | 7 | def insertion_sort(arr: List[T]) -> None: 8 | """ 9 | Insertion Sort 10 | 11 | Time: 12 | O(n^2) - Worst Case 13 | O(n) - Best Case 14 | 15 | Space: 16 | O(1) as sorting happens in-place 17 | """ 18 | for i in range(1, len(arr)): 19 | tmp = arr[i] # value 20 | hole = i # index 21 | while hole > 0 and arr[hole - 1] > tmp: 22 | arr[hole] = arr[hole - 1] 23 | hole -= 1 24 | arr[hole] = tmp 25 | 26 | def bubble_sort(arr: List[T]) -> None: 27 | """ 28 | Bubble Sort 29 | 30 | Time: 31 | O(n^2) 32 | 33 | Space: 34 | O(1) as sorting happens in-place 35 | """ 36 | for i, _ in enumerate(arr): 37 | is_sorted = True 38 | for j in range(len(arr) - i - 1): 39 | if arr[j] > arr[j + 1]: 40 | arr[j], arr[j + 1] = arr[j + 1], arr[j] 41 | is_sorted = False 42 | if is_sorted: 43 | return 44 | 45 | 46 | def merge_sort(arr: List[T]) -> None: 47 | if len(arr) < 2: 48 | return 49 | 50 | mid = len(arr) // 2 51 | left = arr[:mid] 52 | right = arr[mid:] 53 | merge_sort(left) 54 | merge_sort(right) 55 | _merge(left, right, arr) 56 | 57 | 58 | def _merge(left: List[T], right: List[T], origin: List[T]) -> None: 59 | i = k = j = 0 60 | while i < len(left) and j < len(right): 61 | 62 | if left[i] <= right[j]: 63 | origin[k] = left[i] 64 | i += 1 65 | else: 66 | origin[k] = right[j] 67 | j += 1 68 | k += 1 69 | 70 | while i < len(left): 71 | origin[k] = left[i] 72 | i += 1 73 | k += 1 74 | while j < len(right): 75 | origin[k] = right[j] 76 | j += 1 77 | k += 1 78 | 79 | 80 | def quick_sort(arr: List[T]) -> List[T]: 81 | """ 82 | Quick sort algorithm with D&C strategy that produces sorted list 83 | 84 | Time: 85 | O(n*long(n)) - Average 86 | [considered worst case with Random pivot picking strategy] 87 | O(n^2) - worst case without randomized pivot picking 88 | 89 | Space: 90 | O(n) - Because we have to create a new list 91 | """ 92 | size = len(arr) 93 | if size < 2: 94 | return arr 95 | pivot = random.randint(0, size - 1) 96 | left = [] 97 | right = [] 98 | for i in range(size): 99 | if i != pivot: 100 | if arr[i] < arr[pivot]: 101 | left.append(arr[i]) 102 | else: 103 | right.append(arr[i]) 104 | return quick_sort(left) + [arr[pivot]] + quick_sort(right) 105 | 106 | 107 | def qsort(arr): 108 | """ 109 | In-place quick sort algorithm with D&C strategy 110 | 111 | Time: 112 | O(n*long(n)) - Average 113 | [considered worst case with Random pivot picking strategy] 114 | O(n^2) - worst case without randomized pivot picking 115 | 116 | Space: 117 | O(1) 118 | """ 119 | __qsort(arr, 0, len(arr) - 1) 120 | 121 | 122 | def __qsort(arr, start, end): 123 | if start < end: 124 | pivot_idx = partition(arr, start, end) 125 | __qsort(arr, start, pivot_idx - 1) 126 | __qsort(arr, pivot_idx + 1, end) 127 | 128 | 129 | def partition(arr, start, end) -> int: 130 | pivot = arr[end] 131 | index = start 132 | for i in range(start, end): 133 | if arr[i] <= pivot: 134 | arr[i], arr[index] = arr[index], arr[i] 135 | index += 1 136 | arr[index], arr[end] = arr[end], arr[index] 137 | return index 138 | 139 | 140 | if __name__ == '__main__': 141 | a = [2, 4, 1, 6, 8, 5, 3, 7] 142 | # bubble_sort(a) 143 | b = [8, 11, 13, 16, 9, 6, 23, 7] 144 | # merge_sort(b) 145 | c = [2, 44, 41, 63, 88, 52, 3, 37] 146 | d = [7, 2, 4, 1, 5, 3] 147 | qsort(a) 148 | qsort(b) 149 | qsort(c) 150 | qsort(d) 151 | # insertion_sort(d) 152 | print('Bubble Sort', a) 153 | print('Merge Sort', b) 154 | print('Quick Sort', c) 155 | print('Insertion Sort', d) 156 | -------------------------------------------------------------------------------- /LinkedList/.ipynb_checkpoints/Part2-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linked List Part 2\n", 8 | "\n", 9 | "## Set 1 | Counting Number of Nodes\n", 10 | "\n", 11 | "To find the length of a Linked List we need to count the number of nodes\n", 12 | "![image](Linkedlist_find_length.png)\n", 13 | "\n", 14 | "### Iterative Solution:\n", 15 | "\n", 16 | "1. Initialize count as 0 \n", 17 | "2. Initialize a node pointer, current = head.\n", 18 | "3. Do following while current is not NULL\n", 19 | " 1. current = current -> next\n", 20 | " 2. count++;\n", 21 | "4. Return count " 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 9, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "class Node:\n", 31 | " \n", 32 | " def __init__(self, data):\n", 33 | " self.data = data\n", 34 | " self.next = None" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 10, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "class LinkedList:\n", 44 | " \n", 45 | " def __init__(self):\n", 46 | " self.head = None\n", 47 | " \n", 48 | " def push(self, new_data):\n", 49 | " new_node = Node(new_data)\n", 50 | " new_node.next = self.head\n", 51 | " self.head = new_node\n", 52 | " \n", 53 | " def length(self):\n", 54 | " \"\"\"Counts the number of nodes\"\"\"\n", 55 | " tmp = self.head\n", 56 | " count = 0\n", 57 | " \n", 58 | " # Loop until the next is None (the end is reached)\n", 59 | " while tmp:\n", 60 | " count += 1\n", 61 | " tmp = tmp.next\n", 62 | " return count" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 11, 68 | "metadata": {}, 69 | "outputs": [ 70 | { 71 | "name": "stdout", 72 | "output_type": "stream", 73 | "text": [ 74 | "Count of nodes is : 5\n" 75 | ] 76 | } 77 | ], 78 | "source": [ 79 | "llist = LinkedList() \n", 80 | "llist.push(1) \n", 81 | "llist.push(3) \n", 82 | "llist.push(1) \n", 83 | "llist.push(2)\n", 84 | "llist.push(1) \n", 85 | "print(\"Count of nodes is :\",llist.length())" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "------\n", 93 | "## Set 2 | Search an Element\n", 94 | "This function will search s given key in a given linked list and return true if found, false otherwise.\n", 95 | "\n", 96 | "### Recursive Solution\n", 97 | "1. If head is NULL, return false.\n", 98 | "2. If head's key is same as x, return true;\n", 99 | "3. Else return search(head->next, x) " 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 34, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "class LinkedList:\n", 109 | " \n", 110 | " def __init__(self):\n", 111 | " self.head = None\n", 112 | " \n", 113 | " def print_llist(self):\n", 114 | " \"\"\"Prints the data from the linked list\"\"\"\n", 115 | " tmp = self.head\n", 116 | " while (tmp):\n", 117 | " print(tmp.data, end=' -> ')\n", 118 | " tmp = tmp.next\n", 119 | " print('None')\n", 120 | " \n", 121 | " def push(self, new_data):\n", 122 | " new_node = Node(new_data)\n", 123 | " new_node.next = self.head\n", 124 | " self.head = new_node\n", 125 | " \n", 126 | " def search(self, key):\n", 127 | " \"\"\"Searches if the given node is present\"\"\"\n", 128 | " current = self.head\n", 129 | " \n", 130 | " while current is not None:\n", 131 | " if current.data == key:\n", 132 | " return True\n", 133 | " current = current.next\n", 134 | " \n", 135 | " return False" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 36, 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "name": "stdout", 145 | "output_type": "stream", 146 | "text": [ 147 | "Yes\n" 148 | ] 149 | } 150 | ], 151 | "source": [ 152 | "llist1 = LinkedList() \n", 153 | " \n", 154 | "llist1.push(10) \n", 155 | "llist1.push(30) \n", 156 | "llist1.push(11) \n", 157 | "llist1.push(21) \n", 158 | "llist1.push(14)\n", 159 | " \n", 160 | "if llist1.search(11): \n", 161 | " print(\"Found!\") \n", 162 | "else: \n", 163 | " print(\"Not found!\")" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [] 172 | } 173 | ], 174 | "metadata": { 175 | "kernelspec": { 176 | "display_name": "Python 3.8.2 64-bit", 177 | "language": "python", 178 | "name": "python38264bitc1c0e47f0bef41228abb9a7d720d2718" 179 | }, 180 | "language_info": { 181 | "codemirror_mode": { 182 | "name": "ipython", 183 | "version": 3 184 | }, 185 | "file_extension": ".py", 186 | "mimetype": "text/x-python", 187 | "name": "python", 188 | "nbconvert_exporter": "python", 189 | "pygments_lexer": "ipython3", 190 | "version": "3.8.5" 191 | } 192 | }, 193 | "nbformat": 4, 194 | "nbformat_minor": 4 195 | } 196 | -------------------------------------------------------------------------------- /LinkedList/geeks/Part3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linked Lists Part 3\n", 8 | "\n", 9 | "## Set 1 | Detect A loop\n", 10 | "Given a linked list, check if the linked list has loop or not. Below diagram shows a linked list with a loop.\n", 11 | "\n", 12 | "![image](Linked-List-Loop.gif)\n", 13 | "\n", 14 | "**Hashing Approach:**\n", 15 | "\n", 16 | "Traverse the list one by one and keep putting the node addresses in a Hash Table. At any point, if NULL is reached then return false and if next of current node points to any of the previously stored nodes in Hash then return true. " 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "class Node:\n", 26 | " \n", 27 | " def __init__(self, data):\n", 28 | " self.data = data\n", 29 | " self.next = None" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "class LinkedList:\n", 39 | " \n", 40 | " def __init__(self):\n", 41 | " self.head = None\n", 42 | " \n", 43 | " def push(self, new_data):\n", 44 | " \"\"\"Add Node at the head position\"\"\"\n", 45 | " new_node = Node(new_data)\n", 46 | " new_node.next = self.head\n", 47 | " self.head = new_node\n", 48 | " \n", 49 | " def detect_loop(self):\n", 50 | " \"\"\"Detects if the linked list contains a loop\"\"\"\n", 51 | " nodes_set = set()\n", 52 | " tmp = self.head\n", 53 | " while tmp:\n", 54 | " if tmp in nodes_set:\n", 55 | " return True\n", 56 | " nodes_set.add(tmp)\n", 57 | " tmp = tmp.next\n", 58 | " return False" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 4, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "True\n" 71 | ] 72 | } 73 | ], 74 | "source": [ 75 | "llist = LinkedList()\n", 76 | "llist.push(20)\n", 77 | "llist.push(4)\n", 78 | "llist.push(15)\n", 79 | "llist.push(10)\n", 80 | "\n", 81 | "# Create a loop for testing\n", 82 | "llist.head.next.next.next.next = llist.head\n", 83 | "print(llist.detect_loop())" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "## Set 2 | Find the length of the loop\n", 91 | "\n", 92 | "This function will chech wheather a given Linked List contains loop and if loop exists it will return a count of nodes in that loop.\n", 93 | "\n", 94 | "**Algorithm**:\n", 95 | "\n", 96 | "1. Find a common point in the loop by using the _Floyd's Cycle Detection Algorithm_.\n", 97 | "2. Store the pointer in a temporary variable and keep a count.\n", 98 | "3. Traverse the linked list until the same node is reached again and increase the count while moving to the next node.\n", 99 | "4. Print the ocunt as length of loop" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 7, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "class LinkedList:\n", 109 | " \n", 110 | " def __init__(self):\n", 111 | " self.head = None\n", 112 | " \n", 113 | " def push(self, new_data):\n", 114 | " \"\"\"Add Node at the head position\"\"\"\n", 115 | " new_node = Node(new_data)\n", 116 | " new_node.next = self.head\n", 117 | " self.head = new_node\n", 118 | " \n", 119 | " def detect_loop_length(self):\n", 120 | " \"\"\"Detects if loop is present and returns its length\"\"\"\n", 121 | " if not self.head:\n", 122 | " return 0\n", 123 | " slow = self.head\n", 124 | " fast = self.head\n", 125 | " flag = 0\n", 126 | " \n", 127 | " while (slow and slow.next and fast \n", 128 | " and fast.next and fast.next.next):\n", 129 | " if slow == fast and flag != 0:\n", 130 | " count = 1\n", 131 | " slow = slow.next\n", 132 | " while slow != fast:\n", 133 | " slow = slow.next\n", 134 | " count += 1\n", 135 | " return count\n", 136 | " \n", 137 | " slow = slow.next\n", 138 | " fast = fast.next.next\n", 139 | " flag = 1\n", 140 | " return 0" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 9, 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "name": "stdout", 150 | "output_type": "stream", 151 | "text": [ 152 | "4\n" 153 | ] 154 | } 155 | ], 156 | "source": [ 157 | "llist1 = LinkedList()\n", 158 | "llist1.push(20)\n", 159 | "llist1.push(4)\n", 160 | "llist1.push(15)\n", 161 | "llist1.push(10)\n", 162 | "llist1.push(32)\n", 163 | "\n", 164 | "# Create a loop for testing\n", 165 | "llist1.head.next.next.next.next = llist1.head\n", 166 | "print(llist1.detect_loop_length())" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [] 175 | } 176 | ], 177 | "metadata": { 178 | "kernelspec": { 179 | "display_name": "Python 3.8.2 64-bit", 180 | "language": "python", 181 | "name": "python38264bitc1c0e47f0bef41228abb9a7d720d2718" 182 | }, 183 | "language_info": { 184 | "codemirror_mode": { 185 | "name": "ipython", 186 | "version": 3 187 | }, 188 | "file_extension": ".py", 189 | "mimetype": "text/x-python", 190 | "name": "python", 191 | "nbconvert_exporter": "python", 192 | "pygments_lexer": "ipython3", 193 | "version": "3.8.5" 194 | } 195 | }, 196 | "nbformat": 4, 197 | "nbformat_minor": 4 198 | } 199 | -------------------------------------------------------------------------------- /LinkedList/geeks/Part2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linked List Part 2\n", 8 | "\n", 9 | "## Set 1 | Counting Number of Nodes\n", 10 | "\n", 11 | "To find the length of a Linked List we need to count the number of nodes\n", 12 | "![image](Linkedlist_find_length.png)\n", 13 | "\n", 14 | "### Iterative Solution:\n", 15 | "\n", 16 | "1. Initialize count as 0 \n", 17 | "2. Initialize a node pointer, current = head.\n", 18 | "3. Do following while current is not NULL\n", 19 | " 1. current = current -> next\n", 20 | " 2. count++;\n", 21 | "4. Return count " 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "class Node:\n", 31 | " \n", 32 | " def __init__(self, data):\n", 33 | " self.data = data\n", 34 | " self.next = None" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 2, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "class LinkedList:\n", 44 | " \n", 45 | " def __init__(self):\n", 46 | " self.head = None\n", 47 | " \n", 48 | " def push(self, new_data):\n", 49 | " new_node = Node(new_data)\n", 50 | " new_node.next = self.head\n", 51 | " self.head = new_node\n", 52 | " \n", 53 | " def length(self):\n", 54 | " \"\"\"Counts the number of nodes\"\"\"\n", 55 | " tmp = self.head\n", 56 | " count = 0\n", 57 | " \n", 58 | " # Loop until the next is None (the end is reached)\n", 59 | " while tmp:\n", 60 | " count += 1\n", 61 | " tmp = tmp.next\n", 62 | " return count" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 3, 68 | "metadata": {}, 69 | "outputs": [ 70 | { 71 | "name": "stdout", 72 | "output_type": "stream", 73 | "text": [ 74 | "Count of nodes is : 5\n" 75 | ] 76 | } 77 | ], 78 | "source": [ 79 | "llist = LinkedList() \n", 80 | "llist.push(1) \n", 81 | "llist.push(3) \n", 82 | "llist.push(1) \n", 83 | "llist.push(2)\n", 84 | "llist.push(1) \n", 85 | "print(\"Count of nodes is :\",llist.length())" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "------\n", 93 | "## Set 2 | Search an Element\n", 94 | "This function will search s given key in a given linked list and return true if found, false otherwise.\n", 95 | "\n", 96 | "### Recursive Solution\n", 97 | "1. If head is NULL, return false.\n", 98 | "2. If head's key is same as x, return true;\n", 99 | "3. Else return search(head->next, x) " 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 4, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "class LinkedList:\n", 109 | " \n", 110 | " def __init__(self):\n", 111 | " self.head = None\n", 112 | " \n", 113 | " def push(self, new_data):\n", 114 | " \"\"\"Add node to the linked list\"\"\"\n", 115 | " new_node = Node(new_data)\n", 116 | " new_node.next = self.head\n", 117 | " self.head = new_node\n", 118 | " \n", 119 | " def search(self, key):\n", 120 | " \"\"\"Searches if the given node is present\"\"\"\n", 121 | " current = self.head\n", 122 | " \n", 123 | " while current is not None:\n", 124 | " if current.data == key:\n", 125 | " return True\n", 126 | " current = current.next\n", 127 | " \n", 128 | " return False" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 5, 134 | "metadata": {}, 135 | "outputs": [ 136 | { 137 | "name": "stdout", 138 | "output_type": "stream", 139 | "text": [ 140 | "Found!\n" 141 | ] 142 | } 143 | ], 144 | "source": [ 145 | "llist1 = LinkedList() \n", 146 | " \n", 147 | "llist1.push(10) \n", 148 | "llist1.push(30) \n", 149 | "llist1.push(11) \n", 150 | "llist1.push(21) \n", 151 | "llist1.push(14)\n", 152 | " \n", 153 | "if llist1.search(11): \n", 154 | " print(\"Found!\") \n", 155 | "else: \n", 156 | " print(\"Not found!\")" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "## Set 3 | Get Nth node\n", 164 | "\n", 165 | "### Algorithm: \n", 166 | "\n", 167 | "1. Initialize count = 0\n", 168 | "2. Loop through the link list\n", 169 | " 1. if count is equal to the passed index then return current\n", 170 | " node\n", 171 | " 2. Increment count\n", 172 | " 3. change current to point to next of the current" 173 | ] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": 16, 178 | "metadata": {}, 179 | "outputs": [], 180 | "source": [ 181 | "class LinkedList:\n", 182 | " \n", 183 | " def __init__(self):\n", 184 | " self.head = None\n", 185 | " \n", 186 | " def push(self, new_data):\n", 187 | " \"\"\"Add node to the linked list\"\"\"\n", 188 | " new_node = Node(new_data)\n", 189 | " new_node.next = self.head\n", 190 | " self.head = new_node\n", 191 | " \n", 192 | " def get_nth(self, index):\n", 193 | " \"\"\"Searches and retrieves node on the given index\"\"\"\n", 194 | " tmp = self.head\n", 195 | " count = 0\n", 196 | " \n", 197 | " while tmp:\n", 198 | " if count == index:\n", 199 | " return tmp.data\n", 200 | " count += 1\n", 201 | " tmp = tmp.next\n", 202 | " \n", 203 | " # If the index isn't in this linked list\n", 204 | " raise IndexError(\n", 205 | " f'{index} is not present in the given linked list'\n", 206 | " )" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": 18, 212 | "metadata": {}, 213 | "outputs": [ 214 | { 215 | "name": "stdout", 216 | "output_type": "stream", 217 | "text": [ 218 | "Element at index 3 is : 4\n" 219 | ] 220 | } 221 | ], 222 | "source": [ 223 | "llist3 = LinkedList() \n", 224 | "llist3.push(1) \n", 225 | "llist3.push(4) \n", 226 | "llist3.push(1) \n", 227 | "llist3.push(12) \n", 228 | "llist3.push(1) \n", 229 | "\n", 230 | "print(\"Element at index 3 is :\", llist3.get_nth(3))" 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": 20, 236 | "metadata": {}, 237 | "outputs": [ 238 | { 239 | "ename": "IndexError", 240 | "evalue": "12 is not present in the given linked list", 241 | "output_type": "error", 242 | "traceback": [ 243 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 244 | "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", 245 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Raise IndexError\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Element at index 3 is :\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mllist3\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_nth\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m12\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 246 | "\u001b[0;32m\u001b[0m in \u001b[0;36mget_nth\u001b[0;34m(self, index)\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;31m# If the index isn't in this linked list\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 32\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mIndexError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf'{index} is not present in the given linked list'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 247 | "\u001b[0;31mIndexError\u001b[0m: 12 is not present in the given linked list" 248 | ] 249 | } 250 | ], 251 | "source": [ 252 | "# Raise IndexError\n", 253 | "print(\"Element at index 3 is :\", llist3.get_nth(12))" 254 | ] 255 | }, 256 | { 257 | "cell_type": "markdown", 258 | "metadata": {}, 259 | "source": [ 260 | "## Set 4 | Count Number of Occurances\n", 261 | "\n", 262 | "Given a singly linked list and a key, count number of occurrences of given key in linked list. For example, if given linked list is 1->2->1->2->1->3->1 and given key is 1, then output should be 4. Time Complexity: `O(n)`\n", 263 | "\n", 264 | "### Algorithm:\n", 265 | "1. Initialize count as zero.\n", 266 | "2. Loop through each element of linked list:\n", 267 | " - If element data is equal to the passed number then increment the count.\n", 268 | "3. Return count. " 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 21, 274 | "metadata": {}, 275 | "outputs": [], 276 | "source": [ 277 | "class LinkedList:\n", 278 | " \n", 279 | " def __init__(self):\n", 280 | " self.head = None\n", 281 | " \n", 282 | " def push(self, new_data):\n", 283 | " \"\"\"Add node to the linked list\"\"\"\n", 284 | " new_node = Node(new_data)\n", 285 | " new_node.next = self.head\n", 286 | " self.head = new_node\n", 287 | " \n", 288 | " def count(self, value):\n", 289 | " \"\"\"Counts the number of occurances of the given value\"\"\"\n", 290 | " tmp = self.head\n", 291 | " count = 0\n", 292 | " \n", 293 | " while tmp:\n", 294 | " if tmp.data == value:\n", 295 | " count += 1\n", 296 | " tmp = tmp.next\n", 297 | " return count" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": 24, 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "name": "stdout", 307 | "output_type": "stream", 308 | "text": [ 309 | "count of 1 is 3\n" 310 | ] 311 | } 312 | ], 313 | "source": [ 314 | "llist4 = LinkedList() \n", 315 | "llist4.push(1) \n", 316 | "llist4.push(3) \n", 317 | "llist4.push(1) \n", 318 | "llist4.push(2) \n", 319 | "llist4.push(1) \n", 320 | " \n", 321 | "# Check for the count function \n", 322 | "print(f\"count of 1 is {llist4.count(1)}\")" 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "All the methods in a one code" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": null, 335 | "metadata": {}, 336 | "outputs": [], 337 | "source": [ 338 | "class LinkedList:\n", 339 | " \n", 340 | " def __init__(self):\n", 341 | " self.head = None\n", 342 | " \n", 343 | " def push(self, new_data):\n", 344 | " \"\"\"Add node to the linked list\"\"\"\n", 345 | " new_node = Node(new_data)\n", 346 | " new_node.next = self.head\n", 347 | " self.head = new_node\n", 348 | " \n", 349 | " def length(self):\n", 350 | " \"\"\"Counts the number of nodes\"\"\"\n", 351 | " tmp = self.head\n", 352 | " count = 0\n", 353 | " while tmp:\n", 354 | " count += 1\n", 355 | " tmp = tmp.next\n", 356 | " return count\n", 357 | " \n", 358 | " def search(self, key):\n", 359 | " \"\"\"Searches if the given node is present\"\"\"\n", 360 | " current = self.head\n", 361 | " while current is not None:\n", 362 | " if current.data == key:\n", 363 | " return True\n", 364 | " current = current.next\n", 365 | " return False\n", 366 | " \n", 367 | " def get_nth(self, index):\n", 368 | " \"\"\"Searches and retrieves node on the given index\"\"\"\n", 369 | " tmp = self.head\n", 370 | " count = 0\n", 371 | " while tmp:\n", 372 | " if count == index:\n", 373 | " return tmp.data\n", 374 | " count += 1\n", 375 | " tmp = tmp.next\n", 376 | " \n", 377 | " # If the index isn't in this linked list\n", 378 | " raise IndexError(\n", 379 | " f'{index} is not present in the given linked list'\n", 380 | " )\n", 381 | " \n", 382 | " def count(self, value):\n", 383 | " \"\"\"Counts the number of occurances of the given value\"\"\"\n", 384 | " tmp = self.head\n", 385 | " count = 0\n", 386 | " while tmp:\n", 387 | " if tmp.data == value:\n", 388 | " count += 1\n", 389 | " tmp = tmp.next\n", 390 | " return count" 391 | ] 392 | } 393 | ], 394 | "metadata": { 395 | "kernelspec": { 396 | "display_name": "Python 3.8.2 64-bit", 397 | "language": "python", 398 | "name": "python38264bitc1c0e47f0bef41228abb9a7d720d2718" 399 | }, 400 | "language_info": { 401 | "codemirror_mode": { 402 | "name": "ipython", 403 | "version": 3 404 | }, 405 | "file_extension": ".py", 406 | "mimetype": "text/x-python", 407 | "name": "python", 408 | "nbconvert_exporter": "python", 409 | "pygments_lexer": "ipython3", 410 | "version": "3.8.5" 411 | } 412 | }, 413 | "nbformat": 4, 414 | "nbformat_minor": 4 415 | } 416 | -------------------------------------------------------------------------------- /LinkedList/.ipynb_checkpoints/Part1-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linked List Part 1\n", 8 | "## Set 1 | Introduction\n", 9 | "Linked List is a linear data structure. Unlike arrays, linked list elements are not stored at a contiguous location; the elements are linked using pointers.\n", 10 | "![title](Linkedlist.png)\n", 11 | "\n", 12 | "### Why Linked List?\n", 13 | "Arrays have following limitations.\n", 14 | "1. The size is fixed: We must know the upper limit on the number of elements in advance and the allocated memory is always equal to the upper limit.\n", 15 | "2. Inserting a new element in an array of elements is expensive because the room has to be created for the new elements and existing elements have to be shifted.\n", 16 | "\n", 17 | "### Advantages of Linked Lists\n", 18 | "1. Dynamic size\n", 19 | "2. Ease of insertion/deletion\n", 20 | "\n", 21 | "### Drawbacks:\n", 22 | "1. Random access is not allowed. We have to access elements sequentially starting from the first node. We can't do a binary search with its default implementation.\n", 23 | "2. Extra memory space for a pointer is required with each element of the list.\n", 24 | "3. Not cache friendly\n", 25 | "\n", 26 | "## Representation:\n", 27 | "A Linked list is represented by a pointer to the first node of the linked list. The first node is called **Head**. If the linked list is empty, then the value of the head is NULL.\n", 28 | "\n", 29 | "Each node in a linked list consists of at least two parts:\n", 30 | "1. Data\n", 31 | "2. Pointer (Or Reference) to the next node." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 11, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "class Node:\n", 41 | " \n", 42 | " def __init__(self, data):\n", 43 | " self.data = data\n", 44 | " self.next = None # Initially this is null\n", 45 | " \n", 46 | "\n", 47 | "class LinkedList:\n", 48 | " \n", 49 | " def __init__(self):\n", 50 | " self.head = None\n", 51 | " \n", 52 | " def printList(self):\n", 53 | " \"\"\"Prints the data from the linked list\"\"\"\n", 54 | " tmp = self.head\n", 55 | " while (tmp):\n", 56 | " print(tmp.data, end=' -> ')\n", 57 | " tmp = tmp.next" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 12, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "# We'll create a linked list with 3 nodes\n", 67 | "llist = LinkedList()\n", 68 | "\n", 69 | "# Set up first node as head\n", 70 | "llist.head = Node(1)\n", 71 | "second = Node(2)\n", 72 | "third = Node(3)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | " Three nodes have been created. \n", 80 | " We have references to these three blocks as head, \n", 81 | " second and third \n", 82 | " \n", 83 | " llist.head second third \n", 84 | " | | | \n", 85 | " | | | \n", 86 | " +----+------+ +----+------+ +----+------+ \n", 87 | " | 1 | None | | 2 | None | | 3 | None | \n", 88 | " +----+------+ +----+------+ +----+------+" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 13, 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "# Link first node (head) with second\n", 98 | "llist.head.next = second" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "Now next of first Node refers to second. So they \n", 106 | " both are linked. \n", 107 | " \n", 108 | " llist.head second third \n", 109 | " | | | \n", 110 | " | | | \n", 111 | " +----+------+ +----+------+ +----+------+ \n", 112 | " | 1 | o-------->| 2 | null | | 3 | null | \n", 113 | " +----+------+ +----+------+ +----+------+ " 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 14, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "# Link second node with the third node\n", 123 | "second.next = third" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "Now next of second Node refers to third. So all three \n", 131 | " nodes are linked. \n", 132 | " \n", 133 | " llist.head second third \n", 134 | " | | | \n", 135 | " | | | \n", 136 | " +----+------+ +----+------+ +----+------+ \n", 137 | " | 1 | o-------->| 2 | o-------->| 3 | null | \n", 138 | " +----+------+ +----+------+ +----+------+ " 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": 15, 144 | "metadata": {}, 145 | "outputs": [ 146 | { 147 | "name": "stdout", 148 | "output_type": "stream", 149 | "text": [ 150 | "1, 2, 3, " 151 | ] 152 | } 153 | ], 154 | "source": [ 155 | "'''Lets traverse thecreated list and print the data of each node'''\n", 156 | "llist.printList()" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "-----------\n", 164 | "## Set 2 | Inserting a node\n", 165 | "Node can be added in three ways:\n", 166 | "1. At the fron of the linked list.\n", 167 | "2. After a given node.\n", 168 | "3. At the end of the linked list\n", 169 | "\n", 170 | "### Add a node at the front:\n", 171 | "The new node will be added before the head of the Linked List. Newly added node will become the new head.\n", 172 | "\n", 173 | "![title](Linkedlist_insert_at_start.png)\n", 174 | "\n", 175 | "Time complexity of `push()` is `O(1)` as it does constant amount of work." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 45, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | " class LinkedList:\n", 185 | " \n", 186 | " def __init__(self):\n", 187 | " self.head = None\n", 188 | " \n", 189 | " def printList(self):\n", 190 | " \"\"\"Prints the data from the linked list\"\"\"\n", 191 | " tmp = self.head\n", 192 | " while (tmp):\n", 193 | " print(tmp.data)\n", 194 | " tmp = tmp.next\n", 195 | " \n", 196 | " # New function to insert a node at the beginning\n", 197 | " def push(self, new_data):\n", 198 | " \"\"\"Inserts node at the beginning\"\"\"\n", 199 | " new_node = Node(new_data)\n", 200 | " \n", 201 | " # Old head becomes next node\n", 202 | " new_node.next = self.head\n", 203 | " \n", 204 | " # Set up new head\n", 205 | " self.head = new_node" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "### Add a node after a given node: \n", 213 | "We are given pointer to a node, and the new node is inserted after the given node\n", 214 | "\n", 215 | "![image](Linkedlist_insert_middle.png)\n", 216 | "\n", 217 | "Time complexity of insertAfter() is O(1) as it does constant amount of work" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 46, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | " class LinkedList:\n", 227 | " \n", 228 | " def __init__(self):\n", 229 | " self.head = None\n", 230 | " \n", 231 | " def printList(self):\n", 232 | " \"\"\"Prints the data from the linked list\"\"\"\n", 233 | " tmp = self.head\n", 234 | " while (tmp):\n", 235 | " print(tmp.data)\n", 236 | " tmp = tmp.next\n", 237 | " \n", 238 | " def push(self, new_data):\n", 239 | " \"\"\"Inserts node at the beginning\"\"\"\n", 240 | " new_node = Node(new_data)\n", 241 | " new_node.next = self.head\n", 242 | " self.head = new_node\n", 243 | " \n", 244 | " # New function to insert a node after given node\n", 245 | " def insert_after(self, prev_node, new_data):\n", 246 | " \"\"\"Inserts node after given node\"\"\"\n", 247 | " # Check if the Previous node exists\n", 248 | " if prev_node is None:\n", 249 | " return \"Previous node must be in LinkedList\"\n", 250 | " \n", 251 | " new_node = Node(new_data)\n", 252 | " \n", 253 | " # Make next of new node as next of previous node\n", 254 | " new_node.next = prev_node.next\n", 255 | " \n", 256 | " # Make next of previous node as new node\n", 257 | " prev_node.next = new_node" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": {}, 263 | "source": [ 264 | "### Add a node at the end:\n", 265 | "The new node will be added after the last node. For example if the given Linked List has 5->10->15->20 and we add an item 30 at the end, then the Linked List becomes 5->10->15->20->30.\n", 266 | "Since the Linked List is represented by the head first, we have to traverse the list till end and then change the next of last node to new node.\n", 267 | "\n", 268 | "![imnage](Linkedlist_insert_last.png)\n", 269 | "\n", 270 | "Time complexity of append is O(n) where n is the number of nodes in linked list. Since there is a loop from head to end, the function does O(n) work.\n", 271 | "This method can also be optimized to work in O(1) by keeping an extra pointer to tail of linked list." 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": 47, 277 | "metadata": {}, 278 | "outputs": [], 279 | "source": [ 280 | " class LinkedList:\n", 281 | " \n", 282 | " def __init__(self):\n", 283 | " self.head = None\n", 284 | " \n", 285 | " def printList(self):\n", 286 | " \"\"\"Prints the data from the linked list\"\"\"\n", 287 | " tmp = self.head\n", 288 | " while (tmp):\n", 289 | " print(tmp.data)\n", 290 | " tmp = tmp.next\n", 291 | " \n", 292 | " def push(self, new_data):\n", 293 | " \"\"\"Inserts node at the beginning\"\"\"\n", 294 | " new_node = Node(new_data)\n", 295 | " new_node.next = self.head\n", 296 | " self.head = new_node\n", 297 | " \n", 298 | " def insert_after(self, prev_node, new_data):\n", 299 | " \"\"\"Inserts node after given node\"\"\"\n", 300 | " if prev_node is None:\n", 301 | " return \"Previous node must be in linked list\"\n", 302 | " new_node = Node(new_data) \n", 303 | " new_node.next = prev_node.next\n", 304 | " prev_node.next = new_node\n", 305 | " \n", 306 | " # New function to append a node at the end\n", 307 | " def append(self, new_data):\n", 308 | " \"\"\"Appends node at the end of the linked list\"\"\"\n", 309 | " new_node = Node(new_data)\n", 310 | " \n", 311 | " # If the llist is empty make the new node as head\n", 312 | " if self.head is None:\n", 313 | " self.head = new_node\n", 314 | " return\n", 315 | " \n", 316 | " # Traverse till the last node\n", 317 | " last = self.head\n", 318 | " while (last.next):\n", 319 | " last = last.next\n", 320 | " \n", 321 | " last.next = new_node" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": 48, 327 | "metadata": {}, 328 | "outputs": [ 329 | { 330 | "name": "stdout", 331 | "output_type": "stream", 332 | "text": [ 333 | "1\n", 334 | "7\n", 335 | "8\n", 336 | "6\n", 337 | "4\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "llist1 = LinkedList()\n", 343 | "llist1.append(6)\n", 344 | "llist1.push(7)\n", 345 | "llist1.push(1)\n", 346 | "llist1.append(4)\n", 347 | "llist1.insert_after(llist1.head.next, 8)\n", 348 | "llist1.printList()" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "------------\n", 356 | "## Set 3 | Deleting a node\n", 357 | "\n", 358 | "To delete a node from the linked list, we need to do the following:\n", 359 | "1. Find the previous node of the node to be deleted.\n", 360 | "2. Change the next of the previous node.\n", 361 | "3. Free memory for the node to be deleted.\n", 362 | "\n", 363 | "![image](Linkedlist_deletion.png)" 364 | ] 365 | }, 366 | { 367 | "cell_type": "code", 368 | "execution_count": 49, 369 | "metadata": {}, 370 | "outputs": [], 371 | "source": [ 372 | " class LinkedList:\n", 373 | " \n", 374 | " def __init__(self):\n", 375 | " self.head = None\n", 376 | " \n", 377 | " def printList(self):\n", 378 | " \"\"\"Prints the data from the linked list\"\"\"\n", 379 | " tmp = self.head\n", 380 | " while (tmp):\n", 381 | " print(tmp.data)\n", 382 | " tmp = tmp.next\n", 383 | " \n", 384 | " def push(self, new_data):\n", 385 | " \"\"\"Inserts node at the beginning\"\"\"\n", 386 | " new_node = Node(new_data)\n", 387 | " new_node.next = self.head\n", 388 | " self.head = new_node\n", 389 | " \n", 390 | " def insert_after(self, prev_node, new_data):\n", 391 | " \"\"\"Inserts node after given node\"\"\"\n", 392 | " if prev_node is None:\n", 393 | " return \"Previous node must be in linked list\"\n", 394 | " new_node = Node(new_data) \n", 395 | " new_node.next = prev_node.next\n", 396 | " prev_node.next = new_node\n", 397 | " \n", 398 | " \n", 399 | " def append(self, new_data):\n", 400 | " \"\"\"Appends node at the end of the linked list\"\"\"\n", 401 | " new_node = Node(new_data)\n", 402 | " if self.head is None:\n", 403 | " self.head = new_node\n", 404 | " return\n", 405 | " last = self.head\n", 406 | " while last.next:\n", 407 | " last = last.next\n", 408 | " last.next = new_node\n", 409 | " \n", 410 | " # New function to delete a node\n", 411 | " def delete_node(self, key):\n", 412 | " \"\"\"Deletes the first occurance of the key\"\"\"\n", 413 | " tmp = self.head\n", 414 | " \n", 415 | " # If the head node holds the key to be deleted\n", 416 | " if tmp is not None:\n", 417 | " if tmp.data == key:\n", 418 | " self.head = tmp.next\n", 419 | " tmp = None\n", 420 | " return\n", 421 | " \n", 422 | " # Search for the key to be deleted\n", 423 | " while tmp is not None:\n", 424 | " if tmp.data == key:\n", 425 | " break\n", 426 | " prev = tmp\n", 427 | " tmp = tmp.next\n", 428 | " \n", 429 | " # If key was not found\n", 430 | " if tmp == None:\n", 431 | " return\n", 432 | " \n", 433 | " # Unlink the node from linked list\n", 434 | " prev.next = tmp.next\n", 435 | " tmp = None" 436 | ] 437 | }, 438 | { 439 | "cell_type": "code", 440 | "execution_count": 50, 441 | "metadata": {}, 442 | "outputs": [ 443 | { 444 | "name": "stdout", 445 | "output_type": "stream", 446 | "text": [ 447 | "Created Linked List: \n", 448 | "2\n", 449 | "3\n", 450 | "1\n", 451 | "7\n", 452 | "\n", 453 | "Linked List after Deletion of 1:\n", 454 | "2\n", 455 | "3\n", 456 | "7\n" 457 | ] 458 | } 459 | ], 460 | "source": [ 461 | "llist2 = LinkedList() \n", 462 | "llist2.push(7) \n", 463 | "llist2.push(1) \n", 464 | "llist2.push(3) \n", 465 | "llist2.push(2) \n", 466 | " \n", 467 | "print(\"Created Linked List: \") \n", 468 | "llist2.printList() \n", 469 | "llist2.delete_node(1) \n", 470 | "print(\"\\nLinked List after Deletion of 1:\") \n", 471 | "llist2.printList() " 472 | ] 473 | }, 474 | { 475 | "cell_type": "markdown", 476 | "metadata": {}, 477 | "source": [ 478 | "---------\n", 479 | "## Set 4 | Deleting a note at a given position\n", 480 | "\n", 481 | "If the node to be deleted is the root, simply delete it. To delete a middle node, we must have a pointer to the node previous to the node to be deleted. So if positions are not zero, we run a loop position-1 times and get a pointer to the previous node." 482 | ] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "execution_count": 52, 487 | "metadata": {}, 488 | "outputs": [], 489 | "source": [ 490 | " class LinkedList:\n", 491 | " \n", 492 | " def __init__(self):\n", 493 | " self.head = None\n", 494 | " \n", 495 | " def printList(self):\n", 496 | " \"\"\"Prints the data from the linked list\"\"\"\n", 497 | " tmp = self.head\n", 498 | " while (tmp):\n", 499 | " print(tmp.data)\n", 500 | " tmp = tmp.next\n", 501 | " \n", 502 | " def push(self, new_data):\n", 503 | " \"\"\"Inserts node at the beginning\"\"\"\n", 504 | " new_node = Node(new_data)\n", 505 | " new_node.next = self.head\n", 506 | " self.head = new_node\n", 507 | " \n", 508 | " def insert_after(self, prev_node, new_data):\n", 509 | " \"\"\"Inserts node after given node\"\"\"\n", 510 | " if prev_node is None:\n", 511 | " return \"Previous node must be in linked list\"\n", 512 | " new_node = Node(new_data) \n", 513 | " new_node.next = prev_node.next\n", 514 | " prev_node.next = new_node\n", 515 | " \n", 516 | " \n", 517 | " def append(self, new_data):\n", 518 | " \"\"\"Appends node at the end of the linked list\"\"\"\n", 519 | " new_node = Node(new_data)\n", 520 | " if self.head is None:\n", 521 | " self.head = new_node\n", 522 | " return\n", 523 | " last = self.head\n", 524 | " while last.next:\n", 525 | " last = last.next\n", 526 | " last.next = new_node\n", 527 | "\n", 528 | " def delete_node(self, key):\n", 529 | " \"\"\"Deletes the first occurance of the key\"\"\"\n", 530 | " tmp = self.head\n", 531 | " if tmp is not None:\n", 532 | " if tmp.data == key:\n", 533 | " self.head = tmp.next\n", 534 | " tmp = None\n", 535 | " return\n", 536 | " while tmp is not None:\n", 537 | " if tmp.data == key:\n", 538 | " break\n", 539 | " prev = tmp\n", 540 | " tmp = tmp.next\n", 541 | " if tmp == None:\n", 542 | " return\n", 543 | " prev.next = tmp.next\n", 544 | " tmp = None\n", 545 | " \n", 546 | " # New function to delete a node at a given position\n", 547 | " def delete_at(self, position):\n", 548 | " \"\"\"Deletes node at a given position\"\"\"\n", 549 | " # If linked list empty\n", 550 | " if self.head is None:\n", 551 | " return\n", 552 | " \n", 553 | " tmp = self.head\n", 554 | " \n", 555 | " # If heads need to be removed\n", 556 | " if position == 0:\n", 557 | " self.head = tmp.next\n", 558 | " tmp = None\n", 559 | " \n", 560 | " # Find previous node of the node to be deleted\n", 561 | " for i in range(position - 1):\n", 562 | " tmp = tmp.next\n", 563 | " if tmp is None:\n", 564 | " break\n", 565 | " \n", 566 | " # If position is more than number of nodes\n", 567 | " if tmp is None or tmp.next is None:\n", 568 | " return \n", 569 | " \n", 570 | " # Node temp.next is the node to be deleted \n", 571 | " # store pointer to the next of node to be deleted\n", 572 | " next_node = tmp.next.next\n", 573 | " \n", 574 | " # Unlink the node\n", 575 | " tmp.next = None\n", 576 | " tmp.next = next_node" 577 | ] 578 | }, 579 | { 580 | "cell_type": "code", 581 | "execution_count": 55, 582 | "metadata": {}, 583 | "outputs": [ 584 | { 585 | "name": "stdout", 586 | "output_type": "stream", 587 | "text": [ 588 | "Created Linked List: \n", 589 | "8\n", 590 | "2\n", 591 | "3\n", 592 | "1\n", 593 | "7\n", 594 | "\n", 595 | "Linked List after Deletion at position 4: \n", 596 | "8\n", 597 | "2\n", 598 | "1\n", 599 | "7\n" 600 | ] 601 | } 602 | ], 603 | "source": [ 604 | "llist3 = LinkedList() \n", 605 | "llist3.push(7) \n", 606 | "llist3.push(1) \n", 607 | "llist3.push(3) \n", 608 | "llist3.push(2) \n", 609 | "llist3.push(8) \n", 610 | " \n", 611 | "print(\"Created Linked List: \")\n", 612 | "llist3.printList() \n", 613 | "llist3.delete_at(2) \n", 614 | "print(\"\\nLinked List after Deletion at position 4: \")\n", 615 | "llist3.printList() " 616 | ] 617 | }, 618 | { 619 | "cell_type": "code", 620 | "execution_count": null, 621 | "metadata": {}, 622 | "outputs": [], 623 | "source": [] 624 | } 625 | ], 626 | "metadata": { 627 | "kernelspec": { 628 | "display_name": "Python 3.8.2 64-bit", 629 | "language": "python", 630 | "name": "python38264bitc1c0e47f0bef41228abb9a7d720d2718" 631 | }, 632 | "language_info": { 633 | "codemirror_mode": { 634 | "name": "ipython", 635 | "version": 3 636 | }, 637 | "file_extension": ".py", 638 | "mimetype": "text/x-python", 639 | "name": "python", 640 | "nbconvert_exporter": "python", 641 | "pygments_lexer": "ipython3", 642 | "version": "3.8.5" 643 | } 644 | }, 645 | "nbformat": 4, 646 | "nbformat_minor": 4 647 | } 648 | -------------------------------------------------------------------------------- /LinkedList/geeks/Part1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linked List Part 1\n", 8 | "## Set 1 | Introduction\n", 9 | "Linked List is a linear data structure. Unlike arrays, linked list elements are not stored at a contiguous location; the elements are linked using pointers.\n", 10 | "![title](Linkedlist.png)\n", 11 | "\n", 12 | "### Why Linked List?\n", 13 | "Arrays have following limitations.\n", 14 | "1. The size is fixed: We must know the upper limit on the number of elements in advance and the allocated memory is always equal to the upper limit.\n", 15 | "2. Inserting a new element in an array of elements is expensive because the room has to be created for the new elements and existing elements have to be shifted.\n", 16 | "\n", 17 | "### Advantages of Linked Lists\n", 18 | "1. Dynamic size\n", 19 | "2. Ease of insertion/deletion\n", 20 | "\n", 21 | "### Drawbacks:\n", 22 | "1. Random access is not allowed. We have to access elements sequentially starting from the first node. We can't do a binary search with its default implementation.\n", 23 | "2. Extra memory space for a pointer is required with each element of the list.\n", 24 | "3. Not cache friendly\n", 25 | "\n", 26 | "## Representation:\n", 27 | "A Linked list is represented by a pointer to the first node of the linked list. The first node is called **Head**. If the linked list is empty, then the value of the head is NULL.\n", 28 | "\n", 29 | "Each node in a linked list consists of at least two parts:\n", 30 | "1. Data\n", 31 | "2. Pointer (Or Reference) to the next node." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 37, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "class Node:\n", 41 | " \n", 42 | " def __init__(self, data):\n", 43 | " self.data = data\n", 44 | " self.next = None # Initially this is null\n", 45 | " \n", 46 | "\n", 47 | "class LinkedList:\n", 48 | " \n", 49 | " def __init__(self):\n", 50 | " self.head = None\n", 51 | " \n", 52 | " def print_llist(self):\n", 53 | " \"\"\"Prints the data from the linked list\"\"\"\n", 54 | " tmp = self.head\n", 55 | " while (tmp):\n", 56 | " print(tmp.data, end=' -> ')\n", 57 | " tmp = tmp.next\n", 58 | " print('None')" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 39, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "# We'll create a linked list with 3 nodes\n", 68 | "llist = LinkedList()\n", 69 | "\n", 70 | "# Set up first node as head\n", 71 | "llist.head = Node(1)\n", 72 | "second = Node(2)\n", 73 | "third = Node(3)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | " Three nodes have been created. \n", 81 | " We have references to these three blocks as head, \n", 82 | " second and third \n", 83 | " \n", 84 | " llist.head second third \n", 85 | " | | | \n", 86 | " | | | \n", 87 | " +----+------+ +----+------+ +----+------+ \n", 88 | " | 1 | None | | 2 | None | | 3 | None | \n", 89 | " +----+------+ +----+------+ +----+------+" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 40, 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [ 98 | "# Link first node (head) with second\n", 99 | "llist.head.next = second" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "Now next of first Node refers to second. So they \n", 107 | " both are linked. \n", 108 | " \n", 109 | " llist.head second third \n", 110 | " | | | \n", 111 | " | | | \n", 112 | " +----+------+ +----+------+ +----+------+ \n", 113 | " | 1 | o-------->| 2 | null | | 3 | null | \n", 114 | " +----+------+ +----+------+ +----+------+ " 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 41, 120 | "metadata": {}, 121 | "outputs": [], 122 | "source": [ 123 | "# Link second node with the third node\n", 124 | "second.next = third" 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": {}, 130 | "source": [ 131 | "Now next of second Node refers to third. So all three \n", 132 | " nodes are linked. \n", 133 | " \n", 134 | " llist.head second third \n", 135 | " | | | \n", 136 | " | | | \n", 137 | " +----+------+ +----+------+ +----+------+ \n", 138 | " | 1 | o-------->| 2 | o-------->| 3 | null | \n", 139 | " +----+------+ +----+------+ +----+------+ " 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 42, 145 | "metadata": {}, 146 | "outputs": [ 147 | { 148 | "name": "stdout", 149 | "output_type": "stream", 150 | "text": [ 151 | "1 -> 2 -> 3 -> None\n" 152 | ] 153 | } 154 | ], 155 | "source": [ 156 | "'''Lets traverse thecreated list and print the data of each node'''\n", 157 | "llist.print_llist()" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": {}, 163 | "source": [ 164 | "-----------\n", 165 | "## Set 2 | Inserting a node\n", 166 | "Node can be added in three ways:\n", 167 | "1. At the fron of the linked list.\n", 168 | "2. After a given node.\n", 169 | "3. At the end of the linked list\n", 170 | "\n", 171 | "### Add a node at the front:\n", 172 | "The new node will be added before the head of the Linked List. Newly added node will become the new head.\n", 173 | "\n", 174 | "![title](Linkedlist_insert_at_start.png)\n", 175 | "\n", 176 | "Time complexity of `push()` is `O(1)` as it does constant amount of work." 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": 43, 182 | "metadata": {}, 183 | "outputs": [], 184 | "source": [ 185 | " class LinkedList:\n", 186 | " \n", 187 | " def __init__(self):\n", 188 | " self.head = None\n", 189 | " \n", 190 | " def print_llist(self):\n", 191 | " \"\"\"Prints the data from the linked list\"\"\"\n", 192 | " tmp = self.head\n", 193 | " while (tmp):\n", 194 | " print(tmp.data, end=' -> ')\n", 195 | " tmp = tmp.next\n", 196 | " print('None')\n", 197 | " \n", 198 | " # New function to insert a node at the beginning\n", 199 | " def push(self, new_data):\n", 200 | " \"\"\"Inserts node at the beginning\"\"\"\n", 201 | " new_node = Node(new_data)\n", 202 | " \n", 203 | " # Old head becomes next node\n", 204 | " new_node.next = self.head\n", 205 | " \n", 206 | " # Set up new head\n", 207 | " self.head = new_node" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "### Add a node after a given node: \n", 215 | "We are given pointer to a node, and the new node is inserted after the given node\n", 216 | "\n", 217 | "![image](Linkedlist_insert_middle.png)\n", 218 | "\n", 219 | "Time complexity of insertAfter() is O(1) as it does constant amount of work" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 45, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [ 228 | " class LinkedList:\n", 229 | " \n", 230 | " def __init__(self):\n", 231 | " self.head = None\n", 232 | " \n", 233 | " def print_llist(self):\n", 234 | " \"\"\"Prints the data from the linked list\"\"\"\n", 235 | " tmp = self.head\n", 236 | " while (tmp):\n", 237 | " print(tmp.data, end=' -> ')\n", 238 | " tmp = tmp.next\n", 239 | " print('None')\n", 240 | " \n", 241 | " def push(self, new_data):\n", 242 | " \"\"\"Inserts node at the beginning\"\"\"\n", 243 | " new_node = Node(new_data)\n", 244 | " new_node.next = self.head\n", 245 | " self.head = new_node\n", 246 | " \n", 247 | " # New function to insert a node after given node\n", 248 | " def insert_after(self, prev_node, new_data):\n", 249 | " \"\"\"Inserts node after given node\"\"\"\n", 250 | " # Check if the Previous node exists\n", 251 | " if prev_node is None:\n", 252 | " return \"Previous node must be in LinkedList\"\n", 253 | " \n", 254 | " new_node = Node(new_data)\n", 255 | " \n", 256 | " # Make next of new node as next of previous node\n", 257 | " new_node.next = prev_node.next\n", 258 | " \n", 259 | " # Make next of previous node as new node\n", 260 | " prev_node.next = new_node" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "### Add a node at the end:\n", 268 | "The new node will be added after the last node. For example if the given Linked List has 5->10->15->20 and we add an item 30 at the end, then the Linked List becomes 5->10->15->20->30.\n", 269 | "Since the Linked List is represented by the head first, we have to traverse the list till end and then change the next of last node to new node.\n", 270 | "\n", 271 | "![imnage](Linkedlist_insert_last.png)\n", 272 | "\n", 273 | "Time complexity of append is O(n) where n is the number of nodes in linked list. Since there is a loop from head to end, the function does O(n) work.\n", 274 | "This method can also be optimized to work in O(1) by keeping an extra pointer to tail of linked list." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 46, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [ 283 | " class LinkedList:\n", 284 | " \n", 285 | " def __init__(self):\n", 286 | " self.head = None\n", 287 | " \n", 288 | " def print_llist(self):\n", 289 | " \"\"\"Prints the data from the linked list\"\"\"\n", 290 | " tmp = self.head\n", 291 | " while (tmp):\n", 292 | " print(tmp.data, end=' -> ')\n", 293 | " tmp = tmp.next\n", 294 | " print('None')\n", 295 | " \n", 296 | " def push(self, new_data):\n", 297 | " \"\"\"Inserts node at the beginning\"\"\"\n", 298 | " new_node = Node(new_data)\n", 299 | " new_node.next = self.head\n", 300 | " self.head = new_node\n", 301 | " \n", 302 | " def insert_after(self, prev_node, new_data):\n", 303 | " \"\"\"Inserts node after given node\"\"\"\n", 304 | " if prev_node is None:\n", 305 | " return \"Previous node must be in linked list\"\n", 306 | " new_node = Node(new_data) \n", 307 | " new_node.next = prev_node.next\n", 308 | " prev_node.next = new_node\n", 309 | " \n", 310 | " # New function to append a node at the end\n", 311 | " def append(self, new_data):\n", 312 | " \"\"\"Appends node at the end of the linked list\"\"\"\n", 313 | " new_node = Node(new_data)\n", 314 | " \n", 315 | " # If the llist is empty make the new node as head\n", 316 | " if self.head is None:\n", 317 | " self.head = new_node\n", 318 | " return\n", 319 | " \n", 320 | " # Traverse till the last node\n", 321 | " last = self.head\n", 322 | " while (last.next):\n", 323 | " last = last.next\n", 324 | " \n", 325 | " last.next = new_node" 326 | ] 327 | }, 328 | { 329 | "cell_type": "code", 330 | "execution_count": 48, 331 | "metadata": {}, 332 | "outputs": [ 333 | { 334 | "name": "stdout", 335 | "output_type": "stream", 336 | "text": [ 337 | "1 -> 7 -> 8 -> 6 -> 4 -> None\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "llist1 = LinkedList()\n", 343 | "llist1.append(6)\n", 344 | "llist1.push(7)\n", 345 | "llist1.push(1)\n", 346 | "llist1.append(4)\n", 347 | "llist1.insert_after(llist1.head.next, 8)\n", 348 | "llist1.print_llist()" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "------------\n", 356 | "## Set 3 | Deleting a node\n", 357 | "\n", 358 | "To delete a node from the linked list, we need to do the following:\n", 359 | "1. Find the previous node of the node to be deleted.\n", 360 | "2. Change the next of the previous node.\n", 361 | "3. Free memory for the node to be deleted.\n", 362 | "\n", 363 | "![image](Linkedlist_deletion.png)" 364 | ] 365 | }, 366 | { 367 | "cell_type": "code", 368 | "execution_count": 50, 369 | "metadata": {}, 370 | "outputs": [], 371 | "source": [ 372 | " class LinkedList:\n", 373 | " \n", 374 | " def __init__(self):\n", 375 | " self.head = None\n", 376 | " \n", 377 | " def print_llist(self):\n", 378 | " \"\"\"Prints the data from the linked list\"\"\"\n", 379 | " tmp = self.head\n", 380 | " while (tmp):\n", 381 | " print(tmp.data, end=' -> ')\n", 382 | " tmp = tmp.next\n", 383 | " print('None')\n", 384 | " \n", 385 | " def push(self, new_data):\n", 386 | " \"\"\"Inserts node at the beginning\"\"\"\n", 387 | " new_node = Node(new_data)\n", 388 | " new_node.next = self.head\n", 389 | " self.head = new_node\n", 390 | " \n", 391 | " def insert_after(self, prev_node, new_data):\n", 392 | " \"\"\"Inserts node after given node\"\"\"\n", 393 | " if prev_node is None:\n", 394 | " return \"Previous node must be in linked list\"\n", 395 | " new_node = Node(new_data) \n", 396 | " new_node.next = prev_node.next\n", 397 | " prev_node.next = new_node\n", 398 | " \n", 399 | " \n", 400 | " def append(self, new_data):\n", 401 | " \"\"\"Appends node at the end of the linked list\"\"\"\n", 402 | " new_node = Node(new_data)\n", 403 | " if self.head is None:\n", 404 | " self.head = new_node\n", 405 | " return\n", 406 | " last = self.head\n", 407 | " while last.next:\n", 408 | " last = last.next\n", 409 | " last.next = new_node\n", 410 | " \n", 411 | " # New function to delete a node\n", 412 | " def delete_node(self, key):\n", 413 | " \"\"\"Deletes the first occurance of the key\"\"\"\n", 414 | " tmp = self.head\n", 415 | " \n", 416 | " # If the head node holds the key to be deleted\n", 417 | " if tmp is not None:\n", 418 | " if tmp.data == key:\n", 419 | " self.head = tmp.next\n", 420 | " tmp = None\n", 421 | " return\n", 422 | " \n", 423 | " # Search for the key to be deleted\n", 424 | " while tmp is not None:\n", 425 | " if tmp.data == key:\n", 426 | " break\n", 427 | " prev = tmp\n", 428 | " tmp = tmp.next\n", 429 | " \n", 430 | " # If key was not found\n", 431 | " if tmp == None:\n", 432 | " return\n", 433 | " \n", 434 | " # Unlink the node from linked list\n", 435 | " prev.next = tmp.next\n", 436 | " tmp = None" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": 52, 442 | "metadata": {}, 443 | "outputs": [ 444 | { 445 | "name": "stdout", 446 | "output_type": "stream", 447 | "text": [ 448 | "Created Linked List: \n", 449 | "2 -> 3 -> 1 -> 7 -> None\n", 450 | "\n", 451 | "Linked List after Deletion of 1:\n", 452 | "2 -> 3 -> 7 -> None\n" 453 | ] 454 | } 455 | ], 456 | "source": [ 457 | "llist2 = LinkedList() \n", 458 | "llist2.push(7) \n", 459 | "llist2.push(1) \n", 460 | "llist2.push(3) \n", 461 | "llist2.push(2) \n", 462 | " \n", 463 | "print(\"Created Linked List: \") \n", 464 | "llist2.print_llist() \n", 465 | "llist2.delete_node(1) \n", 466 | "print(\"\\nLinked List after Deletion of 1:\") \n", 467 | "llist2.print_llist() " 468 | ] 469 | }, 470 | { 471 | "cell_type": "markdown", 472 | "metadata": {}, 473 | "source": [ 474 | "---------\n", 475 | "## Set 4 | Deleting a note at a given position\n", 476 | "\n", 477 | "If the node to be deleted is the root, simply delete it. To delete a middle node, we must have a pointer to the node previous to the node to be deleted. So if positions are not zero, we run a loop position-1 times and get a pointer to the previous node." 478 | ] 479 | }, 480 | { 481 | "cell_type": "code", 482 | "execution_count": 53, 483 | "metadata": {}, 484 | "outputs": [], 485 | "source": [ 486 | " class LinkedList:\n", 487 | " \n", 488 | " def __init__(self):\n", 489 | " self.head = None\n", 490 | " \n", 491 | " def print_llist(self):\n", 492 | " \"\"\"Prints the data from the linked list\"\"\"\n", 493 | " tmp = self.head\n", 494 | " while tmp:\n", 495 | " print(tmp.data, end=' -> ')\n", 496 | " tmp = tmp.next\n", 497 | " print('None')\n", 498 | " \n", 499 | " def push(self, new_data):\n", 500 | " \"\"\"Inserts node at the beginning\"\"\"\n", 501 | " new_node = Node(new_data)\n", 502 | " new_node.next = self.head\n", 503 | " self.head = new_node\n", 504 | " \n", 505 | " def insert_after(self, prev_node, new_data):\n", 506 | " \"\"\"Inserts node after given node\"\"\"\n", 507 | " if prev_node is None:\n", 508 | " return \"Previous node must be in linked list\"\n", 509 | " new_node = Node(new_data) \n", 510 | " new_node.next = prev_node.next\n", 511 | " prev_node.next = new_node\n", 512 | " \n", 513 | " \n", 514 | " def append(self, new_data):\n", 515 | " \"\"\"Appends node at the end of the linked list\"\"\"\n", 516 | " new_node = Node(new_data)\n", 517 | " if self.head is None:\n", 518 | " self.head = new_node\n", 519 | " return\n", 520 | " last = self.head\n", 521 | " while last.next:\n", 522 | " last = last.next\n", 523 | " last.next = new_node\n", 524 | "\n", 525 | " def delete_node(self, key):\n", 526 | " \"\"\"Deletes the first occurance of the key\"\"\"\n", 527 | " tmp = self.head\n", 528 | " if tmp is not None:\n", 529 | " if tmp.data == key:\n", 530 | " self.head = tmp.next\n", 531 | " tmp = None\n", 532 | " return\n", 533 | " while tmp is not None:\n", 534 | " if tmp.data == key:\n", 535 | " break\n", 536 | " prev = tmp\n", 537 | " tmp = tmp.next\n", 538 | " if tmp == None:\n", 539 | " return\n", 540 | " prev.next = tmp.next\n", 541 | " tmp = None\n", 542 | " \n", 543 | " # New function to delete a node at a given position\n", 544 | " def delete_at(self, position):\n", 545 | " \"\"\"Deletes node at a given position\"\"\"\n", 546 | " # If linked list empty\n", 547 | " if self.head is None:\n", 548 | " return\n", 549 | " \n", 550 | " tmp = self.head\n", 551 | " \n", 552 | " # If heads need to be removed\n", 553 | " if position == 0:\n", 554 | " self.head = tmp.next\n", 555 | " tmp = None\n", 556 | " \n", 557 | " # Find previous node of the node to be deleted\n", 558 | " for i in range(position - 1):\n", 559 | " tmp = tmp.next\n", 560 | " if tmp is None:\n", 561 | " break\n", 562 | " \n", 563 | " # If position is more than number of nodes\n", 564 | " if tmp is None or tmp.next is None:\n", 565 | " return \n", 566 | " \n", 567 | " # Node temp.next is the node to be deleted \n", 568 | " # store pointer to the next of node to be deleted\n", 569 | " next_node = tmp.next.next\n", 570 | " \n", 571 | " # Unlink the node\n", 572 | " tmp.next = None\n", 573 | " tmp.next = next_node" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": 54, 579 | "metadata": {}, 580 | "outputs": [ 581 | { 582 | "name": "stdout", 583 | "output_type": "stream", 584 | "text": [ 585 | "Created Linked List: \n", 586 | "8 -> 2 -> 3 -> 1 -> 7 -> None\n", 587 | "\n", 588 | "Linked List after Deletion at position 4: \n", 589 | "8 -> 2 -> 1 -> 7 -> None\n" 590 | ] 591 | } 592 | ], 593 | "source": [ 594 | "llist3 = LinkedList() \n", 595 | "llist3.push(7) \n", 596 | "llist3.push(1) \n", 597 | "llist3.push(3) \n", 598 | "llist3.push(2) \n", 599 | "llist3.push(8) \n", 600 | " \n", 601 | "print(\"Created Linked List: \")\n", 602 | "llist3.print_llist() \n", 603 | "llist3.delete_at(2) \n", 604 | "print(\"\\nLinked List after Deletion at position 4: \")\n", 605 | "llist3.print_llist() " 606 | ] 607 | }, 608 | { 609 | "cell_type": "code", 610 | "execution_count": null, 611 | "metadata": {}, 612 | "outputs": [], 613 | "source": [] 614 | } 615 | ], 616 | "metadata": { 617 | "kernelspec": { 618 | "display_name": "Python 3.8.2 64-bit", 619 | "language": "python", 620 | "name": "python38264bitc1c0e47f0bef41228abb9a7d720d2718" 621 | }, 622 | "language_info": { 623 | "codemirror_mode": { 624 | "name": "ipython", 625 | "version": 3 626 | }, 627 | "file_extension": ".py", 628 | "mimetype": "text/x-python", 629 | "name": "python", 630 | "nbconvert_exporter": "python", 631 | "pygments_lexer": "ipython3", 632 | "version": "3.8.5" 633 | } 634 | }, 635 | "nbformat": 4, 636 | "nbformat_minor": 4 637 | } 638 | --------------------------------------------------------------------------------