From be31c486c4b6c688d76c2bfb796fb9f24da3f5a8 Mon Sep 17 00:00:00 2001 From: Anshul Choudhary <34908313+achoudh5@users.noreply.github.com> Date: Sun, 6 Oct 2019 12:30:38 -0400 Subject: [PATCH 001/455] Update useful_links.md --- useful_links.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index 3058ba55..cb105393 100644 --- a/useful_links.md +++ b/useful_links.md @@ -62,6 +62,10 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://hacktoberfestswaglist.com/#least-involvement-to-most-involvement +- https://networklore.com/ansible/ + +- https://www.quora.com/How-is-VPN-different-from-proxy + ## Others @@ -73,4 +77,4 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://wsvincent.com/ -- https://machinelearningmastery.com \ No newline at end of file +- https://machinelearningmastery.com From 80e15602183aec37ab8c50b283d9c38eee6704d4 Mon Sep 17 00:00:00 2001 From: Mauro Coppola Date: Sun, 6 Oct 2019 19:35:48 +0200 Subject: [PATCH 002/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c09ffad..7da39334 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called `useful_links.txt` and 2 main directories: **Data Structures** and **Algorithms**. +As of now, the repository contains a file called [`useful_links.txt`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. ### Data Structures From eb5f09c21183a1ce5cc1d2da5217370514d56e78 Mon Sep 17 00:00:00 2001 From: Mauro Coppola Date: Sun, 6 Oct 2019 19:37:39 +0200 Subject: [PATCH 003/455] Minor fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7da39334..1d6c7a6a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`useful_links.txt`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. +As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. ### Data Structures From 7bbaf4844deccbfc2f46b8611cb0a1ca63b5e54e Mon Sep 17 00:00:00 2001 From: Ayush Shukla Date: Mon, 7 Oct 2019 00:27:42 +0530 Subject: [PATCH 004/455] Added more resources to the repository --- useful_links.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index 3058ba55..7eddbab6 100644 --- a/useful_links.md +++ b/useful_links.md @@ -1,6 +1,6 @@ # Useful links -This is a list of articles, tutorials, questions and videos that may be useful for algorithms and data structures learning. +This is a list of articles, tutorials, questions, books and videos that may be useful for algorithms and data structures learning. ## Questions @@ -16,10 +16,16 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://github.com/eon01/kubernetes-workshop +- http://cp-algorithms.com/ + +- https://www.hackerearth.com/practice/codemonk/ + ## Videos - https://www.youtube.com/watch?v=mSzUb7f47qk +- https://www.youtube.com/user/mycodeschool + ## Topics - https://en.wikipedia.org/wiki/Data_deduplication @@ -28,8 +34,18 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://docs.gitlab.com/ce/development/architecture.html +## Books + +- https://drive.google.com/open?id=1d23_sJdK8XPBJEi-4oUrMnrYMhU2fDcI + +- https://drive.google.com/open?id=1sBSGJ8gUakcn0NuQam4BRhRCQfsTrrwh + ## Articles +- https://www.topcoder.com/community/competitive-programming/tutorials/dynamic-programming-from-novice-to-advanced/ + +- https://www.hackerearth.com/practice/notes/getting-started-with-the-sport-of-programming/ + - https://github.com/alex/what-happens-when - https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a From 58a2bca935105dac8e7d39e365da83aac7442e6b Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 6 Oct 2019 23:07:20 +0200 Subject: [PATCH 005/455] A @dataclass tutorial Really cool feature from Python 3.7 :) --- useful_links.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index 3058ba55..ce26f9db 100644 --- a/useful_links.md +++ b/useful_links.md @@ -16,6 +16,9 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://github.com/eon01/kubernetes-workshop +- https://realpython.com/python-data-classes/ + + ## Videos - https://www.youtube.com/watch?v=mSzUb7f47qk @@ -73,4 +76,4 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://wsvincent.com/ -- https://machinelearningmastery.com \ No newline at end of file +- https://machinelearningmastery.com From cfac62b2e6f71a2ddb8dbbe706e314dea0b61586 Mon Sep 17 00:00:00 2001 From: BiaHawk <48568610+BiaHawk@users.noreply.github.com> Date: Sun, 6 Oct 2019 19:08:54 -0300 Subject: [PATCH 006/455] Add files via upload --- .../doubly_linked_list/doubly_linked_list.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 data_structures/doubly_linked_list/doubly_linked_list.py diff --git a/data_structures/doubly_linked_list/doubly_linked_list.py b/data_structures/doubly_linked_list/doubly_linked_list.py new file mode 100644 index 00000000..2702ac1a --- /dev/null +++ b/data_structures/doubly_linked_list/doubly_linked_list.py @@ -0,0 +1,75 @@ +class Node: + def __init__(self, data = None, next, previous = None): + self.data = data + self.next = None + self.previous = previous + +class Lista: + + def __init__(self): + self.first = self.last = Node() + + def empty(self): + return self.first.data == self.last.data + + + def search(self, data): + if self.empty(): return None + + auxiliar = self.first.next + while auxiliar.next != None and auxiliar.data != data: + auxiliar = auxiliar.next + + if auxiliar.data == data: + return auxiliar.data + + return None + + def append(self, data): + self.last.next = Node(data = data, next = None, previous = self.last) + self.last = self.last.next + + + def __str__(self): + + if self.empty(): + return "" + + aux = self.first + format_ = "" + + while aux.next != None: + if aux.data!= None: + format_ += str(aux.data) + " " + aux = aux.next + format_ += str(aux.data) + "" + + return format_ + + def remove(self, data): + if self.empty(): return None + + auxiliar = self.first.next + + while auxiliar != None and auxiliar.data != data: + auxiliar = auxiliar.next + + if auxiliar == None: return None + else: + item = auxiliar.data + + if auxiliar.previous != None: + auxiliar.previous.next = auxiliar.next + if auxiliar.next != None: + auxiliar.next.previous = auxiliar.previous + + if self.empty(): self.last = self.first = Node() + elif auxiliar.next == None: self.last = auxiliar.previous + + del auxiliar + return item + + + + #the auxiliar variable is to help like a flag in the code, like aux too + #If something isn't right, or in another language it is bc I am a native portuguese speaker, so I translated my code From 7d4a7cd6e4272de53f726926470c67f747fcbf30 Mon Sep 17 00:00:00 2001 From: Targgus Date: Sun, 6 Oct 2019 17:08:08 -0600 Subject: [PATCH 007/455] Added Select Sort --- data_structures/array/select_sort.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 data_structures/array/select_sort.py diff --git a/data_structures/array/select_sort.py b/data_structures/array/select_sort.py new file mode 100644 index 00000000..51322430 --- /dev/null +++ b/data_structures/array/select_sort.py @@ -0,0 +1,26 @@ + +def findSmallest(arr): + smallest = arr[0] + smallest_index = 0 + + for i in range(1, len(arr)): + + if arr[i] < smallest: + smallest = arr[i] + smallest_index = i + return smallest_index + + + +def selectionSort(arr): + newArr = [] + + for i in range(len(arr)): + smallest = findSmallest(arr) + newArr.append(arr.pop(smallest)) + + return newArr + +array = [100, 5, 72, 41, 80, 1, 99, 36, 27, 78] + +print(selectionSort(array)) # [1, 5, 27, 36, 41, 72, 78, 80, 99, 100] \ No newline at end of file From b564f0811c5e494c52e5a3cdb6f1d301c958ae1d Mon Sep 17 00:00:00 2001 From: Simon Bukin Date: Sun, 6 Oct 2019 17:07:49 -0700 Subject: [PATCH 008/455] Add insertion sort algorithm --- data_structures/array/insertion_sort.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 data_structures/array/insertion_sort.py diff --git a/data_structures/array/insertion_sort.py b/data_structures/array/insertion_sort.py new file mode 100644 index 00000000..59d381e1 --- /dev/null +++ b/data_structures/array/insertion_sort.py @@ -0,0 +1,17 @@ +""" +High Level Description: +For every element in the given list, find it's correct index by iterating +backwards and finding a slot. This forms a sorted array. + +Time Complexity: +Every element is visited, which contributes O(n). Swapping backwards takes +O(n/2) time on average, meaning that the total complexity is O(n^2) +""" + +def insertion_sort(lst): + for i, _ in enumerate(lst): + j = i + while(j > 0 and lst[i] < lst[j]): + j -= 1 + lst[j], lst[i] = lst[i], lst[j] + return lst \ No newline at end of file From 002a0e393b78d99a986781fee82656c5fe60a7f9 Mon Sep 17 00:00:00 2001 From: Simon Bukin Date: Sun, 6 Oct 2019 17:12:02 -0700 Subject: [PATCH 009/455] add insertion sort algorithm --- data_structures/array/insertion-sort.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 data_structures/array/insertion-sort.py diff --git a/data_structures/array/insertion-sort.py b/data_structures/array/insertion-sort.py new file mode 100644 index 00000000..59d381e1 --- /dev/null +++ b/data_structures/array/insertion-sort.py @@ -0,0 +1,17 @@ +""" +High Level Description: +For every element in the given list, find it's correct index by iterating +backwards and finding a slot. This forms a sorted array. + +Time Complexity: +Every element is visited, which contributes O(n). Swapping backwards takes +O(n/2) time on average, meaning that the total complexity is O(n^2) +""" + +def insertion_sort(lst): + for i, _ in enumerate(lst): + j = i + while(j > 0 and lst[i] < lst[j]): + j -= 1 + lst[j], lst[i] = lst[i], lst[j] + return lst \ No newline at end of file From 9f1b9999d4e1740a32c01295587b6a17a70f8030 Mon Sep 17 00:00:00 2001 From: Simon Bukin Date: Sun, 6 Oct 2019 17:14:06 -0700 Subject: [PATCH 010/455] fix duped file --- data_structures/array/insertion-sort.py | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 data_structures/array/insertion-sort.py diff --git a/data_structures/array/insertion-sort.py b/data_structures/array/insertion-sort.py deleted file mode 100644 index 59d381e1..00000000 --- a/data_structures/array/insertion-sort.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -High Level Description: -For every element in the given list, find it's correct index by iterating -backwards and finding a slot. This forms a sorted array. - -Time Complexity: -Every element is visited, which contributes O(n). Swapping backwards takes -O(n/2) time on average, meaning that the total complexity is O(n^2) -""" - -def insertion_sort(lst): - for i, _ in enumerate(lst): - j = i - while(j > 0 and lst[i] < lst[j]): - j -= 1 - lst[j], lst[i] = lst[i], lst[j] - return lst \ No newline at end of file From efb9047a61626276e2d2edf5400104a3fae60c55 Mon Sep 17 00:00:00 2001 From: Targgus Date: Sun, 6 Oct 2019 19:04:19 -0600 Subject: [PATCH 011/455] Added Quick Sort --- data_structures/array/quick_sort.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 data_structures/array/quick_sort.py diff --git a/data_structures/array/quick_sort.py b/data_structures/array/quick_sort.py new file mode 100644 index 00000000..ddc87147 --- /dev/null +++ b/data_structures/array/quick_sort.py @@ -0,0 +1,23 @@ +""" +Quicksort Running Time: +Quick sort average case is O(n log n) + each level takes O(n) but splitting the data is O(log n) + O(n) * O(log n) = O(n log n) +Worse case is O(log n2) + if pivot is smallest value, each level is O(n) and splitting the data is O(n) + O(n) * O(n) = O(n2) +""" + +# quicksort function +def quicksort(array): + if len(array) < 2: + return array + else: + pivot = array[0] + less = [i for i in array[1:] if i <= pivot] + greater = [i for i in array[1:] if i > pivot] + return quicksort(less) + [pivot] + quicksort(greater) + +array = [100, 5, 72, 41, 80, 1, 99, 36, 27, 78] +print(quicksort(array)) # [1, 5, 27, 36, 41, 72, 78, 80, 99, 100] + From e9130b56e036627c9d1e38876bf92d8d971f96e6 Mon Sep 17 00:00:00 2001 From: AbbasAbi <53376159+AbbasAbi@users.noreply.github.com> Date: Mon, 7 Oct 2019 07:19:56 +0330 Subject: [PATCH 012/455] Dynamic programing The description of Dynamic programming with Python examples. --- useful_links.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index 3058ba55..3d34b1e8 100644 --- a/useful_links.md +++ b/useful_links.md @@ -62,6 +62,8 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://hacktoberfestswaglist.com/#least-involvement-to-most-involvement +- https://skerritt.blog/dynamic-programming/ + ## Others @@ -73,4 +75,4 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://wsvincent.com/ -- https://machinelearningmastery.com \ No newline at end of file +- https://machinelearningmastery.com From a54bb441c31d70296000c0a9ebf17aa7bea8da07 Mon Sep 17 00:00:00 2001 From: Sayak Naskar Date: Mon, 7 Oct 2019 11:13:40 +0530 Subject: [PATCH 013/455] Add owasp-top-10-security-risks-part-iv.html --- useful_links.md | 1 + 1 file changed, 1 insertion(+) diff --git a/useful_links.md b/useful_links.md index 3d34b1e8..ba783912 100644 --- a/useful_links.md +++ b/useful_links.md @@ -64,6 +64,7 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://skerritt.blog/dynamic-programming/ +- https://blog.sucuri.net/2019/01/owasp-top-10-security-risks-part-iv.html ## Others From 0fbd4e554cb906c0c54d23b9e89d8bc49d87a535 Mon Sep 17 00:00:00 2001 From: Simon Bukin Date: Sun, 6 Oct 2019 22:49:02 -0700 Subject: [PATCH 014/455] Move insertion-sort to algorithms/sorting --- {data_structures/array => algorithms/sorting}/insertion_sort.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {data_structures/array => algorithms/sorting}/insertion_sort.py (100%) diff --git a/data_structures/array/insertion_sort.py b/algorithms/sorting/insertion_sort.py similarity index 100% rename from data_structures/array/insertion_sort.py rename to algorithms/sorting/insertion_sort.py From 26210aed49fcc25ea758d34687e0a36e750862a6 Mon Sep 17 00:00:00 2001 From: kibe <47016873+kibebr@users.noreply.github.com> Date: Mon, 7 Oct 2019 05:54:37 -0400 Subject: [PATCH 015/455] Grammar it's -> its --- algorithms/sorting/insertion_sort.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algorithms/sorting/insertion_sort.py b/algorithms/sorting/insertion_sort.py index 59d381e1..30f77694 100644 --- a/algorithms/sorting/insertion_sort.py +++ b/algorithms/sorting/insertion_sort.py @@ -1,6 +1,6 @@ """ High Level Description: -For every element in the given list, find it's correct index by iterating +For every element in the given list, find its correct index by iterating backwards and finding a slot. This forms a sorted array. Time Complexity: @@ -14,4 +14,4 @@ def insertion_sort(lst): while(j > 0 and lst[i] < lst[j]): j -= 1 lst[j], lst[i] = lst[i], lst[j] - return lst \ No newline at end of file + return lst From 183f1f1b154dd3064b521b49fcbe7be45c394a91 Mon Sep 17 00:00:00 2001 From: Mohit Saini Date: Mon, 7 Oct 2019 16:42:20 +0530 Subject: [PATCH 016/455] added gcd --- algorithms/math/greatest_common_divisor.py | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 algorithms/math/greatest_common_divisor.py diff --git a/algorithms/math/greatest_common_divisor.py b/algorithms/math/greatest_common_divisor.py new file mode 100644 index 00000000..05f57ce0 --- /dev/null +++ b/algorithms/math/greatest_common_divisor.py @@ -0,0 +1,29 @@ +""" +High Level Description: +Given two input integers, find their Greatest Common Divisor. + +Time Complexity: +O(log(n)) +""" +# Iterative Solution +def gcd(x, y): + if x==0: + return y + if y==0: + return x + + while x%y != 0: + rem = x%y; + x = y + y = rem + + return y + +# Recursive Solution +def gcd(x, y): + if x==0: + return y + if y==0: + return x + + return gcd(y, x%y) \ No newline at end of file From ba14beea8a55c17f2f8dce6e430ca53c72ba78ba Mon Sep 17 00:00:00 2001 From: Sayak Naskar Date: Mon, 7 Oct 2019 17:08:31 +0530 Subject: [PATCH 017/455] Update useful_links.md --- useful_links.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index ba783912..b0108a2b 100644 --- a/useful_links.md +++ b/useful_links.md @@ -30,6 +30,8 @@ This is a list of articles, tutorials, questions and videos that may be useful f ## Articles +- https://blog.sucuri.net/2019/01/owasp-top-10-security-risks-part-iv.html + - https://github.com/alex/what-happens-when - https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a @@ -64,7 +66,6 @@ This is a list of articles, tutorials, questions and videos that may be useful f - https://skerritt.blog/dynamic-programming/ -- https://blog.sucuri.net/2019/01/owasp-top-10-security-risks-part-iv.html ## Others From 892156f4a9588c0bd785ed4b8051976fd596d7c3 Mon Sep 17 00:00:00 2001 From: Sayak Naskar Date: Mon, 7 Oct 2019 17:13:42 +0530 Subject: [PATCH 018/455] Update useful_links.md --- useful_links.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/useful_links.md b/useful_links.md index 1638c143..60d93df1 100644 --- a/useful_links.md +++ b/useful_links.md @@ -42,8 +42,6 @@ This is a list of articles, tutorials, questions, books and videos that may be u ## Articles -- https://blog.sucuri.net/2019/01/owasp-top-10-security-risks-part-iv.html - - https://www.topcoder.com/community/competitive-programming/tutorials/dynamic-programming-from-novice-to-advanced/ - https://www.hackerearth.com/practice/notes/getting-started-with-the-sport-of-programming/ @@ -52,6 +50,8 @@ This is a list of articles, tutorials, questions, books and videos that may be u - https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a +- https://blog.sucuri.net/2019/01/owasp-top-10-security-risks-part-iv.html + - https://www.cloudflare.com/learning/dns/what-is-dns/ - https://www.keycdn.com/blog/difference-between-http-and-https From fb9e9cfd50d291dbcedd485c74227d3522fb2f55 Mon Sep 17 00:00:00 2001 From: Sayak Naskar Date: Mon, 7 Oct 2019 17:20:39 +0530 Subject: [PATCH 019/455] Update useful_links.md --- useful_links.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index 60d93df1..5299774d 100644 --- a/useful_links.md +++ b/useful_links.md @@ -50,7 +50,7 @@ This is a list of articles, tutorials, questions, books and videos that may be u - https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a -- https://blog.sucuri.net/2019/01/owasp-top-10-security-risks-part-iv.html +- https://blog.sucuri.net/2018/10/owasp-top-10-security-risks-part-i.html - https://www.cloudflare.com/learning/dns/what-is-dns/ From 6bb4eed15631583a13a90f1ef797e15296a8a335 Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Mon, 7 Oct 2019 17:45:47 +0530 Subject: [PATCH 020/455] Added a minimal logo as required! --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9db3c80c..621c2b80 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Python Data Structures +# Python Data Structures This repository contains data structures and algorithms questions in Python. ## :dart: Objective -The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: +The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavor to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: ## :file_folder: Structure of the repository @@ -12,7 +12,7 @@ As of now, the repository contains a file called `useful_links.txt` and 2 main d ### Data Structures -Contains all data structure questions categorised into sub-directories like stack, queue, etc according to their type. +Contains all data structure questions categorized into sub-directories like stack, queue, etc. according to their type. 1. Array 2. Dictionary From 4c81c0452c9406df20c5961b08a9cf472c38df94 Mon Sep 17 00:00:00 2001 From: John Henson Date: Mon, 7 Oct 2019 06:32:24 -0600 Subject: [PATCH 021/455] Moved select_sort.py to algorithms/sorting/ --- {data_structures/array => algorithms/sorting}/select_sort.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {data_structures/array => algorithms/sorting}/select_sort.py (100%) diff --git a/data_structures/array/select_sort.py b/algorithms/sorting/select_sort.py similarity index 100% rename from data_structures/array/select_sort.py rename to algorithms/sorting/select_sort.py From c25535cd59c42b6bb973f876d2bd29b767eb7bf1 Mon Sep 17 00:00:00 2001 From: brilam Date: Mon, 7 Oct 2019 09:13:07 -0400 Subject: [PATCH 022/455] Added Check Permutations question from CTCI Q 1.2 --- algorithms/strings/check_permutations.py | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 algorithms/strings/check_permutations.py diff --git a/algorithms/strings/check_permutations.py b/algorithms/strings/check_permutations.py new file mode 100644 index 00000000..3763159b --- /dev/null +++ b/algorithms/strings/check_permutations.py @@ -0,0 +1,51 @@ +""" +Question: +Check Permutation: Given two strings, write a method to decide if +one is a permutation of the other. +Source: Cracking the Code Interview 6th Edition Question 1.2 + +Time Complexity: +Every letter must be looped which means O(n) time complexity. Then, +we must check if each letter is in the dictionary which is another +O(n) time complexity. Overall, the total time complexity is O(n^2). +""" + +letter_counts = {} + + +def check_permutations(word1, word2): + # Case 1: Not matching length + if len(word1) != len(word2): + return False + # Case 2: Both strings have a length of zero + if len(word1) == 0 and len(word2) == 0: + return True + # Case 3: One Letter Strings + if len(word1) == 1 and len(word2) == 1: + return word1[0] == word2[0] + # Case 4: Length greater than 1 for both strings and lengths are equal + else: + populate_letter_count(word1) + # Loop through each letter (looping is an O(n) operation) + for letter in word2: + # Check if it the letter is in the dictionary (checking is O(n) operation) + if letter_counts.get(letter) is not None: + curr_count = letter_counts.get(letter) + if curr_count == 1: + letter_counts.pop(letter) + else: + letter_counts[letter] = curr_count - 1 + else: + return False + return True + + +def populate_letter_count(word1): + # Loop through each letter (looping is an O(n) operation) + for letter in word1: + # Check if it the letter is in the dictionary (checking is O(n) operation) + if letter_counts.get(letter) is None: + letter_counts[letter] = 1 + else: + curr_count = letter_counts.get(letter) + 1 + letter_counts[letter] = curr_count From 0270d6a2a3636a563755a6a85001c6a23e2250f4 Mon Sep 17 00:00:00 2001 From: Suprit Bhattacharjee Date: Mon, 7 Oct 2019 18:59:26 +0530 Subject: [PATCH 023/455] Added LCS --- algorithms/dynamic_programming/lcs.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 algorithms/dynamic_programming/lcs.py diff --git a/algorithms/dynamic_programming/lcs.py b/algorithms/dynamic_programming/lcs.py new file mode 100644 index 00000000..5a5f97ad --- /dev/null +++ b/algorithms/dynamic_programming/lcs.py @@ -0,0 +1,25 @@ +''' +We are given two sequences and we +need to find the length of the +longest common subsequence +''' + +def lcs(S1, S2): + m = len(S1) + n = len(S2) + + + LCS = [[-1]*(n + 1) for i in range(m + 1)] + + + for i in range(m + 1): + for j in range(n + 1): + if i == 0 or j == 0 : + LCS[i][j] = 0 + elif S1[i-1] == S2[j-1]: + LCS[i][j] = LCS[i-1][j-1]+1 + else: + LCS[i][j] = max(LCS[i-1][j], LCS[i][j-1]) + + + return LCS[m][n] From 24a9975fe758b8b4cddcfc2c7c713dcc89bab527 Mon Sep 17 00:00:00 2001 From: Suprit Bhattacharjee Date: Mon, 7 Oct 2019 19:07:24 +0530 Subject: [PATCH 024/455] Added Rod Cutting Problem --- algorithms/dynamic_programming/lcs.py | 5 +---- algorithms/dynamic_programming/rod_cutting.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 algorithms/dynamic_programming/rod_cutting.py diff --git a/algorithms/dynamic_programming/lcs.py b/algorithms/dynamic_programming/lcs.py index 5a5f97ad..b6adc851 100644 --- a/algorithms/dynamic_programming/lcs.py +++ b/algorithms/dynamic_programming/lcs.py @@ -1,17 +1,15 @@ ''' We are given two sequences and we need to find the length of the -longest common subsequence +longest common subsequence ''' def lcs(S1, S2): m = len(S1) n = len(S2) - LCS = [[-1]*(n + 1) for i in range(m + 1)] - for i in range(m + 1): for j in range(n + 1): if i == 0 or j == 0 : @@ -21,5 +19,4 @@ def lcs(S1, S2): else: LCS[i][j] = max(LCS[i-1][j], LCS[i][j-1]) - return LCS[m][n] diff --git a/algorithms/dynamic_programming/rod_cutting.py b/algorithms/dynamic_programming/rod_cutting.py new file mode 100644 index 00000000..c11d1085 --- /dev/null +++ b/algorithms/dynamic_programming/rod_cutting.py @@ -0,0 +1,17 @@ +INT_MIN = -32767 + +def cutRod(price, n): + values = [0 for i in range(n+1)] + values[0] = 0 + + for i in range(1, n+1): + max_value = INT_MIN + for j in range(i): + max_value = max(max_value, price[j] + values[i-j-1]) + values[i] = max_value + + return values[n] + +arr = [1, 5, 8, 9, 10, 17, 17, 20] +size = len(arr) +print("Maximum Obtainable Value is " + str(cutRod(arr, size))) From 174517e756aff046b9b91005029aaf389cdae593 Mon Sep 17 00:00:00 2001 From: Suprit Bhattacharjee Date: Mon, 7 Oct 2019 19:12:34 +0530 Subject: [PATCH 025/455] Added problem statement --- algorithms/dynamic_programming/rod_cutting.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/algorithms/dynamic_programming/rod_cutting.py b/algorithms/dynamic_programming/rod_cutting.py index c11d1085..6db53392 100644 --- a/algorithms/dynamic_programming/rod_cutting.py +++ b/algorithms/dynamic_programming/rod_cutting.py @@ -1,3 +1,11 @@ +''' +Given a rod of length n units and an +array of prices that contains prices +of all pieces of size less than n. We +need to find the maximum maximum price +obtainable by cutting the rod and +selling it. +''' INT_MIN = -32767 def cutRod(price, n): @@ -11,7 +19,3 @@ def cutRod(price, n): values[i] = max_value return values[n] - -arr = [1, 5, 8, 9, 10, 17, 17, 20] -size = len(arr) -print("Maximum Obtainable Value is " + str(cutRod(arr, size))) From f00ad4c08f84082aaba4955d4f90341a75dca05f Mon Sep 17 00:00:00 2001 From: Suprit Bhattacharjee Date: Mon, 7 Oct 2019 19:27:12 +0530 Subject: [PATCH 026/455] Renamed lcs.py --- .../dynamic_programming/{lcs.py => longest_common_subsequence.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename algorithms/dynamic_programming/{lcs.py => longest_common_subsequence.py} (100%) diff --git a/algorithms/dynamic_programming/lcs.py b/algorithms/dynamic_programming/longest_common_subsequence.py similarity index 100% rename from algorithms/dynamic_programming/lcs.py rename to algorithms/dynamic_programming/longest_common_subsequence.py From 1a1d38e964a65f7eccddcabb3fcff49b20152230 Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Mon, 7 Oct 2019 19:57:27 +0530 Subject: [PATCH 027/455] Changed the logo, with the link as required. --- README.md | 2 +- logo/PDS.png | Bin 0 -> 22034 bytes logo/logo.png | Bin 0 -> 12958 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 logo/PDS.png create mode 100644 logo/logo.png diff --git a/README.md b/README.md index 621c2b80..06295444 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Python Data Structures +# Python Data Structures This repository contains data structures and algorithms questions in Python. diff --git a/logo/PDS.png b/logo/PDS.png new file mode 100644 index 0000000000000000000000000000000000000000..6b78ac13e6ce560ea2e53592dc6b3c673aa68cfb GIT binary patch literal 22034 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 literal 0 HcmV?d00001 diff --git a/logo/logo.png b/logo/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f535e3f29976b84a3669ab439235afaea4f6cc GIT binary patch literal 12958 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 literal 0 HcmV?d00001 From 352d5adba0e7cdf85d7e19a4e3b8c576bb5f46a9 Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Mon, 7 Oct 2019 20:37:10 +0530 Subject: [PATCH 028/455] Added the array rotation question, without using temp array. --- data_structures/array/Array_Rotations.py | 61 ++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 data_structures/array/Array_Rotations.py diff --git a/data_structures/array/Array_Rotations.py b/data_structures/array/Array_Rotations.py new file mode 100644 index 00000000..509bc5ca --- /dev/null +++ b/data_structures/array/Array_Rotations.py @@ -0,0 +1,61 @@ +""" +Array Rotations:- + +Given an array, rotate the elements of the array without using the temp array. + +Solution:- + Rotate the given array one at a time, and then call the rotation function n times,(n being the times rotated) + +Note:- Code using the temp array is also given. +""" + +#==================== Method 1: Using Temp array to do so, takes O(n) time.====================== + +# def rotations(L, N, D): +# temp = [] + +# for a in range(0, d): +# temp.append(L[a]) + +# for a in range(0, n-d): +# L[a] = L[a+d] + +# for a in range(0, d): +# L.append(temp[a]) + +# print(L) + + + +# n=8 +# d=3 +# rotations(L, n ,d) + +# ============ Method 2, rotate by one element at a time.============== + + +def rotateLeft(arr): + temp = arr[0] + length = len(arr) + + for item in range(0, length-1): + arr[item] = arr[item+1] + arr[item+1] = temp + + return arr + + +def rotations(arr, n): + for a in range(0, n): + rotateLeft(arr) + printRotations(arr) + + +def printRotations(arr): + for a in arr: + print(a,"",end = "") + +L = [1, 2, 3, 4, 5, 6, 7, 8] +rotations(L, 3) + + From 3125330d9c7a87f3486fc86c5f2d2aa6735c97ef Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 7 Oct 2019 21:25:54 +0530 Subject: [PATCH 029/455] Revert "Added a minimal logo as required!" --- README.md | 6 +-- data_structures/array/Array_Rotations.py | 61 ----------------------- logo/PDS.png | Bin 22034 -> 0 bytes logo/logo.png | Bin 12958 -> 0 bytes 4 files changed, 3 insertions(+), 64 deletions(-) delete mode 100644 data_structures/array/Array_Rotations.py delete mode 100644 logo/PDS.png delete mode 100644 logo/logo.png diff --git a/README.md b/README.md index 4815d195..0aa691a2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Python Data Structures +# Python Data Structures This repository contains data structures and algorithms questions in Python. ## :dart: Objective -The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavor to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: +The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: ## :file_folder: Structure of the repository @@ -12,7 +12,7 @@ As of now, the repository contains a file called [`useful_links.md`](useful_link ### Data Structures -Contains all data structure questions categorized into sub-directories like stack, queue, etc. according to their type. +Contains all data structure questions categorised into sub-directories like stack, queue, etc according to their type. 1. Array 2. Dictionary diff --git a/data_structures/array/Array_Rotations.py b/data_structures/array/Array_Rotations.py deleted file mode 100644 index 509bc5ca..00000000 --- a/data_structures/array/Array_Rotations.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Array Rotations:- - -Given an array, rotate the elements of the array without using the temp array. - -Solution:- - Rotate the given array one at a time, and then call the rotation function n times,(n being the times rotated) - -Note:- Code using the temp array is also given. -""" - -#==================== Method 1: Using Temp array to do so, takes O(n) time.====================== - -# def rotations(L, N, D): -# temp = [] - -# for a in range(0, d): -# temp.append(L[a]) - -# for a in range(0, n-d): -# L[a] = L[a+d] - -# for a in range(0, d): -# L.append(temp[a]) - -# print(L) - - - -# n=8 -# d=3 -# rotations(L, n ,d) - -# ============ Method 2, rotate by one element at a time.============== - - -def rotateLeft(arr): - temp = arr[0] - length = len(arr) - - for item in range(0, length-1): - arr[item] = arr[item+1] - arr[item+1] = temp - - return arr - - -def rotations(arr, n): - for a in range(0, n): - rotateLeft(arr) - printRotations(arr) - - -def printRotations(arr): - for a in arr: - print(a,"",end = "") - -L = [1, 2, 3, 4, 5, 6, 7, 8] -rotations(L, 3) - - diff --git a/logo/PDS.png b/logo/PDS.png deleted file mode 100644 index 6b78ac13e6ce560ea2e53592dc6b3c673aa68cfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22034 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 diff --git a/logo/logo.png b/logo/logo.png deleted file mode 100644 index e9f535e3f29976b84a3669ab439235afaea4f6cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12958 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 From 5725655d209c26659d8e103fef507681934895ed Mon Sep 17 00:00:00 2001 From: Jay Welborn Date: Mon, 7 Oct 2019 12:56:47 -0400 Subject: [PATCH 030/455] Determine if Binary Tree is Symmetric --- .../binary_trees/symmetric_binary_tree.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/binary_trees/symmetric_binary_tree.py diff --git a/data_structures/binary_trees/symmetric_binary_tree.py b/data_structures/binary_trees/symmetric_binary_tree.py new file mode 100644 index 00000000..8f742715 --- /dev/null +++ b/data_structures/binary_trees/symmetric_binary_tree.py @@ -0,0 +1,37 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +def isSymmetric(self, root: TreeNode) -> bool: + """ + function to determine if the provided TreeNode is the root + of a symmetric binary tree + """ + + def isMirror(left: TreeNode, right: TreeNode) -> bool: + """ + Utility function to determine if two trees mirror each other. If the root and + all subtrees searched here are mirrors, then the tree as a whole is symmetric + """ + + # Two null values are mirrors + if left is None and right is None: + return True + + # If only one value is null, these trees do not mirror each other + if left is None or right is None: + return False + + # If the values are not equal, the trees do not mirror each other + if left.val != right.val: + return False + + # If left.left mirrors right.right, and left.right mirrors right.left, + # the subtrees mirror each other + return isMirror(left.left, right.right) and isMirror(left.right, right.left) + + return isMirror(root, root) + From 72f4108b6966ecbd7bf7435cc22ed330a4012478 Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Mon, 7 Oct 2019 22:44:56 +0530 Subject: [PATCH 031/455] Added a logo 'python-ds' to the read-me --- README.md | 2 +- logo/logo.png | Bin 0 -> 9910 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 logo/logo.png diff --git a/README.md b/README.md index 0aa691a2..b2c6fe9a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Python Data Structures +# ![](logo\logo.png) Python Data Structures This repository contains data structures and algorithms questions in Python. diff --git a/logo/logo.png b/logo/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..28749cb76889825a2f93f55013728fad2adaabec GIT binary patch literal 9910 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 literal 0 HcmV?d00001 From 552f4a578a466172de9fd1b7defc88a9b8b57038 Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Mon, 7 Oct 2019 22:47:31 +0530 Subject: [PATCH 032/455] Added a logo 'python-ds' to the read-me --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2c6fe9a..8b990237 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ![](logo\logo.png) Python Data Structures +# Python Data Structures This repository contains data structures and algorithms questions in Python. From 5e72847bed3357b0e258181b27919fcdb7897f57 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 7 Oct 2019 22:57:29 +0530 Subject: [PATCH 033/455] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b990237..ccc30cf3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Python Data Structures +![logo](logo/logo.png) + +# Python Data Structures and Algorithms This repository contains data structures and algorithms questions in Python. From 5a7c28751e558e2523f4853455a3118a9d32775c Mon Sep 17 00:00:00 2001 From: 17-Vishal Date: Tue, 8 Oct 2019 04:49:33 +0530 Subject: [PATCH 034/455] Added Largest area of rectangle in histogram in Stack --- .../Largest Rectangle area in a Histogram.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 data_structures/stack/Largest Rectangle area in a Histogram.py diff --git a/data_structures/stack/Largest Rectangle area in a Histogram.py b/data_structures/stack/Largest Rectangle area in a Histogram.py new file mode 100644 index 00000000..63201e36 --- /dev/null +++ b/data_structures/stack/Largest Rectangle area in a Histogram.py @@ -0,0 +1,47 @@ +''' +Largest rectangle area in a histogram:: +Find the largest rectangular area possible in a given histogram where the largest rectangle can be made of a number of contiguous bars. For simplicity, assume that all bars have same width and the width is 1 unit. + + +''' + +def max_area_histogram(histogram): + + stack = list() + + max_area = 0 # Initialize max area + + index = 0 + while index < len(histogram): + + + if (not stack) or (histogram[stack[-1]] <= histogram[index]): + stack.append(index) + index += 1 + + + else: + + top_of_stack = stack.pop() + + area = (histogram[top_of_stack] * + ((index - stack[-1] - 1) + if stack else index)) + + max_area = max(max_area, area) + + while stack: + + top_of_stack = stack.pop() + + area = (histogram[top_of_stack] * + ((index - stack[-1] - 1) + if stack else index)) + + max_area = max(max_area, area) + + + return max_area +hist = [4, 7, 1, 8, 4, 9, 5] +print("Maximum area is", + max_area_histogram(hist)) \ No newline at end of file From 6743ae79e07112318dd860c95b888fa2c77be683 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 8 Oct 2019 13:42:35 +0530 Subject: [PATCH 035/455] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ![logo](logo/logo.png) 2 ​ 3 # Python Data Structures and Algorithms 4 ​ 5 This repository contains data structures and algorithms questions in Python. 6 ​ 7 ## :dart: Objective 8 ​ 9 The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: 10 ​ 11 ## :file_folder: Structure of the repository 12 ​ 13 As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. 14 ​ 15 ### Data Structures 16 ​ 17 Contains all data structure questions categorised into sub-directories like stack, queue, etc according to their type. 18 ​ 19    1. Array 20    2. Dictionary 21    3. Binary Search Tree   22    4. Linked List   23    5. Stack   24    6. Graphs   25    7. Circular Linked List 26 ​ 27 ### Algorithms 28 ​ 29 Contains algorithm-based questions like dynamic programming, greedy etc. 30 ​ 31 ## :clipboard: Things need to be done 32 ​ 33 As you can see, the repo is still in its infancy. Here are some key things in the to-do. 34 ​ 35    1. Queue questions 36    2. Algorithms   37        2.1. Dynamic Programming   38        2.2. Greedy   39    3. More questions in data structures, especially for graph, circular linked list, tries, heaps and hash. 40 ​ 41 ## :raised_hand: Contributing 42 ​ 43 Contributions are always welcomed. :smiley: 44 Feel free to raise new issues, file new PRs and star and fork this repo! :wink: 45 ​ 46 Here are some guidelines: 47 --- README.md | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index ccc30cf3..e3bded18 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Python Data Structures and Algorithms -This repository contains data structures and algorithms questions in Python. +This repository contains data structures and algorithms concepts and questions in Python. ## :dart: Objective @@ -16,27 +16,35 @@ As of now, the repository contains a file called [`useful_links.md`](useful_link Contains all data structure questions categorised into sub-directories like stack, queue, etc according to their type. - 1. Array - 2. Dictionary - 3. Binary Search Tree - 4. Linked List - 5. Stack - 6. Graphs - 7. Circular Linked List +1. Array +2. Dictionary +3. Binary Search Tree +4. Linked List +5. Stack +6. Graphs +7. Circular Linked List ### Algorithms -Contains algorithm-based questions like dynamic programming, greedy etc. +This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - + +1. Dynamic Programming +2. Math +3. Sorting + +### Useful Links + +This file is for storing some useful websites, or articles, or videos that can be useful for interview preparations and help to increase knowledge. ## :clipboard: Things need to be done As you can see, the repo is still in its infancy. Here are some key things in the to-do. - 1. Queue questions - 2. Algorithms - 2.1. Dynamic Programming - 2.2. Greedy - 3. More questions in data structures, especially for graph, circular linked list, tries, heaps and hash. +1. Queue questions +2. Algorithms + 2.1. Dynamic Programming + 2.2. Greedy +3. More questions in data structures, especially for graph, circular linked list, tries, heaps and hash. ## :raised_hand: Contributing @@ -45,6 +53,6 @@ Feel free to raise new issues, file new PRs and star and fork this repo! :wink: Here are some guidelines: - 1. Clone the repo to your local machine - 2. Make the new branch and name it accordingly - 3. File the PR and wait for the review :) +1. Clone the repo to your local machine +2. Make the new branch and name it accordingly +3. File the PR and wait for the review :) From a72cb325e58fc41ad3f297fbc6a1413c305c808d Mon Sep 17 00:00:00 2001 From: Inquis1t0r Date: Tue, 8 Oct 2019 10:13:21 +0200 Subject: [PATCH 036/455] moved check_permutations.py --- data_structures/strings/check_permutations.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 data_structures/strings/check_permutations.py diff --git a/data_structures/strings/check_permutations.py b/data_structures/strings/check_permutations.py new file mode 100644 index 00000000..3763159b --- /dev/null +++ b/data_structures/strings/check_permutations.py @@ -0,0 +1,51 @@ +""" +Question: +Check Permutation: Given two strings, write a method to decide if +one is a permutation of the other. +Source: Cracking the Code Interview 6th Edition Question 1.2 + +Time Complexity: +Every letter must be looped which means O(n) time complexity. Then, +we must check if each letter is in the dictionary which is another +O(n) time complexity. Overall, the total time complexity is O(n^2). +""" + +letter_counts = {} + + +def check_permutations(word1, word2): + # Case 1: Not matching length + if len(word1) != len(word2): + return False + # Case 2: Both strings have a length of zero + if len(word1) == 0 and len(word2) == 0: + return True + # Case 3: One Letter Strings + if len(word1) == 1 and len(word2) == 1: + return word1[0] == word2[0] + # Case 4: Length greater than 1 for both strings and lengths are equal + else: + populate_letter_count(word1) + # Loop through each letter (looping is an O(n) operation) + for letter in word2: + # Check if it the letter is in the dictionary (checking is O(n) operation) + if letter_counts.get(letter) is not None: + curr_count = letter_counts.get(letter) + if curr_count == 1: + letter_counts.pop(letter) + else: + letter_counts[letter] = curr_count - 1 + else: + return False + return True + + +def populate_letter_count(word1): + # Loop through each letter (looping is an O(n) operation) + for letter in word1: + # Check if it the letter is in the dictionary (checking is O(n) operation) + if letter_counts.get(letter) is None: + letter_counts[letter] = 1 + else: + curr_count = letter_counts.get(letter) + 1 + letter_counts[letter] = curr_count From d7395e6e25a2085bb8d201b77153e4af6720291e Mon Sep 17 00:00:00 2001 From: Inquis1t0r Date: Tue, 8 Oct 2019 10:13:39 +0200 Subject: [PATCH 037/455] Delete check_permutations.py --- algorithms/strings/check_permutations.py | 51 ------------------------ 1 file changed, 51 deletions(-) delete mode 100644 algorithms/strings/check_permutations.py diff --git a/algorithms/strings/check_permutations.py b/algorithms/strings/check_permutations.py deleted file mode 100644 index 3763159b..00000000 --- a/algorithms/strings/check_permutations.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Question: -Check Permutation: Given two strings, write a method to decide if -one is a permutation of the other. -Source: Cracking the Code Interview 6th Edition Question 1.2 - -Time Complexity: -Every letter must be looped which means O(n) time complexity. Then, -we must check if each letter is in the dictionary which is another -O(n) time complexity. Overall, the total time complexity is O(n^2). -""" - -letter_counts = {} - - -def check_permutations(word1, word2): - # Case 1: Not matching length - if len(word1) != len(word2): - return False - # Case 2: Both strings have a length of zero - if len(word1) == 0 and len(word2) == 0: - return True - # Case 3: One Letter Strings - if len(word1) == 1 and len(word2) == 1: - return word1[0] == word2[0] - # Case 4: Length greater than 1 for both strings and lengths are equal - else: - populate_letter_count(word1) - # Loop through each letter (looping is an O(n) operation) - for letter in word2: - # Check if it the letter is in the dictionary (checking is O(n) operation) - if letter_counts.get(letter) is not None: - curr_count = letter_counts.get(letter) - if curr_count == 1: - letter_counts.pop(letter) - else: - letter_counts[letter] = curr_count - 1 - else: - return False - return True - - -def populate_letter_count(word1): - # Loop through each letter (looping is an O(n) operation) - for letter in word1: - # Check if it the letter is in the dictionary (checking is O(n) operation) - if letter_counts.get(letter) is None: - letter_counts[letter] = 1 - else: - curr_count = letter_counts.get(letter) + 1 - letter_counts[letter] = curr_count From b7064ad01782a13ebca6efd7259ffb51acc92e27 Mon Sep 17 00:00:00 2001 From: Jay Welborn Date: Tue, 8 Oct 2019 09:23:32 -0400 Subject: [PATCH 038/455] Merge list of sorted Linked Lists Recursively merge a list of sorted linked list into one sorted list containing all elements. --- .../linked_list/merge_list_of_linked_lists.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/linked_list/merge_list_of_linked_lists.py diff --git a/data_structures/linked_list/merge_list_of_linked_lists.py b/data_structures/linked_list/merge_list_of_linked_lists.py new file mode 100644 index 00000000..c232f1a9 --- /dev/null +++ b/data_structures/linked_list/merge_list_of_linked_lists.py @@ -0,0 +1,37 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +def merge_two_lists(self, l1: ListNode, l2: ListNode): + if not l1 and not l2: + return + elif not l2: + return l1 + elif not l1: + return l2 + + if (l1.val < l2.val): + l1.next = self.merge_two_lists(l1.next, l2) + return l1 + l2.next = self.merge_two_lists(l1, l2.next) + return l2 + + +def mergeKLists(self, lists: List[ListNode]) -> ListNode: + length = len(lists) + if length == 0: + return; + elif length == 1: + return lists[0] + elif length == 2: + return self.merge_two_lists(lists[0], lists[1]) + + mid = length // 2 + + left_half = lists[:mid] + right_half = lists[mid:] + + return self.merge_two_lists(self.mergeKLists(left_half), self.mergeKLists(right_half)) + From 0baff8452bc848895e14db60ad55fc26870a4e70 Mon Sep 17 00:00:00 2001 From: Jay Welborn Date: Tue, 8 Oct 2019 09:24:29 -0400 Subject: [PATCH 039/455] Update merge_list_of_linked_lists.py --- .../linked_list/merge_list_of_linked_lists.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data_structures/linked_list/merge_list_of_linked_lists.py b/data_structures/linked_list/merge_list_of_linked_lists.py index c232f1a9..016e5610 100644 --- a/data_structures/linked_list/merge_list_of_linked_lists.py +++ b/data_structures/linked_list/merge_list_of_linked_lists.py @@ -4,7 +4,7 @@ # self.val = x # self.next = None -def merge_two_lists(self, l1: ListNode, l2: ListNode): +def merge_two_lists(l1: ListNode, l2: ListNode): if not l1 and not l2: return elif not l2: @@ -13,25 +13,25 @@ def merge_two_lists(self, l1: ListNode, l2: ListNode): return l2 if (l1.val < l2.val): - l1.next = self.merge_two_lists(l1.next, l2) + l1.next = merge_two_lists(l1.next, l2) return l1 - l2.next = self.merge_two_lists(l1, l2.next) + l2.next = merge_two_lists(l1, l2.next) return l2 -def mergeKLists(self, lists: List[ListNode]) -> ListNode: +def mergeKLists(lists: List[ListNode]) -> ListNode: length = len(lists) if length == 0: return; elif length == 1: return lists[0] elif length == 2: - return self.merge_two_lists(lists[0], lists[1]) + return merge_two_lists(lists[0], lists[1]) mid = length // 2 left_half = lists[:mid] right_half = lists[mid:] - return self.merge_two_lists(self.mergeKLists(left_half), self.mergeKLists(right_half)) + return merge_two_lists(mergeKLists(left_half), mergeKLists(right_half)) From 32500f7e125db452de71f737bc89291c0c6cf243 Mon Sep 17 00:00:00 2001 From: Mohit Saini Date: Wed, 9 Oct 2019 01:00:14 +0530 Subject: [PATCH 040/455] added stairs --- .../dynamic_programming/climbing_stairs.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 algorithms/dynamic_programming/climbing_stairs.py diff --git a/algorithms/dynamic_programming/climbing_stairs.py b/algorithms/dynamic_programming/climbing_stairs.py new file mode 100644 index 00000000..ad1c1302 --- /dev/null +++ b/algorithms/dynamic_programming/climbing_stairs.py @@ -0,0 +1,21 @@ +""" +High Level Description: +You are climbing a stair case. It takes n steps to reach to the top. +Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? + +Time Complexity: +O(log(n)) +""" + +def climbStairs(n): + if n==0 or n==1: + return 1 + first= 1 + second= 1 + ans= 0 + + for i in range(2, n+1): + ans = first + second + second = first + first = ans + return ans \ No newline at end of file From 4044d9a9b98e6c7c788e17a33df8ea54cb3e7aee Mon Sep 17 00:00:00 2001 From: Mohit Saini Date: Wed, 9 Oct 2019 01:13:15 +0530 Subject: [PATCH 041/455] added dp problems --- .../dynamic_programming/climbing_stairs.py | 2 +- .../dynamic_programming/max_subarray.py | 18 +++++++++++++++ .../dynamic_programming/unique_grid_paths.py | 23 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 algorithms/dynamic_programming/max_subarray.py create mode 100644 algorithms/dynamic_programming/unique_grid_paths.py diff --git a/algorithms/dynamic_programming/climbing_stairs.py b/algorithms/dynamic_programming/climbing_stairs.py index ad1c1302..01400a51 100644 --- a/algorithms/dynamic_programming/climbing_stairs.py +++ b/algorithms/dynamic_programming/climbing_stairs.py @@ -4,7 +4,7 @@ Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? Time Complexity: -O(log(n)) +O(n) """ def climbStairs(n): diff --git a/algorithms/dynamic_programming/max_subarray.py b/algorithms/dynamic_programming/max_subarray.py new file mode 100644 index 00000000..585f03ee --- /dev/null +++ b/algorithms/dynamic_programming/max_subarray.py @@ -0,0 +1,18 @@ +""" +High Level Description: +Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. + +Time Complexity: +O(n) +""" +# Iterative Solution +def maxSubArray(self, A): + if not A: + return 0 + + curSum = maxSum = A[0] + for num in A[1:]: + curSum = max(num, curSum + num) + maxSum = max(maxSum, curSum) + + return maxSum \ No newline at end of file diff --git a/algorithms/dynamic_programming/unique_grid_paths.py b/algorithms/dynamic_programming/unique_grid_paths.py new file mode 100644 index 00000000..a672650f --- /dev/null +++ b/algorithms/dynamic_programming/unique_grid_paths.py @@ -0,0 +1,23 @@ +""" +High Level Description: +A preson is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). +The preson can only move either down or right at any point in time. +The preson is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). +How many possible unique paths are there? + +Time Complexity: +O(m*n) +""" +def numberOfPaths(m, n): + count = [[0 for x in range(m)] for y in range(n)] + + for i in range(m): + count[i][0] = 1; + + for j in range(n): + count[0][j] = 1; + + for i in range(1, m): + for j in range(n): + count[i][j] = count[i-1][j] + count[i][j-1] + return count[m-1][n-1] \ No newline at end of file From e787cd2ad75703808c13c3947e0dbbd7c1a02a83 Mon Sep 17 00:00:00 2001 From: Mohit Saini Date: Wed, 9 Oct 2019 01:16:36 +0530 Subject: [PATCH 042/455] added dp problems --- .../dynamic_programming/edit_distance.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 algorithms/dynamic_programming/edit_distance.py diff --git a/algorithms/dynamic_programming/edit_distance.py b/algorithms/dynamic_programming/edit_distance.py new file mode 100644 index 00000000..e792ab6c --- /dev/null +++ b/algorithms/dynamic_programming/edit_distance.py @@ -0,0 +1,28 @@ +""" +High Level Description: +Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2. +You have the following 3 operations permitted on a word: +Insert a character +Delete a character +Replace a character + +Time Complexity: +O(m*n) +""" +def editDistDP(str1, str2, m, n): + dp = [[0 for x in range(n+1)] for x in range(m+1)] + + for i in range(m+1): + for j in range(n+1): + if i == 0: + dp[i][j] = j + elif j == 0: + dp[i][j] = i + elif str1[i-1] == str2[j-1]: + dp[i][j] = dp[i-1][j-1] + else: + dp[i][j] = 1 + min(dp[i][j-1], # Insert + dp[i-1][j], # Remove + dp[i-1][j-1]) # Replace + + return dp[m][n] \ No newline at end of file From f92d8e2eaadfacec4658e2724833be1ba784e127 Mon Sep 17 00:00:00 2001 From: KristoferSoler Date: Tue, 8 Oct 2019 21:54:27 +0200 Subject: [PATCH 043/455] =?UTF-8?q?=E2=9C=A8=20Added.=20index.md=20per=20s?= =?UTF-8?q?ubfolder=20and=20updater=20script.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- algorithms/dynamic_programming/index.md | 4 +++ algorithms/math/index.md | 3 ++ algorithms/sorting/index.md | 4 +++ data_structures/array/index.md | 34 +++++++++++++++++++ data_structures/binary_trees/index.md | 3 ++ data_structures/bst/index.md | 31 +++++++++++++++++ data_structures/circular_linked_list/index.md | 5 +++ data_structures/doubly_linked_list/index.md | 3 ++ data_structures/graphs/index.md | 3 ++ data_structures/linked_list/index.md | 11 ++++++ data_structures/stack/index.md | 6 ++++ data_structures/strings/index.md | 3 ++ index_updater.py | 27 +++++++++++++++ 13 files changed, 137 insertions(+) create mode 100644 algorithms/dynamic_programming/index.md create mode 100644 algorithms/math/index.md create mode 100644 algorithms/sorting/index.md create mode 100644 data_structures/array/index.md create mode 100644 data_structures/binary_trees/index.md create mode 100644 data_structures/bst/index.md create mode 100644 data_structures/circular_linked_list/index.md create mode 100644 data_structures/doubly_linked_list/index.md create mode 100644 data_structures/graphs/index.md create mode 100644 data_structures/linked_list/index.md create mode 100644 data_structures/stack/index.md create mode 100644 data_structures/strings/index.md create mode 100755 index_updater.py diff --git a/algorithms/dynamic_programming/index.md b/algorithms/dynamic_programming/index.md new file mode 100644 index 00000000..4f69b4f8 --- /dev/null +++ b/algorithms/dynamic_programming/index.md @@ -0,0 +1,4 @@ +# Index of dynamic_programming + +* longest_common_subsequence.py +* rod_cutting.py diff --git a/algorithms/math/index.md b/algorithms/math/index.md new file mode 100644 index 00000000..e1a3a6e9 --- /dev/null +++ b/algorithms/math/index.md @@ -0,0 +1,3 @@ +# Index of math + +* greatest_common_divisor.py diff --git a/algorithms/sorting/index.md b/algorithms/sorting/index.md new file mode 100644 index 00000000..7cc2e7f9 --- /dev/null +++ b/algorithms/sorting/index.md @@ -0,0 +1,4 @@ +# Index of sorting + +* insertion_sort.py +* select_sort.py diff --git a/data_structures/array/index.md b/data_structures/array/index.md new file mode 100644 index 00000000..e171d8a1 --- /dev/null +++ b/data_structures/array/index.md @@ -0,0 +1,34 @@ +# Index of array + +* permutations_of_word.py +* sorted_array_three_common_elements.py +* dutch_flag_problem.py +* partition_three_parts_equal_sum.py +* binary_search_infinite_array.py +* largest_element.py +* right_place.py +* rotation.py +* find_missing_numbers.py +* three_largest_elements.py +* triplet_sum.py +* max_product.py +* moves_zeros_to_end.py +* pivot_index.py +* intersection_sorted_array.py +* max_triplet_sum.py +* number_of_1_in_sorted_array.py +* square_of_sorted_array.py +* max_consecutive_ones.py +* max_product_three_elements.py +* kadane_algorithm.py +* all_numbers_divisible.py +* duplicates.py +* majority_element.py +* find_sum.py +* quick_sort.py +* peak_element.py +* union_sorted_array.py +* min_product.py +* sort_by_parity.py +* duplicate.py +* product_of_array_except_self.py diff --git a/data_structures/binary_trees/index.md b/data_structures/binary_trees/index.md new file mode 100644 index 00000000..ce9cf6c6 --- /dev/null +++ b/data_structures/binary_trees/index.md @@ -0,0 +1,3 @@ +# Index of binary_trees + +* symmetric_binary_tree.py diff --git a/data_structures/bst/index.md b/data_structures/bst/index.md new file mode 100644 index 00000000..cd965d52 --- /dev/null +++ b/data_structures/bst/index.md @@ -0,0 +1,31 @@ +# Index of bst + +* deletion.py +* sorted_array_to_bst.py +* print_left_node.py +* diameter.py +* bfs.py +* check_if_bt_if_bst.py +* trim_bst.py +* bt_to_bst.py +* binary_search_tree.py +* convert_bst_to_right_node_tree.py +* kth_largest_in_bst.py +* range_sum.py +* dfs_iterative.py +* print_ancestor.py +* min_max_value_in_bst.py +* check_bt_is_subtree_of_another_bt.py +* ceil.py +* closest_element.py +* kth_smallest_in_bst.py +* insertion_iterative.py +* lowest_common_ancestor.py +* dfs_recursion.py +* search.py +* insertion_recursive.py +* duplicate_keys.py +* merge_sum.py +* linked_list_to_bst.py +* reverse_inorder_traversal.py +* average_of_levels.py diff --git a/data_structures/circular_linked_list/index.md b/data_structures/circular_linked_list/index.md new file mode 100644 index 00000000..863e4602 --- /dev/null +++ b/data_structures/circular_linked_list/index.md @@ -0,0 +1,5 @@ +# Index of circular_linked_list + +* check_circular_linked_list.py +* delete.py +* traversal.py diff --git a/data_structures/doubly_linked_list/index.md b/data_structures/doubly_linked_list/index.md new file mode 100644 index 00000000..0888a31f --- /dev/null +++ b/data_structures/doubly_linked_list/index.md @@ -0,0 +1,3 @@ +# Index of doubly_linked_list + +* doubly_linked_list.py diff --git a/data_structures/graphs/index.md b/data_structures/graphs/index.md new file mode 100644 index 00000000..ccd77d4c --- /dev/null +++ b/data_structures/graphs/index.md @@ -0,0 +1,3 @@ +# Index of graphs + +* adjeceny_list.py diff --git a/data_structures/linked_list/index.md b/data_structures/linked_list/index.md new file mode 100644 index 00000000..a32a47e0 --- /dev/null +++ b/data_structures/linked_list/index.md @@ -0,0 +1,11 @@ +# Index of linked_list + +* remove.py +* pair_swap.py +* reverse.py +* linked_list.py +* cycle_detection.py +* remove_nth_node_from_end.py +* odd_even_arrangement.py +* merge_linked_list.py +* remove_duplicates.py diff --git a/data_structures/stack/index.md b/data_structures/stack/index.md new file mode 100644 index 00000000..089a2739 --- /dev/null +++ b/data_structures/stack/index.md @@ -0,0 +1,6 @@ +# Index of stack + +* valid_parenthesis.py +* Largest Rectangle area in a Histogram.py +* remove_duplicates_adjacent.py +* validate_stack_sequence.py diff --git a/data_structures/strings/index.md b/data_structures/strings/index.md new file mode 100644 index 00000000..470b7bbe --- /dev/null +++ b/data_structures/strings/index.md @@ -0,0 +1,3 @@ +# Index of strings + +* check_permutations.py diff --git a/index_updater.py b/index_updater.py new file mode 100755 index 00000000..8eaae0b7 --- /dev/null +++ b/index_updater.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +import sys +import os + +# Terminal parameters. +if len(sys.argv[1:]) == 0: + print('Please, give a path') + sys.exit() +else: + mypath = sys.argv[1] + +# Going trought folders and subfolders. +for root, dirs, files in os.walk(mypath): + curr_files = list() + curr_folder = os.path.basename(root) + + for name in files: + if name.endswith('.py') and not name == '__init__py' and not dirs: + curr_files.append(name) + + # If we have files, write "index.md" + if curr_files: + with open(os.path.join(root, 'index.md'), mode='w') as md_file: + md_file.write('# Index of {}\n\n'.format(curr_folder)) + for line in curr_files: + md_file.write('* ' + line + '\n') From ed11236c0fab23aea24aff4d6009c1328fa3bb10 Mon Sep 17 00:00:00 2001 From: ANKUSH GOYAL Date: Wed, 9 Oct 2019 12:12:18 +0530 Subject: [PATCH 044/455] updated missing return statement. --- data_structures/array/product_of_array_except_self.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/array/product_of_array_except_self.py b/data_structures/array/product_of_array_except_self.py index 8db6aac1..3ab5bf0c 100644 --- a/data_structures/array/product_of_array_except_self.py +++ b/data_structures/array/product_of_array_except_self.py @@ -12,3 +12,5 @@ def product(arr): for i in reversed(range(len(arr))): prods[i] = prods[i] * temp temp = temp * arr[i] + + return temp From f751678a1893b4e201e2e82a3a3d1fb13d89f3a5 Mon Sep 17 00:00:00 2001 From: Jannik Wempe Date: Wed, 9 Oct 2019 09:05:28 +0200 Subject: [PATCH 045/455] add additional solution by sorting letters --- data_structures/strings/check_permutations.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data_structures/strings/check_permutations.py b/data_structures/strings/check_permutations.py index 3763159b..83ecd6e9 100644 --- a/data_structures/strings/check_permutations.py +++ b/data_structures/strings/check_permutations.py @@ -49,3 +49,8 @@ def populate_letter_count(word1): else: curr_count = letter_counts.get(letter) + 1 letter_counts[letter] = curr_count + +######################################################### +# additional solution by sorting the letters of the words +def check_permutation2(word1, word2): + sorted(word1) == sorted(word2) From 79b77765ae2eba18e65cd83400f704e33ec40950 Mon Sep 17 00:00:00 2001 From: ThanasisMpalatsoukas Date: Wed, 9 Oct 2019 11:28:16 +0300 Subject: [PATCH 046/455] Created new sorting algorithm merge_sort --- algorithms/sorting/insertion_sort.py | 1 - algorithms/sorting/merge_sort.py | 51 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 algorithms/sorting/merge_sort.py diff --git a/algorithms/sorting/insertion_sort.py b/algorithms/sorting/insertion_sort.py index 30f77694..75ba7514 100644 --- a/algorithms/sorting/insertion_sort.py +++ b/algorithms/sorting/insertion_sort.py @@ -2,7 +2,6 @@ High Level Description: For every element in the given list, find its correct index by iterating backwards and finding a slot. This forms a sorted array. - Time Complexity: Every element is visited, which contributes O(n). Swapping backwards takes O(n/2) time on average, meaning that the total complexity is O(n^2) diff --git a/algorithms/sorting/merge_sort.py b/algorithms/sorting/merge_sort.py new file mode 100644 index 00000000..f9eb554c --- /dev/null +++ b/algorithms/sorting/merge_sort.py @@ -0,0 +1,51 @@ +""" +High level explanation: + +mergeSort is a Divide and conquer algorithm that splits in halves the array and +then builds it back up by merging and sorting at the same time its elements. + +Time complexity: + +mergeSort has a time complexity of O(n log n). +""" + +def mergeSort(arr): + if len(arr) >1: + mid = len(arr)//2 #Finding the mid of the array + L = arr[:mid] # Dividing the array elements + R = arr[mid:] # into 2 halves + + mergeSort(L) # Sorting the first half + mergeSort(R) # Sorting the second half + + i = j = k = 0 + + # Copy data to temp arrays L[] and R[] + while i < len(L) and j < len(R): + if L[i] < R[j]: + arr[k] = L[i] + i+=1 + else: + arr[k] = R[j] + j+=1 + k+=1 + + # Checking if any element was left + while i < len(L): + arr[k] = L[i] + i+=1 + k+=1 + + while j < len(R): + arr[k] = R[j] + j+=1 + k+=1 + +test_array = [10,30,20,100,40,80,90,210,34] + +mergeSort(test_array) + +print(test_array) + +# This code is contributed by Mayank Khanna +# and extented by thanasis mpalatsoukas From 42bf0b48d015a318040a0c5916295e7a9896a2b4 Mon Sep 17 00:00:00 2001 From: braceritchie Date: Wed, 9 Oct 2019 17:39:26 +0530 Subject: [PATCH 047/455] Determine if an expression is balanced using stack --- data_structures/stack/balanced_expression.py | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 data_structures/stack/balanced_expression.py diff --git a/data_structures/stack/balanced_expression.py b/data_structures/stack/balanced_expression.py new file mode 100644 index 00000000..784666c0 --- /dev/null +++ b/data_structures/stack/balanced_expression.py @@ -0,0 +1,24 @@ +# simple program to check if an expression is balanced using stack +stack = [] +def checkBalanced(expr): + for i in expr: + if i == "{" or i == "[" or i == "(": + stack.append(i) + elif i == "}" or i == "]" or i == ")": + temp = stack.pop() + if i == "}" and temp != "{": + return False + elif i == "]" and temp != "[": + return False + elif i == ")" and temp != "(": + return False + + return True + +# main function +expr = input() +result = checkBalanced(expr) +if result: + print("Expression is balanced") +else: + print("Expression is not balanced") From 56e19e00ee5a4463573e07771e72c4f9a77ceb16 Mon Sep 17 00:00:00 2001 From: Yashyasvi Agarwal Date: Wed, 9 Oct 2019 18:05:13 +0530 Subject: [PATCH 048/455] added a new string question added a new question on string anagrams with a very efficient solution --- .DS_Store | Bin 0 -> 6148 bytes data_structures/.DS_Store | Bin 0 -> 6148 bytes data_structures/strings/are_anagrams.py | 39 ++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 .DS_Store create mode 100644 data_structures/.DS_Store create mode 100644 data_structures/strings/are_anagrams.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1a991386647f7079dbbb35e8f377a1781c2a38f7 GIT binary patch literal 6148 zcmeHKO>Wab6n@hh>KLJ9fz&R&L1Gc1q|kPOkW88^A^}1e!2(cf*P*fMdaBrNR6>w9 z+yS@&N8tn<7kMK7ti7};*$<9 z(kPSt_^QFSYj$nW*qTnaw|AOuduMmnbf?8ZD|zoK zc{O^B9`8|?9sqA*sg5d)uN6iegPLJbUjY*gcY;MerDN1xz?Ku`{oF)BXU0}j0XSk z!4w_!uFmr`mI@V}m_B?keP^amC`{fR{kt-qn5WQ`MggP1q5|vcvLW{W-mlO9izIVp z6fg?>R|+tz>vubNCB3&Uy`0!k^VjzY0}Dx}n*IW&nYArT9VWF)yh7=!2s z^aI*!+k8jbpXi6=12VI_m>Q>-9zrlPF#ATcGqc(!*wF%j@Md8fzySaYm9S#taF5VD z>4sE{Mwch6p%su_xDQ!oVg9AlQ=J0tv{ktt?fLi zTlQ|lZai(+7sGKn9~OQw%RN6EIWLEC7zKWI7Kg?7G)e}O=u?!OWN-W;%05u=X_`(j zK-+%sK91%i=lOA(6n>mUnX0F2oS(%>n9jX)mV~*AH^r6x)-T3b$9m=Z5?>L(w(OC! zw^$r?nzG$(Et_)D>$RHlu+v>GZOhs}c>V5j_W8@#Z{L6XyuSIRl0eYTNuFs~jlWkG z8_WPRzzl3F1Lg#@8r!---WM~#4E#3(bUsK_Lf2raQ5_vPs4D~?NQ17y zQX|fw2%U@_ zL;Zj7@B9CH5a`N}BPt2Sl^RzmXsA|bkSZYKM3jYWw8hBs^9+ZJQPo!KP literal 0 HcmV?d00001 diff --git a/data_structures/strings/are_anagrams.py b/data_structures/strings/are_anagrams.py new file mode 100644 index 00000000..7eb7dbc1 --- /dev/null +++ b/data_structures/strings/are_anagrams.py @@ -0,0 +1,39 @@ +""" +Question: +Check whether two strings are anagram of each other: +Write a function to check whether two given strings are anagram of each other or not. An anagram of a string is another string that contains same characters, only the order of characters can be different. For example, “abcd” and “dabc” are anagram of each other. +Source:A very Common Interview Question,asked in companies like Amazon,Goldman Sachs and Nagarro. + +Time Complexity: +The goal is to complete this question in O(n). +This solution is optimized by using bit manipulation. If we start at a value of 0 and XOR all the characters of both strings, we should return an end value of 0 if they are anagrams because there would be an even occurrence of all characters in the anagram. + +Space Complexity: +The space complexity of this approach is O(1). +""" +# Function to check whether two strings are anagrams of each other +def are_anagrams(string1, string2): + + # If two strings have different size we return False as they cannot be anagrams of each other + if (len(string1) != len(string2)): + return False + # Variable to store the Xor Value + xor_value = 0 + for i in range(len(string1)): + xor_value = xor_value ^ ord(string1[i]) + xor_value = xor_value ^ ord(string2[i]) + + if(xor_value==0): + return True + else: + return False + +# Code To test The Function +string1 = "thestringsareanagrams" +string2 = "arethestringsanagrams" +if(are_anagrams(string1, string2)): + print("The two strings are anagram of each other") +else: + print("The two strings are not anagram of each other") + + From 090882886814464b7d00d43227987b2aba1b86d0 Mon Sep 17 00:00:00 2001 From: Bakhtiyor Ruziev <32102033+theruziev@users.noreply.github.com> Date: Wed, 9 Oct 2019 16:47:21 +0300 Subject: [PATCH 049/455] Add Quicksort --- algorithms/sorting/qsort.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 algorithms/sorting/qsort.py diff --git a/algorithms/sorting/qsort.py b/algorithms/sorting/qsort.py new file mode 100644 index 00000000..395955a0 --- /dev/null +++ b/algorithms/sorting/qsort.py @@ -0,0 +1,27 @@ +""" +High level explanation: +Quicksort algorithm is that if we can efficiently partition a list, +then we can efficiently sort it. Partitioning a list means that +we pick a pivot item in the list, and then modify the list +to move all items larger than the pivot to the right and all +smaller items to the left. + +Once the pivot is done, we can do the same operation to the +left and right sections of the list recursively until the list is sorted. + +Time complexity: +Quicksort has a time complexity of O(n log n). +""" + + +def qsort(arr): + if len(arr) <= 1: + return arr + pivot = arr.pop() + greater, lesser = [], [] + for item in arr: + if item > pivot: + greater.append(item) + else: + lesser.append(item) + return qsort(lesser) + [pivot] + qsort(greater) From 5a99356ac10e91d671ee550df1d51d24180f477f Mon Sep 17 00:00:00 2001 From: Bakhtiyor Ruziev Date: Wed, 9 Oct 2019 16:58:39 +0300 Subject: [PATCH 050/455] Add queue data structure --- data_structures/queue/queue.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 data_structures/queue/queue.py diff --git a/data_structures/queue/queue.py b/data_structures/queue/queue.py new file mode 100644 index 00000000..78fde90f --- /dev/null +++ b/data_structures/queue/queue.py @@ -0,0 +1,30 @@ +class Queue: + """ + Queue is an abstract data structure, somewhat similar to Stacks. + Unlike stacks, a queue is open at both its ends. One end is always used to insert data (enqueue) + and the other is used to remove data (dequeue). + Queue follows First-In-First-Out methodology, i.e., the data item stored first will be accessed first. + + """ + + def __init__(self): + self.entries = [] + self.length = 0 + self.front = 0 + + def put(self, item): + self.entries.append(item) + self.length += 1 + + def get(self): + self.length -= 1 + de_queued = self.entries[self.front] + self.entries = self.entries[1:] + return de_queued + + def rotate(self, rotation): + for i in range(rotation): + self.put(self.get()) + + def size(self): + return self.length From 13b83478f34bd13ad31f2110f10c3de8b96f8f86 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 9 Oct 2019 22:20:43 +0530 Subject: [PATCH 051/455] Rename Largest Rectangle area in a Histogram.py to largest_rectangle_area_in_histogram.py --- ...in a Histogram.py => largest_rectangle_area_in_histogram.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename data_structures/stack/{Largest Rectangle area in a Histogram.py => largest_rectangle_area_in_histogram.py} (97%) diff --git a/data_structures/stack/Largest Rectangle area in a Histogram.py b/data_structures/stack/largest_rectangle_area_in_histogram.py similarity index 97% rename from data_structures/stack/Largest Rectangle area in a Histogram.py rename to data_structures/stack/largest_rectangle_area_in_histogram.py index 63201e36..bee42b5b 100644 --- a/data_structures/stack/Largest Rectangle area in a Histogram.py +++ b/data_structures/stack/largest_rectangle_area_in_histogram.py @@ -44,4 +44,4 @@ def max_area_histogram(histogram): return max_area hist = [4, 7, 1, 8, 4, 9, 5] print("Maximum area is", - max_area_histogram(hist)) \ No newline at end of file + max_area_histogram(hist)) From 306ad37f30ee90c463990c4a6bb242f8882d6e01 Mon Sep 17 00:00:00 2001 From: John Henson Date: Wed, 9 Oct 2019 11:01:47 -0600 Subject: [PATCH 052/455] Added Bubble Sort --- algorithms/sorting/bubble_sort.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 algorithms/sorting/bubble_sort.py diff --git a/algorithms/sorting/bubble_sort.py b/algorithms/sorting/bubble_sort.py new file mode 100644 index 00000000..c1ef4fe3 --- /dev/null +++ b/algorithms/sorting/bubble_sort.py @@ -0,0 +1,12 @@ +''' +Bubble Sort worst time complexity occurs when every item in array is sorted - O(n^2) +Best time scenario is when array is already sorted - O(n) +''' + +def bubbleSort(array): + n = len(array) + + for i in range(n): + for j in range(0, n-i-1): + if array[j] > array[j+1]: + array[j], array[j+1] = array[j+1], array[j] \ No newline at end of file From bffff70d57c8ff93a1a49043f6a5d1f5ef2a618d Mon Sep 17 00:00:00 2001 From: ThanasisMpalatsoukas Date: Wed, 9 Oct 2019 21:08:02 +0300 Subject: [PATCH 053/455] k-means was added as a subfolder of k-means --- algorithms/clustering/k-means.py | 110 +++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 algorithms/clustering/k-means.py diff --git a/algorithms/clustering/k-means.py b/algorithms/clustering/k-means.py new file mode 100644 index 00000000..6a139b23 --- /dev/null +++ b/algorithms/clustering/k-means.py @@ -0,0 +1,110 @@ +""" + HIGH LEVEL EXPLANATION: + + K-MEANS is a static custering algorithm that is used on machine learning to cluster + information together. The way that it works is that you are chosing K points that will + be put on random positions. After each repetition each point is assigned to each clustering + point depending on which cluster is closest to the point. After that the new position of each + cluster is chosen by finding the average position of all points that were assigned to that cluster. +""" + +import random +import math + +# Create a point class functioning more like a data structure +class Point: + + x = 0 + y = 0 + + def __init__(self,x,y): + self.x = x + self.y = y + +k = int(input("Select how many centroids you need")) +n = int(input("Select how many random points do you want")) + +centroids = [] +points = [] + +# Creating a multidimensional array here with our point structure +# +# [ [Point*n]*k ] + +centroid_points = [ [ Point(0,0) for i in range(n)] for j in range(k)] +amount_of_centroids_on_each_point = [] + +# randomization of points +for i in range(k): + point = Point(random.uniform(10,100),random.uniform(10,100)) + centroids.append(point) + +for i in range(n): + point = Point(random.uniform(10,100),random.uniform(10,100)) + points.append(point) + + + +failSafeCounter = 0 +flag = 0 + +# Main functionallity +while flag == 0 and failSafeCounter < 1000: + + flag = 0 + + #Reseting this array + for i in range(n): + amount_of_centroids_on_each_point.append(0) + + for i in range(n): + + # Looping through the points array to find the + # cluster with the minimum ditance from the point + # and assigning it to that + minimum = 99999999 + lower_centroid = -1 + + for j in range(k): + + # Finding the cluster here with the miminum distance from the point + distance = math.sqrt( (centroids[j].x-points[i].x)*(centroids[j].x-points[i].x) + (centroids[j].y-points[i].y)*(centroids[j].y-points[i].y )) + if (distance < minimum): + minimum = distance + lower_centroid = j + + # Assigning point to the cluster + centroid_points[lower_centroid][amount_of_centroids_on_each_point[lower_centroid]].x = points[i].x + centroid_points[lower_centroid][amount_of_centroids_on_each_point[lower_centroid]].y = points[i].y + amount_of_centroids_on_each_point[lower_centroid] += 1 + + failSafeCounter+=1 + + for i in range(k): + avgx = 0 + avgy = 0 + counter = 0 + + for j in range(n): + if (not(centroid_points[i][j].x == 0 and centroid_points[i][j].y == 0)): + avgx+=centroid_points[i][j].x + avgy+=centroid_points[i][j].y + counter+=1 + + if counter!=0: + + if centroids[i].x != (avgx/counter) or centroids[i].y != (avgy/counter): + flag = 1 + + centroids[i].x = (avgx/counter) + centroids[i].y = (avgy/counter) + + +# Loop through the points list to show the results +for i in range(k): + print('Cluster {} has the following points:\n'.format(i)) + for j in range(n): + if (not(centroid_points[i][j].x == 0 and centroid_points[i][j].y == 0)): + print('x:{},y:{}'.format(centroid_points[i][j].x,centroid_points[i][j].y)) + + print('\n') From d36e77c791739ae7d5da4397391b60100a1016d3 Mon Sep 17 00:00:00 2001 From: yashyasviagarwal <43351143+yashyasviagarwal@users.noreply.github.com> Date: Thu, 10 Oct 2019 00:05:59 +0530 Subject: [PATCH 054/455] Delete .DS_Store remove .DS_Store files --- data_structures/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data_structures/.DS_Store diff --git a/data_structures/.DS_Store b/data_structures/.DS_Store deleted file mode 100644 index 0cf877ff3c0dc8ef7e2f47ab7cc50ac42e895f3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!D`z;5S_K1T8g2lP)GwkEcB3z4>k^VjzY0}Dx}n*IW&nYArT9VWF)yh7=!2s z^aI*!+k8jbpXi6=12VI_m>Q>-9zrlPF#ATcGqc(!*wF%j@Md8fzySaYm9S#taF5VD z>4sE{Mwch6p%su_xDQ!oVg9AlQ=J0tv{ktt?fLi zTlQ|lZai(+7sGKn9~OQw%RN6EIWLEC7zKWI7Kg?7G)e}O=u?!OWN-W;%05u=X_`(j zK-+%sK91%i=lOA(6n>mUnX0F2oS(%>n9jX)mV~*AH^r6x)-T3b$9m=Z5?>L(w(OC! zw^$r?nzG$(Et_)D>$RHlu+v>GZOhs}c>V5j_W8@#Z{L6XyuSIRl0eYTNuFs~jlWkG z8_WPRzzl3F1Lg#@8r!---WM~#4E#3(bUsK_Lf2raQ5_vPs4D~?NQ17y zQX|fw2%U@_ zL;Zj7@B9CH5a`N}BPt2Sl^RzmXsA|bkSZYKM3jYWw8hBs^9+ZJQPo!KP From fcb4e93a667035ed9b9bf80a8ad2f4247ca5b731 Mon Sep 17 00:00:00 2001 From: yashyasviagarwal <43351143+yashyasviagarwal@users.noreply.github.com> Date: Thu, 10 Oct 2019 00:07:30 +0530 Subject: [PATCH 055/455] Delete .DS_Store removed .DS_Store file --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 1a991386647f7079dbbb35e8f377a1781c2a38f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKO>Wab6n@hh>KLJ9fz&R&L1Gc1q|kPOkW88^A^}1e!2(cf*P*fMdaBrNR6>w9 z+yS@&N8tn<7kMK7ti7};*$<9 z(kPSt_^QFSYj$nW*qTnaw|AOuduMmnbf?8ZD|zoK zc{O^B9`8|?9sqA*sg5d)uN6iegPLJbUjY*gcY;MerDN1xz?Ku`{oF)BXU0}j0XSk z!4w_!uFmr`mI@V}m_B?keP^amC`{fR{kt-qn5WQ`MggP1q5|vcvLW{W-mlO9izIVp z6fg?>R|+tz>vubNCB3&Uy`0! Date: Wed, 9 Oct 2019 21:48:52 +0300 Subject: [PATCH 056/455] Added algorithm which finds the nth prime --- algorithms/math/prime.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 algorithms/math/prime.py diff --git a/algorithms/math/prime.py b/algorithms/math/prime.py new file mode 100644 index 00000000..ef981c9d --- /dev/null +++ b/algorithms/math/prime.py @@ -0,0 +1,16 @@ +def prime(limit): + + count = 1 + while(count Date: Thu, 10 Oct 2019 00:36:23 +0530 Subject: [PATCH 057/455] fixed naming convention --- algorithms/dynamic_programming/climbing_stairs.py | 2 +- algorithms/dynamic_programming/edit_distance.py | 2 +- algorithms/dynamic_programming/max_subarray.py | 14 +++++++------- .../dynamic_programming/unique_grid_paths.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/algorithms/dynamic_programming/climbing_stairs.py b/algorithms/dynamic_programming/climbing_stairs.py index 01400a51..6633a7a4 100644 --- a/algorithms/dynamic_programming/climbing_stairs.py +++ b/algorithms/dynamic_programming/climbing_stairs.py @@ -7,7 +7,7 @@ O(n) """ -def climbStairs(n): +def climb_stairs(n): if n==0 or n==1: return 1 first= 1 diff --git a/algorithms/dynamic_programming/edit_distance.py b/algorithms/dynamic_programming/edit_distance.py index e792ab6c..e897987f 100644 --- a/algorithms/dynamic_programming/edit_distance.py +++ b/algorithms/dynamic_programming/edit_distance.py @@ -9,7 +9,7 @@ Time Complexity: O(m*n) """ -def editDistDP(str1, str2, m, n): +def edit_dist(str1, str2, m, n): dp = [[0 for x in range(n+1)] for x in range(m+1)] for i in range(m+1): diff --git a/algorithms/dynamic_programming/max_subarray.py b/algorithms/dynamic_programming/max_subarray.py index 585f03ee..c55a0b6a 100644 --- a/algorithms/dynamic_programming/max_subarray.py +++ b/algorithms/dynamic_programming/max_subarray.py @@ -6,13 +6,13 @@ O(n) """ # Iterative Solution -def maxSubArray(self, A): - if not A: +def max_sub_array(self, arr): + if not arr: return 0 - curSum = maxSum = A[0] - for num in A[1:]: - curSum = max(num, curSum + num) - maxSum = max(maxSum, curSum) + cur_sum = max_sum = arr[0] + for num in arr[1:]: + cur_sum = max(num, cur_sum + num) + max_sum = max(max_sum, cur_sum) - return maxSum \ No newline at end of file + return max_sum \ No newline at end of file diff --git a/algorithms/dynamic_programming/unique_grid_paths.py b/algorithms/dynamic_programming/unique_grid_paths.py index a672650f..89953f7f 100644 --- a/algorithms/dynamic_programming/unique_grid_paths.py +++ b/algorithms/dynamic_programming/unique_grid_paths.py @@ -8,7 +8,7 @@ Time Complexity: O(m*n) """ -def numberOfPaths(m, n): +def number_of_paths(m, n): count = [[0 for x in range(m)] for y in range(n)] for i in range(m): From 37328cc3dea7ede004704ea2561dc1550989cf16 Mon Sep 17 00:00:00 2001 From: Bakhtiyor Ruziev Date: Wed, 9 Oct 2019 22:08:51 +0300 Subject: [PATCH 058/455] Add check for a queue emptiness --- data_structures/queue/queue.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/queue/queue.py b/data_structures/queue/queue.py index 78fde90f..a02ae3ab 100644 --- a/data_structures/queue/queue.py +++ b/data_structures/queue/queue.py @@ -17,6 +17,8 @@ def put(self, item): self.length += 1 def get(self): + if self.length <= 0: + return self.length -= 1 de_queued = self.entries[self.front] self.entries = self.entries[1:] From ea803fc3296d758dc6b6916e1b26a7b4b158672c Mon Sep 17 00:00:00 2001 From: Dakshit Mohan <34478954+Chhaganlaal@users.noreply.github.com> Date: Thu, 10 Oct 2019 01:40:06 +0530 Subject: [PATCH 059/455] Nth Fibonacci Number of the Sequence Calculate the nth Fibonacci Number of the Sequence --- algorithms/math/fibonacci_number.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 algorithms/math/fibonacci_number.py diff --git a/algorithms/math/fibonacci_number.py b/algorithms/math/fibonacci_number.py new file mode 100644 index 00000000..ce15e1ca --- /dev/null +++ b/algorithms/math/fibonacci_number.py @@ -0,0 +1,23 @@ +def calc_fib(num): + while len(fib)<=num: + n = len(fib) + fib.append((fib[n-1]+fib[n-2])) + +def main(): + print("Enter the Position of the Number in the Sequence or \'0\' to Quit: ") + num = 0 + fib = list() + fib.append(0) + fib.append(1) + while True: + num = int(input()) + if(num<=0): + break + + if len(fib)<=num: + calc_fib(num) + + print('Fibonacci Number at Position '+str(num)+' is: '+str(fib[num])) + +if __name__ == '__main__': + main() From e6ddb76fc87d497c8d9e083eb4f68cc284856abb Mon Sep 17 00:00:00 2001 From: Giovanni De Luca <36264038+jotaro-sama@users.noreply.github.com> Date: Thu, 10 Oct 2019 05:54:58 +0200 Subject: [PATCH 060/455] add link about linear time sorting --- useful_links.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/useful_links.md b/useful_links.md index cc222d26..117c1cf9 100644 --- a/useful_links.md +++ b/useful_links.md @@ -84,6 +84,8 @@ This is a list of articles, tutorials, questions, books and videos that may be u - https://skerritt.blog/dynamic-programming/ +- https://cs.nyu.edu/courses/fall17/CSCI-UA.0102-001/Notes/LinearSort.html + ## Others From a4b087d76243ee976cce257a89607485e3c37fef Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 10:12:52 +0530 Subject: [PATCH 061/455] Add serverless articles in useful_links --- useful_links.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/useful_links.md b/useful_links.md index cc222d26..e9ddda4c 100644 --- a/useful_links.md +++ b/useful_links.md @@ -84,7 +84,7 @@ This is a list of articles, tutorials, questions, books and videos that may be u - https://skerritt.blog/dynamic-programming/ - +- https://martinfowler.com/articles/serverless.html ## Others From b7228c1654f5863db7d497bb354c29058f66ca28 Mon Sep 17 00:00:00 2001 From: som-cs Date: Thu, 10 Oct 2019 16:53:16 +0530 Subject: [PATCH 062/455] Added Bubble sort --- algorithms/sorting/bubbleSort.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 algorithms/sorting/bubbleSort.py diff --git a/algorithms/sorting/bubbleSort.py b/algorithms/sorting/bubbleSort.py new file mode 100644 index 00000000..59b8f16c --- /dev/null +++ b/algorithms/sorting/bubbleSort.py @@ -0,0 +1,18 @@ +""" +High level explanation: +Bubble sort: +is a simple sorting algorithm that repeatedly steps through the list, +compares adjacent elements and swaps them if they are in the wrong order. +The pass through the list is repeated until the list is sorted. + +Time Complexity: +Bubble sort has a time complexity of О(n^2) +""" + + +def bubbleSort(arr): + for i in range(0,len(arr)): + for j in range(0,len(arr)-1): + if (arr[j] > arr[j+1]): + arr[j] , arr[j+1] = arr[j+1] , arr[j] + return arr From 419d6bbd4349fad4e06d2342501327b087062199 Mon Sep 17 00:00:00 2001 From: John Henson Date: Thu, 10 Oct 2019 06:39:50 -0600 Subject: [PATCH 063/455] Corrected time complexity statement --- algorithms/sorting/bubble_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/sorting/bubble_sort.py b/algorithms/sorting/bubble_sort.py index c1ef4fe3..781b1f5a 100644 --- a/algorithms/sorting/bubble_sort.py +++ b/algorithms/sorting/bubble_sort.py @@ -1,5 +1,5 @@ ''' -Bubble Sort worst time complexity occurs when every item in array is sorted - O(n^2) +Bubble Sort worst time complexity occurs when array is reverse sorted - O(n^2) Best time scenario is when array is already sorted - O(n) ''' From f6ed8f7562bf5541a43bb8e0a75abb544974ddc5 Mon Sep 17 00:00:00 2001 From: Jay Welborn Date: Thu, 10 Oct 2019 09:41:42 -0400 Subject: [PATCH 064/455] Modified to match style of other files --- .../linked_list/merge_list_of_linked_lists.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_structures/linked_list/merge_list_of_linked_lists.py b/data_structures/linked_list/merge_list_of_linked_lists.py index 016e5610..396561c1 100644 --- a/data_structures/linked_list/merge_list_of_linked_lists.py +++ b/data_structures/linked_list/merge_list_of_linked_lists.py @@ -1,10 +1,10 @@ -# Definition for singly-linked list. -# class ListNode: -# def __init__(self, x): -# self.val = x -# self.next = None +class Node: -def merge_two_lists(l1: ListNode, l2: ListNode): + def __init__(self, x): + self.val = x + self.next = None + +def merge_two_lists(l1: Node, l2: Node): if not l1 and not l2: return elif not l2: @@ -19,7 +19,7 @@ def merge_two_lists(l1: ListNode, l2: ListNode): return l2 -def mergeKLists(lists: List[ListNode]) -> ListNode: +def mergeKLists(lists: List[Node]) -> Node: length = len(lists) if length == 0: return; From 09bc916083714137410a0949f817142d5809a0ec Mon Sep 17 00:00:00 2001 From: Tarun Garg Date: Thu, 10 Oct 2019 19:47:05 +0530 Subject: [PATCH 065/455] Added Luhn Algorithm --- algorithms/miscellaneous/index.md | 3 ++ algorithms/miscellaneous/luhn_algorithm.py | 35 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 algorithms/miscellaneous/index.md create mode 100644 algorithms/miscellaneous/luhn_algorithm.py diff --git a/algorithms/miscellaneous/index.md b/algorithms/miscellaneous/index.md new file mode 100644 index 00000000..b45d88c6 --- /dev/null +++ b/algorithms/miscellaneous/index.md @@ -0,0 +1,3 @@ +# Index of miscellaneous + +* luhn_algorithm.py \ No newline at end of file diff --git a/algorithms/miscellaneous/luhn_algorithm.py b/algorithms/miscellaneous/luhn_algorithm.py new file mode 100644 index 00000000..1a20a9e4 --- /dev/null +++ b/algorithms/miscellaneous/luhn_algorithm.py @@ -0,0 +1,35 @@ +""" +Luhn algorithm or Luhn formula is a simple checksum formula +used to validate a variety of identification numbers, such as +credit card numbers, IMEI numbers, National Provider Identifier numbers +in some of the Countries +""" + +""" +It takes a number as an input +(Assuming cardnumber as a string) +and returns true or false +based upon whether number is valid or not +""" + +def checkLuhn(cardNumber): + cardLen = len(cardNumber) + + checkSum = 0 + + isParity = False + + for digit in range(cardLen-1,-1,-1): + if isParity: + cal = int(cardNumber[digit])*2 + else: + cal = int(cardNumber[digit]) + + if cal>9: + checkSum += cal -9 + else: + checkSum += cal + + isParity = not isParity + + return checkSum%10==0 From 58b1f94f2441043e0cd70d929d71eeea9e2fbc8b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 21:39:11 +0530 Subject: [PATCH 066/455] Delete k-means.py --- algorithms/clustering/k-means.py | 110 ------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 algorithms/clustering/k-means.py diff --git a/algorithms/clustering/k-means.py b/algorithms/clustering/k-means.py deleted file mode 100644 index 6a139b23..00000000 --- a/algorithms/clustering/k-means.py +++ /dev/null @@ -1,110 +0,0 @@ -""" - HIGH LEVEL EXPLANATION: - - K-MEANS is a static custering algorithm that is used on machine learning to cluster - information together. The way that it works is that you are chosing K points that will - be put on random positions. After each repetition each point is assigned to each clustering - point depending on which cluster is closest to the point. After that the new position of each - cluster is chosen by finding the average position of all points that were assigned to that cluster. -""" - -import random -import math - -# Create a point class functioning more like a data structure -class Point: - - x = 0 - y = 0 - - def __init__(self,x,y): - self.x = x - self.y = y - -k = int(input("Select how many centroids you need")) -n = int(input("Select how many random points do you want")) - -centroids = [] -points = [] - -# Creating a multidimensional array here with our point structure -# -# [ [Point*n]*k ] - -centroid_points = [ [ Point(0,0) for i in range(n)] for j in range(k)] -amount_of_centroids_on_each_point = [] - -# randomization of points -for i in range(k): - point = Point(random.uniform(10,100),random.uniform(10,100)) - centroids.append(point) - -for i in range(n): - point = Point(random.uniform(10,100),random.uniform(10,100)) - points.append(point) - - - -failSafeCounter = 0 -flag = 0 - -# Main functionallity -while flag == 0 and failSafeCounter < 1000: - - flag = 0 - - #Reseting this array - for i in range(n): - amount_of_centroids_on_each_point.append(0) - - for i in range(n): - - # Looping through the points array to find the - # cluster with the minimum ditance from the point - # and assigning it to that - minimum = 99999999 - lower_centroid = -1 - - for j in range(k): - - # Finding the cluster here with the miminum distance from the point - distance = math.sqrt( (centroids[j].x-points[i].x)*(centroids[j].x-points[i].x) + (centroids[j].y-points[i].y)*(centroids[j].y-points[i].y )) - if (distance < minimum): - minimum = distance - lower_centroid = j - - # Assigning point to the cluster - centroid_points[lower_centroid][amount_of_centroids_on_each_point[lower_centroid]].x = points[i].x - centroid_points[lower_centroid][amount_of_centroids_on_each_point[lower_centroid]].y = points[i].y - amount_of_centroids_on_each_point[lower_centroid] += 1 - - failSafeCounter+=1 - - for i in range(k): - avgx = 0 - avgy = 0 - counter = 0 - - for j in range(n): - if (not(centroid_points[i][j].x == 0 and centroid_points[i][j].y == 0)): - avgx+=centroid_points[i][j].x - avgy+=centroid_points[i][j].y - counter+=1 - - if counter!=0: - - if centroids[i].x != (avgx/counter) or centroids[i].y != (avgy/counter): - flag = 1 - - centroids[i].x = (avgx/counter) - centroids[i].y = (avgy/counter) - - -# Loop through the points list to show the results -for i in range(k): - print('Cluster {} has the following points:\n'.format(i)) - for j in range(n): - if (not(centroid_points[i][j].x == 0 and centroid_points[i][j].y == 0)): - print('x:{},y:{}'.format(centroid_points[i][j].x,centroid_points[i][j].y)) - - print('\n') From 20d9d5fd39fe4c3219334d106a810fa428a0f51a Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 21:59:29 +0530 Subject: [PATCH 067/455] Create __init__.py --- algorithms/greedy/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 algorithms/greedy/__init__.py diff --git a/algorithms/greedy/__init__.py b/algorithms/greedy/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/algorithms/greedy/__init__.py @@ -0,0 +1 @@ + From 262a0f3a6baa1926014514b2f03bc52493b3bfb9 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 22:14:25 +0530 Subject: [PATCH 068/455] Update bubbleSort.py --- algorithms/sorting/bubbleSort.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algorithms/sorting/bubbleSort.py b/algorithms/sorting/bubbleSort.py index 59b8f16c..eb465760 100644 --- a/algorithms/sorting/bubbleSort.py +++ b/algorithms/sorting/bubbleSort.py @@ -10,9 +10,9 @@ """ -def bubbleSort(arr): - for i in range(0,len(arr)): - for j in range(0,len(arr)-1): +def bubble_sort(arr): + for i in range(0, len(arr)): + for j in range(0, len(arr)-1): if (arr[j] > arr[j+1]): arr[j] , arr[j+1] = arr[j+1] , arr[j] return arr From 4f239de5ef26f1037c1991e4fdb2a350558e9b27 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 22:14:52 +0530 Subject: [PATCH 069/455] Rename bubbleSort.py to bubble_sort.py --- algorithms/sorting/{bubbleSort.py => bubble_sort.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename algorithms/sorting/{bubbleSort.py => bubble_sort.py} (100%) diff --git a/algorithms/sorting/bubbleSort.py b/algorithms/sorting/bubble_sort.py similarity index 100% rename from algorithms/sorting/bubbleSort.py rename to algorithms/sorting/bubble_sort.py From e44f5a0f79033fe2b021bb5d26d16d0c522e534d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 22:21:08 +0530 Subject: [PATCH 070/455] Delete bubble_sort.py --- algorithms/sorting/bubble_sort.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 algorithms/sorting/bubble_sort.py diff --git a/algorithms/sorting/bubble_sort.py b/algorithms/sorting/bubble_sort.py deleted file mode 100644 index eb465760..00000000 --- a/algorithms/sorting/bubble_sort.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -High level explanation: -Bubble sort: -is a simple sorting algorithm that repeatedly steps through the list, -compares adjacent elements and swaps them if they are in the wrong order. -The pass through the list is repeated until the list is sorted. - -Time Complexity: -Bubble sort has a time complexity of О(n^2) -""" - - -def bubble_sort(arr): - for i in range(0, len(arr)): - for j in range(0, len(arr)-1): - if (arr[j] > arr[j+1]): - arr[j] , arr[j+1] = arr[j+1] , arr[j] - return arr From 9308a0ee3c2effed044d176fb67fed0b72d2e2a5 Mon Sep 17 00:00:00 2001 From: M4cs Date: Thu, 10 Oct 2019 13:50:19 -0400 Subject: [PATCH 071/455] Change useful_links.md to sub-files --- useful_links.md => articles.md | 58 +++------------------------------- books.md | 10 ++++++ misc.md | 15 +++++++++ topics.md | 17 ++++++++++ tutorials.md | 13 ++++++++ videos.md | 9 ++++++ 6 files changed, 68 insertions(+), 54 deletions(-) rename useful_links.md => articles.md (56%) create mode 100644 books.md create mode 100644 misc.md create mode 100644 topics.md create mode 100644 tutorials.md create mode 100644 videos.md diff --git a/useful_links.md b/articles.md similarity index 56% rename from useful_links.md rename to articles.md index 5c20e67f..4ba71571 100644 --- a/useful_links.md +++ b/articles.md @@ -1,46 +1,8 @@ -# Useful links +# Articles -This is a list of articles, tutorials, questions, books and videos that may be useful for algorithms and data structures learning. +This is a list of articles that may be useful for algorithms and data structures learning. -## Questions - -- https://stackoverflow.com/questions/35390533/actual-difference-between-data-compression-and-data-deduplication - -- https://stackoverflow.com/questions/40200413/sessions-vs-token-based-authentication - -- https://stackoverflow.com/questions/15678406/when-to-use-myisam-and-innodb - -## Tutorials - -- https://cstack.github.io/db_tutorial/ - -- https://github.com/eon01/kubernetes-workshop - -- http://cp-algorithms.com/ - -- https://realpython.com/python-data-classes/ - -## Videos - -- https://www.youtube.com/watch?v=mSzUb7f47qk - -- https://www.youtube.com/user/mycodeschool - -## Topics - -- https://en.wikipedia.org/wiki/Data_deduplication - -- https://searchstorage.techtarget.com/definition/data-deduplication - -- https://docs.gitlab.com/ce/development/architecture.html - -## Books - -- https://drive.google.com/open?id=1d23_sJdK8XPBJEi-4oUrMnrYMhU2fDcI - -- https://drive.google.com/open?id=1sBSGJ8gUakcn0NuQam4BRhRCQfsTrrwh - -## Articles +## Links: - https://www.topcoder.com/community/competitive-programming/tutorials/dynamic-programming-from-novice-to-advanced/ @@ -86,16 +48,4 @@ This is a list of articles, tutorials, questions, books and videos that may be u - https://cs.nyu.edu/courses/fall17/CSCI-UA.0102-001/Notes/LinearSort.html -- https://martinfowler.com/articles/serverless.html - -## Others - -- https://google.github.io/eng-practices/review/reviewer/ - -- https://www.preining.info - -- https://cheatsheetseries.owasp.org - -- https://wsvincent.com/ - -- https://machinelearningmastery.com +- https://martinfowler.com/articles/serverless.html \ No newline at end of file diff --git a/books.md b/books.md new file mode 100644 index 00000000..88b69d20 --- /dev/null +++ b/books.md @@ -0,0 +1,10 @@ +# Books + +This is a list of links to books that may be useful for algorithms and data structures learning. + +## Links: + +- https://drive.google.com/open?id=1d23_sJdK8XPBJEi-4oUrMnrYMhU2fDcI + +- https://drive.google.com/open?id=1sBSGJ8gUakcn0NuQam4BRhRCQfsTrrwh + diff --git a/misc.md b/misc.md new file mode 100644 index 00000000..de317d49 --- /dev/null +++ b/misc.md @@ -0,0 +1,15 @@ +# Miscellaneous + +This is a list of misc links that may be useful when learning or researching data structures and algorithms. + +## Links: + +- https://google.github.io/eng-practices/review/reviewer/ + +- https://www.preining.info + +- https://cheatsheetseries.owasp.org + +- https://wsvincent.com/ + +- https://machinelearningmastery.com diff --git a/topics.md b/topics.md new file mode 100644 index 00000000..bf8c7be2 --- /dev/null +++ b/topics.md @@ -0,0 +1,17 @@ +# Topics + +This is a list of links to topics that may be helpful in learning or researching data structures and algorithms. + +## Links: + +- https://en.wikipedia.org/wiki/Data_deduplication + +- https://searchstorage.techtarget.com/definition/data-deduplication + +- https://docs.gitlab.com/ce/development/architecture.html + +- https://stackoverflow.com/questions/35390533/actual-difference-between-data-compression-and-data-deduplication + +- https://stackoverflow.com/questions/40200413/sessions-vs-token-based-authentication + +- https://stackoverflow.com/questions/15678406/when-to-use-myisam-and-innodb \ No newline at end of file diff --git a/tutorials.md b/tutorials.md new file mode 100644 index 00000000..42c45d10 --- /dev/null +++ b/tutorials.md @@ -0,0 +1,13 @@ +# Tutorials + +This is a list of links to tutorials that may be helpful in learning or researching data structures and algorithms. + +## Links: + +- https://cstack.github.io/db_tutorial/ + +- https://github.com/eon01/kubernetes-workshop + +- http://cp-algorithms.com/ + +- https://realpython.com/python-data-classes/ \ No newline at end of file diff --git a/videos.md b/videos.md new file mode 100644 index 00000000..0ac8813e --- /dev/null +++ b/videos.md @@ -0,0 +1,9 @@ +# Videos + +This is a list of video links that may be useful for algorithms and data structures learning. + +## Links: + +- https://www.youtube.com/watch?v=mSzUb7f47qk + +- https://www.youtube.com/user/mycodeschool \ No newline at end of file From 434c127ea4c49eb8d6bf65c71ff6ee10361d994e Mon Sep 17 00:00:00 2001 From: M4cs Date: Thu, 10 Oct 2019 13:52:28 -0400 Subject: [PATCH 072/455] Create table of contents --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e3bded18..33f49eeb 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,16 @@ This directory contains various types of algorithm questions like Dynamic Progra ### Useful Links -This file is for storing some useful websites, or articles, or videos that can be useful for interview preparations and help to increase knowledge. +You can find useful links in this repository in the different markdown files. Below is a table of contents. + +| Category | Link | +| :-- | :--: | +| Articles | [Click Here](https://github.com/prabhupant/python-ds/blob/master/articles.md) | +| Books | [Click Here](https://github.com/prabhupant/python-ds/blob/master/books.md) | +| Topics | [Click Here](https://github.com/prabhupant/python-ds/blob/master/topics.md) | +| Tutorials | [Click Here](https://github.com/prabhupant/python-ds/blob/master/tutorials.md) | +| Videos | [Click Here](https://github.com/prabhupant/python-ds/blob/master/videos.md) | +| Misc. | [Click Here](https://github.com/prabhupant/python-ds/blob/master/misc.md) | ## :clipboard: Things need to be done From 3a679e7aa48171deada428931a7e990057a7061e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 23:41:03 +0530 Subject: [PATCH 073/455] Move all useful links in a separate folder --- articles.md => bookmarks/articles.md | 0 books.md => bookmarks/books.md | 0 misc.md => bookmarks/misc.md | 0 topics.md => bookmarks/topics.md | 0 tutorials.md => bookmarks/tutorials.md | 0 videos.md => bookmarks/videos.md | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename articles.md => bookmarks/articles.md (100%) rename books.md => bookmarks/books.md (100%) rename misc.md => bookmarks/misc.md (100%) rename topics.md => bookmarks/topics.md (100%) rename tutorials.md => bookmarks/tutorials.md (100%) rename videos.md => bookmarks/videos.md (100%) diff --git a/articles.md b/bookmarks/articles.md similarity index 100% rename from articles.md rename to bookmarks/articles.md diff --git a/books.md b/bookmarks/books.md similarity index 100% rename from books.md rename to bookmarks/books.md diff --git a/misc.md b/bookmarks/misc.md similarity index 100% rename from misc.md rename to bookmarks/misc.md diff --git a/topics.md b/bookmarks/topics.md similarity index 100% rename from topics.md rename to bookmarks/topics.md diff --git a/tutorials.md b/bookmarks/tutorials.md similarity index 100% rename from tutorials.md rename to bookmarks/tutorials.md diff --git a/videos.md b/bookmarks/videos.md similarity index 100% rename from videos.md rename to bookmarks/videos.md From 3f30a7ad14bad1b02929dbb5f1e2cf9637d4ae94 Mon Sep 17 00:00:00 2001 From: Max Bridgland <34947910+M4cs@users.noreply.github.com> Date: Thu, 10 Oct 2019 14:13:36 -0400 Subject: [PATCH 074/455] Update ToC for files that moved. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 33f49eeb..7c062df8 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,12 @@ You can find useful links in this repository in the different markdown files. Be | Category | Link | | :-- | :--: | -| Articles | [Click Here](https://github.com/prabhupant/python-ds/blob/master/articles.md) | -| Books | [Click Here](https://github.com/prabhupant/python-ds/blob/master/books.md) | -| Topics | [Click Here](https://github.com/prabhupant/python-ds/blob/master/topics.md) | -| Tutorials | [Click Here](https://github.com/prabhupant/python-ds/blob/master/tutorials.md) | -| Videos | [Click Here](https://github.com/prabhupant/python-ds/blob/master/videos.md) | -| Misc. | [Click Here](https://github.com/prabhupant/python-ds/blob/master/misc.md) | +| Articles | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/articles.md) | +| Books | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/books.md) | +| Topics | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/topics.md) | +| Tutorials | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/tutorials.md) | +| Videos | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/videos.md) | +| Misc. | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/misc.md) | ## :clipboard: Things need to be done From 7682c2a921e24571aab83f0ed7637b42f7ca2e12 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Oct 2019 23:45:11 +0530 Subject: [PATCH 075/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c062df8..cfb2b679 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ This directory contains various types of algorithm questions like Dynamic Progra 2. Math 3. Sorting -### Useful Links +### Bookmarks You can find useful links in this repository in the different markdown files. Below is a table of contents. From 588f6044fb3d077a6d382e43b5d0aadf61309d3d Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Thu, 10 Oct 2019 23:56:18 +0530 Subject: [PATCH 076/455] Palindromic string question added Our task is to find given string is the palindromic string or not --- data_structures/strings/Palindromic_String.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 data_structures/strings/Palindromic_String.py diff --git a/data_structures/strings/Palindromic_String.py b/data_structures/strings/Palindromic_String.py new file mode 100644 index 00000000..086808ae --- /dev/null +++ b/data_structures/strings/Palindromic_String.py @@ -0,0 +1,19 @@ +""" +Question +You have been given a String S. You need to find and print whether this string is a palindrome or not. If yes, print "YES" (without quotes), else print "NO" (without quotes). +Source Hackerearth +Input Format: +The first and only line of input contains the String S. The String shall consist of lowercase English alphabets only. +ex: aba,abc +Output Format: +Print the required answer on a single line. +ex: YES,NO +""" + +def palindrome(string): + if(string==string[::-1]): # Check if string is equal to reverse of the string using string slicing method + print('YES') # the print YES + else: + print('NO') # else print NO +string=input() # Take input string from the user +palindrome(string) # pass the input to the user defined function palindrome From 769b19921c991d361f9d546bece413f45e0510f6 Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Fri, 11 Oct 2019 00:11:25 +0530 Subject: [PATCH 077/455] Changed the matrix_layer_rotation wrt pep8 --- .../array/matrix_layer_rotation.py | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 data_structures/array/matrix_layer_rotation.py diff --git a/data_structures/array/matrix_layer_rotation.py b/data_structures/array/matrix_layer_rotation.py new file mode 100644 index 00000000..ef5d36c7 --- /dev/null +++ b/data_structures/array/matrix_layer_rotation.py @@ -0,0 +1,88 @@ +""" +Description: + +Matrix Layer Rotation + +You are given a 2D matrix of dimension mxn and a positive integer r. You have to rotate the +matrix r times and print the resultant matrix. Rotation should be in anti-clockwise direction. +Rotation of a 4x5 matrix is represented by the following figure. Note that in one rotation, +you have to shift elements by one step only. This is shifting the elemment. +Note:- Minimum of m and n will be even. + +Start First Second + 1 2 3 4 2 3 4 5 3 4 5 6 +12 1 2 5 -> 1 2 3 6 -> 2 3 4 7 +11 4 3 6 12 1 4 7 1 2 1 8 +10 9 8 7 11 10 9 8 12 11 10 9 +""" + + +# Function to rotate the sides of the matrix in place. +def matrix_rotate(matrix, m, n, i=0, j=0): + if (m, n) == (1, 1): + return matrix + if (m, n) == (2, 2): + temp = matrix[i][j] + matrix[i][j] = matrix[i + 1][j] + matrix[i + 1][j] = matrix[i + 1][j + 1] + matrix[i + 1][j + 1] = matrix[i + 1][j] + matrix[i + 1][j] = temp + return matrix + else: + temp = matrix[i][j] + # top + for a in range(j, n - j - 1): + matrix[i][a] = matrix[i][a + 1] + matrix[i][n - j - 1] = matrix[i + 1][n - j - 1] + # right + for a in range(i + 1, m - i - 2): + matrix[a][n - 1 - j] = matrix[a + 1][n - 1 - j] + matrix[m - j - 2][n - j - 1] = matrix[m - j - 1][n - j - 1] + # bottom + for a in range(n - j - 1, j, -1): + matrix[m - j - 1][a] = matrix[m - j - 1][a - 1] + matrix[m - j - 1][j] = matrix[m - j - 2][j] + # left + for a in range(m - i - 2, i, -1): + matrix[a][i] = matrix[a - 1][i] + matrix[i + 1][j] = temp + return matrix + + +def driver_code(matrix, r): + m = len(matrix) + n = len(matrix[0]) + i, j = 0, 0 + s = 0 + while (i, j) < (m // 2, n // 2): # Checking for the maximum values of i, j. + for _ in range(r): + s = matrix_rotate(matrix, m, n, i, j) + i += 1 + j += 1 + print_matrix(s) + + +def print_matrix(matrix): + m = len(matrix) + n = len(matrix[0]) + print('\n'.join([' '.join(['{:n}'.format(item) for item in row]) + for row in matrix])) + + +if __name__ == '__main__': + mnr = input().rstrip().split() + + m = int(mnr[0]) + + n = int(mnr[1]) + + r = int(mnr[2]) + + matrix2d = [] + + for _ in range(m): + matrix2d.append(list(map(int, input().rstrip().split()))) + + driver_code(matrix2d, r) + + From 6cfacc6a720a35ad4c3fcd6775853035bc08ab87 Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Fri, 11 Oct 2019 00:13:59 +0530 Subject: [PATCH 078/455] Toogle_String_Program is updated Question is to convert upper case characters to lower case and vice-versa. --- data_structures/strings/ Toggle_String.py | 30 +++++++++++++++++++ data_structures/strings/Palindromic_String.py | 19 ------------ 2 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 data_structures/strings/ Toggle_String.py delete mode 100644 data_structures/strings/Palindromic_String.py diff --git a/data_structures/strings/ Toggle_String.py b/data_structures/strings/ Toggle_String.py new file mode 100644 index 00000000..ed039282 --- /dev/null +++ b/data_structures/strings/ Toggle_String.py @@ -0,0 +1,30 @@ +""" +Question +You have been given a String S consisting of uppercase and lowercase English alphabets. You need to change the case of each alphabet +in this String. That is, all the uppercase letters should be converted to lowercase and all the lowercase letters should be converted +to uppercase. You need to then print the resultant String to output. +Source Hackerearth + +SAMPLE INPUT +abcdE +SAMPLE OUTPUT +ABCDe +""" + +def ToggleString1(string): + return string.swapcase() + +def ToggleString2(string): + toggleString='' + for s in string: + if s.isupper(): + toggleString+=s.lower() + elif s.islower(): + toggleString+=s.upper() + return toggleString + + + +string=input() +print(ToggleString1(string)) # method 1 +print(ToggleString2(string)) # method 2 diff --git a/data_structures/strings/Palindromic_String.py b/data_structures/strings/Palindromic_String.py deleted file mode 100644 index 086808ae..00000000 --- a/data_structures/strings/Palindromic_String.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Question -You have been given a String S. You need to find and print whether this string is a palindrome or not. If yes, print "YES" (without quotes), else print "NO" (without quotes). -Source Hackerearth -Input Format: -The first and only line of input contains the String S. The String shall consist of lowercase English alphabets only. -ex: aba,abc -Output Format: -Print the required answer on a single line. -ex: YES,NO -""" - -def palindrome(string): - if(string==string[::-1]): # Check if string is equal to reverse of the string using string slicing method - print('YES') # the print YES - else: - print('NO') # else print NO -string=input() # Take input string from the user -palindrome(string) # pass the input to the user defined function palindrome From c3b4be9f59465a2aeeb8851ae31632e55f03025e Mon Sep 17 00:00:00 2001 From: Saurabh Rai Date: Fri, 11 Oct 2019 00:45:41 +0530 Subject: [PATCH 079/455] Updated the Index and added sieve_of_eratosthenes --- algorithms/math/index.md | 3 +++ algorithms/math/sieve_of_eratosthenes.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 algorithms/math/sieve_of_eratosthenes.py diff --git a/algorithms/math/index.md b/algorithms/math/index.md index e1a3a6e9..62d635c8 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -1,3 +1,6 @@ # Index of math * greatest_common_divisor.py +* fibbonacci_number.py +* prime.py +* sieve_of_eratosthenes.py diff --git a/algorithms/math/sieve_of_eratosthenes.py b/algorithms/math/sieve_of_eratosthenes.py new file mode 100644 index 00000000..929d17e0 --- /dev/null +++ b/algorithms/math/sieve_of_eratosthenes.py @@ -0,0 +1,18 @@ +""" +Description: +Sieve of Eratosthenes is a very fast method (loglog(n)) of finding primes upto a given number. +""" + + +def sieve(n): + prime_list = [] + for i in range(2, n+1): + if i not in prime_list: + print(i) + for j in range(i*i, n+1, i): + prime_list.append(j) + + +if __name__ == '__main__': + input_number = int(input("Provide a number upto which primes are to be found :")) + sieve(input_number) From 085b5c7a92f6adfec1d63d0c4b44cc5e27904fbe Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Fri, 11 Oct 2019 00:47:21 +0530 Subject: [PATCH 080/455] Minor changes added removed useful_links.md in the read.md file and added bookmarks directory --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfb2b679..fefd5a03 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. +As of now, the repository contains a file called [`index_updater.py`](index_updater.py) and 3 main directories and 1 [**logo**](logo) directory : [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks). ### Data Structures From 6114d4c80c5a585cc2e2ce0156c72439fed02297 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 11 Oct 2019 00:58:04 +0530 Subject: [PATCH 081/455] Add license and contributing in Readme --- README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index cfb2b679..f5804763 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -![logo](logo/logo.png) +![logo](logo/logo.png) # Python Data Structures and Algorithms -This repository contains data structures and algorithms concepts and questions in Python. +This repository contains data structures and algorithms concepts and questions in Python. ## :dart: Objective @@ -16,17 +16,17 @@ As of now, the repository contains a file called [`useful_links.md`](useful_link Contains all data structure questions categorised into sub-directories like stack, queue, etc according to their type. -1. Array +1. Array 2. Dictionary -3. Binary Search Tree -4. Linked List -5. Stack -6. Graphs +3. Binary Search Tree +4. Linked List +5. Stack +6. Graphs 7. Circular Linked List ### Algorithms -This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - +This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - 1. Dynamic Programming 2. Math @@ -50,9 +50,9 @@ You can find useful links in this repository in the different markdown files. Be As you can see, the repo is still in its infancy. Here are some key things in the to-do. 1. Queue questions -2. Algorithms - 2.1. Dynamic Programming - 2.2. Greedy +2. Algorithms + 2.1. Dynamic Programming + 2.2. Greedy 3. More questions in data structures, especially for graph, circular linked list, tries, heaps and hash. ## :raised_hand: Contributing @@ -60,8 +60,9 @@ As you can see, the repo is still in its infancy. Here are some key things in th Contributions are always welcomed. :smiley: Feel free to raise new issues, file new PRs and star and fork this repo! :wink: -Here are some guidelines: +To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) -1. Clone the repo to your local machine -2. Make the new branch and name it accordingly -3. File the PR and wait for the review :) + +## :page_facing_up: License + +MIT @ Prabhu Pant \ No newline at end of file From aeee48257fea6095b30c99b9062314143fd485d2 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 11 Oct 2019 00:58:15 +0530 Subject: [PATCH 082/455] Add contributing.md --- CONTRIBUTING.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..1f0c24e6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,92 @@ +# Contributing + +This is a project that is for the community and its true essence is only possible when it is community driven. + +Please feel free to contribute to this project and be a part of this. Anything from raising issues to adding new features or even a typo in documentations, all are welcome. Please report issues here [https://github.com/prabhupant/python-ds/issues](https://github.com/prabhupant/python-ds/issues). It is also recommended to go through the Contributions Best Practices below to help organize contributions :smiley: + +## Contributions Best Practices + +### Commits + +* Write clear meaningful git commit messages (Do read [http://chris.beams.io/posts/git-commit/](http://chris.beams.io/posts/git-commit/)) + +* Make sure your PR's description contains GitHub's special numeric reference to the related issue. + +* While adding questions, please make sure that you add only a single new question per PR as it becomes easy to review and maintain many PRs. + +* When you make minor changes to a PR of yours, make sure you squash your commits afterwards so that you don't have an absurd number of commits for a single PR. (Learn how to squash commits at [https://davidwalsh.name/squash-commits-git](https://davidwalsh.name/squash-commits-git)) + +### Issues + +Feel free to open up any issue in the repository, whether it is about code improvements or bug fixes or documentation. You can also use any label you want to associate with the issue. Please provide a clear description of the issue while filing it :smiley: + +### Code Styling Guide + +Python follows a Pep8 styling. Styling the code according to it makes it universally appealing and more readable. Also, if all data structures and algorithms are written in a similar style code, then it will be easy for everyone to implement them. So please follow Pep8 styling conventions (most notably, avoid using camelCase and prefer snake_case while naming functions and files). You can find the Pep8 styling guide here [https://www.python.org/dev/peps/pep-0008/](https://www.python.org/dev/peps/pep-0008/) + +### Questions + +While there are infinite number of data structure and algorithm questions, it is impossible to collect all of them here. So please add only those questions that are either unique or tricky or have some mind blowing approach to solve them. Also, try not to file a PR for a question which is already present in the repo. Interesting questions and implementations are always welcomed :wink: + +For filing a PR for a new question, please open a issue first for the same and then reference it in the PR. For example, let's say you want to add a new question called "find max element in array". So first head over to the issues tab and create a new issue called "New question: find max element in array". Then if you want to work on it, please mention it in the description. After you are done writing the code and ready to file a PR, refer to the issue number in the PR description. Let's say the issue number was #23. So in the PR description, it should be "Fixes #23". That's it! :smiley: + +### Bookmarks + +The Bookmarks directory is for storing awesome links to articles, videos, slides, talks, etc that are interesting and can help in increasing knowledge for a specific topic. There has been many PRs for adding new links in Bookmarks and most of them refered to either a whole book or DS Algo MOOCs, please refrain from adding them. Here are some points that you must consider before contributing to Bookmarks - + +* Don't add a link to a MOOC or course (like DS Algo MIT lectures) + +* Ask yourself "Is the link interesting enough that someone will really love it?" or "Is it something that an interviewer might ask in the interview to test you?" or "Is it some common or amazing thing people don't have enough knowledge about?". If yes to any of them, then sure, quickly file the PR :wink: + +* If an article has more than one part, be sure to refer to the first only in the PR. + +## How To Contribute? + +You can add anything to the repo as long as it is related to programming and increasing knowledge :smiley: + +0. Firstly, fork the repo to your GitHub account. Just to get familiar with some terms, this will be the `origin`. To state `origin` and `upstream` explicitly, + +https://github.com/prabhupant/python-ds = upstream +https://github.com/your-username/python-ds = origin + +You will be making all your changes to origin and then file a PR to upstream from there. + +1. Make sure to make a clone of the repository. + +```bash +$ git clone https://github.com/prabhupant/python-ds +``` + +2. Now `cd` into the directory and create a new branch for the issue. Let's call the branch `max-number-in-array` + +```bash +$ git checkout -b max-number-in-array +``` + +3. Make your changes and add and commit them + +```bash +$ git add . +$ git commit -m "Add max number in array" +``` + +4. Now push the branch to your origin + +```bash +$ git push origin max-number-in-array +``` + +5. Now head to your GitHub account and open your fork of python-ds i.e, the origin, and create a PR to the upstream from there. GitHub will automatically detect the upstream for you. + +6. Write a good brief description and refer to the issue (if any) and submit the PR. + +7. Now wait for the approval :smiley: + +## Join The Development + +Before you join the development, please fork and clone the repository to your local machine and explore it. Don't worry nothing will happen, atmost some code might not work :wink: + +Feel free to contribute and be a part of this endeavour :beers: + + + From 367a9f024dca44422b9667b8fd4c9c7aee90f2a0 Mon Sep 17 00:00:00 2001 From: Christian L Moreno Date: Thu, 10 Oct 2019 21:32:55 -0300 Subject: [PATCH 083/455] Fix code style. Remove two semicolon. What do semicolon in python? --- .../dynamic_programming/climbing_stairs.py | 3 +- .../dynamic_programming/edit_distance.py | 39 ++++++++++--------- .../longest_common_subsequence.py | 3 +- .../dynamic_programming/max_subarray.py | 7 +++- algorithms/dynamic_programming/rod_cutting.py | 5 ++- .../dynamic_programming/unique_grid_paths.py | 29 +++++++------- 6 files changed, 49 insertions(+), 37 deletions(-) diff --git a/algorithms/dynamic_programming/climbing_stairs.py b/algorithms/dynamic_programming/climbing_stairs.py index 6633a7a4..b47ffa3a 100644 --- a/algorithms/dynamic_programming/climbing_stairs.py +++ b/algorithms/dynamic_programming/climbing_stairs.py @@ -1,7 +1,8 @@ """ High Level Description: You are climbing a stair case. It takes n steps to reach to the top. -Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? +Each time you can either climb 1 or 2 steps. In how many distinct ways can you +climb to the top? Time Complexity: O(n) diff --git a/algorithms/dynamic_programming/edit_distance.py b/algorithms/dynamic_programming/edit_distance.py index e897987f..dde466a9 100644 --- a/algorithms/dynamic_programming/edit_distance.py +++ b/algorithms/dynamic_programming/edit_distance.py @@ -1,7 +1,8 @@ """ High Level Description: -Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2. -You have the following 3 operations permitted on a word: +Given two words word1 and word2, find the minimum number of operations +required to convert word1 to word2. You have the following 3 operations +permitted on a word: Insert a character Delete a character Replace a character @@ -9,20 +10,22 @@ Time Complexity: O(m*n) """ + + def edit_dist(str1, str2, m, n): - dp = [[0 for x in range(n+1)] for x in range(m+1)] - - for i in range(m+1): - for j in range(n+1): - if i == 0: - dp[i][j] = j - elif j == 0: - dp[i][j] = i - elif str1[i-1] == str2[j-1]: - dp[i][j] = dp[i-1][j-1] - else: - dp[i][j] = 1 + min(dp[i][j-1], # Insert - dp[i-1][j], # Remove - dp[i-1][j-1]) # Replace - - return dp[m][n] \ No newline at end of file + dp = [[0 for x in range(n+1)] for x in range(m+1)] + + for i in range(m+1): + for j in range(n+1): + if i == 0: + dp[i][j] = j + elif j == 0: + dp[i][j] = i + elif str1[i-1] == str2[j-1]: + dp[i][j] = dp[i-1][j-1] + else: + dp[i][j] = 1 + min(dp[i][j-1], # Insert + dp[i-1][j], # Remove + dp[i-1][j-1]) # Replace + + return dp[m][n] diff --git a/algorithms/dynamic_programming/longest_common_subsequence.py b/algorithms/dynamic_programming/longest_common_subsequence.py index b6adc851..d8a5e66e 100644 --- a/algorithms/dynamic_programming/longest_common_subsequence.py +++ b/algorithms/dynamic_programming/longest_common_subsequence.py @@ -4,6 +4,7 @@ longest common subsequence ''' + def lcs(S1, S2): m = len(S1) n = len(S2) @@ -12,7 +13,7 @@ def lcs(S1, S2): for i in range(m + 1): for j in range(n + 1): - if i == 0 or j == 0 : + if i == 0 or j == 0: LCS[i][j] = 0 elif S1[i-1] == S2[j-1]: LCS[i][j] = LCS[i-1][j-1]+1 diff --git a/algorithms/dynamic_programming/max_subarray.py b/algorithms/dynamic_programming/max_subarray.py index c55a0b6a..5a1caa43 100644 --- a/algorithms/dynamic_programming/max_subarray.py +++ b/algorithms/dynamic_programming/max_subarray.py @@ -1,10 +1,13 @@ """ High Level Description: -Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. +Given an integer array nums, find the contiguous subarray (containing at least +one number) which has the largest sum and return its sum. Time Complexity: O(n) """ + + # Iterative Solution def max_sub_array(self, arr): if not arr: @@ -15,4 +18,4 @@ def max_sub_array(self, arr): cur_sum = max(num, cur_sum + num) max_sum = max(max_sum, cur_sum) - return max_sum \ No newline at end of file + return max_sum diff --git a/algorithms/dynamic_programming/rod_cutting.py b/algorithms/dynamic_programming/rod_cutting.py index 6db53392..9e807bb0 100644 --- a/algorithms/dynamic_programming/rod_cutting.py +++ b/algorithms/dynamic_programming/rod_cutting.py @@ -4,10 +4,11 @@ of all pieces of size less than n. We need to find the maximum maximum price obtainable by cutting the rod and -selling it. +selling it. ''' INT_MIN = -32767 + def cutRod(price, n): values = [0 for i in range(n+1)] values[0] = 0 @@ -15,7 +16,7 @@ def cutRod(price, n): for i in range(1, n+1): max_value = INT_MIN for j in range(i): - max_value = max(max_value, price[j] + values[i-j-1]) + max_value = max(max_value, price[j] + values[i-j-1]) values[i] = max_value return values[n] diff --git a/algorithms/dynamic_programming/unique_grid_paths.py b/algorithms/dynamic_programming/unique_grid_paths.py index 89953f7f..a5518ba3 100644 --- a/algorithms/dynamic_programming/unique_grid_paths.py +++ b/algorithms/dynamic_programming/unique_grid_paths.py @@ -1,23 +1,26 @@ """ High Level Description: -A preson is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). -The preson can only move either down or right at any point in time. -The preson is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). +A preson is located at the top-left corner of a m x n grid (marked 'Start' in +the diagram below). The preson can only move either down or right at any point +in time. The preson is trying to reach the bottom-right corner of the grid +(marked 'Finish' in the diagram below). How many possible unique paths are there? Time Complexity: O(m*n) """ -def number_of_paths(m, n): - count = [[0 for x in range(m)] for y in range(n)] - for i in range(m): - count[i][0] = 1; - for j in range(n): - count[0][j] = 1; +def number_of_paths(m, n): + count = [[0 for x in range(m)] for y in range(n)] - for i in range(1, m): - for j in range(n): - count[i][j] = count[i-1][j] + count[i][j-1] - return count[m-1][n-1] \ No newline at end of file + for i in range(m): + count[i][0] = 1 + + for j in range(n): + count[0][j] = 1 + + for i in range(1, m): + for j in range(n): + count[i][j] = count[i-1][j] + count[i][j-1] + return count[m-1][n-1] From 17a13be062c4a9b6c6d557af144c1e310543b390 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 11 Oct 2019 09:45:49 +0530 Subject: [PATCH 084/455] Add BFF Soundcloud --- bookmarks/articles.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookmarks/articles.md b/bookmarks/articles.md index 4ba71571..16fc7323 100644 --- a/bookmarks/articles.md +++ b/bookmarks/articles.md @@ -48,4 +48,6 @@ This is a list of articles that may be useful for algorithms and data structures - https://cs.nyu.edu/courses/fall17/CSCI-UA.0102-001/Notes/LinearSort.html -- https://martinfowler.com/articles/serverless.html \ No newline at end of file +- https://martinfowler.com/articles/serverless.html + +- https://samnewman.io/patterns/architectural/bff/ From 25df00b5b351395fc689d8ba47ecac16e6e965b3 Mon Sep 17 00:00:00 2001 From: Jay Welborn Date: Fri, 11 Oct 2019 09:19:24 -0400 Subject: [PATCH 085/455] Update merge_list_of_linked_lists.py --- data_structures/linked_list/merge_list_of_linked_lists.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/linked_list/merge_list_of_linked_lists.py b/data_structures/linked_list/merge_list_of_linked_lists.py index 396561c1..9f004a4b 100644 --- a/data_structures/linked_list/merge_list_of_linked_lists.py +++ b/data_structures/linked_list/merge_list_of_linked_lists.py @@ -4,7 +4,7 @@ def __init__(self, x): self.val = x self.next = None -def merge_two_lists(l1: Node, l2: Node): +def merge_two_lists(l1, l2): if not l1 and not l2: return elif not l2: @@ -19,7 +19,7 @@ def merge_two_lists(l1: Node, l2: Node): return l2 -def mergeKLists(lists: List[Node]) -> Node: +def mergeKLists(lists): length = len(lists) if length == 0: return; From 9d44d148d1e6eb56c4810be07bcc52a364d27776 Mon Sep 17 00:00:00 2001 From: Jay Welborn Date: Fri, 11 Oct 2019 09:19:55 -0400 Subject: [PATCH 086/455] Update merge_list_of_linked_lists.py --- data_structures/linked_list/merge_list_of_linked_lists.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/linked_list/merge_list_of_linked_lists.py b/data_structures/linked_list/merge_list_of_linked_lists.py index 9f004a4b..3ba77c26 100644 --- a/data_structures/linked_list/merge_list_of_linked_lists.py +++ b/data_structures/linked_list/merge_list_of_linked_lists.py @@ -4,6 +4,7 @@ def __init__(self, x): self.val = x self.next = None + def merge_two_lists(l1, l2): if not l1 and not l2: return @@ -34,4 +35,3 @@ def mergeKLists(lists): right_half = lists[mid:] return merge_two_lists(mergeKLists(left_half), mergeKLists(right_half)) - From 7f064db78a694e995ba942f058d7ff8a86c5f7ed Mon Sep 17 00:00:00 2001 From: Oishika Pradhan Date: Fri, 11 Oct 2019 19:20:05 +0530 Subject: [PATCH 087/455] Added Prim's MST to graph algorithms --- data_structures/graphs/PrimsMST.py | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 data_structures/graphs/PrimsMST.py diff --git a/data_structures/graphs/PrimsMST.py b/data_structures/graphs/PrimsMST.py new file mode 100644 index 00000000..e88b2b4b --- /dev/null +++ b/data_structures/graphs/PrimsMST.py @@ -0,0 +1,53 @@ +#Uses adjacency matrix representation of graph to calculate Minimum Spanning Tree + +import sys + +class Graph(): + + def __init__(self, vertices): + self.V = vertices + self.graph = [[0 for column in range(vertices)] for row in range(vertices)] + + #Function to print generated MST + def printMST(self, parent): + print("Edge \t Weight") + for i in range(1, self.V): + print(parent[i], "-", i, "\t", self.graph[i][parent[i]]) + + #Function to find vertex with min. distance from set of vertices + #not included in MST + def minValue(self, key, MSTSet): + minval = sys.maxsize + + for v in range(self.V): + if (key[v] < minval) and (MSTSet[v] == False): + minval = key[v] + min_index = v + return min_index + + #Function to construct Prim's MST + def MST(self): + key = [sys.maxsize] * self.V + parent = [None] * self.V + key[0] = 0 + MSTSet = [False] * self.V + parent[0] = -1 + + for j in range(self.V): + u = self.minValue(key, MSTSet) + MSTSet[u] = True + + for v in range(self.V): + if (self.graph[u][v] > 0) and (MSTSet[v] == False) and (key[v] > self.graph[u][v]): + key[v] = self.graph[u][v] + parent[v] = u + + self.printMST(parent) + +g = Graph(4) +g.graph = [ [0, 2, 0, 6], + [2, 0, 3, 8], + [0, 3, 0, 0], + [6, 8, 0, 0]] + +g.MST() \ No newline at end of file From 06d82f33787a3029c1952eae44b78570bb57bce5 Mon Sep 17 00:00:00 2001 From: sanket099 Date: Fri, 11 Oct 2019 21:37:27 +0530 Subject: [PATCH 088/455] new question added --- .../strings/adjacent_vowel_pairs.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 data_structures/strings/adjacent_vowel_pairs.py diff --git a/data_structures/strings/adjacent_vowel_pairs.py b/data_structures/strings/adjacent_vowel_pairs.py new file mode 100644 index 00000000..e028b46c --- /dev/null +++ b/data_structures/strings/adjacent_vowel_pairs.py @@ -0,0 +1,34 @@ +''' +Question : +Given a string consisting of English alphabets, the task is to count the number of adjacent pairs of vowels. +For example : +Input: str = “abaebio” +Output: 2 +(a, e) and (i, o) are the only valid pairs. +Source:A very Common Interview Question. + +Time Complexity : The goal is to complete this question in O(n). +''' + +#function to check whether a character is vowel or not +def is_vowel(character): + if character.lower() in ['a', 'e', 'i', 'o', 'u']: + return True + else: + return False + + +#function to find the number of adjacent vowel pairs. +def adjacent_pairs(string): + string=string.lower() + n=len(string) + count = 0 + for i in range(0,n): + if ((is_vowel(string[i]) and is_vowel(string[i + 1]))): + count += 1 + return count + +#driver code +string=input("enter string") +print (adjacent_pairs(string),"is the number of adjacent pairs of vowels") + From 1eabcbcf567311b4fce52c34298fb16d066ee2a2 Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Fri, 11 Oct 2019 22:06:41 +0530 Subject: [PATCH 089/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fefd5a03..b8accf57 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`index_updater.py`](index_updater.py) and 3 main directories and 1 [**logo**](logo) directory : [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks). +As of now, the repository contains 1 [**logo**](logo) directory and 3 main directories : [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks). ### Data Structures From f3157fec5ce61c127a9c8887256826e97cfce27e Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Fri, 11 Oct 2019 22:14:26 +0530 Subject: [PATCH 090/455] Update and rename Toggle_String.py to toggle_string.py --- .../{ Toggle_String.py => toggle_string.py} | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) rename data_structures/strings/{ Toggle_String.py => toggle_string.py} (64%) diff --git a/data_structures/strings/ Toggle_String.py b/data_structures/strings/toggle_string.py similarity index 64% rename from data_structures/strings/ Toggle_String.py rename to data_structures/strings/toggle_string.py index ed039282..ed2def82 100644 --- a/data_structures/strings/ Toggle_String.py +++ b/data_structures/strings/toggle_string.py @@ -11,20 +11,22 @@ ABCDe """ -def ToggleString1(string): +def toggle_string_1(string): return string.swapcase() -def ToggleString2(string): - toggleString='' +def toggle_string_2(string): + toggle_string='' for s in string: if s.isupper(): - toggleString+=s.lower() + toggle_string+=s.lower() elif s.islower(): - toggleString+=s.upper() - return toggleString + toggle_string+=s.upper() + else: + toggle_string+=s + return toggle_string string=input() -print(ToggleString1(string)) # method 1 -print(ToggleString2(string)) # method 2 +print(toggle_string_1(string)) # method 1 +print(toggle_string_2(string)) # method 2 From 8f5f27f13dd520bd84882f994e038d5470e3195b Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Fri, 11 Oct 2019 22:17:54 +0530 Subject: [PATCH 091/455] Update toggle_string.py --- data_structures/strings/toggle_string.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/data_structures/strings/toggle_string.py b/data_structures/strings/toggle_string.py index ed2def82..a7292c31 100644 --- a/data_structures/strings/toggle_string.py +++ b/data_structures/strings/toggle_string.py @@ -24,9 +24,10 @@ def toggle_string_2(string): else: toggle_string+=s return toggle_string - - string=input() -print(toggle_string_1(string)) # method 1 -print(toggle_string_2(string)) # method 2 + +# method 1 +print(toggle_string_1(string)) +# method 2 +print(toggle_string_2(string)) From afd1c644042192e5985bec18f3606c709f0e1e15 Mon Sep 17 00:00:00 2001 From: Shardul Silswal Date: Fri, 11 Oct 2019 23:47:11 +0530 Subject: [PATCH 092/455] Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f5804763..19bcf5e9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. +As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: [**Data Structures**](data_structures) and **Algorithms**. ### Data Structures @@ -65,4 +65,4 @@ To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) ## :page_facing_up: License -MIT @ Prabhu Pant \ No newline at end of file +MIT @ Prabhu Pant From 0a4761999ee4d0f84a17a268c4e2d23505769ddf Mon Sep 17 00:00:00 2001 From: Shardul Silswal Date: Fri, 11 Oct 2019 23:48:21 +0530 Subject: [PATCH 093/455] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 19bcf5e9..33774a50 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: [**Data Structures**](data_structures) and **Algorithms**. +As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: [**Data Structures**](data_structures) and [**Algorithms**](algorithms). ### Data Structures From b0f2c8aa773a4831cfb93dbfa45eb2a1c97a71e3 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 12 Oct 2019 00:41:42 +0530 Subject: [PATCH 094/455] Update merge_list_of_linked_lists.py --- data_structures/linked_list/merge_list_of_linked_lists.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/linked_list/merge_list_of_linked_lists.py b/data_structures/linked_list/merge_list_of_linked_lists.py index 3ba77c26..de99e07e 100644 --- a/data_structures/linked_list/merge_list_of_linked_lists.py +++ b/data_structures/linked_list/merge_list_of_linked_lists.py @@ -20,7 +20,7 @@ def merge_two_lists(l1, l2): return l2 -def mergeKLists(lists): +def merge_k_lists(lists): length = len(lists) if length == 0: return; @@ -34,4 +34,4 @@ def mergeKLists(lists): left_half = lists[:mid] right_half = lists[mid:] - return merge_two_lists(mergeKLists(left_half), mergeKLists(right_half)) + return merge_two_lists(merge_k_lists(left_half), merge_k_lists(right_half)) From 555a0a497cd8384adc40f4bc03569a79cf776bb1 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 12 Oct 2019 01:13:01 +0530 Subject: [PATCH 095/455] Create pull_request_template.md --- .github/pull_request_template.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..72c0d14d --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,23 @@ +# Description + +Please include a summary of the change and which issue is fixed or what question/feature you have added. + +Fixes # (issue) + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature/question +- [ ] This change requires a documentation update +- [ ] Bookmark link + +# Checklist: + +- [ ] My code follows the style guidelines of this project i.e. [Pep8](https://www.python.org/dev/peps/pep-0008/) +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] Any dependent changes have been merged and published in downstream modules +- [ ] I have squashed unnecessary commits From 81d08f70a9f76fd56ac0582babaf04117722719f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 12 Oct 2019 01:17:08 +0530 Subject: [PATCH 096/455] changes in readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f5804763..fea48b90 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ This directory contains various types of algorithm questions like Dynamic Progra 1. Dynamic Programming 2. Math 3. Sorting +4. Greedy +5. Misc ### Bookmarks @@ -65,4 +67,4 @@ To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) ## :page_facing_up: License -MIT @ Prabhu Pant \ No newline at end of file +MIT @ Prabhu Pant From 16511e3db4f2fe5d1d6a2fff036fe0a7c3f5cd25 Mon Sep 17 00:00:00 2001 From: Mirali Ahmadli Date: Sat, 12 Oct 2019 15:59:06 +0900 Subject: [PATCH 097/455] Added Graph Algorithms --- algorithms/graph/bfs.py | 49 +++++++++++++++++++++++++++++++++++++++ algorithms/graph/dfs.py | 45 +++++++++++++++++++++++++++++++++++ algorithms/graph/index.md | 4 ++++ 3 files changed, 98 insertions(+) create mode 100644 algorithms/graph/bfs.py create mode 100644 algorithms/graph/dfs.py create mode 100644 algorithms/graph/index.md diff --git a/algorithms/graph/bfs.py b/algorithms/graph/bfs.py new file mode 100644 index 00000000..6c64f75f --- /dev/null +++ b/algorithms/graph/bfs.py @@ -0,0 +1,49 @@ +# Python3 Program to print BFS traversal +# from a given source vertex. BFS(int s) +# traverses vertices reachable from s. +from collections import defaultdict + +# This class represents a directed graph +# using adjacency list representation +class Graph: + + # Constructor + def __init__(self): + + # default dictionary to store graph + self.graph = defaultdict(list) + + # function to add an edge to graph + def addEdge(self,u,v): + self.graph[u].append(v) + + # Function to print a BFS of graph + def BFS(self, s): + + # Mark all the vertices as not visited + visited = [False] * (len(self.graph)) + + # Create a queue for BFS + queue = [] + + # Mark the source node as + # visited and enqueue it + queue.append(s) + visited[s] = True + + while queue: + + # Dequeue a vertex from + # queue and print it + s = queue.pop(0) + print (s, end = " ") + + # Get all adjacent vertices of the + # dequeued vertex s. If a adjacent + # has not been visited, then mark it + # visited and enqueue it + for i in self.graph[s]: + if visited[i] == False: + queue.append(i) + visited[i] = True + \ No newline at end of file diff --git a/algorithms/graph/dfs.py b/algorithms/graph/dfs.py new file mode 100644 index 00000000..fbd33795 --- /dev/null +++ b/algorithms/graph/dfs.py @@ -0,0 +1,45 @@ +# Python program to print DFS traversal for complete graph +from collections import defaultdict + +# This class represents a directed graph using adjacency +# list representation +class Graph: + + # Constructor + def __init__(self): + + # default dictionary to store graph + self.graph = defaultdict(list) + + # function to add an edge to graph + def addEdge(self,u,v): + self.graph[u].append(v) + + # A function used by DFS + def DFSUtil(self, v, visited): + + # Mark the current node as visited and print it + visited[v]= True + print v, + + # Recur for all the vertices adjacent to + # this vertex + for i in self.graph[v]: + if visited[i] == False: + self.DFSUtil(i, visited) + + + # The function to do DFS traversal. It uses + # recursive DFSUtil() + def DFS(self): + V = len(self.graph) #total vertices + + # Mark all the vertices as not visited + visited =[False]*(V) + + # Call the recursive helper function to print + # DFS traversal starting from all vertices one + # by one + for i in range(V): + if visited[i] == False: + self.DFSUtil(i, visited) \ No newline at end of file diff --git a/algorithms/graph/index.md b/algorithms/graph/index.md new file mode 100644 index 00000000..e5197adc --- /dev/null +++ b/algorithms/graph/index.md @@ -0,0 +1,4 @@ +# Index of graph + +* dfs.py +* bfs.py From 07d639e1f3ea604abee72f25acdf40c94bb2139d Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Sat, 12 Oct 2019 07:08:12 +0000 Subject: [PATCH 098/455] update and link files in index.md --- .theia/settings.json | 3 + algorithms/dynamic_programming/index.md | 8 ++- algorithms/greedy/index.md | 1 + algorithms/math/index.md | 5 +- algorithms/miscellaneous/index.md | 2 +- algorithms/sorting/index.md | 7 +- data_structures/array/index.md | 64 +++++++++---------- data_structures/binary_trees/index.md | 2 +- data_structures/bst/index.md | 60 ++++++++--------- data_structures/circular_linked_list/index.md | 8 +-- data_structures/doubly_linked_list/index.md | 2 +- data_structures/graphs/index.md | 2 +- data_structures/linked_list/index.md | 20 +++--- data_structures/queue/index.md | 3 + data_structures/stack/index.md | 8 +-- data_structures/strings/index.md | 5 +- 16 files changed, 110 insertions(+), 90 deletions(-) create mode 100644 .theia/settings.json create mode 100644 algorithms/greedy/index.md create mode 100644 data_structures/queue/index.md diff --git a/.theia/settings.json b/.theia/settings.json new file mode 100644 index 00000000..651011e0 --- /dev/null +++ b/.theia/settings.json @@ -0,0 +1,3 @@ +{ + "editor.autoSave": "on" +} \ No newline at end of file diff --git a/algorithms/dynamic_programming/index.md b/algorithms/dynamic_programming/index.md index 4f69b4f8..2e55dae7 100644 --- a/algorithms/dynamic_programming/index.md +++ b/algorithms/dynamic_programming/index.md @@ -1,4 +1,8 @@ # Index of dynamic_programming -* longest_common_subsequence.py -* rod_cutting.py +* [Longest Common Subsequence](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/longest_common_subsequence.py) +* [Rod Cutting](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/rod_cutting.py) +* [Max Subarray](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/max_subarray.py) +* [Unique Grid Paths](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/unique_grid_paths.py) +* [Edit Distance](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/edit_distance.py) + diff --git a/algorithms/greedy/index.md b/algorithms/greedy/index.md new file mode 100644 index 00000000..d9b79484 --- /dev/null +++ b/algorithms/greedy/index.md @@ -0,0 +1 @@ +# Index of Greedy \ No newline at end of file diff --git a/algorithms/math/index.md b/algorithms/math/index.md index e1a3a6e9..e2732002 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -1,3 +1,6 @@ # Index of math -* greatest_common_divisor.py +* [Greatest Common Divisor](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/greatest_common_divisor.py) +* [Fibonacci Number](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/fibonacci_number.py) +* [Nth Prime Number](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/prime.py) +* [Sieve of Erastothenes](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/sieve_of_eratosthenes.py) diff --git a/algorithms/miscellaneous/index.md b/algorithms/miscellaneous/index.md index b45d88c6..af9ea249 100644 --- a/algorithms/miscellaneous/index.md +++ b/algorithms/miscellaneous/index.md @@ -1,3 +1,3 @@ # Index of miscellaneous -* luhn_algorithm.py \ No newline at end of file +* [Luhn Algorithm](https://github.com/prabhupant/python-ds/blob/master/algorithms/miscellaneous/luhn_algorithm.py) \ No newline at end of file diff --git a/algorithms/sorting/index.md b/algorithms/sorting/index.md index 7cc2e7f9..6e76b265 100644 --- a/algorithms/sorting/index.md +++ b/algorithms/sorting/index.md @@ -1,4 +1,7 @@ # Index of sorting -* insertion_sort.py -* select_sort.py +* [Insertion Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/insertion_sort.py) +* [Merge Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/merge_sort.py) +* [Quick Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/qsort.py) +* [Select Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/select_sort.py) +* [Bubble Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/bubble_sort.py) \ No newline at end of file diff --git a/data_structures/array/index.md b/data_structures/array/index.md index e171d8a1..31adcfe5 100644 --- a/data_structures/array/index.md +++ b/data_structures/array/index.md @@ -1,34 +1,34 @@ # Index of array -* permutations_of_word.py -* sorted_array_three_common_elements.py -* dutch_flag_problem.py -* partition_three_parts_equal_sum.py -* binary_search_infinite_array.py -* largest_element.py -* right_place.py -* rotation.py -* find_missing_numbers.py -* three_largest_elements.py -* triplet_sum.py -* max_product.py -* moves_zeros_to_end.py -* pivot_index.py -* intersection_sorted_array.py -* max_triplet_sum.py -* number_of_1_in_sorted_array.py -* square_of_sorted_array.py -* max_consecutive_ones.py -* max_product_three_elements.py -* kadane_algorithm.py -* all_numbers_divisible.py -* duplicates.py -* majority_element.py -* find_sum.py -* quick_sort.py -* peak_element.py -* union_sorted_array.py -* min_product.py -* sort_by_parity.py -* duplicate.py -* product_of_array_except_self.py +* [Permumations of Word](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/permutations_of_word.py) +* [Common Elements of three sorted arrays](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/sorted_array_three_common_elements.py) +* [Dutch Flag Problem](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/dutch_flag_problem.py) +* [Partition an array into three parts with equal sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/partition_three_parts_equal_sum.py) +* [Binary search on an Infinite array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/binary_search_infinite_array.py) +* [Largest Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/largest_element.py) +* [Right Place](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/right_place.py) +* [Rotation](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/rotation.py) +* [Find missing number](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/find_missing_numbers.py) +* [Three Largest Elements](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/three_largest_elements.py) +* [Triplet Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/triplet_sum.py) +* [Max Product](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_product.py) +* [Moves to Zero](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/moves_zeros_to_end.py) +* [Pivot Index](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/pivot_index.py) +* [Intersection of Two Sorted Arrays](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/intersection_sorted_array.py) +* [Max Triplet Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_triplet_sum.py) +* [Number of 1's in Sorted Array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/number_of_1_in_sorted_array.py) +* [Square of Sorted Array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/square_of_sorted_array.py) +* [Max Consecutive 1's](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_consecutive_ones.py) +* [Max Product Three Elements](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_product_three_elements.py) +* [Kadane Algorithm](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/kadane_algorithm.py) +* [All Numbers Divisible](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/all_numbers_divisible.py) +* [Duplicates](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/duplicates.py) +* [Majority Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/majority_element.py) +* [Find Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/find_sum.py) +* [Quick Sort](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/quick_sort.py) +* [Peak Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/peak_element.py) +* [Union Sorted Array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/union_sorted_array.py) +* [Min Product](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/min_product.py) +* [Sort By Parity](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/sort_by_parity.py) +* [Duplicate](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/duplicate.py) +* [Product of Array Except Self](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/product_of_array_except_self.py) diff --git a/data_structures/binary_trees/index.md b/data_structures/binary_trees/index.md index ce9cf6c6..1e36ce75 100644 --- a/data_structures/binary_trees/index.md +++ b/data_structures/binary_trees/index.md @@ -1,3 +1,3 @@ # Index of binary_trees -* symmetric_binary_tree.py +* [Symmetric Binary Tree]()https://github.com/prabhupant/python-ds/blob/master/data_structures/binary_trees/symmetric_binary_tree.py diff --git a/data_structures/bst/index.md b/data_structures/bst/index.md index cd965d52..7dfc2c51 100644 --- a/data_structures/bst/index.md +++ b/data_structures/bst/index.md @@ -1,31 +1,31 @@ -# Index of bst +# Index of BST -* deletion.py -* sorted_array_to_bst.py -* print_left_node.py -* diameter.py -* bfs.py -* check_if_bt_if_bst.py -* trim_bst.py -* bt_to_bst.py -* binary_search_tree.py -* convert_bst_to_right_node_tree.py -* kth_largest_in_bst.py -* range_sum.py -* dfs_iterative.py -* print_ancestor.py -* min_max_value_in_bst.py -* check_bt_is_subtree_of_another_bt.py -* ceil.py -* closest_element.py -* kth_smallest_in_bst.py -* insertion_iterative.py -* lowest_common_ancestor.py -* dfs_recursion.py -* search.py -* insertion_recursive.py -* duplicate_keys.py -* merge_sum.py -* linked_list_to_bst.py -* reverse_inorder_traversal.py -* average_of_levels.py +* [[Deletion](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/deletion.py) +* [Sorted Array To BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/sorted_array_to_bst.py) +* [Print Left Node](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/print_left_node.py) +* [Diameter](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/diameter.py) +* [BFS](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/bfs.py) +* [Check if BT is BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/check_if_bt_if_bst.py) +* [Trim BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/trim_bst.py) +* [BT to BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/bt_to_bst.py) +* [Binary Search Tree](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/binary_search_tree.py) +* [Convert BST to Right Node Tree](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/convert_bst_to_right_node_tree.py) +* [kth largest in BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/kth_largest_in_bst.py) +* [Range Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/range_sum.py) +* [DFS Iterative](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/dfs_iterative.py) +* [Print Ancestor](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/print_ancestor.py) +* [Min Max Value in BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/min_max_value_in_bst.py) +* [Check BT is Subtree of another BT](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/check_bt_is_subtree_of_another_bt.py) +* [Ceil](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/ceil.py) +* [Closest Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/closest_element.py) +* [kth smallest in BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/kth_smallest_in_bst.py) +* [Insertion Iterative](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/insertion_iterative.py) +* [Lowest Common Ancestor](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/lowest_common_ancestor.py) +* [DFS Recursion](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/dfs_recursion.py) +* [Search](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/search.py) +* [Insertion Recursive](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/insertion_recursive.py) +* [Duplicate Keys](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/duplicate_keys.py) +* [Merge Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/merge_sum.py) +* [Linked List to BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/linked_list_to_bst.py) +* [Reverse Inorder Traversal](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/reverse_inorder_traversal.py) +* [Average of Levels](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/average_of_levels.py) diff --git a/data_structures/circular_linked_list/index.md b/data_structures/circular_linked_list/index.md index 863e4602..985f8082 100644 --- a/data_structures/circular_linked_list/index.md +++ b/data_structures/circular_linked_list/index.md @@ -1,5 +1,5 @@ -# Index of circular_linked_list +# Index of circular linked list -* check_circular_linked_list.py -* delete.py -* traversal.py +* [Check Circular Linked List ](https://github.com/prabhupant/python-ds/blob/master/data_structures/circular_linked_list/check_circular_linked_list.py) +* [Delete ](https://github.com/prabhupant/python-ds/blob/master/data_structures/circular_linked_list/delete.py) +* [Traversal](https://github.com/prabhupant/python-ds/blob/master/data_structures/circular_linked_list/traversal.py) diff --git a/data_structures/doubly_linked_list/index.md b/data_structures/doubly_linked_list/index.md index 0888a31f..9e193d24 100644 --- a/data_structures/doubly_linked_list/index.md +++ b/data_structures/doubly_linked_list/index.md @@ -1,3 +1,3 @@ # Index of doubly_linked_list -* doubly_linked_list.py +* [Doubly Linked List](https://github.com/prabhupant/python-ds/blob/master/data_structures/doubly_linked_list/doubly_linked_list.py) diff --git a/data_structures/graphs/index.md b/data_structures/graphs/index.md index ccd77d4c..d921832c 100644 --- a/data_structures/graphs/index.md +++ b/data_structures/graphs/index.md @@ -1,3 +1,3 @@ # Index of graphs -* adjeceny_list.py +* [Adjacency List](https://github.com/prabhupant/python-ds/blob/master/data_structures/graphs/adjeceny_list.py) diff --git a/data_structures/linked_list/index.md b/data_structures/linked_list/index.md index a32a47e0..fd1158e8 100644 --- a/data_structures/linked_list/index.md +++ b/data_structures/linked_list/index.md @@ -1,11 +1,11 @@ -# Index of linked_list +# Index of linked list -* remove.py -* pair_swap.py -* reverse.py -* linked_list.py -* cycle_detection.py -* remove_nth_node_from_end.py -* odd_even_arrangement.py -* merge_linked_list.py -* remove_duplicates.py +* [Remove](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/remove.py) +* [Pair Swap](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/pair_swap.py) +* [Reverse](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/reverse.py) +* [Linked List](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/linked_list.py) +* [Cycle Detection](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/cycle_detection.py) +* [Remove nth Node from End](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/remove_nth_node_from_end.py) +* [Odd-Even Arrangement](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/odd_even_arrangement.py) +* [Merge Linked List](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/merge_linked_list.py) +* [Remove Duplicates](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/remove_duplicates.py) diff --git a/data_structures/queue/index.md b/data_structures/queue/index.md new file mode 100644 index 00000000..d4e739e5 --- /dev/null +++ b/data_structures/queue/index.md @@ -0,0 +1,3 @@ +# Index of Queue + +[Queue](https://github.com/prabhupant/python-ds/blob/master/data_structures/queue/queue.py) \ No newline at end of file diff --git a/data_structures/stack/index.md b/data_structures/stack/index.md index 089a2739..604a0586 100644 --- a/data_structures/stack/index.md +++ b/data_structures/stack/index.md @@ -1,6 +1,6 @@ # Index of stack -* valid_parenthesis.py -* Largest Rectangle area in a Histogram.py -* remove_duplicates_adjacent.py -* validate_stack_sequence.py +* [Valid Parentheses](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/valid_parenthesis.py) +* [Largest Rectangle Area in a Histogram](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/largest_rectangle_area_in_histogram.py) +* [Remove Duplicates Adjacent](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/remove_duplicates_adjacent.py) +* [Validate Stack Sequence](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/validate_stack_sequence.py) diff --git a/data_structures/strings/index.md b/data_structures/strings/index.md index 470b7bbe..77cee22e 100644 --- a/data_structures/strings/index.md +++ b/data_structures/strings/index.md @@ -1,3 +1,6 @@ # Index of strings -* check_permutations.py +* [Check Permutations](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/check_permutations.py) +* [Are Anagrams](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/are_anagrams.py) +* [Adjacent Vowel Pairs](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/adjacent_vowel_pairs.py) +* [Toggle String](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/toggle_string.py) \ No newline at end of file From 885837ce442bb23db464586c3136fd80c4ed7be1 Mon Sep 17 00:00:00 2001 From: Louie Tan Date: Sat, 12 Oct 2019 01:22:02 -0700 Subject: [PATCH 099/455] Add least_common_multiple --- algorithms/math/least_common_multiple.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 algorithms/math/least_common_multiple.py diff --git a/algorithms/math/least_common_multiple.py b/algorithms/math/least_common_multiple.py new file mode 100644 index 00000000..4c11c390 --- /dev/null +++ b/algorithms/math/least_common_multiple.py @@ -0,0 +1,8 @@ +""" +Given two input integers, find their Least Common Multiple. +""" + +from greatest_common_divisor import gcd + +def lcm(x, y): + return abs(x * y) // gcd(x, y) From 8abd9ce4ef36724c570942e050979a60e7a41551 Mon Sep 17 00:00:00 2001 From: Miguel Mendes Date: Sat, 12 Oct 2019 10:59:59 +0100 Subject: [PATCH 100/455] Refactor luhn algo --- algorithms/miscellaneous/luhn_algorithm.py | 73 +++++++++++++--------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/algorithms/miscellaneous/luhn_algorithm.py b/algorithms/miscellaneous/luhn_algorithm.py index 1a20a9e4..e6d4b20d 100644 --- a/algorithms/miscellaneous/luhn_algorithm.py +++ b/algorithms/miscellaneous/luhn_algorithm.py @@ -1,35 +1,48 @@ -""" -Luhn algorithm or Luhn formula is a simple checksum formula -used to validate a variety of identification numbers, such as -credit card numbers, IMEI numbers, National Provider Identifier numbers -in some of the Countries -""" - -""" -It takes a number as an input -(Assuming cardnumber as a string) -and returns true or false -based upon whether number is valid or not -""" - -def checkLuhn(cardNumber): - cardLen = len(cardNumber) - - checkSum = 0 - - isParity = False - - for digit in range(cardLen-1,-1,-1): - if isParity: - cal = int(cardNumber[digit])*2 +def check_luhn(card_number): + """ + Luhn algorithm or Luhn formula is a simple checksum formula + used to validate a variety of identification numbers, such as + credit card numbers, IMEI numbers, National Provider Identifier numbers + in some of the countries. + + It takes a number as an input + (Assuming cardnumber as a string) + and returns true or false + based upon whether number is valid or not + + :param card_number: + :return: bool: valid or not + + Examples: + + >>> check_luhn("950123440000") + False + >>> check_luhn("490154203237518") + True + """ + card_len = len(card_number) + + check_sum = 0 + + is_parity = False + + for digit in range(card_len - 1, -1, -1): + if is_parity: + cal = int(card_number[digit]) * 2 else: - cal = int(cardNumber[digit]) + cal = int(card_number[digit]) - if cal>9: - checkSum += cal -9 + if cal > 9: + check_sum += cal - 9 else: - checkSum += cal + check_sum += cal + + is_parity = not is_parity + + return check_sum % 10 == 0 + - isParity = not isParity +if __name__ == "__main__": + import doctest - return checkSum%10==0 + doctest.testmod() From 2119d03030efc5832a8ed900ad8fc2e9f402c494 Mon Sep 17 00:00:00 2001 From: Shardul Silswal Date: Sat, 12 Oct 2019 22:45:40 +0530 Subject: [PATCH 101/455] updated Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 33774a50..c197b7d9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: [**Data Structures**](data_structures) and [**Algorithms**](algorithms). +As of now, the repository contains 3 main directories: [**Bookmarks**](bookmarks), [**Data Structures**](data_structures) and [**Algorithms**](algorithms). ### Data Structures From 6ff19d4ed4c7189b7657613d1f1dd8c09d5ef524 Mon Sep 17 00:00:00 2001 From: Oishika Pradhan Date: Sat, 12 Oct 2019 22:46:40 +0530 Subject: [PATCH 102/455] Added Prim's MST to graph algorithms --- data_structures/graphs/PrimsMST.py | 31 +++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/data_structures/graphs/PrimsMST.py b/data_structures/graphs/PrimsMST.py index e88b2b4b..e8dcfe98 100644 --- a/data_structures/graphs/PrimsMST.py +++ b/data_structures/graphs/PrimsMST.py @@ -1,20 +1,23 @@ -#Uses adjacency matrix representation of graph to calculate Minimum Spanning Tree +# Uses adjacency matrix representation of graph to calculate Minimum +# Spanning Tree import sys + class Graph(): - + def __init__(self, vertices): self.V = vertices - self.graph = [[0 for column in range(vertices)] for row in range(vertices)] - - #Function to print generated MST + self.graph = [[0 for column in range(vertices)] + for row in range(vertices)] + + # Function to print generated MST def printMST(self, parent): print("Edge \t Weight") for i in range(1, self.V): print(parent[i], "-", i, "\t", self.graph[i][parent[i]]) - #Function to find vertex with min. distance from set of vertices + # Function to find vertex with min. distance from set of vertices #not included in MST def minValue(self, key, MSTSet): minval = sys.maxsize @@ -25,7 +28,7 @@ def minValue(self, key, MSTSet): min_index = v return min_index - #Function to construct Prim's MST + # Function to construct Prim's MST def MST(self): key = [sys.maxsize] * self.V parent = [None] * self.V @@ -38,16 +41,18 @@ def MST(self): MSTSet[u] = True for v in range(self.V): - if (self.graph[u][v] > 0) and (MSTSet[v] == False) and (key[v] > self.graph[u][v]): + if (self.graph[u][v] > 0) and (MSTSet[v] == + False) and (key[v] > self.graph[u][v]): key[v] = self.graph[u][v] parent[v] = u self.printMST(parent) + g = Graph(4) -g.graph = [ [0, 2, 0, 6], - [2, 0, 3, 8], - [0, 3, 0, 0], - [6, 8, 0, 0]] +g.graph = [[0, 2, 0, 6], + [2, 0, 3, 8], + [0, 3, 0, 0], + [6, 8, 0, 0]] -g.MST() \ No newline at end of file +g.MST() From 225ace0194eeea411234966bb16a85b9a41369f9 Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Sat, 12 Oct 2019 23:35:10 +0530 Subject: [PATCH 103/455] update readme.md 1. fixed invalid file link ```useful_links.md``` 2. added links to sub-directories --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index fea48b90..2fe23045 100644 --- a/README.md +++ b/README.md @@ -10,29 +10,30 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains a file called [`useful_links.md`](useful_links.md) and 2 main directories: **Data Structures** and **Algorithms**. +As of now, the repository contains 3 main directories: **[Data Structures](data_structures)**, **[Algorithms](algorithms)** and **[Bookmarks](bookmarks)**. ### Data Structures Contains all data structure questions categorised into sub-directories like stack, queue, etc according to their type. -1. Array -2. Dictionary -3. Binary Search Tree -4. Linked List -5. Stack -6. Graphs -7. Circular Linked List +1. [Array](data_structures/array) +2. [Dictionary]() +3. [Binary Search Tree](data_structures/bst) +4. [Linked List](data_structures/linked_list) +5. [Stack](data_structures/stack) +6. [Graphs](data_structures/graphs) +7. [Circular Linked List](data_structures/circular_linked_list) +8. [Doubly Linked List](data_structures/doubly_linked_list) ### Algorithms This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - -1. Dynamic Programming -2. Math -3. Sorting -4. Greedy -5. Misc +1. [Dynamic Programming](algorithms/dynamic_programming) +2. [Math](algorithms/math) +3. [Sorting](algorithms/sorting) +4. [Greedy](algorithms/greedy) +5. [Misc](algorithms/miscellaneous) ### Bookmarks From bae46eebac0811abad0a6e71221afe63d066d6f7 Mon Sep 17 00:00:00 2001 From: rockyjain Date: Sun, 13 Oct 2019 03:16:24 +0530 Subject: [PATCH 104/455] added segment tree ds --- data_structures/segment_tree/index.md | 3 + .../segment_tree/min_in_range_queries.py | 107 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 data_structures/segment_tree/index.md create mode 100644 data_structures/segment_tree/min_in_range_queries.py diff --git a/data_structures/segment_tree/index.md b/data_structures/segment_tree/index.md new file mode 100644 index 00000000..712399ee --- /dev/null +++ b/data_structures/segment_tree/index.md @@ -0,0 +1,3 @@ +# Index of segment_tree + +* min_in_range_queries.py diff --git a/data_structures/segment_tree/min_in_range_queries.py b/data_structures/segment_tree/min_in_range_queries.py new file mode 100644 index 00000000..1992d4c9 --- /dev/null +++ b/data_structures/segment_tree/min_in_range_queries.py @@ -0,0 +1,107 @@ +''' +Question: +Given an array A of size N, there are two types of queries on this array. +1. q l r: In this query you need to print the minimum in the sub-array . +2. u l r v In this query you need to update the range from l to r by v. + +Time Complexity: +update query: log(n) +min in range query: log(n) +''' + +import math as mt + +class SegmentTree: + def __init__(self, array): + self.MAX_INT = 2**31-1 + self.src = array + self.len = len(array) + self.total_nodes = (2**mt.ceil(mt.log(self.len, 2))*2-1) + self.tree = [0] * self.total_nodes + self.dues = [0] * self.total_nodes + + def build(self): + self.build_tree(l=0, r=self.len-1, par=0) + + def build_tree(self, l, r, par): + if l == r: + self.tree[par] = self.src[l] + return + div = (l+r)//2 + self.build_tree(l, div, (par<<1)+1) + self.build_tree(div+1, r, (par<<1)+2) + self.tree[par]=min(self.tree[(par<<1)+1], self.tree[(par<<1)+2]) + + def min_in_range(self, low, high): + return self.min_(low, high, 0, self.len-1, 0) + + def min_(self, low, high, left, right, par): + if low > right or high < left: + return self.MAX_INT + + if self.dues[par] > 0: + self.tree[par] += self.dues[par] + if left is not right: + self.dues[(par<<1)+1] += self.dues[par] + self.dues[(par<<1)+2] += self.dues[par] + self.dues[par]=0; + + if low <= left and high >= right: + return self.tree[par] + + div = int((right+left)/2) + + return min(self.min_(low, high, left, div, (par<<1)+1), + self.min_(low, high, div+1, right, (par<<1)+2) ) + + def update_range(self, low, high, value): + return self.update(low, high, value, 0, self.len-1, 0) + + def update(self, low, high, value, left, right, par): + if self.dues[par] > 0: + self.tree[par] += self.dues[par] + if left is not right: + self.dues[(par<<1)+1] += self.dues[par] + self.dues[(par<<1)+2] += self.dues[par] + self.dues[par]=0; + + if low > right or high < left: + return; + + if low <= left and high >= right: + self.tree[par] += value + if(left is not right): + self.dues[(par<<1)+1] += value + self.dues[(par<<1)+2] += value + return + + div = (right+left)//2 + self.update(low, high, value, left, div, (par<<1)+1) + self.update(low, high, value, div+1, right, (par<<1)+2) + + +if __name__=='__main__': + + array = list(map(int, input('Enter space seprated number\n').strip().split(' '))) + sg = SegmentTree(array) + sg.build() + + n_query = int(input('Enter number of queries\n')) + print('Query format\nq low high (to find minimum in range e.g: q 0 3)\nu low high value (to add "value" to all elements e.g: u 3 4 99)') + + while n_query: + n_query -= 1 + args = input('Enter query: ').strip().split(' ') + if args[0] == 'q' and len(args) == 3: + print(sg.min_in_range(low=int(args[1]), high=int(args[2]))) + elif args[0] == 'u' and len(args) == 4: + sg.update_range(low=int(args[1]), high=int(args[2]), value=int(args[3])) + print('Update Successfully!') + else: + print('Invalid query format') + n_query += 1 + + + + + From bcb157e5b350e9fd2bd0d22f099aeaab9e684ead Mon Sep 17 00:00:00 2001 From: Shanoop Padmanabhan Date: Sun, 13 Oct 2019 18:25:29 +0800 Subject: [PATCH 105/455] Add longest_palindromic_subsequence Add longest_palindromic_subsequence to dynamic programming examples --- .../longest_palindromic_subsequence.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 algorithms/dynamic_programming/longest_palindromic_subsequence.py diff --git a/algorithms/dynamic_programming/longest_palindromic_subsequence.py b/algorithms/dynamic_programming/longest_palindromic_subsequence.py new file mode 100644 index 00000000..e0d6f3bd --- /dev/null +++ b/algorithms/dynamic_programming/longest_palindromic_subsequence.py @@ -0,0 +1,40 @@ +''' +Question : +Given a string consisting of English alphabets, the task is to count the alphabets in the longest palindromic subsequence. + +For example : +Input: str = "BBABCBCAB" +Output: 7 +"BABCBAB" is the longest palindromic subseuqnce in it. "BBBBB"" and "BBCBB" are also palindromic subsequences of the given sequence, but not the longest ones. + +Source: https://www.geeksforgeeks.org/python-program-for-longest-palindromic-subsequence-dp-12/ +''' + +def lps(str): + n = len(str) + + # Create a table to store results of subproblems + L = [[0 for x in range(n)] for x in range(n)] + + # Strings of length 1 are palindrome of length 1 + for i in range(n): + L[i][i] = 1 + + # Build the table. Note that the lower + # diagonal values of table are + # useless and not filled in the process. + for cl in range(2, n + 1): + for i in range(n-cl + 1): + j = i + cl-1 + if str[i] == str[j] and cl == 2: + L[i][j] = 2 + elif str[i] == str[j]: + L[i][j] = L[i + 1][j-1] + 2 + else: + L[i][j] = max(L[i][j-1], L[i + 1][j]); + + return L[0][n-1] + +# Test inputs +seq = "BBABCBCAB" +print("The length of the LPS is " + str(lps(seq))) From 33f51165f7a63a8e8354c88775f6658a6c7ca38c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 13 Oct 2019 19:13:08 +0530 Subject: [PATCH 106/455] Add second largest in BST --- data_structures/bst/second_largest_in_bst.py | 55 ++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 data_structures/bst/second_largest_in_bst.py diff --git a/data_structures/bst/second_largest_in_bst.py b/data_structures/bst/second_largest_in_bst.py new file mode 100644 index 00000000..598b36bb --- /dev/null +++ b/data_structures/bst/second_largest_in_bst.py @@ -0,0 +1,55 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def find_largest(root): + curr = root + while curr: + if not curr.right: + return curr.val + curr = curr.right + + +def second_largest(root): + if not root or (not root.left and not root.right): + return "BST should have atleast 2 nodes" + + curr = root + + while curr: + if curr.left and not curr.right: + return find_largest(curr.left) + + if curr.right and not curr.right.left and not curr.right.right: + return curr.val + + curr = curr.right + + +def insert(root, key): + if root == None: + return Node(key) + if key < root.val: + root.left = insert(root.left, key) + elif key > root.val: + root.right = insert(root.right, key) + return root + + +if __name__ == '__main__': + root = Node(6) + insert(root, 5) + insert(root, 3) + insert(root, 10) + insert(root, 4) + insert(root, 11) + insert(root, 14) + insert(root, 1) + + print(second_largest(root)) + + From 9b3b25d2826aa47d693dd82102af8442ed6d9f26 Mon Sep 17 00:00:00 2001 From: BiaHawk <48568610+BiaHawk@users.noreply.github.com> Date: Sun, 13 Oct 2019 18:27:37 -0300 Subject: [PATCH 107/455] Add files via upload --- algorithms/greedy/dijkstra_greedy.py | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 algorithms/greedy/dijkstra_greedy.py diff --git a/algorithms/greedy/dijkstra_greedy.py b/algorithms/greedy/dijkstra_greedy.py new file mode 100644 index 00000000..32aaba6d --- /dev/null +++ b/algorithms/greedy/dijkstra_greedy.py @@ -0,0 +1,37 @@ +def dijkstra(graph, start, end): + shortest_distance = {} + non_visited_nodes = {} + for i in graph: + non_visited_nodes[i] = graph[i] + + infinit = float('inf') + + for no in non_visited_nodes: + shortest_distance[no] = infinit + shortest_distance[start] = 0 + + while non_visited_nodes != {}: + shortest_extracted_node = None + for i in non_visited_nodes: + if shortest_extracted_node is None: + shortest_extracted_node = i + elif shortest_distance[i] < shortest_distance[shortest_extracted_node]: + shortest_extracted_node = i + + for no_v, Weight in graph[shortest_extracted_node]: + if Weight + shortest_distance[shortest_extracted_node] < shortest_distance[no_v]: + shortest_distance[no_v] = Weight + shortest_distance[shortest_extracted_node] + non_visited_nodes.pop(shortest_extracted_node) + return shortest_distance + +#in this case, I made a graph within the code, but I didn't put here, you can create your graph the way you like. +#this algorithm needs the start, end, and weight, but you can remove the weight as well +#I will leave my example here, how I use this algorithm to solve the shortest path problem +# V is vertex, u is edges and W IS WEIGHT. + +cities, origin, destiny = map(int, input().split()) +graph = {i:[] for i in range(1, cities+1)} +for i in range(cities-1): + u, v, w = map(int, input().split()) + graph[v].append((u, w)) + graph[u].append((v, w)) \ No newline at end of file From 9f0c5d4997567655ec3a1606fcdc09dbbf8e738f Mon Sep 17 00:00:00 2001 From: Dixith <7497698+dixith@users.noreply.github.com> Date: Mon, 14 Oct 2019 14:35:13 +0530 Subject: [PATCH 108/455] Created simlplified array rotation logic Simplified logic uses slicing of array --- data_structures/array/rotation_simplified.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data_structures/array/rotation_simplified.py diff --git a/data_structures/array/rotation_simplified.py b/data_structures/array/rotation_simplified.py new file mode 100644 index 00000000..554b18d5 --- /dev/null +++ b/data_structures/array/rotation_simplified.py @@ -0,0 +1,5 @@ +def rotate(arr, d): + return arr[d:]+arr[:d] + +arr = [1,2,3,4,5] +print(rotate(arr, 1)) From 1032c21e37704c37c781ce78d7877f8880fd13b6 Mon Sep 17 00:00:00 2001 From: Dixith <7497698+dixith@users.noreply.github.com> Date: Mon, 14 Oct 2019 14:36:57 +0530 Subject: [PATCH 109/455] Added link of rotation_simplified.py --- data_structures/array/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/data_structures/array/index.md b/data_structures/array/index.md index 31adcfe5..df2e3fe5 100644 --- a/data_structures/array/index.md +++ b/data_structures/array/index.md @@ -8,6 +8,7 @@ * [Largest Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/largest_element.py) * [Right Place](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/right_place.py) * [Rotation](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/rotation.py) +* [Rotation Simplified](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/rotation_simplified.py) * [Find missing number](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/find_missing_numbers.py) * [Three Largest Elements](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/three_largest_elements.py) * [Triplet Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/triplet_sum.py) From 97b92a10412107bdf36d8f237998170d07eeb92b Mon Sep 17 00:00:00 2001 From: Oishika Pradhan Date: Mon, 14 Oct 2019 16:30:06 +0530 Subject: [PATCH 110/455] Added Topological Sort to graph algorithms --- data_structures/graphs/TopoSort.py | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 data_structures/graphs/TopoSort.py diff --git a/data_structures/graphs/TopoSort.py b/data_structures/graphs/TopoSort.py new file mode 100644 index 00000000..3591882a --- /dev/null +++ b/data_structures/graphs/TopoSort.py @@ -0,0 +1,44 @@ +# Topological sorting of Directed Acyclic Graph +from collections import defaultdict + + +class Graph: + def __init__(self, vertices): + self.graph = defaultdict(list) + self.V = vertices + + def addEdge(self, u, v): + self.graph[u].append(v) + + def topologicalSortUtil(self, v, visited, stack): + + visited[v] = True + + for i in self.graph[v]: + if not visited[i]: + self.topologicalSortUtil(i, visited, stack) + + stack.insert(0, v) + + # Topological sort function + def topologicalSort(self): + visited = [False] * self.V + stack = [] + + for i in range(self.V): + if (visited[i] == False): + self.topologicalSortUtil(i, visited, stack) + + print(stack) + + +g = Graph(6) +g.addEdge(5, 2) +g.addEdge(5, 0) +g.addEdge(4, 0) +g.addEdge(4, 1) +g.addEdge(2, 3) +g.addEdge(3, 1) + +print("One possible Topological Sort of the graph is:") +g.topologicalSort() From da953ff2b5ab2160016bd307e8f76e2bdf6e6c2c Mon Sep 17 00:00:00 2001 From: Nauman Ahmad Date: Mon, 14 Oct 2019 18:16:15 +0500 Subject: [PATCH 111/455] Add heap sort to Algorithms folder --- algorithms/sorting/heap_sort.py | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 algorithms/sorting/heap_sort.py diff --git a/algorithms/sorting/heap_sort.py b/algorithms/sorting/heap_sort.py new file mode 100644 index 00000000..49e30a59 --- /dev/null +++ b/algorithms/sorting/heap_sort.py @@ -0,0 +1,51 @@ +''' +High Level Description: +This algorithm segments the list into sorted and unsorted parts. +It converts the unsorted segment of the list to a Heap data structure, so that we can efficiently determine the largest element. +Time Complexity: +The overall time complexity is O(nlog(n)). +''' + +def heapify(nums, heap_size, root_index): + # Assume the index of the largest element is the root index + largest = root_index + left_child = (2 * root_index) + 1 + right_child = (2 * root_index) + 2 + + # If the left child of the root is a valid index, and the element is greater + # than the current largest element, then update the largest element + if left_child < heap_size and nums[left_child] > nums[largest]: + largest = left_child + + # Do the same for the right child of the root + if right_child < heap_size and nums[right_child] > nums[largest]: + largest = right_child + + # If the largest element is no longer the root element, swap them + if largest != root_index: + nums[root_index], nums[largest] = nums[largest], nums[root_index] + # Heapify the new root element to ensure it's the largest + heapify(nums, heap_size, largest) + + +def heap_sort(nums): + n = len(nums) + + # Create a Max Heap from the list + # The 2nd argument of range means we stop at the element before -1 i.e. + # the first element of the list. + # The 3rd argument of range means we iterate backwards, reducing the count + # of i by 1 + for i in range(n, -1, -1): + heapify(nums, n, i) + + # Move the root of the max heap to the end of + for i in range(n - 1, 0, -1): + nums[i], nums[0] = nums[0], nums[i] + heapify(nums, i, 0) + + +# Verify it works +random_list_of_nums = [35, 12, 43, 8, 51] +heap_sort(random_list_of_nums) +print(random_list_of_nums) \ No newline at end of file From 3b8a9e4fe6c4f348d2706adb733439aee4204f9a Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Mon, 14 Oct 2019 20:00:07 +0530 Subject: [PATCH 112/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b8accf57..d0ce3282 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains 1 [**logo**](logo) directory and 3 main directories : [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks). +As of now, the repository contains [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks) directories. ### Data Structures From 9ccbf6840d2b1689abdaf54d8abd2537e5a1668a Mon Sep 17 00:00:00 2001 From: Anil Kumar Teegala <34655912+AnilKumarTeegala@users.noreply.github.com> Date: Mon, 14 Oct 2019 20:02:14 +0530 Subject: [PATCH 113/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d0ce3282..3248168a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The open source community has helped me a lot during my interview preparations a ## :file_folder: Structure of the repository -As of now, the repository contains [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks) directories. +As of now, the repository contains [**Data Structures**](data_structures), [**Algorithms**](algorithms) and [**bookmarks**](bookmarks) are the main directories. ### Data Structures From b0b1f6cae380da80b612a8f3a02a1f4e79157d3f Mon Sep 17 00:00:00 2001 From: tsaideepak7 <47642563+tsaideepak7@users.noreply.github.com> Date: Mon, 14 Oct 2019 20:09:31 +0530 Subject: [PATCH 114/455] updated README Added graphs to algorithm section --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fea48b90..0ef0b78f 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,11 @@ Contains all data structure questions categorised into sub-directories like stac This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - 1. Dynamic Programming -2. Math -3. Sorting -4. Greedy +2. Graphs +3. Greedy +4. Math 5. Misc +6. Sorting ### Bookmarks From eaa647556fdc2ba4cf362c37838f8710f261fe2f Mon Sep 17 00:00:00 2001 From: tsaideepak7 <47642563+tsaideepak7@users.noreply.github.com> Date: Mon, 14 Oct 2019 20:16:08 +0530 Subject: [PATCH 115/455] Added finding all paths algorithm --- algorithms/graph/find_all_paths.py | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 algorithms/graph/find_all_paths.py diff --git a/algorithms/graph/find_all_paths.py b/algorithms/graph/find_all_paths.py new file mode 100644 index 00000000..9152bf2a --- /dev/null +++ b/algorithms/graph/find_all_paths.py @@ -0,0 +1,32 @@ +''' +find all the possible paths in a directed cyclic graph from +a start point to a end point. +''' + + + + +def find_all_paths(graph, start, end, path=[]): + path = path + [start] + if start == end: + return [path] + if start not in graph.keys(): + return [] + paths = [] + for node in graph[start]: + if node not in path: #to prevent cyclic rotations + newpaths = find_all_paths(graph, node, end, path) + #print(newpaths) + for newpath in newpaths: + paths.append(newpath) + return paths + + +graph={1:[2,4], + 2:[3], + 4:[5], + 3:[5] + } + +for i in graph.keys(): + print(i,'to 5',find_all_paths(graph,i,5)) From da5ee60faa42b8400120837440f8e62563b2b82f Mon Sep 17 00:00:00 2001 From: MiKueen Date: Mon, 14 Oct 2019 20:35:10 +0530 Subject: [PATCH 116/455] Added binary tree leetcode questions --- .../binary-tree-level-order-traversal.py | 52 +++++++++++++++ .../flatten-binary-tree-to-linked-list.py | 59 +++++++++++++++++ .../maximum-depth-of-binary-tree.py | 53 +++++++++++++++ .../minimum-depth-of-binary-tree.py | 55 ++++++++++++++++ data_structures/binary_trees/path-sum.py | 64 +++++++++++++++++++ 5 files changed, 283 insertions(+) create mode 100644 data_structures/binary_trees/binary-tree-level-order-traversal.py create mode 100644 data_structures/binary_trees/flatten-binary-tree-to-linked-list.py create mode 100644 data_structures/binary_trees/maximum-depth-of-binary-tree.py create mode 100644 data_structures/binary_trees/minimum-depth-of-binary-tree.py create mode 100644 data_structures/binary_trees/path-sum.py diff --git a/data_structures/binary_trees/binary-tree-level-order-traversal.py b/data_structures/binary_trees/binary-tree-level-order-traversal.py new file mode 100644 index 00000000..36d2f319 --- /dev/null +++ b/data_structures/binary_trees/binary-tree-level-order-traversal.py @@ -0,0 +1,52 @@ +''' +Author : MiKueen +Level : Medium +Problem Statement : Binary Tree Level Order Traversal + +Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). + +For example: +Given binary tree [3,9,20,null,null,15,7], + 3 + / \ + 9 20 + / \ + 15 7 +return its level order traversal as: +[ + [3], + [9,20], + [15,7] +] +''' + +from collections import deque + +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def levelOrder(self, root): + """ + :type root: TreeNode + :rtype: List[List[int]] + """ + if not root: + return [] + level, res = deque([root]), [] + while level: + next_level = [] + for i in range(len(level)): + node = level.popleft() + if node.left: + level.append(node.left) + if node.right: + level.append(node.right) + next_level.append(node.val) + res.append(next_level) + return res + \ No newline at end of file diff --git a/data_structures/binary_trees/flatten-binary-tree-to-linked-list.py b/data_structures/binary_trees/flatten-binary-tree-to-linked-list.py new file mode 100644 index 00000000..1c0362a1 --- /dev/null +++ b/data_structures/binary_trees/flatten-binary-tree-to-linked-list.py @@ -0,0 +1,59 @@ +''' +Author : MiKueen +Level : Medium +Problem Statement : Flatten Binary Tree to Linked List + +Given a binary tree, flatten it to a linked list in-place. +For example, given the following tree: + 1 + / \ + 2 5 + / \ \ +3 4 6 + +The flattened tree should look like: +1 + \ + 2 + \ + 3 + \ + 4 + \ + 5 + \ + 6 + +Approach : Recursive solution +1. Flatten left subtree +2. Find tail of left subtree +3. Attach tail of left subtree to starting node of right subtree +4. Flatten right subtree +''' + +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def flatten(self, root): + """ + :type root: TreeNode + :rtype: None Do not return anything, modify root in-place instead. + """ + + if not root: + return + + right = root.right + if root.left: + self.flatten(root.left) + tail = root.left + while tail.right: + tail = tail.right + root.left, root.right, tail.right = None, root.left, right + self.flatten(right) + \ No newline at end of file diff --git a/data_structures/binary_trees/maximum-depth-of-binary-tree.py b/data_structures/binary_trees/maximum-depth-of-binary-tree.py new file mode 100644 index 00000000..cb65fb92 --- /dev/null +++ b/data_structures/binary_trees/maximum-depth-of-binary-tree.py @@ -0,0 +1,53 @@ +''' +Author : MiKueen +Level : Easy +Problem Statement : Maximum Depth of Binary Tree + +Given a binary tree, find its maximum depth. +The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. +Note: A leaf is a node with no children. + +Example: +Given binary tree [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +return its depth = 3. +''' + +from collections import deque + +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def maxDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + + # BFS solution + if not root: + return 0 + if root.left is None and root.right is None: + return 1 + + depth, level = 0, deque([root]) + while level: + depth += 1 + for i in range(len(level)): + node = level.popleft() + if node.left: + level.append(node.left) + if node.right: + level.append(node.right) + return depth + \ No newline at end of file diff --git a/data_structures/binary_trees/minimum-depth-of-binary-tree.py b/data_structures/binary_trees/minimum-depth-of-binary-tree.py new file mode 100644 index 00000000..2dbbf5df --- /dev/null +++ b/data_structures/binary_trees/minimum-depth-of-binary-tree.py @@ -0,0 +1,55 @@ +''' +Author : MiKueen +Level : Easy +Problem Statement : Minimum Depth of Binary Tree + +Given a binary tree, find its minimum depth. +The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. +Note: A leaf is a node with no children. + +Example: +Given binary tree [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +return its minimum depth = 2. +''' + +from collections import deque + +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def minDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + + # BFS solution + if not root: + return 0 + if root.left is None and root.right is None: + return 1 + + depth, level = 1, deque([root]) + while level: + for i in range(len(level)): + node = level.popleft() + if node.left is None and node.right is None: + return depth + if node.left: + level.append(node.left) + if node.right: + level.append(node.right) + depth += 1 + return depth + \ No newline at end of file diff --git a/data_structures/binary_trees/path-sum.py b/data_structures/binary_trees/path-sum.py new file mode 100644 index 00000000..69bc80be --- /dev/null +++ b/data_structures/binary_trees/path-sum.py @@ -0,0 +1,64 @@ +''' +Author : MiKueen +Level : Medium +Problem Statement : Path Sum II + +Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. +Note: A leaf is a node with no children. + +Example: +Given the below binary tree and sum = 22, + 5 + / \ + 4 8 + / / \ + 11 13 4 + / \ / \ +7 2 5 1 +Return: +[ + [5,4,11,2], + [5,8,4,5] +] +''' + +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def pathSum(self, root, sum): + """ + :type root: TreeNode + :type sum: int + :rtype: List[List[int]] + """ + + # DFS solution + if not root: + return [] + if root.left is None and root.right is None: + if sum == root.val: + return [[root.val]] + else: + return [] + + res = [] + left, right = [], [] + sum -= root.val + + if root.left: + left = self.pathSum(root.left, sum) + if root.right: + right = self.pathSum(root.right, sum) + + for l in left: + res.append([root.val] + l) + for r in right: + res.append([root.val] + r) + + return res + \ No newline at end of file From 7818a3a51346781ecb55249e7d064174dc4b207b Mon Sep 17 00:00:00 2001 From: sanket099 Date: Mon, 14 Oct 2019 23:27:12 +0530 Subject: [PATCH 117/455] finding all substrings --- .../strings/finding_all_substrings.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 data_structures/strings/finding_all_substrings.py diff --git a/data_structures/strings/finding_all_substrings.py b/data_structures/strings/finding_all_substrings.py new file mode 100644 index 00000000..acbae381 --- /dev/null +++ b/data_structures/strings/finding_all_substrings.py @@ -0,0 +1,26 @@ +''' +Question : Print and Count all the substrings of a given string. +Sample Input : hello +Sample Output : ['h', 'he', 'hel', 'hell', 'hello', 'e', 'el', 'ell', 'ello', 'l', 'll', 'llo', 'l', 'lo', 'o'] +15 +Source : Hackerrank''' + +def finding_substrings(string): + + # Get all substrings of string and store them in an empty list + list =[] + count=0 + for i in range(len(string)): + for j in range(i+1,(len(string)+1)): + list.append(string[i:j]) + + count=count+1 + + # printing result + print(list) + print(count) + +#driver code +string = input("enter string: ") +finding_substrings(string) + From 78d16e31598ec39656b26c9b0653ecdf4d179baa Mon Sep 17 00:00:00 2001 From: Oishika Pradhan Date: Tue, 15 Oct 2019 13:21:54 +0530 Subject: [PATCH 118/455] used snake case --- data_structures/graphs/TopoSort.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/data_structures/graphs/TopoSort.py b/data_structures/graphs/TopoSort.py index 3591882a..4cb5dccb 100644 --- a/data_structures/graphs/TopoSort.py +++ b/data_structures/graphs/TopoSort.py @@ -7,38 +7,38 @@ def __init__(self, vertices): self.graph = defaultdict(list) self.V = vertices - def addEdge(self, u, v): + def add_edge(self, u, v): self.graph[u].append(v) - def topologicalSortUtil(self, v, visited, stack): + def topological_sort_util(self, v, visited, stack): visited[v] = True for i in self.graph[v]: if not visited[i]: - self.topologicalSortUtil(i, visited, stack) + self.topological_sort_util(i, visited, stack) stack.insert(0, v) # Topological sort function - def topologicalSort(self): + def topological_sort(self): visited = [False] * self.V stack = [] for i in range(self.V): if (visited[i] == False): - self.topologicalSortUtil(i, visited, stack) + self.topological_sort_util(i, visited, stack) print(stack) g = Graph(6) -g.addEdge(5, 2) -g.addEdge(5, 0) -g.addEdge(4, 0) -g.addEdge(4, 1) -g.addEdge(2, 3) -g.addEdge(3, 1) +g.add_edge(5, 2) +g.add_edge(5, 0) +g.add_edge(4, 0) +g.add_edge(4, 1) +g.add_edge(2, 3) +g.add_edge(3, 1) print("One possible Topological Sort of the graph is:") -g.topologicalSort() +g.topological_sort() From 7ed6283e1811e1ff4c9f7acca474010e6381ccb5 Mon Sep 17 00:00:00 2001 From: Oishika Pradhan Date: Tue, 15 Oct 2019 14:57:01 +0530 Subject: [PATCH 119/455] Added Iterative DFS to graph algorithms --- data_structures/graphs/DFS.py | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 data_structures/graphs/DFS.py diff --git a/data_structures/graphs/DFS.py b/data_structures/graphs/DFS.py new file mode 100644 index 00000000..cc133a1f --- /dev/null +++ b/data_structures/graphs/DFS.py @@ -0,0 +1,46 @@ +# An Iterative DFS solution. +class Graph: + def __init__(self, V): + self.V = V + self.adj = [[] for i in range(V)] + + def add_edge(self, v, w): + self.adj[v].append(w) + + def DFS_util(self, s, visited): + + stack = [] + + stack.append(s) + + while (len(stack) != 0): + + s = stack.pop() + + if (not visited[s]): + print(s, end=" ") + visited[s] = True + + i = 0 + while i < len(self.adj[s]): + if (not visited[self.adj[s][i]]): + stack.append(self.adj[s][i]) + i += 1 + + def DFS(self): + visited = [False] * self.V + for i in range(self.V): + if (not visited[i]): + self.DFS_util(i, visited) + + +if __name__ == '__main__': + + g = Graph(5) + g.add_edge(1, 0) + g.add_edge(2, 1) + g.add_edge(3, 4) + g.add_edge(4, 0) + + print("Following is Depth First Traversal") + g.DFS() From d8d9b1943bf7e18a05386aa2fae28f5259852f69 Mon Sep 17 00:00:00 2001 From: nisag Date: Tue, 15 Oct 2019 20:40:57 +0530 Subject: [PATCH 120/455] add roman to integer --- data_structures/strings/roman_to_integer.py | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 data_structures/strings/roman_to_integer.py diff --git a/data_structures/strings/roman_to_integer.py b/data_structures/strings/roman_to_integer.py new file mode 100644 index 00000000..e9e830ec --- /dev/null +++ b/data_structures/strings/roman_to_integer.py @@ -0,0 +1,40 @@ +''' +Question: +Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M and their values are 1,5,10,50,100,500,1000 respectively.Given a roman numeral,convert it to an integer.Input is guaranteed to be within the range from 1 to 3999. + +Example 1: +Input : 'XI' +Output : 11 + +Example 2: +Input : 'CCCXL' +Output : 340 + +Source: Interview question. + +Time Complexity : O(n) +Space Complexity : O(1) + +''' + +# Function to convert a roman numeral to an integer +def roman_to_integer(input): + romans={'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000} + sum=0 + for i in range(input): + # Getting the value of the symbol + value=romans[input[i]] + # Comparing if the next value is bigger or smaller than the current value + if i+1value: + # If it is big, the value is subtracted from the sum + sum-=value + else: + sum+=value + return sum + +# Main code +print("Roman to integer conversion of") +input=input.upper() +roman_to_integer(input) + From 6ea3e65b6dfc5804ff0d2e620a1b117e043e73a3 Mon Sep 17 00:00:00 2001 From: Uday032 Date: Wed, 16 Oct 2019 14:07:30 +0530 Subject: [PATCH 121/455] Coin Change --- .DS_Store | Bin 0 -> 8196 bytes algorithms/.DS_Store | Bin 0 -> 6148 bytes algorithms/dynamic_programming/Coin_Change.py | 26 ++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 .DS_Store create mode 100644 algorithms/.DS_Store create mode 100644 algorithms/dynamic_programming/Coin_Change.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d8161af3fe237ccca49ff534de3a3de04ea716a1 GIT binary patch literal 8196 zcmeHM%Wl&^6ur}i#tA~n0;ySggTx}L(iU1IgcR}+io{E}zyeTe*H&ZIv7^`~ln|5+ z{{Z{}pTZaLA$$Owc{EDg2En3$V6HTC=5f#1J#)v-b%}^IQg@T6LPQ1%$MQu~XBeO7 z<&>?ckus2hPn{q-aDvD|pO0zN3TOqi0$KsBfL7q|QvmO5ZpM=LzMR#yRzNH8Un;<# z4<-u7y27bM@#sJ$QUG8M!@|%OKmCCw9{|=BP9!>R;m7y?|cra7A6RS(qwN^kYa9RO=TynHQhvZX|$=`2c?&>#Tf|x(?qaLN? zWV}CRyo)n$AFGEH(U81F4qMM~*1$=yx`(^5GrsRKzD2Srz{-4G+&fr(iZh(AKf`fG z@j!jG`0NYk4F%bEJ-9r7>W6MLYD8)1#$p{yP8dePD0It}@%YBpR@L0TzB8$s zm(>$ zih)A}(g85#!I8bT2#;T2|En8Wq92Nu+0rsjLkNaPuOM5-M{H{r-p0+Oz`a zsKBaRyTbGT_VVxl=XeKtX{~@(;7=>SaxJUXz+IgDn#|r1&$UgIeH3ooZz@qxP>FOL hDAIA@>>q|`n{efvy27bMjKK7V03m~}v;x0Xf$vLMM9u&J literal 0 HcmV?d00001 diff --git a/algorithms/.DS_Store b/algorithms/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..916b7945a1ce5a3a3104c92560c4e474e29c0a4a GIT binary patch literal 6148 zcmeHK(Q4E{6ur}?ZFWm>!9x3(7r}=`wym}W5yDy@`X;RCgUU8(!fqf+X3NzP1WGDIZ0qhODyMMO3Vqt!(96XA9) zOR}OZ4WN)YA}Xnm>keg0-o{`UFbw={4Dh$RDZkl>5}N;hC#P|G?#HPQ4_+Sbqul-~ z1sc&!3TT2Dk1h~*jvN`~l+pk-+t`}WpqAz1?`84FMW&zSlb^*=QFc0?#mcI+w!UH8 zO}n|(eAyeO<6h~NqoV8O&-w1LR}OuxKS|U0hwk}Lqj21BZ9hzt(uNox2BzvsuI5xwZG;^z34C zIek5Q^Ip1ZP{*Bxf{Sq*v^qb$*c6rDsSX4_3|h zZOzxhka<|Z>p8#F{I=xK78vr7Vq6}EImEz^s95YlPMLReQ)Yt-_~q#1s;M#Wjc$!x zCj)w7+MCzeiOFpkFbw>Y4DkBkpfI``D}{3DKqZd=KnrFm(D`S9V;qgH#!4YtAVP%# zRjANM457kdceJ0Yu~MkQN$A6e&^-%%LJ_ie S5Eh8}5s);P$}sRp8TbYc8N4$9 literal 0 HcmV?d00001 diff --git a/algorithms/dynamic_programming/Coin_Change.py b/algorithms/dynamic_programming/Coin_Change.py new file mode 100644 index 00000000..fcf8d87b --- /dev/null +++ b/algorithms/dynamic_programming/Coin_Change.py @@ -0,0 +1,26 @@ +# Dynamic Programming Python implementation of Coin +# Change problem +def count(S, m, n): + # We need n+1 rows as the table is constructed + # in bottom up manner using the base case 0 value + # case (n = 0) + table = [[0 for x in range(m)] for x in range(n+1)] + + # Fill the entries for 0 value case (n = 0) + for i in range(m): + table[0][i] = 1 + + # Fill rest of the table entries in bottom up manner + for i in range(1, n+1): + for j in range(m): + + # Count of solutions including S[j] + x = table[i - S[j]][j] if i-S[j] >= 0 else 0 + + # Count of solutions excluding S[j] + y = table[i][j-1] if j >= 1 else 0 + + # total count + table[i][j] = x + y + + return table[n][m-1] From 12017abcc6fa2d9d5dec3d89e08ce57253b948b2 Mon Sep 17 00:00:00 2001 From: rishabh169 Date: Wed, 16 Oct 2019 14:32:24 +0530 Subject: [PATCH 122/455] Modular Exponentiation --- algorithms/math/modular_exponentiation.py | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 algorithms/math/modular_exponentiation.py diff --git a/algorithms/math/modular_exponentiation.py b/algorithms/math/modular_exponentiation.py new file mode 100644 index 00000000..1d512b45 --- /dev/null +++ b/algorithms/math/modular_exponentiation.py @@ -0,0 +1,24 @@ +# to compute modular power + +# Iterative Function to calculate +# (x^y)%p in O(log y) + +def power(x, y, p) : + res = 1 # Initialize result + + # Update x if it is more + # than or equal to p + x = x % p + + while (y > 0) : + + # If y is odd, multiply + # x with result + if ((y & 1) == 1) : + res = (res * x) % p + + # y must be even now + y = y >> 1 # y = y/2 + x = (x * x) % p + + return res \ No newline at end of file From e27802fb84c369b0d1e41fd4063946edff0e7fc9 Mon Sep 17 00:00:00 2001 From: avats101 <53526065+avats101@users.noreply.github.com> Date: Wed, 16 Oct 2019 18:44:42 +0530 Subject: [PATCH 123/455] Sumoffigitswithoutanyloop Finding Sum off digits of a number untill the sum is singular,without any loops --- algorithms/math/sumofdigits.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 algorithms/math/sumofdigits.py diff --git a/algorithms/math/sumofdigits.py b/algorithms/math/sumofdigits.py new file mode 100644 index 00000000..62ba2177 --- /dev/null +++ b/algorithms/math/sumofdigits.py @@ -0,0 +1,8 @@ +#This is to find the sum of digits of a number untill it is a single digit +n=int(input()) #here n is the number +if n%9!=0: + print(n%9) +else: + print("9") +#this method reduces time complexity by a factor of n and also without using any loop + From 5e79a044fe86cab1ad35f71b9ab9b6bc808ad263 Mon Sep 17 00:00:00 2001 From: David Voigt Date: Wed, 16 Oct 2019 22:01:53 +0200 Subject: [PATCH 124/455] Added recursive function to compute the Fibonacci sequence --- algorithms/math/recursive_fibonacci.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 algorithms/math/recursive_fibonacci.py diff --git a/algorithms/math/recursive_fibonacci.py b/algorithms/math/recursive_fibonacci.py new file mode 100644 index 00000000..4094e6b9 --- /dev/null +++ b/algorithms/math/recursive_fibonacci.py @@ -0,0 +1,19 @@ +""" + Recursivly compute the Fibonacci sequence +""" + +def rec_fib(n): + if n == 1: + return 1 + elif n == 0: + return 0 + else: + return rec_fib(n-1)+rec_fib(n-2) + +def main(): + n : int = int(input("n := ")) + for i in range(0, n): + print(rec_fib(i)) + +if __name__ == "__main__": + main() From 1c2e7aaa74d26febf2c22c4b7343f1471d447ff5 Mon Sep 17 00:00:00 2001 From: LadyZizi34 Date: Wed, 16 Oct 2019 21:10:45 -0300 Subject: [PATCH 125/455] added one_away string question --- data_structures/strings/one_away.py | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 data_structures/strings/one_away.py diff --git a/data_structures/strings/one_away.py b/data_structures/strings/one_away.py new file mode 100644 index 00000000..4ea42273 --- /dev/null +++ b/data_structures/strings/one_away.py @@ -0,0 +1,62 @@ +""" +Question: +One Away: There are three types of edits that can be performed on +strings: insert a character, remove a character, or replace a +character. Given two strings, write a function to check if they +are one edit (or zero edits) away. + +Example: +pale, ple -> true +pales, pale -> true +pale, bale -> true +pale, bake -> false + +Source: Cracking the Code Interview 6th Edition Question 1.5 + +Time Complexity: +We are going through both strings at the same time and stopping when +more than one letter is different, which means O(n) time complexity +on the while loop. No extra space is required. +""" + +def is_one_away(str1, str2): + edit_counter = 0 + i = 0 # str1 index + j = 0 # str2 index + + # Size difference must be less than 1 + if abs(len(str1) - len(str2)) > 1: + return False + + # Compare strings while counting edits + # If letters differ, update counter and compare next letter + # In this case, if strings have different sizes increment only index of the longest + # Otherwise increment both indexes + while i < len(str1) and j < len(str2): + if str1[i] != str2[j]: + # Only one edit is allowed + if edit_counter > 0: + return False + edit_counter += 1 + + if len(str1) > len(str2): + i += 1 + continue + elif len(str1) < len(str2): + j += 1 + continue + i += 1 + j += 1 + + # If one string finished before the other, we will certainly + # have one more edit to consider (adding the last letter), so + # we must check if the edit counter is still empty + if (i < len(str1) or j < len(str2)) and edit_counter > 0: + return False + + return True + +# Driver code +str1 = input("Enter first string: ") +str2 = input("Enter second string: ") +print(is_one_away(str1, str2)) From dcd4c89af0b2623a87e9c3fb7a5e6810b48cb27a Mon Sep 17 00:00:00 2001 From: Robby Renz Date: Wed, 16 Oct 2019 23:04:32 -0500 Subject: [PATCH 126/455] explicitly add exit code of 1 --- index_updater.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index_updater.py b/index_updater.py index 8eaae0b7..296518da 100755 --- a/index_updater.py +++ b/index_updater.py @@ -6,7 +6,7 @@ # Terminal parameters. if len(sys.argv[1:]) == 0: print('Please, give a path') - sys.exit() + sys.exit(1) else: mypath = sys.argv[1] From ffa9769a726547584396c714218848bc660ab758 Mon Sep 17 00:00:00 2001 From: Robby Renz Date: Wed, 16 Oct 2019 23:27:55 -0500 Subject: [PATCH 127/455] fix PEP 8 issues --- algorithms/math/fibonacci_number.py | 13 ++++++++----- algorithms/math/greatest_common_divisor.py | 14 +++++++------- algorithms/math/prime.py | 10 +++++----- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/algorithms/math/fibonacci_number.py b/algorithms/math/fibonacci_number.py index ce15e1ca..ad58a349 100644 --- a/algorithms/math/fibonacci_number.py +++ b/algorithms/math/fibonacci_number.py @@ -1,7 +1,9 @@ +# Program that prints out the fibonacci sequence until a given number + def calc_fib(num): - while len(fib)<=num: + while len(fib) <= num: n = len(fib) - fib.append((fib[n-1]+fib[n-2])) + fib.append((fib[n-1] + fib[n-2])) def main(): print("Enter the Position of the Number in the Sequence or \'0\' to Quit: ") @@ -9,15 +11,16 @@ def main(): fib = list() fib.append(0) fib.append(1) + while True: num = int(input()) - if(num<=0): + if(num <= 0): break - if len(fib)<=num: + if len(fib) <= num: calc_fib(num) - print('Fibonacci Number at Position '+str(num)+' is: '+str(fib[num])) + print('Fibonacci Number at Position ' + str(num) + ' is: ' + str(fib[num])) if __name__ == '__main__': main() diff --git a/algorithms/math/greatest_common_divisor.py b/algorithms/math/greatest_common_divisor.py index 05f57ce0..d00efe53 100644 --- a/algorithms/math/greatest_common_divisor.py +++ b/algorithms/math/greatest_common_divisor.py @@ -7,13 +7,13 @@ """ # Iterative Solution def gcd(x, y): - if x==0: + if x == 0: return y - if y==0: + if y == 0: return x - while x%y != 0: - rem = x%y; + while x % y != 0: + rem = x % y; x = y y = rem @@ -21,9 +21,9 @@ def gcd(x, y): # Recursive Solution def gcd(x, y): - if x==0: + if x == 0: return y - if y==0: + if y == 0: return x - return gcd(y, x%y) \ No newline at end of file + return gcd(y, x % y) \ No newline at end of file diff --git a/algorithms/math/prime.py b/algorithms/math/prime.py index ef981c9d..8dc7143c 100644 --- a/algorithms/math/prime.py +++ b/algorithms/math/prime.py @@ -1,16 +1,16 @@ def prime(limit): count = 1 - while(count Date: Thu, 17 Oct 2019 15:48:33 +0000 Subject: [PATCH 128/455] replace absolute path link with relative path link in index.md --- algorithms/dynamic_programming/index.md | 10 +-- algorithms/math/index.md | 8 +-- algorithms/miscellaneous/index.md | 2 +- algorithms/sorting/index.md | 10 +-- data_structures/array/index.md | 64 +++++++++---------- data_structures/binary_trees/index.md | 2 +- data_structures/bst/index.md | 58 ++++++++--------- data_structures/circular_linked_list/index.md | 6 +- data_structures/doubly_linked_list/index.md | 2 +- data_structures/graphs/index.md | 2 +- data_structures/linked_list/index.md | 18 +++--- data_structures/queue/index.md | 2 +- data_structures/stack/index.md | 8 +-- data_structures/strings/index.md | 8 +-- 14 files changed, 100 insertions(+), 100 deletions(-) diff --git a/algorithms/dynamic_programming/index.md b/algorithms/dynamic_programming/index.md index 2e55dae7..7bfbcd4c 100644 --- a/algorithms/dynamic_programming/index.md +++ b/algorithms/dynamic_programming/index.md @@ -1,8 +1,8 @@ # Index of dynamic_programming -* [Longest Common Subsequence](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/longest_common_subsequence.py) -* [Rod Cutting](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/rod_cutting.py) -* [Max Subarray](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/max_subarray.py) -* [Unique Grid Paths](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/unique_grid_paths.py) -* [Edit Distance](https://github.com/prabhupant/python-ds/blob/master/algorithms/dynamic_programming/edit_distance.py) +* [Longest Common Subsequence](longest_common_subsequence.py) +* [Rod Cutting](rod_cutting.py) +* [Max Subarray](max_subarray.py) +* [Unique Grid Paths](unique_grid_paths.py) +* [Edit Distance](edit_distance.py) diff --git a/algorithms/math/index.md b/algorithms/math/index.md index 2652ceb6..a02f7ae0 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -1,7 +1,7 @@ # Index of math -* [Greatest Common Divisor](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/greatest_common_divisor.py) -* [Fibonacci Number](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/fibonacci_number.py) -* [Nth Prime Number](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/prime.py) -* [Sieve of Erastothenes](https://github.com/prabhupant/python-ds/blob/master/algorithms/math/sieve_of_eratosthenes.py) +* [Greatest Common Divisor](greatest_common_divisor.py) +* [Fibonacci Number](fibonacci_number.py) +* [Nth Prime Number](prime.py) +* [Sieve of Erastothenes](sieve_of_eratosthenes.py) diff --git a/algorithms/miscellaneous/index.md b/algorithms/miscellaneous/index.md index af9ea249..efd1c3ae 100644 --- a/algorithms/miscellaneous/index.md +++ b/algorithms/miscellaneous/index.md @@ -1,3 +1,3 @@ # Index of miscellaneous -* [Luhn Algorithm](https://github.com/prabhupant/python-ds/blob/master/algorithms/miscellaneous/luhn_algorithm.py) \ No newline at end of file +* [Luhn Algorithm](luhn_algorithm.py) \ No newline at end of file diff --git a/algorithms/sorting/index.md b/algorithms/sorting/index.md index 6e76b265..6e83b669 100644 --- a/algorithms/sorting/index.md +++ b/algorithms/sorting/index.md @@ -1,7 +1,7 @@ # Index of sorting -* [Insertion Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/insertion_sort.py) -* [Merge Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/merge_sort.py) -* [Quick Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/qsort.py) -* [Select Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/select_sort.py) -* [Bubble Sort](https://github.com/prabhupant/python-ds/blob/master/algorithms/sorting/bubble_sort.py) \ No newline at end of file +* [Insertion Sort](insertion_sort.py) +* [Merge Sort](merge_sort.py) +* [Quick Sort](qsort.py) +* [Select Sort](select_sort.py) +* [Bubble Sort](bubble_sort.py) \ No newline at end of file diff --git a/data_structures/array/index.md b/data_structures/array/index.md index 31adcfe5..14d1594a 100644 --- a/data_structures/array/index.md +++ b/data_structures/array/index.md @@ -1,34 +1,34 @@ # Index of array -* [Permumations of Word](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/permutations_of_word.py) -* [Common Elements of three sorted arrays](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/sorted_array_three_common_elements.py) -* [Dutch Flag Problem](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/dutch_flag_problem.py) -* [Partition an array into three parts with equal sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/partition_three_parts_equal_sum.py) -* [Binary search on an Infinite array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/binary_search_infinite_array.py) -* [Largest Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/largest_element.py) -* [Right Place](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/right_place.py) -* [Rotation](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/rotation.py) -* [Find missing number](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/find_missing_numbers.py) -* [Three Largest Elements](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/three_largest_elements.py) -* [Triplet Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/triplet_sum.py) -* [Max Product](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_product.py) -* [Moves to Zero](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/moves_zeros_to_end.py) -* [Pivot Index](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/pivot_index.py) -* [Intersection of Two Sorted Arrays](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/intersection_sorted_array.py) -* [Max Triplet Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_triplet_sum.py) -* [Number of 1's in Sorted Array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/number_of_1_in_sorted_array.py) -* [Square of Sorted Array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/square_of_sorted_array.py) -* [Max Consecutive 1's](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_consecutive_ones.py) -* [Max Product Three Elements](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/max_product_three_elements.py) -* [Kadane Algorithm](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/kadane_algorithm.py) -* [All Numbers Divisible](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/all_numbers_divisible.py) -* [Duplicates](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/duplicates.py) -* [Majority Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/majority_element.py) -* [Find Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/find_sum.py) -* [Quick Sort](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/quick_sort.py) -* [Peak Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/peak_element.py) -* [Union Sorted Array](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/union_sorted_array.py) -* [Min Product](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/min_product.py) -* [Sort By Parity](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/sort_by_parity.py) -* [Duplicate](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/duplicate.py) -* [Product of Array Except Self](https://github.com/prabhupant/python-ds/blob/master/data_structures/array/product_of_array_except_self.py) +* [Permumations of Word](permutations_of_word.py) +* [Common Elements of three sorted arrays](sorted_array_three_common_elements.py) +* [Dutch Flag Problem](dutch_flag_problem.py) +* [Partition an array into three parts with equal sum](partition_three_parts_equal_sum.py) +* [Binary search on an Infinite array](binary_search_infinite_array.py) +* [Largest Element](largest_element.py) +* [Right Place](right_place.py) +* [Rotation](rotation.py) +* [Find missing number](find_missing_numbers.py) +* [Three Largest Elements](three_largest_elements.py) +* [Triplet Sum](triplet_sum.py) +* [Max Product](max_product.py) +* [Moves to Zero](moves_zeros_to_end.py) +* [Pivot Index](pivot_index.py) +* [Intersection of Two Sorted Arrays](intersection_sorted_array.py) +* [Max Triplet Sum](max_triplet_sum.py) +* [Number of 1's in Sorted Array](number_of_1_in_sorted_array.py) +* [Square of Sorted Array](square_of_sorted_array.py) +* [Max Consecutive 1's](max_consecutive_ones.py) +* [Max Product Three Elements](max_product_three_elements.py) +* [Kadane Algorithm](kadane_algorithm.py) +* [All Numbers Divisible](all_numbers_divisible.py) +* [Duplicates](duplicates.py) +* [Majority Element](majority_element.py) +* [Find Sum](find_sum.py) +* [Quick Sort](quick_sort.py) +* [Peak Element](peak_element.py) +* [Union Sorted Array](union_sorted_array.py) +* [Min Product](min_product.py) +* [Sort By Parity](sort_by_parity.py) +* [Duplicate](duplicate.py) +* [Product of Array Except Self](product_of_array_except_self.py) diff --git a/data_structures/binary_trees/index.md b/data_structures/binary_trees/index.md index 1e36ce75..4f749eae 100644 --- a/data_structures/binary_trees/index.md +++ b/data_structures/binary_trees/index.md @@ -1,3 +1,3 @@ # Index of binary_trees -* [Symmetric Binary Tree]()https://github.com/prabhupant/python-ds/blob/master/data_structures/binary_trees/symmetric_binary_tree.py +* [Symmetric Binary Tree](symmetric_binary_tree.py) diff --git a/data_structures/bst/index.md b/data_structures/bst/index.md index 7dfc2c51..7e286a69 100644 --- a/data_structures/bst/index.md +++ b/data_structures/bst/index.md @@ -1,31 +1,31 @@ # Index of BST -* [[Deletion](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/deletion.py) -* [Sorted Array To BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/sorted_array_to_bst.py) -* [Print Left Node](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/print_left_node.py) -* [Diameter](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/diameter.py) -* [BFS](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/bfs.py) -* [Check if BT is BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/check_if_bt_if_bst.py) -* [Trim BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/trim_bst.py) -* [BT to BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/bt_to_bst.py) -* [Binary Search Tree](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/binary_search_tree.py) -* [Convert BST to Right Node Tree](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/convert_bst_to_right_node_tree.py) -* [kth largest in BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/kth_largest_in_bst.py) -* [Range Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/range_sum.py) -* [DFS Iterative](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/dfs_iterative.py) -* [Print Ancestor](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/print_ancestor.py) -* [Min Max Value in BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/min_max_value_in_bst.py) -* [Check BT is Subtree of another BT](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/check_bt_is_subtree_of_another_bt.py) -* [Ceil](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/ceil.py) -* [Closest Element](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/closest_element.py) -* [kth smallest in BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/kth_smallest_in_bst.py) -* [Insertion Iterative](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/insertion_iterative.py) -* [Lowest Common Ancestor](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/lowest_common_ancestor.py) -* [DFS Recursion](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/dfs_recursion.py) -* [Search](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/search.py) -* [Insertion Recursive](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/insertion_recursive.py) -* [Duplicate Keys](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/duplicate_keys.py) -* [Merge Sum](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/merge_sum.py) -* [Linked List to BST](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/linked_list_to_bst.py) -* [Reverse Inorder Traversal](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/reverse_inorder_traversal.py) -* [Average of Levels](https://github.com/prabhupant/python-ds/blob/master/data_structures/bst/average_of_levels.py) +* [[Deletion](deletion.py) +* [Sorted Array To BST](sorted_array_to_bst.py) +* [Print Left Node](print_left_node.py) +* [Diameter](diameter.py) +* [BFS](bfs.py) +* [Check if BT is BST](check_if_bt_if_bst.py) +* [Trim BST](trim_bst.py) +* [BT to BST](bt_to_bst.py) +* [Binary Search Tree](binary_search_tree.py) +* [Convert BST to Right Node Tree](convert_bst_to_right_node_tree.py) +* [kth largest in BST](kth_largest_in_bst.py) +* [Range Sum](range_sum.py) +* [DFS Iterative](dfs_iterative.py) +* [Print Ancestor](print_ancestor.py) +* [Min Max Value in BST](min_max_value_in_bst.py) +* [Check BT is Subtree of another BT](check_bt_is_subtree_of_another_bt.py) +* [Ceil](ceil.py) +* [Closest Element](closest_element.py) +* [kth smallest in BST](kth_smallest_in_bst.py) +* [Insertion Iterative](insertion_iterative.py) +* [Lowest Common Ancestor](lowest_common_ancestor.py) +* [DFS Recursion](dfs_recursion.py) +* [Search](search.py) +* [Insertion Recursive](insertion_recursive.py) +* [Duplicate Keys](duplicate_keys.py) +* [Merge Sum](merge_sum.py) +* [Linked List to BST](linked_list_to_bst.py) +* [Reverse Inorder Traversal](reverse_inorder_traversal.py) +* [Average of Levels](average_of_levels.py) diff --git a/data_structures/circular_linked_list/index.md b/data_structures/circular_linked_list/index.md index 985f8082..a14e9993 100644 --- a/data_structures/circular_linked_list/index.md +++ b/data_structures/circular_linked_list/index.md @@ -1,5 +1,5 @@ # Index of circular linked list -* [Check Circular Linked List ](https://github.com/prabhupant/python-ds/blob/master/data_structures/circular_linked_list/check_circular_linked_list.py) -* [Delete ](https://github.com/prabhupant/python-ds/blob/master/data_structures/circular_linked_list/delete.py) -* [Traversal](https://github.com/prabhupant/python-ds/blob/master/data_structures/circular_linked_list/traversal.py) +* [Check Circular Linked List](check_circular_linked_list.py) +* [Delete](delete.py) +* [Traversal](traversal.py) diff --git a/data_structures/doubly_linked_list/index.md b/data_structures/doubly_linked_list/index.md index 9e193d24..0a7d6f6d 100644 --- a/data_structures/doubly_linked_list/index.md +++ b/data_structures/doubly_linked_list/index.md @@ -1,3 +1,3 @@ # Index of doubly_linked_list -* [Doubly Linked List](https://github.com/prabhupant/python-ds/blob/master/data_structures/doubly_linked_list/doubly_linked_list.py) +* [Doubly Linked List](doubly_linked_list.py) diff --git a/data_structures/graphs/index.md b/data_structures/graphs/index.md index d921832c..d65d9378 100644 --- a/data_structures/graphs/index.md +++ b/data_structures/graphs/index.md @@ -1,3 +1,3 @@ # Index of graphs -* [Adjacency List](https://github.com/prabhupant/python-ds/blob/master/data_structures/graphs/adjeceny_list.py) +* [Adjacency List](adjeceny_list.py) diff --git a/data_structures/linked_list/index.md b/data_structures/linked_list/index.md index fd1158e8..7c598aed 100644 --- a/data_structures/linked_list/index.md +++ b/data_structures/linked_list/index.md @@ -1,11 +1,11 @@ # Index of linked list -* [Remove](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/remove.py) -* [Pair Swap](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/pair_swap.py) -* [Reverse](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/reverse.py) -* [Linked List](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/linked_list.py) -* [Cycle Detection](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/cycle_detection.py) -* [Remove nth Node from End](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/remove_nth_node_from_end.py) -* [Odd-Even Arrangement](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/odd_even_arrangement.py) -* [Merge Linked List](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/merge_linked_list.py) -* [Remove Duplicates](https://github.com/prabhupant/python-ds/blob/master/data_structures/linked_list/remove_duplicates.py) +* [Remove](remove.py) +* [Pair Swap](pair_swap.py) +* [Reverse](reverse.py) +* [Linked List](linked_list.py) +* [Cycle Detection](cycle_detection.py) +* [Remove nth Node from End](remove_nth_node_from_end.py) +* [Odd-Even Arrangement](odd_even_arrangement.py) +* [Merge Linked List](merge_linked_list.py) +* [Remove Duplicates](remove_duplicates.py) diff --git a/data_structures/queue/index.md b/data_structures/queue/index.md index d4e739e5..8506ea63 100644 --- a/data_structures/queue/index.md +++ b/data_structures/queue/index.md @@ -1,3 +1,3 @@ # Index of Queue -[Queue](https://github.com/prabhupant/python-ds/blob/master/data_structures/queue/queue.py) \ No newline at end of file +[Queue](queue.py) \ No newline at end of file diff --git a/data_structures/stack/index.md b/data_structures/stack/index.md index 604a0586..1d7bdf6a 100644 --- a/data_structures/stack/index.md +++ b/data_structures/stack/index.md @@ -1,6 +1,6 @@ # Index of stack -* [Valid Parentheses](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/valid_parenthesis.py) -* [Largest Rectangle Area in a Histogram](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/largest_rectangle_area_in_histogram.py) -* [Remove Duplicates Adjacent](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/remove_duplicates_adjacent.py) -* [Validate Stack Sequence](https://github.com/prabhupant/python-ds/blob/master/data_structures/stack/validate_stack_sequence.py) +* [Valid Parentheses](valid_parenthesis.py) +* [Largest Rectangle Area in a Histogram](largest_rectangle_area_in_histogram.py) +* [Remove Duplicates Adjacent](remove_duplicates_adjacent.py) +* [Validate Stack Sequence](validate_stack_sequence.py) diff --git a/data_structures/strings/index.md b/data_structures/strings/index.md index 77cee22e..3f7bf484 100644 --- a/data_structures/strings/index.md +++ b/data_structures/strings/index.md @@ -1,6 +1,6 @@ # Index of strings -* [Check Permutations](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/check_permutations.py) -* [Are Anagrams](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/are_anagrams.py) -* [Adjacent Vowel Pairs](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/adjacent_vowel_pairs.py) -* [Toggle String](https://github.com/prabhupant/python-ds/blob/master/data_structures/strings/toggle_string.py) \ No newline at end of file +* [Check Permutations](check_permutations.py) +* [Are Anagrams](are_anagrams.py) +* [Adjacent Vowel Pairs](adjacent_vowel_pairs.py) +* [Toggle String](toggle_string.py) \ No newline at end of file From d5684e938b84e7326658dea6b96956dec93b3c36 Mon Sep 17 00:00:00 2001 From: ukayaj620 <51906567+ukayaj620@users.noreply.github.com> Date: Fri, 18 Oct 2019 00:02:03 +0700 Subject: [PATCH 129/455] add code and comment shell_sort --- algorithms/sorting/shell_sort.py | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 algorithms/sorting/shell_sort.py diff --git a/algorithms/sorting/shell_sort.py b/algorithms/sorting/shell_sort.py new file mode 100644 index 00000000..27269ec7 --- /dev/null +++ b/algorithms/sorting/shell_sort.py @@ -0,0 +1,40 @@ +''' +Time complexity of shell_sort is O(n2). +In the above implementation gap is reduce by half in every iteration. +here are many other ways to reduce gap which lead to better time complexity. +See this for more details. +''' + +def shell_sort(arr): + + # Start with a big gap, then reduce the gap + n = len(arr) + gap = int(n / 2) + + # Do a gapped insertion sort for this gap size. + # The first gap elements a[0..gap-1] are already in gapped + # order keep adding one more element until the entire array + # is gap sorted + while gap > 0: + + for i in range(gap, n): + + # add a[i] to the elements that have been gap sorted + # save a[i] in temp and make a hole at position i + temp = arr[i] + + # shift earlier gap-sorted elements up until the correct + # location for a[i] is found + j = i + while j >= gap and arr[j - gap] > temp: + arr[j] = arr[j - gap] + j -= gap + + # put temp (the original a[i]) in its correct location + arr[j] = temp + gap = int(gap / 2) + +arr = [ 12, 34, 54, 2, 3] + +shell_sort(arr) +print(arr) \ No newline at end of file From b64ef348c75659e591b28a0a7f73932ae95337f6 Mon Sep 17 00:00:00 2001 From: FARVE14 Date: Thu, 17 Oct 2019 23:08:21 +0530 Subject: [PATCH 130/455] Implementation of stack using linked list --- .../stack/stack_using_linked_list.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 data_structures/stack/stack_using_linked_list.py diff --git a/data_structures/stack/stack_using_linked_list.py b/data_structures/stack/stack_using_linked_list.py new file mode 100644 index 00000000..35323074 --- /dev/null +++ b/data_structures/stack/stack_using_linked_list.py @@ -0,0 +1,70 @@ +""" Use LinkedList class to implement a Stack. """ + +class Element(object): + def __init__(self, value): + self.value = value + self.next = None + +class LinkedList(object): + def __init__(self, head=None): + self.head = head + + def append(self, new_element): + current = self.head + if self.head: + while current.next: + current = current.next + current.next = new_element + else: + self.head = new_element + + def insert_first(self, new_element): + "Insert new element as the head of the LinkedList" + # fetch the current head + current = self.head + new_element.next = current + self.head = new_element + + def delete_first(self): + "Delete the first (head) element in the LinkedList and return it" + current = self.head + if current: + if current.next: + self.head = current.next + else: + self.head = None + return current + else: + return None + +class Stack(object): + def __init__(self,top=None): + self.ll = LinkedList(top) + + def push(self, new_element): + "Push (add) a new element onto the top of the stack" + self.ll.insert_first(new_element) + + def pop(self): + "Pop (remove) the first element off the top of the stack and return it" + return self.ll.delete_first() + +# Test cases +# Set up some Elements +e1 = Element(1) +e2 = Element(2) +e3 = Element(3) +e4 = Element(4) + +# Start setting up a Stack +stack = Stack(e1) + +# Test stack functionality +stack.push(e2) +stack.push(e3) +print stack.pop().value +print stack.pop().value +print stack.pop().value +print stack.pop() +stack.push(e4) +print stack.pop().value From 3006cb00d3a9d5582f8461396f4eb2d6d19c8495 Mon Sep 17 00:00:00 2001 From: Ed Howard Date: Thu, 17 Oct 2019 13:40:29 -0400 Subject: [PATCH 131/455] updated implementation, added basic usage demonstration --- algorithms/sorting/insertion_sort.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/algorithms/sorting/insertion_sort.py b/algorithms/sorting/insertion_sort.py index 75ba7514..b19d9ddd 100644 --- a/algorithms/sorting/insertion_sort.py +++ b/algorithms/sorting/insertion_sort.py @@ -8,9 +8,19 @@ """ def insertion_sort(lst): - for i, _ in enumerate(lst): - j = i - while(j > 0 and lst[i] < lst[j]): - j -= 1 - lst[j], lst[i] = lst[i], lst[j] + for i in range(1,len(lst)): + while(i > 0 and lst[i] < lst[i - 1]): + lst[i], lst[i - 1] = lst[i - 1], lst[i] + i -= 1 return lst + +test_data = [5,9,4,27,3,6] +print insertion_sort(test_data) + +test_data = ['f','b','z','a','x'] +print insertion_sort(test_data) + +# Resulting output: +# [3, 4, 5, 6, 9, 27] +# ['a', 'b', 'f', 'x', 'z'] + From b76a2f2fb5ece8be6a388e843386fb6c4d10d8a1 Mon Sep 17 00:00:00 2001 From: Uday032 Date: Fri, 18 Oct 2019 02:19:03 +0530 Subject: [PATCH 132/455] Delete .DS_Store --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d8161af3fe237ccca49ff534de3a3de04ea716a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHM%Wl&^6ur}i#tA~n0;ySggTx}L(iU1IgcR}+io{E}zyeTe*H&ZIv7^`~ln|5+ z{{Z{}pTZaLA$$Owc{EDg2En3$V6HTC=5f#1J#)v-b%}^IQg@T6LPQ1%$MQu~XBeO7 z<&>?ckus2hPn{q-aDvD|pO0zN3TOqi0$KsBfL7q|QvmO5ZpM=LzMR#yRzNH8Un;<# z4<-u7y27bM@#sJ$QUG8M!@|%OKmCCw9{|=BP9!>R;m7y?|cra7A6RS(qwN^kYa9RO=TynHQhvZX|$=`2c?&>#Tf|x(?qaLN? zWV}CRyo)n$AFGEH(U81F4qMM~*1$=yx`(^5GrsRKzD2Srz{-4G+&fr(iZh(AKf`fG z@j!jG`0NYk4F%bEJ-9r7>W6MLYD8)1#$p{yP8dePD0It}@%YBpR@L0TzB8$s zm(>$ zih)A}(g85#!I8bT2#;T2|En8Wq92Nu+0rsjLkNaPuOM5-M{H{r-p0+Oz`a zsKBaRyTbGT_VVxl=XeKtX{~@(;7=>SaxJUXz+IgDn#|r1&$UgIeH3ooZz@qxP>FOL hDAIA@>>q|`n{efvy27bMjKK7V03m~}v;x0Xf$vLMM9u&J From 567c196f6f97a84390c129020d2fd29a92aeaf05 Mon Sep 17 00:00:00 2001 From: Uday032 Date: Fri, 18 Oct 2019 02:20:11 +0530 Subject: [PATCH 133/455] Delete .DS_Store --- algorithms/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 algorithms/.DS_Store diff --git a/algorithms/.DS_Store b/algorithms/.DS_Store deleted file mode 100644 index 916b7945a1ce5a3a3104c92560c4e474e29c0a4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK(Q4E{6ur}?ZFWm>!9x3(7r}=`wym}W5yDy@`X;RCgUU8(!fqf+X3NzP1WGDIZ0qhODyMMO3Vqt!(96XA9) zOR}OZ4WN)YA}Xnm>keg0-o{`UFbw={4Dh$RDZkl>5}N;hC#P|G?#HPQ4_+Sbqul-~ z1sc&!3TT2Dk1h~*jvN`~l+pk-+t`}WpqAz1?`84FMW&zSlb^*=QFc0?#mcI+w!UH8 zO}n|(eAyeO<6h~NqoV8O&-w1LR}OuxKS|U0hwk}Lqj21BZ9hzt(uNox2BzvsuI5xwZG;^z34C zIek5Q^Ip1ZP{*Bxf{Sq*v^qb$*c6rDsSX4_3|h zZOzxhka<|Z>p8#F{I=xK78vr7Vq6}EImEz^s95YlPMLReQ)Yt-_~q#1s;M#Wjc$!x zCj)w7+MCzeiOFpkFbw>Y4DkBkpfI``D}{3DKqZd=KnrFm(D`S9V;qgH#!4YtAVP%# zRjANM457kdceJ0Yu~MkQN$A6e&^-%%LJ_ie S5Eh8}5s);P$}sRp8TbYc8N4$9 From d3480fa582dedfc2e4db649657ea8404560002ba Mon Sep 17 00:00:00 2001 From: palutlaanirudh Date: Fri, 18 Oct 2019 06:27:59 +0530 Subject: [PATCH 134/455] Added Union-Find data structure --- data_structures/union_find/uf.py | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 data_structures/union_find/uf.py diff --git a/data_structures/union_find/uf.py b/data_structures/union_find/uf.py new file mode 100644 index 00000000..d1f52da3 --- /dev/null +++ b/data_structures/union_find/uf.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +# 0-based indexing is used in this +# n is given as an input, which is the number of elements in the set + +class Union_find: + ''' + Union-Find data structure along with required functions. Takes 'n' (integer) as input + which is the total number of nodes in the structure. + ''' + def __init__ (self, n): + self.ar = [None] * n + for i in range(n): + self.ar[i] = i + self.size = [1] * n + self.n = n + + def root (self, x): + ''' + Function used to find root of a node "x" + Input: node number (integer between 0 and n-1) + Output: node number (integer between 0 and n-1) + ''' + while self.ar[x] != x: + self.ar[x] = self.ar[self.ar[x]] + x = self.ar[x] + return x + + def union (self, a, b): + ''' + Function to perform union of the nodes 'a' and 'b' + Input: node number, node number (integers between 0 and n-1) + Output: none + ''' + print("Union", a, "and", b) + roa = self.root(a) + rob = self.root(b) + if self.size[roa] < self.size[rob]: + self.ar[roa] = self.ar[rob] + self.size[rob] += self.size[roa] + else: + self.ar[rob] = self.ar[roa] + self.size[roa] += self.size[rob] + + def find (self, a, b): + ''' + Function to check if 'a' and 'b' are connected + Input: node number, node number (integers between 0 and n-1) + Output: True or False + ''' + if self.root (a) == self.root (b): + return True + else: + return False + + pass + +if __name__ == "__main__": + uf = Union_find (6) + uf.union (1, 2) + print("2 and 3 connected?", uf.find(2, 3)) + uf.union (1, 3) + uf.union (4, 5) + print("2 and 4 connected?", uf.find(2, 4)) + uf.union (3, 5) + print("2 and 4 connected?", uf.find(2, 4)) + From a144e88212e35a1891c458a7eec9babb3bbe4c0f Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Sun, 20 Oct 2019 19:44:42 +0530 Subject: [PATCH 135/455] update README.md replace absolute links with relative links --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 82fb9772..6b18100c 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,12 @@ You can find useful links in this repository in the different markdown files. Be | Category | Link | | :-- | :--: | -| Articles | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/articles.md) | -| Books | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/books.md) | -| Topics | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/topics.md) | -| Tutorials | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/tutorials.md) | -| Videos | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/videos.md) | -| Misc. | [Click Here](https://github.com/prabhupant/python-ds/blob/master/bookmarks/misc.md) | +| Articles | [Click Here](bookmarks/articles.md) | +| Books | [Click Here](bookmarks/books.md) | +| Topics | [Click Here](bookmarks/topics.md) | +| Tutorials | [Click Here](bookmarks/tutorials.md) | +| Videos | [Click Here](bookmarks/videos.md) | +| Misc. | [Click Here](bookmarks/misc.md) | ## :clipboard: Things need to be done From af527bdd60c51e950632ca2b4102f987b7d385a7 Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Sun, 20 Oct 2019 14:28:51 +0000 Subject: [PATCH 136/455] fix filename typo --- .../graphs/{adjeceny_list.py => adjacency_list.py} | 4 ++-- data_structures/graphs/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename data_structures/graphs/{adjeceny_list.py => adjacency_list.py} (91%) diff --git a/data_structures/graphs/adjeceny_list.py b/data_structures/graphs/adjacency_list.py similarity index 91% rename from data_structures/graphs/adjeceny_list.py rename to data_structures/graphs/adjacency_list.py index 1159430e..6fe60466 100644 --- a/data_structures/graphs/adjeceny_list.py +++ b/data_structures/graphs/adjacency_list.py @@ -17,7 +17,7 @@ def add_edge(self, src, dest): node = AdjNode(dest) node.next = self.graph[src] self.graph[src] = node - + # Adding source node to the destination as it is an # undirected graph node = AdjNode(src) @@ -27,7 +27,7 @@ def add_edge(self, src, dest): def print_graph(self): for i in range(self.V): - print("Adjency list of vertex {}\n head".format(i), end="") + print("Adjacency list of vertex {}\n head".format(i), end="") temp = self.graph[i] while temp: print(" -> {}".format(temp.vertex), end="") diff --git a/data_structures/graphs/index.md b/data_structures/graphs/index.md index d65d9378..7baba1cf 100644 --- a/data_structures/graphs/index.md +++ b/data_structures/graphs/index.md @@ -1,3 +1,3 @@ # Index of graphs -* [Adjacency List](adjeceny_list.py) +* [Adjacency List](adjacency_list.py) From 920974aa2e4bde5631d1148afa39a9af4d8a85fa Mon Sep 17 00:00:00 2001 From: Pablo Miralles Date: Mon, 21 Oct 2019 07:36:24 +0200 Subject: [PATCH 137/455] Implemented FenwickTree --- data_structures/fenwick_tree/fenwick_tree.py | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 data_structures/fenwick_tree/fenwick_tree.py diff --git a/data_structures/fenwick_tree/fenwick_tree.py b/data_structures/fenwick_tree/fenwick_tree.py new file mode 100644 index 00000000..e0d43803 --- /dev/null +++ b/data_structures/fenwick_tree/fenwick_tree.py @@ -0,0 +1,39 @@ + + +# Returns the right most significant bit of an integer. +# For example, 12 is represented by 1100 in binary, so it's LSB is the third position, 4. +def LSB(n): + return n & -n + + +class FenwickTree: + def __init__(self, array): + self.len = len(array)+1 + self.arr = [0] * self.len + for i in range(0, self.len - 1): + self.update(i, array[i]) + + def update(self, index, val): + j = index+1 + while j < self.len: + self.arr[j] += val + j += LSB(j) + + def get_sum(self, index): + sum = 0 + index += 1 + while index > 0: + sum += self.arr[index] + index -= LSB(index) + return sum + + def get_sum_range(self, start, end): + return self.get_sum(end) - self.get_sum(start-1) + + +if __name__ == '__main__': + arr = [1, 2, 3, 4, 5, 6, 7, 8] + fw = FenwickTree(arr) + print(fw.get_sum(3)) + print(fw.get_sum(5)) + print(fw.get_sum_range(1, 7)) From 51cdc0bc3ccdedad0193acb4b4e54869bcc049ce Mon Sep 17 00:00:00 2001 From: Oishika Pradhan Date: Mon, 21 Oct 2019 15:50:16 +0530 Subject: [PATCH 138/455] used pep8 --- data_structures/graphs/PrimsMST.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data_structures/graphs/PrimsMST.py b/data_structures/graphs/PrimsMST.py index e8dcfe98..b0156210 100644 --- a/data_structures/graphs/PrimsMST.py +++ b/data_structures/graphs/PrimsMST.py @@ -12,14 +12,14 @@ def __init__(self, vertices): for row in range(vertices)] # Function to print generated MST - def printMST(self, parent): + def print_MST(self, parent): print("Edge \t Weight") for i in range(1, self.V): print(parent[i], "-", i, "\t", self.graph[i][parent[i]]) # Function to find vertex with min. distance from set of vertices #not included in MST - def minValue(self, key, MSTSet): + def min_value(self, key, MSTSet): minval = sys.maxsize for v in range(self.V): @@ -37,7 +37,7 @@ def MST(self): parent[0] = -1 for j in range(self.V): - u = self.minValue(key, MSTSet) + u = self.min_value(key, MSTSet) MSTSet[u] = True for v in range(self.V): @@ -46,7 +46,7 @@ def MST(self): key[v] = self.graph[u][v] parent[v] = u - self.printMST(parent) + self.print_MST(parent) g = Graph(4) From 2db4c8db4fd2c2eba62f47bbf18817cf0596749e Mon Sep 17 00:00:00 2001 From: Pablo Miralles Date: Mon, 21 Oct 2019 16:37:54 +0200 Subject: [PATCH 139/455] Added comment to Fenwick Tree --- data_structures/fenwick_tree/fenwick_tree.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data_structures/fenwick_tree/fenwick_tree.py b/data_structures/fenwick_tree/fenwick_tree.py index e0d43803..eb7d3c8b 100644 --- a/data_structures/fenwick_tree/fenwick_tree.py +++ b/data_structures/fenwick_tree/fenwick_tree.py @@ -7,6 +7,12 @@ def LSB(n): class FenwickTree: + ''' + A Fenwick Tree allows you to sum a range of elements and update an element in an array in O(log(n)). A segment tree + can also achieve this, but it takes twice the memory, making it less memory efficient. On the other hand, a segment tree + can compute more functions in a range of elements, like the minimum or maximum. + ''' + def __init__(self, array): self.len = len(array)+1 self.arr = [0] * self.len From 07ed3e86b50249ced7b74d8d8beb0aa81830c580 Mon Sep 17 00:00:00 2001 From: Pablo Miralles Date: Mon, 21 Oct 2019 17:04:58 +0200 Subject: [PATCH 140/455] Improved Fenwick Tree's documentation Added an explanation to how it works and some comments to explain what the code does --- data_structures/fenwick_tree/fenwick_tree.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/data_structures/fenwick_tree/fenwick_tree.py b/data_structures/fenwick_tree/fenwick_tree.py index eb7d3c8b..94d42224 100644 --- a/data_structures/fenwick_tree/fenwick_tree.py +++ b/data_structures/fenwick_tree/fenwick_tree.py @@ -11,20 +11,28 @@ class FenwickTree: A Fenwick Tree allows you to sum a range of elements and update an element in an array in O(log(n)). A segment tree can also achieve this, but it takes twice the memory, making it less memory efficient. On the other hand, a segment tree can compute more functions in a range of elements, like the minimum or maximum. + The way it works is that given an index (note that we start with 1 and not 0), the element in the array will be the sum + of the LSB(index) elements below (including index). For example: with index 3, 3 = 11 in binary, and LSB(3) = 1, so this + element is equal to the corresponding element in the original array. But 4 = 100 in binary, so LSB(4) = 4, so it is equal + to the sum of A[0] + A[1] + A[2] + A[3] (the first 4 elements of the original array). ''' def __init__(self, array): self.len = len(array)+1 + # Initialize an array of length n+1 to 0 self.arr = [0] * self.len + # Update the array to the one passed in the parameters for i in range(0, self.len - 1): self.update(i, array[i]) def update(self, index, val): j = index+1 + # Update the value for every element that sums A[index] while j < self.len: self.arr[j] += val j += LSB(j) + # Get the sum of all elements before index (included) def get_sum(self, index): sum = 0 index += 1 @@ -33,6 +41,7 @@ def get_sum(self, index): index -= LSB(index) return sum + # Get the sum of all elements in the range [start, end] def get_sum_range(self, start, end): return self.get_sum(end) - self.get_sum(start-1) From d193f4e953ca9aafb6145440e1c17e86ed8e5f84 Mon Sep 17 00:00:00 2001 From: harman Date: Mon, 21 Oct 2019 23:20:44 +0530 Subject: [PATCH 141/455] Removed theia --- .theia/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .theia/settings.json diff --git a/.theia/settings.json b/.theia/settings.json deleted file mode 100644 index 651011e0..00000000 --- a/.theia/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.autoSave": "on" -} \ No newline at end of file From b3d52d753a851d8ffee4c557bb2918eb018463f9 Mon Sep 17 00:00:00 2001 From: Aaditya Chapagain Date: Tue, 22 Oct 2019 09:22:08 +0545 Subject: [PATCH 142/455] add program to assign unique caps to every person in limited pools of unique caps --- .../dynamic_programming/bit_masking1.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 algorithms/dynamic_programming/bit_masking1.py diff --git a/algorithms/dynamic_programming/bit_masking1.py b/algorithms/dynamic_programming/bit_masking1.py new file mode 100644 index 00000000..21c65630 --- /dev/null +++ b/algorithms/dynamic_programming/bit_masking1.py @@ -0,0 +1,98 @@ +""" +Consider the below problems statement. + +There are 100 different types of caps each having a unique id from 1 to 100. Also, +there are ‘n’ persons each having a collection of a variable number of caps. +One day all of these persons decide to go in a party wearing a cap but to look unique +they decided that none of them will wear the same type of cap. So, count the total number +of arrangements or ways such that none of them is wearing the same type of cap. + +""" + +#Python program to find number of ways to wear hats +from collections import defaultdict + +class AssignCap: + + # Initialize variables + def __init__(self): + + self.allmask = 0 + + self.total_caps = 100 + + self.caps = defaultdict(list) + + + # Mask is the set of persons, i is the current cap number. + def countWaysUtil(self,dp, mask, cap_no): + + # If all persons are wearing a cap so we + # are done and this is one way so return 1 + if mask == self.allmask: + return 1 + + # If not everyone is wearing a cap and also there are no more + # caps left to process, so there is no way, thus return 0; + if cap_no > self.total_caps: + return 0 + + # If we have already solved this subproblem, return the answer. + if dp[mask][cap_no]!= -1 : + return dp[mask][cap_no] + + # Ways, when we don't include this cap in our arrangement + # or solution set + ways = self.countWaysUtil(dp, mask, cap_no + 1) + + # assign ith cap one by one to all the possible persons + # and recur for remaining caps. + if cap_no in self.caps: + + for ppl in self.caps[cap_no]: + + # if person 'ppl' is already wearing a cap then continue + if mask & (1 << ppl) : continue + + # Else assign him this cap and recur for remaining caps with + # new updated mask vector + ways += self.countWaysUtil(dp, mask | (1 << ppl), cap_no + 1) + + ways = ways % (10**9 + 7) + + # Save the result and return it + dp[mask][cap_no] = ways + + return dp[mask][cap_no] + + + + def countWays(self,N): + + # Reads n lines from standard input for current test case + # create dictionary for cap. cap[i] = list of person having + # cap no i + for ppl in range(N): + + cap_possessed_by_person = map(int, input().strip().split()) + + for i in cap_possessed_by_person: + + self.caps[i].append(ppl) + + # allmask is used to check if all persons + # are included or not, set all n bits as 1 + self.allmask = (1 << N) -1 + + # Initialize all entries in dp as -1 + dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)] + + # Call recursive function countWaysUtil + # result will be in dp[0][1] + print (self.countWaysUtil(dp, 0, 1,)) + +#Driver Program +def main(): + No_of_people = int(input()) # number of persons in every test case + + AssignCap().countWays(No_of_people) From 8b0a455e4328f08c42210e748d0ff2c6d0cbe789 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 22 Oct 2019 10:05:45 +0530 Subject: [PATCH 143/455] Update tutorials.md --- bookmarks/tutorials.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookmarks/tutorials.md b/bookmarks/tutorials.md index 42c45d10..3f4c4bb1 100644 --- a/bookmarks/tutorials.md +++ b/bookmarks/tutorials.md @@ -10,4 +10,6 @@ This is a list of links to tutorials that may be helpful in learning or research - http://cp-algorithms.com/ -- https://realpython.com/python-data-classes/ \ No newline at end of file +- https://realpython.com/python-data-classes/ + +- https://chrisalbon.com From 97bb0e5bbc50e8a1a3a566efc32f1600b88f8a84 Mon Sep 17 00:00:00 2001 From: Aaditya Chapagain Date: Tue, 22 Oct 2019 10:34:25 +0545 Subject: [PATCH 144/455] add program to find k palindrome in a string --- .../dynamic_programming/k_palindrome1.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 algorithms/dynamic_programming/k_palindrome1.py diff --git a/algorithms/dynamic_programming/k_palindrome1.py b/algorithms/dynamic_programming/k_palindrome1.py new file mode 100644 index 00000000..4c78da79 --- /dev/null +++ b/algorithms/dynamic_programming/k_palindrome1.py @@ -0,0 +1,59 @@ +# code to find if given string +# is K-Palindrome or not + +""" +Explanation + +Process all characters one by one staring from either from left or right sides of both strings. +Let us traverse from the right corner, there are two possibilities for every pair of character being traversed. + +If last characters of two strings are same, we ignore last characters and get count for remaining strings. +So we recur for lengths m-1 and n-1 where m is length of str1 and n is length of str2. +If last characters are not same, we consider remove operation on last character of first string and +last character of second string, recursively compute minimum cost for the operations and take minimum of two values. +Remove last char from str1: Recur for m-1 and n. +Remove last char from str2: Recur for m and n-1. +""" + +# Find if given string +# is K-Palindrome or not +def isKPalRec(str1, str2, m, n): + + # If first string is empty, + # the only option is to remove + # all characters of second string + if not m: return n + + # If second string is empty, + # the only option is to remove + # all characters of first string + if not n: return m + + # If last characters of two strings + # are same, ignore last characters + # and get count for remaining strings. + if str1[m-1] == str2[n-1]: + return isKPalRec(str1, str2, m-1, n-1) + + # If last characters are not same, + # 1. Remove last char from str1 and recur for m-1 and n + # 2. Remove last char from str2 and recur for m and n-1 + # Take minimum of above two operations + res = 1 + min(isKPalRec(str1, str2, m-1, n), # Remove from str1 + (isKPalRec(str1, str2, m, n-1))) # Remove from str2 + + return res + +# Returns true if str is k palindrome. +def isKPal(string, k): + revStr = string[::-1] + l = len(string) + + return (isKPalRec(string, revStr, l, l) <= k * 2) + + +# Driver program +string = "acdcb" +k = 2 + +print("Yes" if isKPal(string, k) else "No") \ No newline at end of file From a8e614742a3775a203183ae384d299f7cdc5b821 Mon Sep 17 00:00:00 2001 From: Pooja Gupta Date: Tue, 22 Oct 2019 22:11:44 +0530 Subject: [PATCH 145/455] Created Pigeonhole Sorting --- algorithms/sorting/pigeonhole_sort | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 algorithms/sorting/pigeonhole_sort diff --git a/algorithms/sorting/pigeonhole_sort b/algorithms/sorting/pigeonhole_sort new file mode 100644 index 00000000..213ec03c --- /dev/null +++ b/algorithms/sorting/pigeonhole_sort @@ -0,0 +1,34 @@ +Pigeonhole sorting is a sorting algorithm that is suitable for sorting lists of elements where the number of elements and the number of possible key values are approximately the same. +It requires O(n + Range) time where n is number of elements in input array and ‘Range’ is number of possible values in array. + +def pigeonhole_sort(a): + # size of range of values in the list + # (ie, number of pigeonholes we need) + my_min = min(a) + my_max = max(a) + size = my_max - my_min + 1 + + # our list of pigeonholes + holes = [0] * size + + # Populate the pigeonholes. + for x in a: + assert type(x) is int, "integers only please" + holes[x - my_min] += 1 + + # Put the elements back into the array in order. + i = 0 + for count in range(size): + while holes[count] > 0: + holes[count] -= 1 + a[i] = count + my_min + i += 1 + + +a = [8, 3, 2, 7, 4, 6, 8] +print("Sorted order is : ", end = ' ') + +pigeonhole_sort(a) + +for i in range(0, len(a)): + print(a[i], end = ' ') From f9662c551c8aa974409603294b09a094ebf7a353 Mon Sep 17 00:00:00 2001 From: Pooja Gupta Date: Tue, 22 Oct 2019 22:20:42 +0530 Subject: [PATCH 146/455] Created Permutation Sort --- algorithms/sorting/permutation_sort | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 algorithms/sorting/permutation_sort diff --git a/algorithms/sorting/permutation_sort b/algorithms/sorting/permutation_sort new file mode 100644 index 00000000..f049bf85 --- /dev/null +++ b/algorithms/sorting/permutation_sort @@ -0,0 +1,29 @@ +import random + +# Sorts array a[0..n-1] using Bogo sort +def bogoSort(a): + n = len(a) + while (is_sorted(a)== False): + shuffle(a) + +# To check if array is sorted or not +def is_sorted(a): + n = len(a) + for i in range(0, n-1): + if (a[i] > a[i+1] ): + return False + return True + +# To generate permuatation of the array +def shuffle(a): + n = len(a) + for i in range (0,n): + r = random.randint(0,n-1) + a[i], a[r] = a[r], a[i] + +# Driver code to test above +a = [3, 2, 4, 1, 0, 5] +bogoSort(a) +print("Sorted array :") +for i in range(len(a)): + print ("%d" %a[i]), From ad7930b6fd7ce1d63e64473fa027b135f6c0cb09 Mon Sep 17 00:00:00 2001 From: Pooja Gupta Date: Thu, 24 Oct 2019 14:08:21 +0530 Subject: [PATCH 147/455] Code updated in pep8 --- algorithms/sorting/permutation_sort | 29 --------------------- algorithms/sorting/permutation_sort.py | 36 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 29 deletions(-) delete mode 100644 algorithms/sorting/permutation_sort create mode 100644 algorithms/sorting/permutation_sort.py diff --git a/algorithms/sorting/permutation_sort b/algorithms/sorting/permutation_sort deleted file mode 100644 index f049bf85..00000000 --- a/algorithms/sorting/permutation_sort +++ /dev/null @@ -1,29 +0,0 @@ -import random - -# Sorts array a[0..n-1] using Bogo sort -def bogoSort(a): - n = len(a) - while (is_sorted(a)== False): - shuffle(a) - -# To check if array is sorted or not -def is_sorted(a): - n = len(a) - for i in range(0, n-1): - if (a[i] > a[i+1] ): - return False - return True - -# To generate permuatation of the array -def shuffle(a): - n = len(a) - for i in range (0,n): - r = random.randint(0,n-1) - a[i], a[r] = a[r], a[i] - -# Driver code to test above -a = [3, 2, 4, 1, 0, 5] -bogoSort(a) -print("Sorted array :") -for i in range(len(a)): - print ("%d" %a[i]), diff --git a/algorithms/sorting/permutation_sort.py b/algorithms/sorting/permutation_sort.py new file mode 100644 index 00000000..4912ff9e --- /dev/null +++ b/algorithms/sorting/permutation_sort.py @@ -0,0 +1,36 @@ +import random + +# Sorts array a[0..n-1] using Bogo sort + + +def bogo_sort(a): + n = len(a) + while (is_sorted(a) == False): + shuffle(a) + +# To check if array is sorted or not + + +def is_sorted(a): + n = len(a) + for i in range(0, n - 1): + if (a[i] > a[i + 1]): + return False + return True + +# To generate permuatation of the array + + +def shuffle(a): + n = len(a) + for i in range(0, n): + r = random.randint(0, n - 1) + a[i], a[r] = a[r], a[i] + + +# Driver code to test above +a = [3, 2, 4, 1, 0, 5] +bogo_sort(a) +print("Sorted array :") +for i in range(len(a)): + print("%d" % a[i]), From ef8803faa8e191cef51e39a56c3ce31df8c6b9f0 Mon Sep 17 00:00:00 2001 From: Pooja Gupta Date: Thu, 24 Oct 2019 14:23:32 +0530 Subject: [PATCH 148/455] Updated in pep8 --- .../{pigeonhole_sort => pigeonhole_sort.py} | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) rename algorithms/sorting/{pigeonhole_sort => pigeonhole_sort.py} (61%) diff --git a/algorithms/sorting/pigeonhole_sort b/algorithms/sorting/pigeonhole_sort.py similarity index 61% rename from algorithms/sorting/pigeonhole_sort rename to algorithms/sorting/pigeonhole_sort.py index 213ec03c..5e2777b1 100644 --- a/algorithms/sorting/pigeonhole_sort +++ b/algorithms/sorting/pigeonhole_sort.py @@ -1,22 +1,26 @@ -Pigeonhole sorting is a sorting algorithm that is suitable for sorting lists of elements where the number of elements and the number of possible key values are approximately the same. -It requires O(n + Range) time where n is number of elements in input array and ‘Range’ is number of possible values in array. +#Pigeonhole sorting is a sorting algorithm that is suitable for sorting lists of elements where the number of elements and the number of possible key values are approximately the same. +#It requires O(n + Range) time where n is number of elements in input array and ‘Range’ is number of possible values in array. def pigeonhole_sort(a): - # size of range of values in the list - # (ie, number of pigeonholes we need) my_min = min(a) my_max = max(a) size = my_max - my_min + 1 # our list of pigeonholes + + holes = [0] * size # Populate the pigeonholes. + + for x in a: assert type(x) is int, "integers only please" holes[x - my_min] += 1 # Put the elements back into the array in order. + + i = 0 for count in range(size): while holes[count] > 0: @@ -27,8 +31,6 @@ def pigeonhole_sort(a): a = [8, 3, 2, 7, 4, 6, 8] print("Sorted order is : ", end = ' ') - pigeonhole_sort(a) - for i in range(0, len(a)): print(a[i], end = ' ') From 5071b68d046d3793b597cb857b1af0122a59f5df Mon Sep 17 00:00:00 2001 From: Ed Howard Date: Thu, 24 Oct 2019 14:13:53 -0400 Subject: [PATCH 149/455] Use two list merge routine from merge_list_of_linked_lists.py --- .../linked_list/merge_linked_list.py | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/data_structures/linked_list/merge_linked_list.py b/data_structures/linked_list/merge_linked_list.py index f525d0ab..572f18c4 100644 --- a/data_structures/linked_list/merge_linked_list.py +++ b/data_structures/linked_list/merge_linked_list.py @@ -6,13 +6,29 @@ def __init__(self, val): def merge(l1, l2): - res = curr = Node(0) - while l1 and l2: - if l1.val < l2.val: - curr.next = l1 - l1 = l1.next - else: - curr.next = l2 - l2 = l2.next - curr = curr.next - curr.next = + if not l1 and not l2: + return + elif not l2: + return l1 + elif not l1: + return l2 + + if (l1.val < l2.val): + l1.next = merge(l1.next, l2) + return l1 + l2.next = merge(l1, l2.next) + return l2 + +head1 = Node(1) +head1.next = Node(3) + +head2 = Node(2) +head2.next = Node(4) + +head_merged = merge(head1,head2) + +ptr = head_merged +while ptr: + print ptr.val + ptr = ptr.next + From fd78e37528c8cb12d2a212f970bdf2eae3a4c55f Mon Sep 17 00:00:00 2001 From: Aditya Agashe Date: Fri, 25 Oct 2019 09:58:06 +0530 Subject: [PATCH 150/455] print 1st recurrent character in str --- data_structures/array/recurrentChar.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 data_structures/array/recurrentChar.py diff --git a/data_structures/array/recurrentChar.py b/data_structures/array/recurrentChar.py new file mode 100644 index 00000000..6f0de011 --- /dev/null +++ b/data_structures/array/recurrentChar.py @@ -0,0 +1,17 @@ +#Find out and print First Recurrent character from given string + + +def recc_char(strng): + prev = set() + for char in strng: + if char in prev: + print (char) + return char + prev.add(char) + + return None + +recc_char("acbbac") + + + From b4b247f67df7020a0ca89a37783fe4e9417c519c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 25 Oct 2019 10:47:19 +0530 Subject: [PATCH 151/455] Create flatten_array.py --- data_structures/array/flatten_array.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 data_structures/array/flatten_array.py diff --git a/data_structures/array/flatten_array.py b/data_structures/array/flatten_array.py new file mode 100644 index 00000000..f6a53a2a --- /dev/null +++ b/data_structures/array/flatten_array.py @@ -0,0 +1,11 @@ +# Input - [1,2,3,4,[5,6,7,8],[9,10]] +# Output - [1,2,3,4,5,6,7,8,9,10] + +lst = [1,2,3,4,[5,6,7,8],[9,10]] + +flat = [] + +for sub in lst: + if isinstance(sub, list): + flat.extend(sub) + From 2bf183ecbf0dc9ecbbddccf8cde330a38ede180f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 25 Oct 2019 10:47:55 +0530 Subject: [PATCH 152/455] Update flatten_array.py --- data_structures/array/flatten_array.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/array/flatten_array.py b/data_structures/array/flatten_array.py index f6a53a2a..6be1af3b 100644 --- a/data_structures/array/flatten_array.py +++ b/data_structures/array/flatten_array.py @@ -8,4 +8,6 @@ for sub in lst: if isinstance(sub, list): flat.extend(sub) + else: + flat.append(sub) From 8c0b662bc378a0f56aa22bff2542504a6cba5c26 Mon Sep 17 00:00:00 2001 From: Ed Howard Date: Fri, 25 Oct 2019 18:50:50 -0400 Subject: [PATCH 153/455] removed unused self parameter --- algorithms/dynamic_programming/max_subarray.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/algorithms/dynamic_programming/max_subarray.py b/algorithms/dynamic_programming/max_subarray.py index 5a1caa43..422c29c9 100644 --- a/algorithms/dynamic_programming/max_subarray.py +++ b/algorithms/dynamic_programming/max_subarray.py @@ -8,8 +8,8 @@ """ -# Iterative Solution -def max_sub_array(self, arr): +# Iterative Solution - Kadane's algorithm +def max_sub_array(arr): if not arr: return 0 @@ -19,3 +19,8 @@ def max_sub_array(self, arr): max_sum = max(max_sum, cur_sum) return max_sum + + + +print max_sub_array([1,2,-100,3,4]) + From 411e2721993fdd5b00d9b27fe043a5ae69dbba3d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 26 Oct 2019 07:58:37 +0530 Subject: [PATCH 154/455] Add question explanation --- data_structures/array/dutch_flag_problem.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data_structures/array/dutch_flag_problem.py b/data_structures/array/dutch_flag_problem.py index f898486c..e2e9b596 100644 --- a/data_structures/array/dutch_flag_problem.py +++ b/data_structures/array/dutch_flag_problem.py @@ -1,3 +1,8 @@ +# Given an array containing only 0s, 1s and 2s in a random order, arrange the array such that all 0s come +# before 1s which in turn come before all 2s +# Input - [1,2,0,1,2,1,0,1,2,1,0] +# Output - [0,0,0,1,1,1,1,1,2,2,2] + def dutch(arr): low = 0 mid = 0 From 61a3033488cb5832ae162ed0f5180e46b5329e10 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 26 Oct 2019 08:58:39 +0530 Subject: [PATCH 155/455] Update and rename recurrentChar.py to first_repeating_char.py --- data_structures/array/first_repeating_char.py | 19 +++++++++++++++++++ data_structures/array/recurrentChar.py | 17 ----------------- 2 files changed, 19 insertions(+), 17 deletions(-) create mode 100644 data_structures/array/first_repeating_char.py delete mode 100644 data_structures/array/recurrentChar.py diff --git a/data_structures/array/first_repeating_char.py b/data_structures/array/first_repeating_char.py new file mode 100644 index 00000000..2ba272eb --- /dev/null +++ b/data_structures/array/first_repeating_char.py @@ -0,0 +1,19 @@ +# Find the first character in a string without using extra space +# With extra space its simple. Just check for the element in a hash map +# If present, then it is the recurrent char + +# Without extra space idea - +# The idea is to use an integer variable and uses bits in its binary representation to store whether a +# character is present or not. +# Typically an integer has at-least 32 bits and we need to store presence/absence of only 26 characters. + +def first_recurrence(s): + checker = 0 + pos = 0 + for i in s: + val = ord(i) - ord('a') + if (checker & (1 << val) > 0): + return i + checker = checker | (1 << val) + pos += 1 + return -1 diff --git a/data_structures/array/recurrentChar.py b/data_structures/array/recurrentChar.py deleted file mode 100644 index 6f0de011..00000000 --- a/data_structures/array/recurrentChar.py +++ /dev/null @@ -1,17 +0,0 @@ -#Find out and print First Recurrent character from given string - - -def recc_char(strng): - prev = set() - for char in strng: - if char in prev: - print (char) - return char - prev.add(char) - - return None - -recc_char("acbbac") - - - From 1dc6e36e4879bfb9807b1d626d8e7040fbb3c818 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 26 Oct 2019 09:00:13 +0530 Subject: [PATCH 156/455] Update duplicate.py --- data_structures/array/duplicate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data_structures/array/duplicate.py b/data_structures/array/duplicate.py index 43a598e6..ad4a3fa5 100644 --- a/data_structures/array/duplicate.py +++ b/data_structures/array/duplicate.py @@ -1,3 +1,6 @@ +# Find duplicate in an array of integers given that the integers are in random order and +# not necessarily each integer i is 0 <= i <= N where N = length of array + def duplicate(arr): tortoise = arr[0] hare = arr[0] From dd2827e79ba184ffa39e8bc25528acc56f5e448d Mon Sep 17 00:00:00 2001 From: Mehar Madnani <41502248+imehar@users.noreply.github.com> Date: Sun, 27 Oct 2019 01:10:00 +0530 Subject: [PATCH 157/455] Solved 'n' number of m-faced dice --- algorithms/dynamic_programming/dice.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 algorithms/dynamic_programming/dice.py diff --git a/algorithms/dynamic_programming/dice.py b/algorithms/dynamic_programming/dice.py new file mode 100644 index 00000000..501e2fa1 --- /dev/null +++ b/algorithms/dynamic_programming/dice.py @@ -0,0 +1,23 @@ +''' +Given n dices each with m faces, numbered from 1 to m, +find the number of ways to get a given sum X. +X is the summation of values on each face when all the dice are thrown. + +''' + +dp = [[-1 for i in range(x+1)] for j in range(n+1)] + +def NumOfWays(m, n, x): + if x == 0 and n == 0: + return 1 + if x < 0 or n == 0: + return 0 + if dp[n][x] != -1: + return dp[n][x] + + ans = 0 + for i in range(1, m + 1): + ans += NumOfWays(m, n - 1, x - i) + + dp[n][x] = ans + return ans From 29e0fb6f12dc261cc4435e9ff30c15c3c6e659de Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 11:38:51 +1100 Subject: [PATCH 158/455] Find odd number in array --- data_structures/array/find_odd_number.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 data_structures/array/find_odd_number.py diff --git a/data_structures/array/find_odd_number.py b/data_structures/array/find_odd_number.py new file mode 100644 index 00000000..ea97a2a4 --- /dev/null +++ b/data_structures/array/find_odd_number.py @@ -0,0 +1,12 @@ +def find_odd_number(nums): + """ Find one number in array which is not duplicated, + or exsits odd times. + """ + s = 0 + for n in nums: + s ^= n + return s + + +a = [0, 0, 1, 1, 2, 2, 6, 6, 9, 10, 10] +print(find_odd_number(a)) From 2f2373d2cad8724a50021c42e65965ee9fd966ba Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 12:11:29 +1100 Subject: [PATCH 159/455] Generate random matrix --- data_structures/array/random_matrix.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 data_structures/array/random_matrix.py diff --git a/data_structures/array/random_matrix.py b/data_structures/array/random_matrix.py new file mode 100644 index 00000000..1d2aef59 --- /dev/null +++ b/data_structures/array/random_matrix.py @@ -0,0 +1,24 @@ +def random_matrix(n): + """ Generate random n x n matix without repreated entries in rows or columns. + The entries are integers between 1 and n. + """ + from random import shuffle + + a = list(range(n + 1)) + shuffle(a) + + # Use slicing to left rotate + m = [a[i:] + a[:i] for i in range(n + 1)] + + # Shuffle rows in matrix + shuffle(m) + + # Shuffle cols in matrix (optional) + m = list(map(list, zip(*m))) # Transpose the matrix + shuffle(m) + + return m + + +m = random_matrix(9) +print('\n'.join(map(str, m))) From 405a0eba2f2ac3f598388afb0446d3621afa1f36 Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 12:12:49 +1100 Subject: [PATCH 160/455] Fix typo in desc --- data_structures/array/random_matrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/random_matrix.py b/data_structures/array/random_matrix.py index 1d2aef59..33017c51 100644 --- a/data_structures/array/random_matrix.py +++ b/data_structures/array/random_matrix.py @@ -1,5 +1,5 @@ def random_matrix(n): - """ Generate random n x n matix without repreated entries in rows or columns. + """ Generate random n x n matrix without repeated entries in rows or columns. The entries are integers between 1 and n. """ from random import shuffle From 19ffc10a6185f03f7f2689270a0c7fd49b7a9e26 Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Sun, 27 Oct 2019 08:47:04 +0530 Subject: [PATCH 161/455] Update sumofdigits.py fixed pep8 issues and wrapped code in a function --- algorithms/math/sumofdigits.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/algorithms/math/sumofdigits.py b/algorithms/math/sumofdigits.py index 62ba2177..8dd9040c 100644 --- a/algorithms/math/sumofdigits.py +++ b/algorithms/math/sumofdigits.py @@ -1,8 +1,11 @@ -#This is to find the sum of digits of a number untill it is a single digit -n=int(input()) #here n is the number -if n%9!=0: - print(n%9) -else: - print("9") -#this method reduces time complexity by a factor of n and also without using any loop +# This is to find the sum of digits of a number until it is a single digit + +def sum_of_digits(n): + n = int(input()) # here n is the number + if n % 9 != 0: + print(n % 9) + else: + print("9") + +# This method reduces time complexity by a factor of n and also without using any loop From fc5548595ce344c53209af908b3350862b587e09 Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 14:51:15 +1100 Subject: [PATCH 162/455] Is rotate string --- data_structures/strings/rotate_string.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 data_structures/strings/rotate_string.py diff --git a/data_structures/strings/rotate_string.py b/data_structures/strings/rotate_string.py new file mode 100644 index 00000000..c4493d40 --- /dev/null +++ b/data_structures/strings/rotate_string.py @@ -0,0 +1,21 @@ +def is_rotate_string(A, B): + """ + Given two strings, A and B. + + A shift on A consists of taking string A and moving the leftmost character to the rightmost position. For example, if A = 'abcde', then it will be 'bcdea' after one shift on A. Return True if and only if A can become B after some number of shifts on A. + + :type A: str + :type B: str + :rtype: bool + """ + len_a = len(A) + len_b = len(B) + if len_a != len_b: + return False + if len_a == 0: + return True + for i in range(len_a): + A = A[-1:] + A[:-1] + if A == B: + return True + return False From 1838fee189227207a91719793a57f234ff2ffb6f Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 14:51:27 +1100 Subject: [PATCH 163/455] Add entry for rotate_string.py --- data_structures/strings/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data_structures/strings/index.md b/data_structures/strings/index.md index 3f7bf484..df56b743 100644 --- a/data_structures/strings/index.md +++ b/data_structures/strings/index.md @@ -3,4 +3,5 @@ * [Check Permutations](check_permutations.py) * [Are Anagrams](are_anagrams.py) * [Adjacent Vowel Pairs](adjacent_vowel_pairs.py) -* [Toggle String](toggle_string.py) \ No newline at end of file +* [Toggle String](toggle_string.py) +* [Is Rotate String](rotate_string.py) From 5484dc7742c7c6aa5d7da4e37676008ef933284f Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 14:53:18 +1100 Subject: [PATCH 164/455] Add tests for rotate string --- data_structures/strings/rotate_string.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data_structures/strings/rotate_string.py b/data_structures/strings/rotate_string.py index c4493d40..48edb9d9 100644 --- a/data_structures/strings/rotate_string.py +++ b/data_structures/strings/rotate_string.py @@ -19,3 +19,8 @@ def is_rotate_string(A, B): if A == B: return True return False + + +# Test +print(is_rotate_string('abcde', 'cdeab')) +print(is_rotate_string('abcde', 'abced')) From 523dec5b50eb238031fd71d4bbce7de359381f61 Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 15:14:43 +1100 Subject: [PATCH 165/455] Check if it is perfect square number --- algorithms/math/perfect_square.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 algorithms/math/perfect_square.py diff --git a/algorithms/math/perfect_square.py b/algorithms/math/perfect_square.py new file mode 100644 index 00000000..40e817bb --- /dev/null +++ b/algorithms/math/perfect_square.py @@ -0,0 +1,21 @@ +def is_perfect_square(num): + """ + Given a positive integer num, write a function which returns True if num is a perfect square else False. + + Note: Do not use any built-in library function such as `sqrt`. + + :type num: int + :rtype: bool + """ + i = 0 + while i * i < num: + i += 1 + if i * i == num: + return True + else: + return False + + +# Test +print(is_perfect_square(16)) +print(is_perfect_square(14)) From 330659ddd40fc2e8c9604fa1d205ab0109d326bf Mon Sep 17 00:00:00 2001 From: northtree Date: Sun, 27 Oct 2019 15:15:00 +1100 Subject: [PATCH 166/455] Add entry for perfect_square.py --- algorithms/math/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms/math/index.md b/algorithms/math/index.md index a02f7ae0..e84f7095 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -4,4 +4,5 @@ * [Fibonacci Number](fibonacci_number.py) * [Nth Prime Number](prime.py) * [Sieve of Erastothenes](sieve_of_eratosthenes.py) +* [Perfect Square](perfect_square.py) From 5cec2152fb0fed0d583c878bfe18c530907322da Mon Sep 17 00:00:00 2001 From: Mehar Madnani <41502248+imehar@users.noreply.github.com> Date: Sun, 27 Oct 2019 18:58:28 +0530 Subject: [PATCH 167/455] Changed to follow pep8 --- algorithms/dynamic_programming/dice.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/algorithms/dynamic_programming/dice.py b/algorithms/dynamic_programming/dice.py index 501e2fa1..00129fd3 100644 --- a/algorithms/dynamic_programming/dice.py +++ b/algorithms/dynamic_programming/dice.py @@ -7,17 +7,18 @@ dp = [[-1 for i in range(x+1)] for j in range(n+1)] + def NumOfWays(m, n, x): - if x == 0 and n == 0: - return 1 - if x < 0 or n == 0: - return 0 - if dp[n][x] != -1: - return dp[n][x] + if x == 0 and n == 0: + return 1 + if x < 0 or n == 0: + return 0 + if dp[n][x] != -1: + return dp[n][x] - ans = 0 - for i in range(1, m + 1): - ans += NumOfWays(m, n - 1, x - i) + ans = 0 + for i in range(1, m + 1): + ans += NumOfWays(m, n - 1, x - i) - dp[n][x] = ans - return ans + dp[n][x] = ans + return ans From 6fa80554fa987a09cc6993bc14afa3a3cfb58136 Mon Sep 17 00:00:00 2001 From: quizzicaltrains <56100477+quizzicaltrains@users.noreply.github.com> Date: Sun, 27 Oct 2019 15:36:06 -0700 Subject: [PATCH 168/455] Create topological_sort.py Implementation of topological sort --- algorithms/graph/topological_sort.py | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 algorithms/graph/topological_sort.py diff --git a/algorithms/graph/topological_sort.py b/algorithms/graph/topological_sort.py new file mode 100644 index 00000000..ea214d0d --- /dev/null +++ b/algorithms/graph/topological_sort.py @@ -0,0 +1,33 @@ +from collections import defaultdict + + +def topological_sort(graph: dict) -> list: + """Provides the topologically sorted nodes of a graph in a list. Takes input as a dictionary, + where the key is a node and the value is a list of the nodes that the key is a source node for.""" + + # Keeps track of the "degree" of a node; once this reaches 0, we push it onto the output. + leading_in = defaultdict(lambda: 0) + + for key, values in graph.items(): + if key not in leading_in.keys(): + leading_in[key] = 0 + for node in values: + leading_in[node] += 1 + + queue = [] + output = [] + + for node, degree in leading_in.items(): + if degree == 0: + queue.append(node) + output.append(node) + + while queue: + node = queue.pop(0) + for destination in graph.get(node, []): + leading_in[destination] -= 1 + if leading_in[destination] == 0: + queue.append(destination) + output.append(destination) + + return output From 82a04b689efcf6202b8c32a3f93320ec7a4859c8 Mon Sep 17 00:00:00 2001 From: Mehar Madnani <41502248+imehar@users.noreply.github.com> Date: Mon, 28 Oct 2019 14:56:16 +0530 Subject: [PATCH 169/455] Changed to snake_case --- algorithms/dynamic_programming/dice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algorithms/dynamic_programming/dice.py b/algorithms/dynamic_programming/dice.py index 00129fd3..4c4ec68f 100644 --- a/algorithms/dynamic_programming/dice.py +++ b/algorithms/dynamic_programming/dice.py @@ -8,7 +8,7 @@ dp = [[-1 for i in range(x+1)] for j in range(n+1)] -def NumOfWays(m, n, x): +def num_of_ways(m, n, x): if x == 0 and n == 0: return 1 if x < 0 or n == 0: @@ -18,7 +18,7 @@ def NumOfWays(m, n, x): ans = 0 for i in range(1, m + 1): - ans += NumOfWays(m, n - 1, x - i) + ans += num_of_ways(m, n - 1, x - i) dp[n][x] = ans return ans From 0487d8e17ba12df027b402567fd1344539211a27 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 29 Oct 2019 07:33:49 +0200 Subject: [PATCH 170/455] Fixed problematic fibonacci series --- algorithms/math/fibonacci_number.py | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/algorithms/math/fibonacci_number.py b/algorithms/math/fibonacci_number.py index ad58a349..a355f32f 100644 --- a/algorithms/math/fibonacci_number.py +++ b/algorithms/math/fibonacci_number.py @@ -1,26 +1,15 @@ # Program that prints out the fibonacci sequence until a given number -def calc_fib(num): - while len(fib) <= num: - n = len(fib) - fib.append((fib[n-1] + fib[n-2])) - + def main(): - print("Enter the Position of the Number in the Sequence or \'0\' to Quit: ") - num = 0 - fib = list() - fib.append(0) - fib.append(1) + n = int(input("insert number")) + fib = [1, 1] + for i in range(2,n,1): + print(i) + fib.append(fib[i-1]+fib[i-2]) - while True: - num = int(input()) - if(num <= 0): - break + print(fib) - if len(fib) <= num: - calc_fib(num) - print('Fibonacci Number at Position ' + str(num) + ' is: ' + str(fib[num])) - if __name__ == '__main__': main() From fc0946cabc4ecf4bf2bd0ef7f45054d87086bbfd Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Tue, 29 Oct 2019 15:37:00 +0530 Subject: [PATCH 171/455] fixed pep8 issues --- algorithms/sorting/select_sort.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/algorithms/sorting/select_sort.py b/algorithms/sorting/select_sort.py index 51322430..8ba2cad7 100644 --- a/algorithms/sorting/select_sort.py +++ b/algorithms/sorting/select_sort.py @@ -1,5 +1,5 @@ -def findSmallest(arr): +def find_smallest(arr): smallest = arr[0] smallest_index = 0 @@ -12,15 +12,15 @@ def findSmallest(arr): -def selectionSort(arr): - newArr = [] +def selection_sort(arr): + new_arr = [] for i in range(len(arr)): - smallest = findSmallest(arr) - newArr.append(arr.pop(smallest)) + smallest = find_smallest(arr) + new_arr.append(arr.pop(smallest)) - return newArr + return new_arr array = [100, 5, 72, 41, 80, 1, 99, 36, 27, 78] -print(selectionSort(array)) # [1, 5, 27, 36, 41, 72, 78, 80, 99, 100] \ No newline at end of file +print(selection_sort(array)) # [1, 5, 27, 36, 41, 72, 78, 80, 99, 100] From 103a592e7f42d66238a6b48d688dee8ddd36ae06 Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Tue, 29 Oct 2019 11:36:44 +0000 Subject: [PATCH 172/455] fix: pep8 issues --- .theia/settings.json | 3 ++ algorithms/sorting/bubble_sort.py | 2 +- algorithms/sorting/merge_sort.py | 52 +++++++++++++++---------------- 3 files changed, 30 insertions(+), 27 deletions(-) create mode 100644 .theia/settings.json diff --git a/.theia/settings.json b/.theia/settings.json new file mode 100644 index 00000000..651011e0 --- /dev/null +++ b/.theia/settings.json @@ -0,0 +1,3 @@ +{ + "editor.autoSave": "on" +} \ No newline at end of file diff --git a/algorithms/sorting/bubble_sort.py b/algorithms/sorting/bubble_sort.py index 781b1f5a..85668cac 100644 --- a/algorithms/sorting/bubble_sort.py +++ b/algorithms/sorting/bubble_sort.py @@ -3,7 +3,7 @@ Best time scenario is when array is already sorted - O(n) ''' -def bubbleSort(array): +def bubble_sort(array): n = len(array) for i in range(n): diff --git a/algorithms/sorting/merge_sort.py b/algorithms/sorting/merge_sort.py index f9eb554c..8dbf1d37 100644 --- a/algorithms/sorting/merge_sort.py +++ b/algorithms/sorting/merge_sort.py @@ -1,49 +1,49 @@ """ High level explanation: -mergeSort is a Divide and conquer algorithm that splits in halves the array and +merge_sort is a Divide and conquer algorithm that splits in halves the array and then builds it back up by merging and sorting at the same time its elements. Time complexity: -mergeSort has a time complexity of O(n log n). +merge_sort has a time complexity of O(n log n). """ -def mergeSort(arr): - if len(arr) >1: - mid = len(arr)//2 #Finding the mid of the array - L = arr[:mid] # Dividing the array elements - R = arr[mid:] # into 2 halves - - mergeSort(L) # Sorting the first half - mergeSort(R) # Sorting the second half - +def merge_sort(arr): + if len(arr) >1: + mid = len(arr)//2 #Finding the mid of the array + L = arr[:mid] # Dividing the array elements + R = arr[mid:] # into 2 halves + + merge_sort(L) # Sorting the first half + merge_sort(R) # Sorting the second half + i = j = k = 0 - - # Copy data to temp arrays L[] and R[] - while i < len(L) and j < len(R): - if L[i] < R[j]: - arr[k] = L[i] + + # Copy data to temp arrays L[] and R[] + while i < len(L) and j < len(R): + if L[i] < R[j]: + arr[k] = L[i] i+=1 - else: - arr[k] = R[j] + else: + arr[k] = R[j] j+=1 k+=1 - - # Checking if any element was left - while i < len(L): - arr[k] = L[i] + + # Checking if any element was left + while i < len(L): + arr[k] = L[i] i+=1 k+=1 - - while j < len(R): - arr[k] = R[j] + + while j < len(R): + arr[k] = R[j] j+=1 k+=1 test_array = [10,30,20,100,40,80,90,210,34] -mergeSort(test_array) +merge_sort(test_array) print(test_array) From 65e88cdacc1f1e10a1938c732d4ec741235251ed Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Tue, 29 Oct 2019 17:56:20 +0530 Subject: [PATCH 173/455] delete .theia/settings.json --- .theia/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .theia/settings.json diff --git a/.theia/settings.json b/.theia/settings.json deleted file mode 100644 index 651011e0..00000000 --- a/.theia/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.autoSave": "on" -} \ No newline at end of file From 3b52c094cfdf96a548e4e46cd579511877e25b7c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 30 Oct 2019 16:30:22 +0530 Subject: [PATCH 174/455] Update articles.md --- bookmarks/articles.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/articles.md b/bookmarks/articles.md index 16fc7323..8553d9c4 100644 --- a/bookmarks/articles.md +++ b/bookmarks/articles.md @@ -51,3 +51,5 @@ This is a list of articles that may be useful for algorithms and data structures - https://martinfowler.com/articles/serverless.html - https://samnewman.io/patterns/architectural/bff/ + +- https://www.ultravioletsoftware.com/single-post/2017/03/23/An-introduction-into-the-WSGI-ecosystem From 84641d9615890739156ec4e3378d49f5755daf45 Mon Sep 17 00:00:00 2001 From: Tyrone Damasceno Date: Wed, 30 Oct 2019 08:44:40 -0300 Subject: [PATCH 175/455] Add missing files and lexicographically sorting --- algorithms/dynamic_programming/index.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/algorithms/dynamic_programming/index.md b/algorithms/dynamic_programming/index.md index 7bfbcd4c..d411b44b 100644 --- a/algorithms/dynamic_programming/index.md +++ b/algorithms/dynamic_programming/index.md @@ -1,8 +1,11 @@ # Index of dynamic_programming +* [Climbing Stairs](climbing_stairs.py) +* [Coin Change](Coin_Change.py) +* [Dice](dice.py) +* [Edit Distance](edit_distance.py) * [Longest Common Subsequence](longest_common_subsequence.py) -* [Rod Cutting](rod_cutting.py) +* [Longest Palindromic Subsequence](longest_palindromic_subsequence.py) * [Max Subarray](max_subarray.py) +* [Rod Cutting](rod_cutting.py) * [Unique Grid Paths](unique_grid_paths.py) -* [Edit Distance](edit_distance.py) - From 77539cceedfd0199b895a54b5fc82c4366432a5b Mon Sep 17 00:00:00 2001 From: Tyrone Damasceno Date: Wed, 30 Oct 2019 08:47:12 -0300 Subject: [PATCH 176/455] Rename file with snake_case --- .../dynamic_programming/{Coin_Change.py => coin_change.py} | 0 algorithms/dynamic_programming/index.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename algorithms/dynamic_programming/{Coin_Change.py => coin_change.py} (100%) diff --git a/algorithms/dynamic_programming/Coin_Change.py b/algorithms/dynamic_programming/coin_change.py similarity index 100% rename from algorithms/dynamic_programming/Coin_Change.py rename to algorithms/dynamic_programming/coin_change.py diff --git a/algorithms/dynamic_programming/index.md b/algorithms/dynamic_programming/index.md index d411b44b..0a50f2c6 100644 --- a/algorithms/dynamic_programming/index.md +++ b/algorithms/dynamic_programming/index.md @@ -1,7 +1,7 @@ # Index of dynamic_programming * [Climbing Stairs](climbing_stairs.py) -* [Coin Change](Coin_Change.py) +* [Coin Change](coin_change.py) * [Dice](dice.py) * [Edit Distance](edit_distance.py) * [Longest Common Subsequence](longest_common_subsequence.py) From 18cb65bbb028139d26842d69b0f248784daea2b5 Mon Sep 17 00:00:00 2001 From: harman Date: Wed, 30 Oct 2019 20:44:03 +0530 Subject: [PATCH 177/455] Added daysofweek.py --- data_structures/array/daysofweek.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 data_structures/array/daysofweek.py diff --git a/data_structures/array/daysofweek.py b/data_structures/array/daysofweek.py new file mode 100644 index 00000000..2b279f23 --- /dev/null +++ b/data_structures/array/daysofweek.py @@ -0,0 +1,18 @@ +''' +Given a date, return the corresponding day of the week for that date. +The input is given as three integers representing the day, month and year respectively. +Return the answer as one of the following values {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}. +The given dates are valid dates between the years 1971 and 2100. + +Example 1: +Input: day = 31, month = 8, year = 2019 +Output: "Saturday" +''' + # :type day: int , :type month: int , :type year: int , :rtype: str + +class Solution(object): + def dayOfTheWeek(self, day, month, year): + day_of_week_map = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] + t = [ 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 ] + year -= month < 3 + return day_of_week_map[((year + int(year / 4) - int(year / 100) + int(year / 400) + t[month - 1] + day) % 7)] \ No newline at end of file From 4f60f87caec16c7dda1da35cd33aa286167dea71 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 5 Nov 2019 12:08:30 +0530 Subject: [PATCH 178/455] Update misc.md --- bookmarks/misc.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/misc.md b/bookmarks/misc.md index de317d49..4bb89d2f 100644 --- a/bookmarks/misc.md +++ b/bookmarks/misc.md @@ -13,3 +13,5 @@ This is a list of misc links that may be useful when learning or researching dat - https://wsvincent.com/ - https://machinelearningmastery.com + +- https://stackoverflow.com/questions/10631326/difference-between-select-into-and-insert-into-from-old-table From 0e726f4822512a55fe58986da5fe1a7e0b238e2a Mon Sep 17 00:00:00 2001 From: aaditya Date: Tue, 5 Nov 2019 22:20:46 +0545 Subject: [PATCH 179/455] update - follow the pep8 coding style --- .../dynamic_programming/bit_masking1.py | 171 +++++++++--------- .../dynamic_programming/k_palindrome1.py | 92 +++++----- 2 files changed, 135 insertions(+), 128 deletions(-) diff --git a/algorithms/dynamic_programming/bit_masking1.py b/algorithms/dynamic_programming/bit_masking1.py index 21c65630..e33c47f1 100644 --- a/algorithms/dynamic_programming/bit_masking1.py +++ b/algorithms/dynamic_programming/bit_masking1.py @@ -9,90 +9,91 @@ """ -#Python program to find number of ways to wear hats -from collections import defaultdict - -class AssignCap: - - # Initialize variables - def __init__(self): - - self.allmask = 0 - - self.total_caps = 100 - - self.caps = defaultdict(list) - - - # Mask is the set of persons, i is the current cap number. - def countWaysUtil(self,dp, mask, cap_no): - - # If all persons are wearing a cap so we - # are done and this is one way so return 1 - if mask == self.allmask: +# Python program to find number of ways to wear hats +from collections import defaultdict + + +class AssignCap: + + # Initialize variables + def __init__(self): + + self.allmask = 0 + + self.total_caps = 100 + + self.caps = defaultdict(list) + + # Mask is the set of persons, i is the current cap number. + def countWaysUtil(self, dp, mask, cap_no): + + # If all persons are wearing a cap so we + # are done and this is one way so return 1 + if mask == self.allmask: return 1 - - # If not everyone is wearing a cap and also there are no more - # caps left to process, so there is no way, thus return 0; - if cap_no > self.total_caps: + + # If not everyone is wearing a cap and also there are no more + # caps left to process, so there is no way, thus return 0; + if cap_no > self.total_caps: return 0 - - # If we have already solved this subproblem, return the answer. - if dp[mask][cap_no]!= -1 : - return dp[mask][cap_no] - - # Ways, when we don't include this cap in our arrangement - # or solution set - ways = self.countWaysUtil(dp, mask, cap_no + 1) - - # assign ith cap one by one to all the possible persons - # and recur for remaining caps. - if cap_no in self.caps: - - for ppl in self.caps[cap_no]: - - # if person 'ppl' is already wearing a cap then continue - if mask & (1 << ppl) : continue - - # Else assign him this cap and recur for remaining caps with - # new updated mask vector - ways += self.countWaysUtil(dp, mask | (1 << ppl), cap_no + 1) - - ways = ways % (10**9 + 7) - - # Save the result and return it - dp[mask][cap_no] = ways - - return dp[mask][cap_no] - - - - def countWays(self,N): - - # Reads n lines from standard input for current test case - # create dictionary for cap. cap[i] = list of person having - # cap no i - for ppl in range(N): - - cap_possessed_by_person = map(int, input().strip().split()) - - for i in cap_possessed_by_person: - - self.caps[i].append(ppl) - - # allmask is used to check if all persons - # are included or not, set all n bits as 1 - self.allmask = (1 << N) -1 - - # Initialize all entries in dp as -1 - dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)] - - # Call recursive function countWaysUtil - # result will be in dp[0][1] - print (self.countWaysUtil(dp, 0, 1,)) - -#Driver Program -def main(): - No_of_people = int(input()) # number of persons in every test case - - AssignCap().countWays(No_of_people) + + # If we have already solved this subproblem, return the answer. + if dp[mask][cap_no] != -1: + return dp[mask][cap_no] + + # Ways, when we don't include this cap in our arrangement + # or solution set + ways = self.countWaysUtil(dp, mask, cap_no + 1) + + # assign ith cap one by one to all the possible persons + # and recur for remaining caps. + if cap_no in self.caps: + + for ppl in self.caps[cap_no]: + + # if person 'ppl' is already wearing a cap then continue + if mask & (1 << ppl): + continue + + # Else assign him this cap and recur for remaining caps with + # new updated mask vector + ways += self.countWaysUtil(dp, mask | (1 << ppl), cap_no + 1) + + ways = ways % (10**9 + 7) + + # Save the result and return it + dp[mask][cap_no] = ways + + return dp[mask][cap_no] + + def countWays(self, N): + + # Reads n lines from standard input for current test case + # create dictionary for cap. cap[i] = list of person having + # cap no i + for ppl in range(N): + + cap_possessed_by_person = map(int, input().strip().split()) + + for i in cap_possessed_by_person: + + self.caps[i].append(ppl) + + # allmask is used to check if all persons + # are included or not, set all n bits as 1 + self.allmask = (1 << N) - 1 + + # Initialize all entries in dp as -1 + dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)] + + # Call recursive function countWaysUtil + # result will be in dp[0][1] + print(self.countWaysUtil(dp, 0, 1,)) + +# Driver Program + + +def main(): + No_of_people = int(input()) # number of persons in every test case + + AssignCap().countWays(No_of_people) diff --git a/algorithms/dynamic_programming/k_palindrome1.py b/algorithms/dynamic_programming/k_palindrome1.py index 4c78da79..2903f9e8 100644 --- a/algorithms/dynamic_programming/k_palindrome1.py +++ b/algorithms/dynamic_programming/k_palindrome1.py @@ -1,10 +1,10 @@ -# code to find if given string +# code to find if given string # is K-Palindrome or not """ Explanation -Process all characters one by one staring from either from left or right sides of both strings. +Process all characters one by one staring from either from left or right sides of both strings. Let us traverse from the right corner, there are two possibilities for every pair of character being traversed. If last characters of two strings are same, we ignore last characters and get count for remaining strings. @@ -14,46 +14,52 @@ Remove last char from str1: Recur for m-1 and n. Remove last char from str2: Recur for m and n-1. """ - -# Find if given string -# is K-Palindrome or not -def isKPalRec(str1, str2, m, n): - - # If first string is empty, - # the only option is to remove - # all characters of second string - if not m: return n - - # If second string is empty, - # the only option is to remove - # all characters of first string - if not n: return m - - # If last characters of two strings - # are same, ignore last characters - # and get count for remaining strings. - if str1[m-1] == str2[n-1]: - return isKPalRec(str1, str2, m-1, n-1) - - # If last characters are not same, - # 1. Remove last char from str1 and recur for m-1 and n - # 2. Remove last char from str2 and recur for m and n-1 - # Take minimum of above two operations - res = 1 + min(isKPalRec(str1, str2, m-1, n), # Remove from str1 - (isKPalRec(str1, str2, m, n-1))) # Remove from str2 - - return res - -# Returns true if str is k palindrome. -def isKPal(string, k): - revStr = string[::-1] - l = len(string) - - return (isKPalRec(string, revStr, l, l) <= k * 2) - - -# Driver program + +# Find if given string +# is K-Palindrome or not + + +def isKPalRec(str1, str2, m, n): + + # If first string is empty, + # the only option is to remove + # all characters of second string + if not m: + return n + + # If second string is empty, + # the only option is to remove + # all characters of first string + if not n: + return m + + # If last characters of two strings + # are same, ignore last characters + # and get count for remaining strings. + if str1[m - 1] == str2[n - 1]: + return isKPalRec(str1, str2, m - 1, n - 1) + + # If last characters are not same, + # 1. Remove last char from str1 and recur for m-1 and n + # 2. Remove last char from str2 and recur for m and n-1 + # Take minimum of above two operations + res = 1 + min(isKPalRec(str1, str2, m - 1, n), # Remove from str1 + (isKPalRec(str1, str2, m, n - 1))) # Remove from str2 + + return res + +# Returns true if str is k palindrome. + + +def isKPal(string, k): + revStr = string[::-1] + l = len(string) + + return (isKPalRec(string, revStr, l, l) <= k * 2) + + +# Driver program string = "acdcb" k = 2 - -print("Yes" if isKPal(string, k) else "No") \ No newline at end of file + +print("Yes" if isKPal(string, k) else "No") From b05adc1c5cd5c78cc836e647f1137946d6443f5a Mon Sep 17 00:00:00 2001 From: Sameer Khan Date: Sun, 10 Nov 2019 13:26:58 +0530 Subject: [PATCH 180/455] Updated index.md to remove typo Removed an extra square bracket. --- data_structures/bst/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/bst/index.md b/data_structures/bst/index.md index 7e286a69..97a6320f 100644 --- a/data_structures/bst/index.md +++ b/data_structures/bst/index.md @@ -1,6 +1,6 @@ # Index of BST -* [[Deletion](deletion.py) +* [Deletion](deletion.py) * [Sorted Array To BST](sorted_array_to_bst.py) * [Print Left Node](print_left_node.py) * [Diameter](diameter.py) From d7b52a01af17e0a592b54bb906c210bc3acad53b Mon Sep 17 00:00:00 2001 From: aaditya Date: Wed, 13 Nov 2019 13:50:34 +0545 Subject: [PATCH 181/455] convert camelCase fucntion defination into function defination seperated by underscore --- algorithms/dynamic_programming/bit_masking1.py | 12 ++++++------ algorithms/dynamic_programming/k_palindrome1.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/algorithms/dynamic_programming/bit_masking1.py b/algorithms/dynamic_programming/bit_masking1.py index e33c47f1..b5e3de9b 100644 --- a/algorithms/dynamic_programming/bit_masking1.py +++ b/algorithms/dynamic_programming/bit_masking1.py @@ -25,7 +25,7 @@ def __init__(self): self.caps = defaultdict(list) # Mask is the set of persons, i is the current cap number. - def countWaysUtil(self, dp, mask, cap_no): + def count_ways_util(self, dp, mask, cap_no): # If all persons are wearing a cap so we # are done and this is one way so return 1 @@ -43,7 +43,7 @@ def countWaysUtil(self, dp, mask, cap_no): # Ways, when we don't include this cap in our arrangement # or solution set - ways = self.countWaysUtil(dp, mask, cap_no + 1) + ways = self.count_ways_util(dp, mask, cap_no + 1) # assign ith cap one by one to all the possible persons # and recur for remaining caps. @@ -57,7 +57,7 @@ def countWaysUtil(self, dp, mask, cap_no): # Else assign him this cap and recur for remaining caps with # new updated mask vector - ways += self.countWaysUtil(dp, mask | (1 << ppl), cap_no + 1) + ways += self.count_ways_util(dp, mask | (1 << ppl), cap_no + 1) ways = ways % (10**9 + 7) @@ -66,7 +66,7 @@ def countWaysUtil(self, dp, mask, cap_no): return dp[mask][cap_no] - def countWays(self, N): + def count_ways(self, N): # Reads n lines from standard input for current test case # create dictionary for cap. cap[i] = list of person having @@ -88,7 +88,7 @@ def countWays(self, N): # Call recursive function countWaysUtil # result will be in dp[0][1] - print(self.countWaysUtil(dp, 0, 1,)) + print(self.count_ways_util(dp, 0, 1,)) # Driver Program @@ -96,4 +96,4 @@ def countWays(self, N): def main(): No_of_people = int(input()) # number of persons in every test case - AssignCap().countWays(No_of_people) + AssignCap().count_ways(No_of_people) diff --git a/algorithms/dynamic_programming/k_palindrome1.py b/algorithms/dynamic_programming/k_palindrome1.py index 2903f9e8..8c69e5af 100644 --- a/algorithms/dynamic_programming/k_palindrome1.py +++ b/algorithms/dynamic_programming/k_palindrome1.py @@ -19,7 +19,7 @@ # is K-Palindrome or not -def isKPalRec(str1, str2, m, n): +def is_kpalrec(str1, str2, m, n): # If first string is empty, # the only option is to remove @@ -43,23 +43,23 @@ def isKPalRec(str1, str2, m, n): # 1. Remove last char from str1 and recur for m-1 and n # 2. Remove last char from str2 and recur for m and n-1 # Take minimum of above two operations - res = 1 + min(isKPalRec(str1, str2, m - 1, n), # Remove from str1 - (isKPalRec(str1, str2, m, n - 1))) # Remove from str2 + res = 1 + min(is_kpalrec(str1, str2, m - 1, n), # Remove from str1 + (is_kpalrec(str1, str2, m, n - 1))) # Remove from str2 return res # Returns true if str is k palindrome. -def isKPal(string, k): +def is_kPal(string, k): revStr = string[::-1] l = len(string) - return (isKPalRec(string, revStr, l, l) <= k * 2) + return (is_kpalrec(string, revStr, l, l) <= k * 2) # Driver program string = "acdcb" k = 2 -print("Yes" if isKPal(string, k) else "No") +print("Yes" if is_kPal(string, k) else "No") From 4ae222ff38eb3ec113b54b90db0f5ea84b539dcf Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 19 Nov 2019 10:09:08 +0530 Subject: [PATCH 182/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b18100c..060e92c7 100644 --- a/README.md +++ b/README.md @@ -71,4 +71,4 @@ To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) ## :page_facing_up: License -MIT @ Prabhu Pant +[MIT @ Prabhu Pant](LICENSE) From 281080a65bf206cdfcee18dbbf8efe3bcd31570d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 20 Nov 2019 11:24:07 +0530 Subject: [PATCH 183/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 060e92c7..c76377a1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Python Data Structures and Algorithms -This repository contains data structures and algorithms concepts and questions in Python. +This repository contains data structures and algorithms concepts and questions userful for interviews in Python. ## :dart: Objective From ae23e275e4054cf925d52ecd1cec1f2bbfb15d9a Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 22 Nov 2019 12:16:02 +0530 Subject: [PATCH 184/455] Fix count_zeros.py --- data_structures/array/moves_zeros_to_end.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/moves_zeros_to_end.py b/data_structures/array/moves_zeros_to_end.py index 5c9509bb..036c5cd8 100644 --- a/data_structures/array/moves_zeros_to_end.py +++ b/data_structures/array/moves_zeros_to_end.py @@ -5,5 +5,5 @@ def move(arr): arr[count] = a count += 1 while count < len(nums): - nums[count] = 0 + arr[count] = 0 count += 1 From 52486d8f985b5c00b80434f4f16a2f5492bcaf17 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 22 Nov 2019 22:01:07 +0530 Subject: [PATCH 185/455] Added new questions --- data_structures/graphs/DFS.py | 46 ------------ data_structures/graphs/PrimsMST.py | 58 --------------- data_structures/graphs/TopoSort.py | 44 ------------ data_structures/graphs/bfs.py | 28 ++++++++ data_structures/graphs/dfs.py | 24 +++++++ data_structures/graphs/mother_vertex.py | 5 ++ .../linked_list/sum_of_two_numbers.py | 71 +++++++++++++++++++ 7 files changed, 128 insertions(+), 148 deletions(-) delete mode 100644 data_structures/graphs/DFS.py delete mode 100644 data_structures/graphs/PrimsMST.py delete mode 100644 data_structures/graphs/TopoSort.py create mode 100644 data_structures/graphs/bfs.py create mode 100644 data_structures/graphs/dfs.py create mode 100644 data_structures/graphs/mother_vertex.py create mode 100644 data_structures/linked_list/sum_of_two_numbers.py diff --git a/data_structures/graphs/DFS.py b/data_structures/graphs/DFS.py deleted file mode 100644 index cc133a1f..00000000 --- a/data_structures/graphs/DFS.py +++ /dev/null @@ -1,46 +0,0 @@ -# An Iterative DFS solution. -class Graph: - def __init__(self, V): - self.V = V - self.adj = [[] for i in range(V)] - - def add_edge(self, v, w): - self.adj[v].append(w) - - def DFS_util(self, s, visited): - - stack = [] - - stack.append(s) - - while (len(stack) != 0): - - s = stack.pop() - - if (not visited[s]): - print(s, end=" ") - visited[s] = True - - i = 0 - while i < len(self.adj[s]): - if (not visited[self.adj[s][i]]): - stack.append(self.adj[s][i]) - i += 1 - - def DFS(self): - visited = [False] * self.V - for i in range(self.V): - if (not visited[i]): - self.DFS_util(i, visited) - - -if __name__ == '__main__': - - g = Graph(5) - g.add_edge(1, 0) - g.add_edge(2, 1) - g.add_edge(3, 4) - g.add_edge(4, 0) - - print("Following is Depth First Traversal") - g.DFS() diff --git a/data_structures/graphs/PrimsMST.py b/data_structures/graphs/PrimsMST.py deleted file mode 100644 index b0156210..00000000 --- a/data_structures/graphs/PrimsMST.py +++ /dev/null @@ -1,58 +0,0 @@ -# Uses adjacency matrix representation of graph to calculate Minimum -# Spanning Tree - -import sys - - -class Graph(): - - def __init__(self, vertices): - self.V = vertices - self.graph = [[0 for column in range(vertices)] - for row in range(vertices)] - - # Function to print generated MST - def print_MST(self, parent): - print("Edge \t Weight") - for i in range(1, self.V): - print(parent[i], "-", i, "\t", self.graph[i][parent[i]]) - - # Function to find vertex with min. distance from set of vertices - #not included in MST - def min_value(self, key, MSTSet): - minval = sys.maxsize - - for v in range(self.V): - if (key[v] < minval) and (MSTSet[v] == False): - minval = key[v] - min_index = v - return min_index - - # Function to construct Prim's MST - def MST(self): - key = [sys.maxsize] * self.V - parent = [None] * self.V - key[0] = 0 - MSTSet = [False] * self.V - parent[0] = -1 - - for j in range(self.V): - u = self.min_value(key, MSTSet) - MSTSet[u] = True - - for v in range(self.V): - if (self.graph[u][v] > 0) and (MSTSet[v] == - False) and (key[v] > self.graph[u][v]): - key[v] = self.graph[u][v] - parent[v] = u - - self.print_MST(parent) - - -g = Graph(4) -g.graph = [[0, 2, 0, 6], - [2, 0, 3, 8], - [0, 3, 0, 0], - [6, 8, 0, 0]] - -g.MST() diff --git a/data_structures/graphs/TopoSort.py b/data_structures/graphs/TopoSort.py deleted file mode 100644 index 4cb5dccb..00000000 --- a/data_structures/graphs/TopoSort.py +++ /dev/null @@ -1,44 +0,0 @@ -# Topological sorting of Directed Acyclic Graph -from collections import defaultdict - - -class Graph: - def __init__(self, vertices): - self.graph = defaultdict(list) - self.V = vertices - - def add_edge(self, u, v): - self.graph[u].append(v) - - def topological_sort_util(self, v, visited, stack): - - visited[v] = True - - for i in self.graph[v]: - if not visited[i]: - self.topological_sort_util(i, visited, stack) - - stack.insert(0, v) - - # Topological sort function - def topological_sort(self): - visited = [False] * self.V - stack = [] - - for i in range(self.V): - if (visited[i] == False): - self.topological_sort_util(i, visited, stack) - - print(stack) - - -g = Graph(6) -g.add_edge(5, 2) -g.add_edge(5, 0) -g.add_edge(4, 0) -g.add_edge(4, 1) -g.add_edge(2, 3) -g.add_edge(3, 1) - -print("One possible Topological Sort of the graph is:") -g.topological_sort() diff --git a/data_structures/graphs/bfs.py b/data_structures/graphs/bfs.py new file mode 100644 index 00000000..72a0fff6 --- /dev/null +++ b/data_structures/graphs/bfs.py @@ -0,0 +1,28 @@ +from collections import defaultdict + +class Graph: + + def __init__(self): + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def bfs(self, s): + visited = [False] * len(self.graph) + + queue = [] + + queue.append(s) + visited[s] = True + + while queue: + s = queue.pop(0) + print(s, end=' ') + + for i in self.graph[s]: + if visited[i] == False: + queue.append(i) + visited[i] = True diff --git a/data_structures/graphs/dfs.py b/data_structures/graphs/dfs.py new file mode 100644 index 00000000..b6608f2b --- /dev/null +++ b/data_structures/graphs/dfs.py @@ -0,0 +1,24 @@ +from collections import defaultdict + +class Graph: + + def __init__(self): + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append[v] + + + def dfs_util(self, v, visited): + visited[v] = True + print(v, end=' ') + + for i in self.graph[v]: + if visited[i] == False: + self.dfs_util(i, visited) + + + def dfs(self, v): + visited = [False] * (len(self.graph)) + self.dfs_util(v, visited) diff --git a/data_structures/graphs/mother_vertex.py b/data_structures/graphs/mother_vertex.py new file mode 100644 index 00000000..bc996c78 --- /dev/null +++ b/data_structures/graphs/mother_vertex.py @@ -0,0 +1,5 @@ +# A mother vertex is a vertex such that all other vertices +# can be reached by a path from this vertex + + + diff --git a/data_structures/linked_list/sum_of_two_numbers.py b/data_structures/linked_list/sum_of_two_numbers.py new file mode 100644 index 00000000..2f0ea65a --- /dev/null +++ b/data_structures/linked_list/sum_of_two_numbers.py @@ -0,0 +1,71 @@ +class Node(): + + def __init__(self, val): + self.val = val + self.next = None + + +def push(head, data): + node = Node(data) + curr = head + while curr.next: + curr = curr.next + curr.next = node + + +def print_list(head): + curr = head + while curr: + print(curr.val, end=' ') + curr = curr.next + + +def sum_numbers(head1, head2): + carry = 0 + prev = None + res = None + while head1 is not None or head2 is not None: + data1 = 0 if head1 is None else head1.val + data2 = 0 if head2 is None else head2.val + s = carry + data1 + data2 + carry = 1 if s >= 10 else 0 + s = s if s < 10 else s % 10 + + temp = Node(s) + + # if this is the first node, make it head + if res is None: + res = temp + else: + prev.next = temp + + prev = temp + + # move pointers ahead + if head1 is not None: + head1 = head1.next + if head2 is not None: + head2 = head2.next + + if carry > 0: + temp.next = Node(carry) + + return res + + + + +head1 = Node(1) +push(head1, 2) +push(head1, 3) +push(head1, 4) +print_list(head1) +print() +head2 = Node(5) +push(head2, 2) +push(head2, 1) +push(head2, 3) +print_list(head2) +print() +summmed_list = sum_numbers(head1, head2) +print_list(summmed_list) From 216e3dc078b0291d0f11ab4b18400fdb6c90245b Mon Sep 17 00:00:00 2001 From: vernalhav Date: Sat, 23 Nov 2019 12:15:33 -0300 Subject: [PATCH 186/455] Added LIS to DP --- .../longest_increasing_subsequence.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 algorithms/dynamic_programming/longest_increasing_subsequence.py diff --git a/algorithms/dynamic_programming/longest_increasing_subsequence.py b/algorithms/dynamic_programming/longest_increasing_subsequence.py new file mode 100644 index 00000000..30978c2f --- /dev/null +++ b/algorithms/dynamic_programming/longest_increasing_subsequence.py @@ -0,0 +1,84 @@ +''' +Problem statement: +given an array of N elements, +return the length of the +longest increasing subsequence +of that array +''' + +def memoize(f): + """ + Generic decorator for + Dynamic Programming + problems + """ + cache = dict() + def memoized_f(*args): + if args in cache: + global hits + hits += 1 + return cache[args] + + cache[args] = f(*args) + return cache[args] + + return memoized_f + + +def lis(s): + """ Return length of LIS in array s """ + + ''' + NOTE: array s will be declared in the superscope + of lis_routine, so it doesn't need to be passed + as argument and subsequently not hashed by @memoize + ''' + + @memoize + def lis_routine(cur_index=0, last_index=-1, cur_length=0): + """ + Return length of the longest increasing + subsequence from array s. + + To use, simply call lis(s). The other + parameters will be used in the + recursion + """ + + if cur_index == len(s): + return cur_length + + ''' + Length of the LIS if we include cur_index + is initialized as -1 because we might not + be able to include it if it is less than + the number at last_index. If last_index is + -1, we can take cur_index, as it will be + the first integer in the possible LIS. + ''' + take = -1 + if last_index == -1 or s[last_index] < s[cur_index]: + take = lis_routine(cur_index + 1, cur_index, cur_length + 1) + + # Length of the LIS if we don't include cur_index + not_take = lis_routine(cur_index + 1, last_index, cur_length) + + # Return the greatest LIS (include cur_index or not) + return max(take, not_take) + + return lis_routine() + + +def main(): + """ Simple test cases """ + t1 = [1, 6, 2, 3, 7, 9, 4, 8, 5] + t2 = [9, 8, 7, 6, 5, 4, 3, 2, 1] + t3 = [-1, -1, -1, -1, -1, -1] + + print('LIS of {}: {}'.format(t1, lis(t1))) # Should be 5 + print('LIS of {}: {}'.format(t2, lis(t2))) # Should be 1 + print('LIS of {}: {}'.format(t3, lis(t3))) # Should be 1 + + +if __name__ == '__main__': + main() \ No newline at end of file From 228a6655572e6da9b7bb3ba10567b68728e1c5bb Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:16:10 +0530 Subject: [PATCH 187/455] Delete binary-tree-level-order-traversal.py --- .../binary-tree-level-order-traversal.py | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 data_structures/binary_trees/binary-tree-level-order-traversal.py diff --git a/data_structures/binary_trees/binary-tree-level-order-traversal.py b/data_structures/binary_trees/binary-tree-level-order-traversal.py deleted file mode 100644 index 36d2f319..00000000 --- a/data_structures/binary_trees/binary-tree-level-order-traversal.py +++ /dev/null @@ -1,52 +0,0 @@ -''' -Author : MiKueen -Level : Medium -Problem Statement : Binary Tree Level Order Traversal - -Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). - -For example: -Given binary tree [3,9,20,null,null,15,7], - 3 - / \ - 9 20 - / \ - 15 7 -return its level order traversal as: -[ - [3], - [9,20], - [15,7] -] -''' - -from collections import deque - -# Definition for a binary tree node. -# class TreeNode(object): -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - -class Solution(object): - def levelOrder(self, root): - """ - :type root: TreeNode - :rtype: List[List[int]] - """ - if not root: - return [] - level, res = deque([root]), [] - while level: - next_level = [] - for i in range(len(level)): - node = level.popleft() - if node.left: - level.append(node.left) - if node.right: - level.append(node.right) - next_level.append(node.val) - res.append(next_level) - return res - \ No newline at end of file From b28593b3ff1f57f1a85787b1b08726e996d3041c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:16:16 +0530 Subject: [PATCH 188/455] Delete flatten-binary-tree-to-linked-list.py --- .../flatten-binary-tree-to-linked-list.py | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100644 data_structures/binary_trees/flatten-binary-tree-to-linked-list.py diff --git a/data_structures/binary_trees/flatten-binary-tree-to-linked-list.py b/data_structures/binary_trees/flatten-binary-tree-to-linked-list.py deleted file mode 100644 index 1c0362a1..00000000 --- a/data_structures/binary_trees/flatten-binary-tree-to-linked-list.py +++ /dev/null @@ -1,59 +0,0 @@ -''' -Author : MiKueen -Level : Medium -Problem Statement : Flatten Binary Tree to Linked List - -Given a binary tree, flatten it to a linked list in-place. -For example, given the following tree: - 1 - / \ - 2 5 - / \ \ -3 4 6 - -The flattened tree should look like: -1 - \ - 2 - \ - 3 - \ - 4 - \ - 5 - \ - 6 - -Approach : Recursive solution -1. Flatten left subtree -2. Find tail of left subtree -3. Attach tail of left subtree to starting node of right subtree -4. Flatten right subtree -''' - -# Definition for a binary tree node. -# class TreeNode(object): -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - -class Solution(object): - def flatten(self, root): - """ - :type root: TreeNode - :rtype: None Do not return anything, modify root in-place instead. - """ - - if not root: - return - - right = root.right - if root.left: - self.flatten(root.left) - tail = root.left - while tail.right: - tail = tail.right - root.left, root.right, tail.right = None, root.left, right - self.flatten(right) - \ No newline at end of file From fe17999ad719f35a51f9a9270789781a34cd8a8f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:16:22 +0530 Subject: [PATCH 189/455] Delete maximum-depth-of-binary-tree.py --- .../maximum-depth-of-binary-tree.py | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 data_structures/binary_trees/maximum-depth-of-binary-tree.py diff --git a/data_structures/binary_trees/maximum-depth-of-binary-tree.py b/data_structures/binary_trees/maximum-depth-of-binary-tree.py deleted file mode 100644 index cb65fb92..00000000 --- a/data_structures/binary_trees/maximum-depth-of-binary-tree.py +++ /dev/null @@ -1,53 +0,0 @@ -''' -Author : MiKueen -Level : Easy -Problem Statement : Maximum Depth of Binary Tree - -Given a binary tree, find its maximum depth. -The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. -Note: A leaf is a node with no children. - -Example: -Given binary tree [3,9,20,null,null,15,7], - - 3 - / \ - 9 20 - / \ - 15 7 -return its depth = 3. -''' - -from collections import deque - -# Definition for a binary tree node. -# class TreeNode(object): -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - -class Solution(object): - def maxDepth(self, root): - """ - :type root: TreeNode - :rtype: int - """ - - # BFS solution - if not root: - return 0 - if root.left is None and root.right is None: - return 1 - - depth, level = 0, deque([root]) - while level: - depth += 1 - for i in range(len(level)): - node = level.popleft() - if node.left: - level.append(node.left) - if node.right: - level.append(node.right) - return depth - \ No newline at end of file From fed832176672948fbf6e8319909ceebf69666c22 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:16:30 +0530 Subject: [PATCH 190/455] Delete minimum-depth-of-binary-tree.py --- .../minimum-depth-of-binary-tree.py | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 data_structures/binary_trees/minimum-depth-of-binary-tree.py diff --git a/data_structures/binary_trees/minimum-depth-of-binary-tree.py b/data_structures/binary_trees/minimum-depth-of-binary-tree.py deleted file mode 100644 index 2dbbf5df..00000000 --- a/data_structures/binary_trees/minimum-depth-of-binary-tree.py +++ /dev/null @@ -1,55 +0,0 @@ -''' -Author : MiKueen -Level : Easy -Problem Statement : Minimum Depth of Binary Tree - -Given a binary tree, find its minimum depth. -The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. -Note: A leaf is a node with no children. - -Example: -Given binary tree [3,9,20,null,null,15,7], - - 3 - / \ - 9 20 - / \ - 15 7 -return its minimum depth = 2. -''' - -from collections import deque - -# Definition for a binary tree node. -# class TreeNode(object): -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - -class Solution(object): - def minDepth(self, root): - """ - :type root: TreeNode - :rtype: int - """ - - # BFS solution - if not root: - return 0 - if root.left is None and root.right is None: - return 1 - - depth, level = 1, deque([root]) - while level: - for i in range(len(level)): - node = level.popleft() - if node.left is None and node.right is None: - return depth - if node.left: - level.append(node.left) - if node.right: - level.append(node.right) - depth += 1 - return depth - \ No newline at end of file From 36f3bc9d6de272f948d7d969c62ff7addfa7a600 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:16:35 +0530 Subject: [PATCH 191/455] Delete path-sum.py --- data_structures/binary_trees/path-sum.py | 64 ------------------------ 1 file changed, 64 deletions(-) delete mode 100644 data_structures/binary_trees/path-sum.py diff --git a/data_structures/binary_trees/path-sum.py b/data_structures/binary_trees/path-sum.py deleted file mode 100644 index 69bc80be..00000000 --- a/data_structures/binary_trees/path-sum.py +++ /dev/null @@ -1,64 +0,0 @@ -''' -Author : MiKueen -Level : Medium -Problem Statement : Path Sum II - -Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. -Note: A leaf is a node with no children. - -Example: -Given the below binary tree and sum = 22, - 5 - / \ - 4 8 - / / \ - 11 13 4 - / \ / \ -7 2 5 1 -Return: -[ - [5,4,11,2], - [5,8,4,5] -] -''' - -# Definition for a binary tree node. -# class TreeNode(object): -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - -class Solution(object): - def pathSum(self, root, sum): - """ - :type root: TreeNode - :type sum: int - :rtype: List[List[int]] - """ - - # DFS solution - if not root: - return [] - if root.left is None and root.right is None: - if sum == root.val: - return [[root.val]] - else: - return [] - - res = [] - left, right = [], [] - sum -= root.val - - if root.left: - left = self.pathSum(root.left, sum) - if root.right: - right = self.pathSum(root.right, sum) - - for l in left: - res.append([root.val] + l) - for r in right: - res.append([root.val] + r) - - return res - \ No newline at end of file From c6398bce87f6b0e48241cc487b55a0ffadeac2d4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:17:19 +0530 Subject: [PATCH 192/455] Create print_spiral_tree.py --- .../binary_trees/print_spiral_tree.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 data_structures/binary_trees/print_spiral_tree.py diff --git a/data_structures/binary_trees/print_spiral_tree.py b/data_structures/binary_trees/print_spiral_tree.py new file mode 100644 index 00000000..463823ee --- /dev/null +++ b/data_structures/binary_trees/print_spiral_tree.py @@ -0,0 +1,34 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def print_spiral(root): + + s1 = [] + s2 = [] + + s1.append(root) + + while not len(s1) == 0 or not len(s2) == 0: + + while not len(s1) == 0: + temp = s1.pop() + print(temp.data, end=' ') + + if temp.right: + s2.append(temp.right) + if temp.left: + s2.append(temp.left) + + while not len(s2) == 0: + temp = s2.pop() + print(temp.data, end=' ') + + if temp.left: + s1.append(temp.left) + if temp.right: + s1.append(temp.right) From 1450e5fddcb9f1ffc1c1cc0e248f73d759eea1fe Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:17:48 +0530 Subject: [PATCH 193/455] Create boundary_traversal.py --- .../binary_trees/boundary_traversal.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 data_structures/binary_trees/boundary_traversal.py diff --git a/data_structures/binary_trees/boundary_traversal.py b/data_structures/binary_trees/boundary_traversal.py new file mode 100644 index 00000000..760a6342 --- /dev/null +++ b/data_structures/binary_trees/boundary_traversal.py @@ -0,0 +1,49 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def print_leaves(root): + if root: + print_leaves(root.left) + + if not root.left and not root.right: + print(root.val, end=' ') + + print_leaves(root.right) + +# To ensure top down, print before calling for other +# To ensure bottom up, print after calling + +def print_left_boundary(root): + if root: + if root.left: + print(root.val, end=' ') + print_left_boundary(root.left) + + elif root.right: + print(root.val, end=' ') + print_left_boundary(root.right) + + +def print_right_boundary(root): + if root: + if root.right: + print_right_boundary(root.right) + print(root.val, end=' ') + + elif root.left: + print_right_boundary(root.left) + print(root.val, end=' ') + + +def print_boundary(root): + if root: + print(root.val) + print_left_boundary(root.left) + print_leaves(root.left) + print_leaves(root.right) + print_right_boundary(root.right) From 82906a3c3791bca6a57e0a246646cb1f9076ec65 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:18:10 +0530 Subject: [PATCH 194/455] Create continuous_tree.py --- .../binary_trees/continuous_tree.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 data_structures/binary_trees/continuous_tree.py diff --git a/data_structures/binary_trees/continuous_tree.py b/data_structures/binary_trees/continuous_tree.py new file mode 100644 index 00000000..9522d3bf --- /dev/null +++ b/data_structures/binary_trees/continuous_tree.py @@ -0,0 +1,33 @@ +# A continuous tree is such that the absolute difference between two +# adjacent nodes is 1 + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def continuous(root): + # Can be continuous if + # 1. Root is none + # 2. Both left and right STs are none + # 3. If left ST is none, check for right + # 4. If right ST is none, check for left + # 5. Else check for everything + + if root is None: + return True + + if root.left == None and root.right == None: + return True + + if root.left == None: + return (abs(root.val - root.right.val) == 1) and continuous(root.right) + + if root.right == None: + return (abs(root.val - root.left.val) == 1) and continuous(root.left) + + return (abs(root.val - root.right.val) == 1) and (abs(root.left.val - root.val) == 1) and continuous(root.left) and continuous(root.right) + From 189755d58593eb277d56c0f249eb8d8abcef717b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:18:31 +0530 Subject: [PATCH 195/455] Delete symmetric_binary_tree.py --- .../binary_trees/symmetric_binary_tree.py | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 data_structures/binary_trees/symmetric_binary_tree.py diff --git a/data_structures/binary_trees/symmetric_binary_tree.py b/data_structures/binary_trees/symmetric_binary_tree.py deleted file mode 100644 index 8f742715..00000000 --- a/data_structures/binary_trees/symmetric_binary_tree.py +++ /dev/null @@ -1,37 +0,0 @@ -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - -def isSymmetric(self, root: TreeNode) -> bool: - """ - function to determine if the provided TreeNode is the root - of a symmetric binary tree - """ - - def isMirror(left: TreeNode, right: TreeNode) -> bool: - """ - Utility function to determine if two trees mirror each other. If the root and - all subtrees searched here are mirrors, then the tree as a whole is symmetric - """ - - # Two null values are mirrors - if left is None and right is None: - return True - - # If only one value is null, these trees do not mirror each other - if left is None or right is None: - return False - - # If the values are not equal, the trees do not mirror each other - if left.val != right.val: - return False - - # If left.left mirrors right.right, and left.right mirrors right.left, - # the subtrees mirror each other - return isMirror(left.left, right.right) and isMirror(left.right, right.left) - - return isMirror(root, root) - From 58a4f1a65cbe2531a569080a80ced6f19be6db2c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:18:45 +0530 Subject: [PATCH 196/455] Create foldable_or_symmetric_tree.py --- .../foldable_or_symmetric_tree.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 data_structures/binary_trees/foldable_or_symmetric_tree.py diff --git a/data_structures/binary_trees/foldable_or_symmetric_tree.py b/data_structures/binary_trees/foldable_or_symmetric_tree.py new file mode 100644 index 00000000..0943d62c --- /dev/null +++ b/data_structures/binary_trees/foldable_or_symmetric_tree.py @@ -0,0 +1,31 @@ +# A foldable tree is one such that the mirror of left subtree is equal +# to the right subtree + +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def foldable(left, right): + if left is None and right is None: + return True + + if left is None or right is None: + return False + + return left.val == right.val and foldable(left.left, right.right) and foldable(left.right, right.left) + + +root = Node(4) + +root.left = Node(2) +root.left.left = Node(1) + +root.right = Node(2) +root.right.right = Node(10) + +print(foldable(root.left, root.right)) + From 3979b43cf3c7a9a7550a76620e8c90d29add556c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:19:32 +0530 Subject: [PATCH 197/455] Create evaluate_expresssion_tree.py --- .../binary_trees/evaluate_expresssion_tree.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/binary_trees/evaluate_expresssion_tree.py diff --git a/data_structures/binary_trees/evaluate_expresssion_tree.py b/data_structures/binary_trees/evaluate_expresssion_tree.py new file mode 100644 index 00000000..02bb3066 --- /dev/null +++ b/data_structures/binary_trees/evaluate_expresssion_tree.py @@ -0,0 +1,37 @@ +# In expression tree, the integer values will be at the leaf nodes +# The operands will be all the other internal nodes + +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def evaluate(root): + if root is None: + return 0 + + # Check for leaf node + if root.left is None and root.right is None: + return int(root.data) + + # Evaluate left tree + left_sum = evaluate(root.left) + + # Evaluate right tree + right_sum = evaluate(root.right) + + # Check which operator to apply + if root.data == '+': + return left_sum + right_sum + + elif root.data == '-': + return left_sum - right_sum + + elif root.data == '*': + return left_sum * right_sum + + else: + return left_sum / right_sum From f824a7234cda3dc37ee9bc93145b5cd26c3feb80 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 26 Nov 2019 10:29:42 +0530 Subject: [PATCH 198/455] Create diagonal_tree.py --- data_structures/binary_trees/diagonal_tree.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 data_structures/binary_trees/diagonal_tree.py diff --git a/data_structures/binary_trees/diagonal_tree.py b/data_structures/binary_trees/diagonal_tree.py new file mode 100644 index 00000000..b8dc2082 --- /dev/null +++ b/data_structures/binary_trees/diagonal_tree.py @@ -0,0 +1,38 @@ +# Print tree in a diagonal form + +# We use the distance of slope from the rightmost slope as key +# in a dict and then proceed + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def diagonal_print_util(root, d, diagonal_map): + if root is None: + return + + try: + diagonal_map[d].append(root.val) + except: + diagonal_map[d] = [root.val] + + # Increase vertical distance if left child + diagonal_print_util(root.left, d+1, diagonal_map) + + # Vertical distance remains same for the right child + diagonal_print_util(root.right, d, diagonal_map) + + +def diagonal_print(root): + diagonal_map = dict() + + diagonal_print_util(root, 0, diagonal_map) + + for i in diagonal_map: + for j in diagonal_map[i]: + print(j, end=" ") + print('') From d6a6ee853102593b7f4cfc9c792f8afd79968b83 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 11:05:44 +0530 Subject: [PATCH 199/455] Create logical_and_tree.py --- .../binary_trees/logical_and_tree.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 data_structures/binary_trees/logical_and_tree.py diff --git a/data_structures/binary_trees/logical_and_tree.py b/data_structures/binary_trees/logical_and_tree.py new file mode 100644 index 00000000..1dddf0b0 --- /dev/null +++ b/data_structures/binary_trees/logical_and_tree.py @@ -0,0 +1,21 @@ +# Given a tree that contains only 0s and 1s, convert it into +# a logical AND tree. A logical AND tree is such that +# left_child AND right_child = AND_VALUE + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def convert(root): + if root is None: + return + + convert(root.left) + convert(root.right) + + if root.left and root.right: + root.val = root.left.val & root.right.val From 067ee786086f721ac59991320e6c9d33a62527cc Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 11:06:39 +0530 Subject: [PATCH 200/455] Create flip_tree.py --- data_structures/binary_trees/flip_tree.py | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 data_structures/binary_trees/flip_tree.py diff --git a/data_structures/binary_trees/flip_tree.py b/data_structures/binary_trees/flip_tree.py new file mode 100644 index 00000000..20c8cbf5 --- /dev/null +++ b/data_structures/binary_trees/flip_tree.py @@ -0,0 +1,33 @@ +# Flip a tree such like here +# https://www.geeksforgeeks.org/flip-binary-tree/ + +# Flipping subtree algorithm +# 1. root->left->left = root->right +# 2. root->left->right = root +# 3. root->left = NULL +# 4. root->right = NULL + + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def flip_tree(root): + if root is None: + return root + + if root.left is None and root.right is None: + return root + + flipped_root = flip_tree(root.left) + + root.left.left = root.right + root.left.right = root + root.left = None + root.right = None + + return flipped_root From be24a094012bb3940a4ad85c3af192c236bbd0fd Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 11:07:44 +0530 Subject: [PATCH 201/455] Create left_right_to_down_right.py --- .../binary_trees/left_right_to_down_right.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 data_structures/binary_trees/left_right_to_down_right.py diff --git a/data_structures/binary_trees/left_right_to_down_right.py b/data_structures/binary_trees/left_right_to_down_right.py new file mode 100644 index 00000000..c043bcaa --- /dev/null +++ b/data_structures/binary_trees/left_right_to_down_right.py @@ -0,0 +1,24 @@ +# Convert a tree that is a left right representation to a +# down right representation + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.rigt = None + + +def convert(root): + if root is None: + return + + convert(root.left) + convert(root.right) + + if root.left == None: + root.left = root.right + else: + root.left.right = root.right + + root.right = None From 3f4d8540968686e9e47901dde2524eb169725721 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 11:24:45 +0530 Subject: [PATCH 202/455] Create check_if_graph_is_tree.py --- data_structures/binary_trees/check_if_graph_is_tree.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 data_structures/binary_trees/check_if_graph_is_tree.py diff --git a/data_structures/binary_trees/check_if_graph_is_tree.py b/data_structures/binary_trees/check_if_graph_is_tree.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/data_structures/binary_trees/check_if_graph_is_tree.py @@ -0,0 +1 @@ + From b3f2ad9b8c33fb70a4caa2b93aabcabae5c65b10 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 11:39:43 +0530 Subject: [PATCH 203/455] Create check_cousin.py --- data_structures/binary_trees/check_cousin.py | 36 ++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 data_structures/binary_trees/check_cousin.py diff --git a/data_structures/binary_trees/check_cousin.py b/data_structures/binary_trees/check_cousin.py new file mode 100644 index 00000000..6453eed4 --- /dev/null +++ b/data_structures/binary_trees/check_cousin.py @@ -0,0 +1,36 @@ +# Check if two nodes are cousin or not + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def level(root, node, lev): + if not root: + return 0 + if root == node: + return lev + + l = level(root.left, node, lev + 1) + + if not l == 0: + return l + + l = level(root.right, node, lev + 1) + + +def is_sibling(root, a, b): + if root is None: + return 0 + + return ( (root.left == a and root.right == b) or (root.left == b and root.right == a) or is_sibling(root.left, a, b) or is_sibling(root.right, a, b) ) + + +def is_cousin(root, a, b): + if level(root, a, 1) == level(root, b, 1) and not is_sibling(root, a, b): + return True + else: + return False From e2cd86f7aacbdba80c6db753744fb727662c2fab Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 11:44:09 +0530 Subject: [PATCH 204/455] Create check_all_leaves_at_same_level.py --- .../check_all_leaves_at_same_level.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 data_structures/binary_trees/check_all_leaves_at_same_level.py diff --git a/data_structures/binary_trees/check_all_leaves_at_same_level.py b/data_structures/binary_trees/check_all_leaves_at_same_level.py new file mode 100644 index 00000000..a296fb21 --- /dev/null +++ b/data_structures/binary_trees/check_all_leaves_at_same_level.py @@ -0,0 +1,28 @@ +# check if all the leaves of a tree are at the same level + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def check_util(root, level): + if root is None: + return True + + if root.left is None and root.right is None: + if check.leaf_level == 0: + check.leaf_level = level + return True + + return level == check.leaf_level + + return check_util(root.left, level + 1) and check_util(root.right, level + 1) + + +def check(root): + level = 0 + check.leaf_level = 0 + return check_util(root, level) From d352da37987dd58b7a8d9d532577a630966cc961 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 12:50:13 +0530 Subject: [PATCH 205/455] Update articles.md --- bookmarks/articles.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/articles.md b/bookmarks/articles.md index 8553d9c4..a2b8e1ca 100644 --- a/bookmarks/articles.md +++ b/bookmarks/articles.md @@ -53,3 +53,5 @@ This is a list of articles that may be useful for algorithms and data structures - https://samnewman.io/patterns/architectural/bff/ - https://www.ultravioletsoftware.com/single-post/2017/03/23/An-introduction-into-the-WSGI-ecosystem + +- https://jwt.io/introduction/ From 5ecbd06a5edd9c6ed9b8f89e2fdae8441a34885b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 14:40:48 +0530 Subject: [PATCH 206/455] Create check_divide_in_two_halves.pyt --- .../check_divide_in_two_halves.pyt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 data_structures/binary_trees/check_divide_in_two_halves.pyt diff --git a/data_structures/binary_trees/check_divide_in_two_halves.pyt b/data_structures/binary_trees/check_divide_in_two_halves.pyt new file mode 100644 index 00000000..a51fa90b --- /dev/null +++ b/data_structures/binary_trees/check_divide_in_two_halves.pyt @@ -0,0 +1,33 @@ +# Check if removing an edge of a binary tree can divide +# the tree in two equal halves + +# Count the number of nodes, say n. Then traverse the tree +# in bottom up manner and check if n - s = s + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def count(root): + if not root: + return 0 + return count(root.left) + count(root.right) + 1 + + +def check_util(root, n): + if root == None: + return False + + if count(root) == n - count(root): + return True + + return check_util(root.left, n) || check_util(root.right, n) + + +def check(root): + n = count(rot) + return check_util(root, n) From 1c10fe9288194aa5318bc514b901b08fd72b2e0b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 14:42:33 +0530 Subject: [PATCH 207/455] Update check_divide_in_two_halves.pyt --- data_structures/binary_trees/check_divide_in_two_halves.pyt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data_structures/binary_trees/check_divide_in_two_halves.pyt b/data_structures/binary_trees/check_divide_in_two_halves.pyt index a51fa90b..71603f99 100644 --- a/data_structures/binary_trees/check_divide_in_two_halves.pyt +++ b/data_structures/binary_trees/check_divide_in_two_halves.pyt @@ -21,10 +21,12 @@ def count(root): def check_util(root, n): if root == None: return False - + + # Check for root if count(root) == n - count(root): return True - + + # Check for all the other nodes return check_util(root.left, n) || check_util(root.right, n) From e9f7215aa3ea0892f24a220ac8911d549ee89799 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 15:15:45 +0530 Subject: [PATCH 208/455] Update check_divide_in_two_halves.pyt --- data_structures/binary_trees/check_divide_in_two_halves.pyt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_trees/check_divide_in_two_halves.pyt b/data_structures/binary_trees/check_divide_in_two_halves.pyt index 71603f99..df4f71b3 100644 --- a/data_structures/binary_trees/check_divide_in_two_halves.pyt +++ b/data_structures/binary_trees/check_divide_in_two_halves.pyt @@ -27,7 +27,7 @@ def check_util(root, n): return True # Check for all the other nodes - return check_util(root.left, n) || check_util(root.right, n) + return check_util(root.left, n) or check_util(root.right, n) def check(root): From ac94378fe56fd4e85c3f96a89b09b410b38d51cc Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 15:16:31 +0530 Subject: [PATCH 209/455] Create check_perfect_binary_tree.py --- .../binary_trees/check_perfect_binary_tree.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 data_structures/binary_trees/check_perfect_binary_tree.py diff --git a/data_structures/binary_trees/check_perfect_binary_tree.py b/data_structures/binary_trees/check_perfect_binary_tree.py new file mode 100644 index 00000000..c3f76281 --- /dev/null +++ b/data_structures/binary_trees/check_perfect_binary_tree.py @@ -0,0 +1,38 @@ +# A binary tree is perfect if all the internal nodes have 2 children and +# all the leaves are at the same level + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +# Returns depth of leftmost leaf +def find_depth(root): + d = 0 + while root: + d += 1 + root = root.left + return d + + +def check_perfect(root, d, level=0): + if not root: + return True + + # If leaf node, then its depth must be same as that of other nodes + if root.left is None and root.right is None: + return d == (level + 1) + + # An internal node with only one child + if root.left is None or root.right is None: + return False + + return check_perfect(root.left, d, level+1) and check_perfect(root.right, d, level+1) + + +def is_perfect(root): + d = find_depth(root) + return check_perfect(root, d) From 5e7b10540e57c014f686db51829406eb85dabcb4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 15:16:55 +0530 Subject: [PATCH 210/455] Create check_full_binary_tree.py --- .../binary_trees/check_full_binary_tree.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 data_structures/binary_trees/check_full_binary_tree.py diff --git a/data_structures/binary_trees/check_full_binary_tree.py b/data_structures/binary_trees/check_full_binary_tree.py new file mode 100644 index 00000000..23c03f16 --- /dev/null +++ b/data_structures/binary_trees/check_full_binary_tree.py @@ -0,0 +1,22 @@ +# A full binary tree is one which has 0 or 2 children only + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def check(root): + if root is None: + return True + + if root.left is None and root.right is None: + return True + + if root.left is not None and root.right is not None: + return check(root.left) and check(root.right) + + return False + From 0db2d9a5dc2993a4c9e7347e04933af8eb610b11 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 17:02:07 +0530 Subject: [PATCH 211/455] Create identical_trees.py --- .../binary_trees/identical_trees.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 data_structures/binary_trees/identical_trees.py diff --git a/data_structures/binary_trees/identical_trees.py b/data_structures/binary_trees/identical_trees.py new file mode 100644 index 00000000..1d81cef3 --- /dev/null +++ b/data_structures/binary_trees/identical_trees.py @@ -0,0 +1,18 @@ +# Check if two trees are identical or not + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def identical(root1, root2): + if root1 is None and root2 is None: + return True + + if root1 is not None and root2 is not None: + return root1.val == root2. val and identical(root1.left, root2.left) and identical(root1.right, root2.right) + + return False From a3061aa5c60cdac160db49fc07124bd469321375 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 17:06:13 +0530 Subject: [PATCH 212/455] Create check_if_path_exists.py --- .../binary_trees/check_if_path_exists.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 data_structures/binary_trees/check_if_path_exists.py diff --git a/data_structures/binary_trees/check_if_path_exists.py b/data_structures/binary_trees/check_if_path_exists.py new file mode 100644 index 00000000..be05f876 --- /dev/null +++ b/data_structures/binary_trees/check_if_path_exists.py @@ -0,0 +1,21 @@ +# Check if a given path exists in a tree + +# Traverse the tree in preorder fashion and keep matching the node +# value to the index of the given path + +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def check_path(root, arr, n, index): + if root is None: + return n == 0 + + if root.left == None and root.right == None and root.val == arr[index] and index == n -1: + return True + + return (index < n) and (root.val == arr[index]) and (check_path(root.left, arr, n, index + 1) or check_path(root.right, arr, n, index + 1)) From ed81d7528853cf78f696e60b470169d562b75b4e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 17:17:32 +0530 Subject: [PATCH 213/455] Create print_nodes_at_k_distance_from_root.py --- .../print_nodes_at_k_distance_from_root.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 data_structures/binary_trees/print_nodes_at_k_distance_from_root.py diff --git a/data_structures/binary_trees/print_nodes_at_k_distance_from_root.py b/data_structures/binary_trees/print_nodes_at_k_distance_from_root.py new file mode 100644 index 00000000..a07e0211 --- /dev/null +++ b/data_structures/binary_trees/print_nodes_at_k_distance_from_root.py @@ -0,0 +1,16 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def print_k(root, k): + if root is None: + return + if k == 0: + print(root.val) + else: + print_k(root.left, k-1) + print_k(root.right, k-1) From 40edae390dbfb18904d316a6558a53f5e0bc3e93 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 27 Nov 2019 17:24:58 +0530 Subject: [PATCH 214/455] Create print_path_to_a_node.py --- .../binary_trees/print_path_to_a_node.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 data_structures/binary_trees/print_path_to_a_node.py diff --git a/data_structures/binary_trees/print_path_to_a_node.py b/data_structures/binary_trees/print_path_to_a_node.py new file mode 100644 index 00000000..3e1ece97 --- /dev/null +++ b/data_structures/binary_trees/print_path_to_a_node.py @@ -0,0 +1,34 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def has_path(root, arr, x): + if not root: + return False + + arr.append(root.val) + + if root.val == x: + return True + + if has_path(root.left, arr, x) or has_path(root.right, arr, x): + return True + + # If the required node is not in the left or right subtree, remove + # the parent node from where the fork starts + arr.pop() + return False + + +def print_path(root, x): + arr = [] + + if has_path(root, arr, x): + for i in arr: + print(i, end=' ') + else: + print('Path not present') From 4ce5d5e364098e6923c2f92f9f99621ad7d12499 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 28 Nov 2019 17:17:03 +0530 Subject: [PATCH 215/455] Create maximum_left_node.py --- .../binary_trees/maximum_left_node.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 data_structures/binary_trees/maximum_left_node.py diff --git a/data_structures/binary_trees/maximum_left_node.py b/data_structures/binary_trees/maximum_left_node.py new file mode 100644 index 00000000..8e3f23b2 --- /dev/null +++ b/data_structures/binary_trees/maximum_left_node.py @@ -0,0 +1,22 @@ +# Find the max value in only the left nodes of the tree + +# Do inorder traversal and just keep track of the values + +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def find(root): + res = -999999999999 + + if not root: + return res + + if root.left != None: + res = root.left.val + + return max(find(root.left), res, find(root.right)) From ba60b56897436fabc1b6ebf0bf44110bad14fc09 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 28 Nov 2019 17:23:23 +0530 Subject: [PATCH 216/455] Create longest_path_with_same_value.py --- .../longest_path_with_same_value.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 data_structures/binary_trees/longest_path_with_same_value.py diff --git a/data_structures/binary_trees/longest_path_with_same_value.py b/data_structures/binary_trees/longest_path_with_same_value.py new file mode 100644 index 00000000..288bbf95 --- /dev/null +++ b/data_structures/binary_trees/longest_path_with_same_value.py @@ -0,0 +1,33 @@ +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def length(root, ans): + if not root: + return 0 + + left = length(root.left, ans) + right = length(root.right, ans) + + left_max = 0 + right_max = 0 + + if root.left and root.left.val == root.val: + left_max += 1 + + if root.right and root.right.val == root.val: + right_max += 1 + + ans[0] = max(ans[0], left_max + right_max) + + return max(left_max, right_max) + + +def longest_path(root): + ans = [0] + length(root, ans) + return ans[0] From 281b96c1fa12889be28aa2ef5df63c678a71f0b5 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 29 Nov 2019 12:50:30 +0530 Subject: [PATCH 217/455] Create print_full_nodes.py --- .../binary_trees/print_full_nodes.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 data_structures/binary_trees/print_full_nodes.py diff --git a/data_structures/binary_trees/print_full_nodes.py b/data_structures/binary_trees/print_full_nodes.py new file mode 100644 index 00000000..e76c63c8 --- /dev/null +++ b/data_structures/binary_trees/print_full_nodes.py @@ -0,0 +1,30 @@ +# Given a tree, print all the full nodes of it +# A full node is such that both its children are present + +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def print_full(root): + if not root: + return + if root.left and root.right: + print(root.val, end=' ') + print_full(root.left) + print_full(root.right) + + +root = Node(10) +root.left = Node(8) +root.right = Node(2) + +root.left.left = Node(3) +root.left.right = Node(5) + +root.right.left = Node(7) + +print_full(root) From cc53555698ee81ceb6e6b6547c496b637bbf0210 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 29 Nov 2019 12:53:02 +0530 Subject: [PATCH 218/455] Create print_odd_level_nodes.py --- .../binary_trees/print_odd_level_nodes.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 data_structures/binary_trees/print_odd_level_nodes.py diff --git a/data_structures/binary_trees/print_odd_level_nodes.py b/data_structures/binary_trees/print_odd_level_nodes.py new file mode 100644 index 00000000..bd83c75c --- /dev/null +++ b/data_structures/binary_trees/print_odd_level_nodes.py @@ -0,0 +1,19 @@ +# Print all the nodes at odd levels of a binary tree + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def print_odd(root, is_odd=True): + if not root: + return + + if is_odd: + print(root.val, end=' ') + + print_odd(root, not is_odd) + print_odd(root, not is_odd) From e32d7da57f66d72e37ce91285975a9ddb46fab06 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 29 Nov 2019 13:00:31 +0530 Subject: [PATCH 219/455] Create diameter.py --- data_structures/binary_trees/diameter.py | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 data_structures/binary_trees/diameter.py diff --git a/data_structures/binary_trees/diameter.py b/data_structures/binary_trees/diameter.py new file mode 100644 index 00000000..da1726b7 --- /dev/null +++ b/data_structures/binary_trees/diameter.py @@ -0,0 +1,31 @@ +# Diameter of a binary tree is the longest path between two leaf nodes of a binary tree +# Diameter of a binary tree is maximum value of (left_height + right_height + 1) for each node + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def height(root, ans): + if not root: + return 0 + + lheight = height(root.left, ans) + rheight = height(root.right, ans) + + ans[0] = max(ans[0], 1 + lheight + rheight) + + return 1 + max(lheight, rheight) + + +def diameter(root): + if not root: + return 0 + + ans = [-9999999999] + + h = height(root, ans) + return ans[0] From 2cf191c21942c11fea7691cc073a97008434fe5b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 29 Nov 2019 13:09:02 +0530 Subject: [PATCH 220/455] Create print_all_root_to_leaf_paths.py --- .../print_all_root_to_leaf_paths.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/binary_trees/print_all_root_to_leaf_paths.py diff --git a/data_structures/binary_trees/print_all_root_to_leaf_paths.py b/data_structures/binary_trees/print_all_root_to_leaf_paths.py new file mode 100644 index 00000000..f3c0d2a6 --- /dev/null +++ b/data_structures/binary_trees/print_all_root_to_leaf_paths.py @@ -0,0 +1,37 @@ +# Traverse the tree in preorder fashion +# append value in stack +# if root.left and root.right is None, then print all stack values +# traverse left +# traverse right +# pop from stack + +class Node: + + def __init__(self, val): + self.val = val + self.right = None + self.left = None + + +def print_route(root, stack): + if root == None: + return + + stack.append(root.val) + if root.left == None and root.right == None: + for i in stack: + print(i, end=' ') + print() + + print_route(root.left, stack) + print_route(root.right, stack) + stack.pop() + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(4) +root.left.right = Node(5) + +print_route(root, []) From 5124eab392c6956c3ff75185757e7745acc88b9f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 29 Nov 2019 15:06:21 +0530 Subject: [PATCH 221/455] Create children_sum_property.py --- .../binary_trees/children_sum_property.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 data_structures/binary_trees/children_sum_property.py diff --git a/data_structures/binary_trees/children_sum_property.py b/data_structures/binary_trees/children_sum_property.py new file mode 100644 index 00000000..8894fabe --- /dev/null +++ b/data_structures/binary_trees/children_sum_property.py @@ -0,0 +1,28 @@ +# Check whether a tree statisfies children sum property +# Children sum property is such that every partent = left + right child + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def sum_prop(root): + l = r = 0 + + if not root or (not root.left and not root.right): + return True + + else: + if root.left: + l = root.left.val + + if root.right: + r = root.right.val + + if (root.val == l + r) and sum_prop(root.left) and sum_prop(root.right): + return True + else: + return False From ee5e2ae44a4a3e725393d92b45577263bb978401 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 29 Nov 2019 15:13:50 +0530 Subject: [PATCH 222/455] Create print_nodes_with_no_sibling.py --- .../print_nodes_with_no_sibling.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 data_structures/binary_trees/print_nodes_with_no_sibling.py diff --git a/data_structures/binary_trees/print_nodes_with_no_sibling.py b/data_structures/binary_trees/print_nodes_with_no_sibling.py new file mode 100644 index 00000000..5c7ffc2a --- /dev/null +++ b/data_structures/binary_trees/print_nodes_with_no_sibling.py @@ -0,0 +1,24 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def no_siblings(root): + if root is None: + return + + if root.left is not None and root.right is not None: + no_siblings(root.left) + no_siblings(root.right) + + elif root.right is not None: + print(root.right.val) + no_siblings(root.right) + + elif root.left is not None: + print(root.left.val) + no_siblings(root.left) + From b237acd88a839da0d050e7ced4863ce01a781de4 Mon Sep 17 00:00:00 2001 From: Sri Harsha Date: Sun, 1 Dec 2019 12:16:45 +0530 Subject: [PATCH 223/455] Python script to check if String C is formed by interleaving of String A and String B --- .../strings/check_interleaving_of_strings.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 data_structures/strings/check_interleaving_of_strings.py diff --git a/data_structures/strings/check_interleaving_of_strings.py b/data_structures/strings/check_interleaving_of_strings.py new file mode 100644 index 00000000..e232ed51 --- /dev/null +++ b/data_structures/strings/check_interleaving_of_strings.py @@ -0,0 +1,57 @@ +''' +Question: Given three strings A, B and C. Write a function that checks whether C +is an interleaving of A and B. C is said to be interleaving A and B, if +it contains all characters of A and B and order of all characters in +individual strings is preserved. + +Solution: We include one character from String A or String B and check whether the resultant +string formed so far by one particular interleaving of the the current prefix of String A +and String B form a prefix of String C. This can be achieved using dynamic programming. +This approach relies on fact that in order to determine whether a +substring of String C(upto index k), can be formed by interleaving strings String A +and String B upto indices i and j respectively depends on the characters of +String A and String B upto indices i and j only and not on characters coming afterwards. + +Complexity analysis - +Time complexity : O(m x n) . dp array of size n is filled m times where m and n are lengths of +String A and String B respectively. +Space complexity : O(n) + +''' + +#Function to check if String C is formed by interleaving of String A and B +#Returns a boolean value +def isInterleaving(string_A, string_B, string_C): + #Check if the length of String C is equal to sum of lengths of String A and B + #In other words, check if String C contains all characters of String A and B + if(len(string_C) != len(string_A) + len(string_B)): return False + + #Create an empty array of length of String B + dp = [None] * (len(string_B) + 1) + + for i in range(len(string_A) + 1): + for j in range(len(string_B) + 1): + if(i == 0 and j == 0): + #The first value of array dp always holds True + dp[j] = True + elif(i == 0): + dp[j] = dp[j - 1] and string_B[j - 1] == string_C[j - 1] + elif(j == 0): + dp[j] = dp[j] and string_A[i - 1] == string_C[i - 1] + else: + dp[j] = ((dp[j] and string_A[i - 1] == string_C[i + j - 1]) or (dp[j - 1] and string_B[j - 1] == string_C[i + j - 1])) + + + return dp[len(string_B)] + +#Driver Code +string_A = input("Enter string A") +string_B = input("Enter string B") +string_C = input("Enter string C") + +result = isInterleaving(string_A, string_B, string_C) + +if(result): + print("String C is interleaving String A and String B") +else: + print("String C is not interleaving String A and String B") \ No newline at end of file From a7d522a40483af94cb902bba880f90ee116d704f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 1 Dec 2019 18:52:53 +0530 Subject: [PATCH 224/455] new question --- .../binary_trees/sum_predecessor_successor.py | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 data_structures/binary_trees/sum_predecessor_successor.py diff --git a/data_structures/binary_trees/sum_predecessor_successor.py b/data_structures/binary_trees/sum_predecessor_successor.py new file mode 100644 index 00000000..be333a01 --- /dev/null +++ b/data_structures/binary_trees/sum_predecessor_successor.py @@ -0,0 +1,73 @@ +# Convert a binary tree such that each node is the sum of +# its inorder predecessor and successor + +# Store the inorder traversal in an array. Now while traversing +# replace each node with the values arr[i-1] + arr[i+1] as these +# are the inorder predecessor and successor + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def inorder(root): + if not root: + return None + + arr = [] + stack = [] + + while True: + if root: + stack.append(root) + root = root.left + else: + if not stack: + break + root = stack.pop() + arr.append(root.val) + root = root.right + + return arr + + +def replace_nodes(root, arr): + if not root: + return + + stack = [] + i = 1 + while True: + if root: + stack.append(root) + root = root.left + else: + if not stack: + break + root = stack.pop() + root.val = arr[i-1] + arr[i+1] + i += 1 + root = root.right + + + return root + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(4) +root.left.right = Node(5) +root.right.right = Node(7) +root.right.left = Node(6) + +arr = inorder(root) +print('Inorder traversal original - ', arr) + +new_root = replace_nodes(root, arr) +new_arr = inorder(new_root) +print('New traversal - ', new_arr) + From d33de1e418fd49def40c459636482b46a266cfb4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 2 Dec 2019 11:41:01 +0530 Subject: [PATCH 225/455] Create sum_of_all_nodes.py --- data_structures/binary_trees/sum_of_all_nodes.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 data_structures/binary_trees/sum_of_all_nodes.py diff --git a/data_structures/binary_trees/sum_of_all_nodes.py b/data_structures/binary_trees/sum_of_all_nodes.py new file mode 100644 index 00000000..e5fe0dd1 --- /dev/null +++ b/data_structures/binary_trees/sum_of_all_nodes.py @@ -0,0 +1,15 @@ +# Find the sum of all nodes of a binary tree + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def sum_nodes(root): + if root is None: + return 0 + + return root.val + sum_nodes(root.left) + sum_nodes(root.right) From 83823a6aec5c6f4773261016c65d91d0ad8485bd Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 2 Dec 2019 11:56:31 +0530 Subject: [PATCH 226/455] Create sum_of_all_left_leaves.py --- .../binary_trees/sum_of_all_left_leaves.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 data_structures/binary_trees/sum_of_all_left_leaves.py diff --git a/data_structures/binary_trees/sum_of_all_left_leaves.py b/data_structures/binary_trees/sum_of_all_left_leaves.py new file mode 100644 index 00000000..4ef261f8 --- /dev/null +++ b/data_structures/binary_trees/sum_of_all_left_leaves.py @@ -0,0 +1,47 @@ +# Find the sum of all left leaves of a binary tree + + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def is_leaf(root): + if root is None: + return False + if root.left is None and root.right is None: + return True + return False + + +def sum_left(root): + s = 0 + stack = [] + + while True: + if root: + stack.append(root) + root = root.left + else: + if not stack: + break + root = stack.pop() + if is_leaf(root.left): + s += root.left.val + root = root.right + + return s + + +root = Node(9) +root.left = Node(8) +root.right = Node(6) +root.right.left = Node(1) + +root.left.left = Node(5) +root.left.right = Node(2) + +print(sum_left(root)) From a36d2ad983f8a5b31ebb904df18299ae881ffd01 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 2 Dec 2019 12:02:54 +0530 Subject: [PATCH 227/455] Create sum_of_perfect_binary_tree.py --- .../binary_trees/sum_of_perfect_binary_tree.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 data_structures/binary_trees/sum_of_perfect_binary_tree.py diff --git a/data_structures/binary_trees/sum_of_perfect_binary_tree.py b/data_structures/binary_trees/sum_of_perfect_binary_tree.py new file mode 100644 index 00000000..f438015f --- /dev/null +++ b/data_structures/binary_trees/sum_of_perfect_binary_tree.py @@ -0,0 +1,12 @@ +# https://www.geeksforgeeks.org/find-sum-nodes-given-perfect-binary-tree/ + +import math + +def sum_nodes(l): + leaf_nodes = math.pow(2, l-1) + + s = (leaf_nodes + (leaf_nodes + 1)) / 2 + + res = s * l + + return int(res) From b480e9f4a83b0c8eaea5e0502c402aa945b2e0f3 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 2 Dec 2019 12:11:26 +0530 Subject: [PATCH 228/455] Create largest_subtree_sum.py --- .../binary_trees/largest_subtree_sum.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 data_structures/binary_trees/largest_subtree_sum.py diff --git a/data_structures/binary_trees/largest_subtree_sum.py b/data_structures/binary_trees/largest_subtree_sum.py new file mode 100644 index 00000000..d79002f2 --- /dev/null +++ b/data_structures/binary_trees/largest_subtree_sum.py @@ -0,0 +1,31 @@ +# Find the largest subtree sum in a binary tree +# Do a postorder traversal + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def sum_util(root, ans): + if root is None: + return 0 + + s = root.val + sum_util(root.left, ans) + sum_util(root.right, ans) + + ans[0] = max(ans[0], s) + + return s + + +def find_sum(root): + if root is None: + return 0 + + ans = [-99999999] + + sum_util(root, ans) + + return ans[0] From e84921d59f86525e729af26e20fcb29e14e4aee3 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 2 Dec 2019 12:13:58 +0530 Subject: [PATCH 229/455] Create TO_DO --- data_structures/binary_trees/TO_DO | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data_structures/binary_trees/TO_DO diff --git a/data_structures/binary_trees/TO_DO b/data_structures/binary_trees/TO_DO new file mode 100644 index 00000000..cb734cb7 --- /dev/null +++ b/data_structures/binary_trees/TO_DO @@ -0,0 +1,2 @@ +1. Max width of a binary tree +2. Total width of a binary tree From 2c81da93d04ad46fd1f1f097930ba4c74b0a586d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 3 Dec 2019 11:02:05 +0530 Subject: [PATCH 230/455] Create kosaraju_algorithm.py --- data_structures/graphs/kosaraju_algorithm.py | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 data_structures/graphs/kosaraju_algorithm.py diff --git a/data_structures/graphs/kosaraju_algorithm.py b/data_structures/graphs/kosaraju_algorithm.py new file mode 100644 index 00000000..cfc2a2b0 --- /dev/null +++ b/data_structures/graphs/kosaraju_algorithm.py @@ -0,0 +1,65 @@ +# Reference - https://www.geeksforgeeks.org/strongly-connected-components/ + +# This is used to find all the strongly connected components and does DFS +# 2 times. + +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def dfs_util(self, v, visited): + visited[v] = True + print(v, end=' ') + + for i in self.graph[v]: + if visited[i] == False: + self.dfs_util(i, visited) + + + def fill_order(self, v, visited, stack): + visited[v] = True + for i in self.graph[v]: + if visited[i] == False: + self.fill_order(i, visited, stack) + stack.append(v) + + + def get_transpose(self): + g = Graph(self.V) + + for i in self.graph: + for j in self.graph[i]: + g.add_edge(j, i) + + return g + + + def kosaraju(self): + stack = [] + visited = [False] * self.V + + for i in range(self.V): + if visited[i] == False: + self.fill_order(i, visited, stack) + + gr = self.get_transpose() + + visited = [False] * self.V + + while stack: + i = stack.pop() + if visited[i] == False: + gr.dfs_util(i, visited) + print() + + From b0ffd60867a019c79ce95ccd297a59ed61bceabf Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 3 Dec 2019 11:16:49 +0530 Subject: [PATCH 231/455] Create activity_selection.py --- algorithms/greedy/activity_selection.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 algorithms/greedy/activity_selection.py diff --git a/algorithms/greedy/activity_selection.py b/algorithms/greedy/activity_selection.py new file mode 100644 index 00000000..8dbd822f --- /dev/null +++ b/algorithms/greedy/activity_selection.py @@ -0,0 +1,18 @@ +#Prints a maximum set of activities that can be done by a +#single person, one at a time +#n --> Total number of activities +#s[]--> An array that contains start time of all activities +#f[] --> An array that contains finish time of all activities + +def print_max_activities(s, f): + n = len(f) + + # the first activity is always selected + i = 0 + print(i, end=' ') + + # for the rest + for j in range(n): + if s[j] >= f[i]: + print(j, end=' ') + i = j From 3e7f8fdbcfdcc91ae22369055d354c8d80478b80 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 3 Dec 2019 11:21:15 +0530 Subject: [PATCH 232/455] Create egyptian_fraction.py --- algorithms/greedy/egyptian_fraction.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 algorithms/greedy/egyptian_fraction.py diff --git a/algorithms/greedy/egyptian_fraction.py b/algorithms/greedy/egyptian_fraction.py new file mode 100644 index 00000000..3d3ea79d --- /dev/null +++ b/algorithms/greedy/egyptian_fraction.py @@ -0,0 +1,13 @@ +# Reference - https://www.geeksforgeeks.org/greedy-algorithm-egyptian-fraction/ + +import math + +def egyptian_fraction(nr, dr): + ef = [] + + while nr != 0: + x = math.ceil(dr / nr) + ef.append(x) + + nr = x * nr - dr + dr = dr * x From a8e927939a6e111956891115f0912853a3ddaf4d Mon Sep 17 00:00:00 2001 From: Tejesh Date: Wed, 4 Dec 2019 14:56:35 +0530 Subject: [PATCH 233/455] Update index_updater.py --- index_updater.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index_updater.py b/index_updater.py index 296518da..7f4778ae 100755 --- a/index_updater.py +++ b/index_updater.py @@ -16,7 +16,7 @@ curr_folder = os.path.basename(root) for name in files: - if name.endswith('.py') and not name == '__init__py' and not dirs: + if name.endswith('.py') and not name == '__init__.py' and not dirs: curr_files.append(name) # If we have files, write "index.md" @@ -24,4 +24,5 @@ with open(os.path.join(root, 'index.md'), mode='w') as md_file: md_file.write('# Index of {}\n\n'.format(curr_folder)) for line in curr_files: - md_file.write('* ' + line + '\n') + file_name = line.split('.')[0].replace('_',' ').title() + md_file.write('* [' + file_name + '](' +line + ')\n') From cfe92c10d61aeb1de0fe1abf0bf27150c7ec0e72 Mon Sep 17 00:00:00 2001 From: vernalhav Date: Sun, 15 Dec 2019 19:54:39 -0300 Subject: [PATCH 234/455] Made LIS code simpler --- .../longest_increasing_subsequence.py | 85 +++++++------------ 1 file changed, 32 insertions(+), 53 deletions(-) diff --git a/algorithms/dynamic_programming/longest_increasing_subsequence.py b/algorithms/dynamic_programming/longest_increasing_subsequence.py index 30978c2f..1a00abf2 100644 --- a/algorithms/dynamic_programming/longest_increasing_subsequence.py +++ b/algorithms/dynamic_programming/longest_increasing_subsequence.py @@ -6,67 +6,46 @@ of that array ''' -def memoize(f): - """ - Generic decorator for - Dynamic Programming - problems + +def lis(s, cur_index=0, last_index=-1, cur_length=0, dp=None): """ - cache = dict() - def memoized_f(*args): - if args in cache: - global hits - hits += 1 - return cache[args] + Return length of the longest increasing + subsequence from array s. - cache[args] = f(*args) - return cache[args] + To use, simply call lis(s). The other + parameters will be used in the + recursion + """ - return memoized_f + # Initialize dp dictionary to use in the recursion + if dp == None: + dp = dict() + # Base case: we've gone through the whole array + if cur_index == len(s): + return cur_length -def lis(s): - """ Return length of LIS in array s """ + if dp.get((last_index, cur_index)) is not None: + return dp.get((last_index, cur_index)) # Return stored value ''' - NOTE: array s will be declared in the superscope - of lis_routine, so it doesn't need to be passed - as argument and subsequently not hashed by @memoize + Length of the LIS if we include cur_index + is initialized as -1 because we might not + be able to include it if it is less than + the number at last_index. If last_index is + -1, we can take cur_index, as it will be + the first integer in the possible LIS. ''' - - @memoize - def lis_routine(cur_index=0, last_index=-1, cur_length=0): - """ - Return length of the longest increasing - subsequence from array s. - - To use, simply call lis(s). The other - parameters will be used in the - recursion - """ - - if cur_index == len(s): - return cur_length - - ''' - Length of the LIS if we include cur_index - is initialized as -1 because we might not - be able to include it if it is less than - the number at last_index. If last_index is - -1, we can take cur_index, as it will be - the first integer in the possible LIS. - ''' - take = -1 - if last_index == -1 or s[last_index] < s[cur_index]: - take = lis_routine(cur_index + 1, cur_index, cur_length + 1) - - # Length of the LIS if we don't include cur_index - not_take = lis_routine(cur_index + 1, last_index, cur_length) - - # Return the greatest LIS (include cur_index or not) - return max(take, not_take) - - return lis_routine() + take = -1 + if last_index == -1 or s[last_index] < s[cur_index]: + take = lis(s, cur_index + 1, cur_index, cur_length + 1, dp) + + # Length of the LIS if we don't include cur_index + not_take = lis(s, cur_index + 1, last_index, cur_length, dp) + + # Return the greatest LIS (include cur_index or not) + dp[(last_index, cur_index)] = max(take, not_take) # Store result in cache + return dp.get((last_index, cur_index)) def main(): From f4e2f066fbc67c6f155a6db7b21f014a6255bb56 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 22 Dec 2019 10:01:58 +0530 Subject: [PATCH 235/455] Update README.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index c76377a1..4df4e4a9 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ Contains all data structure questions categorised into sub-directories like stac This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - - 1. [Dynamic Programming](algorithms/dynamic_programming) 2. [Graphs](algorithms/graph) 3. [Greedy](algorithms/greedy) @@ -37,7 +36,6 @@ This directory contains various types of algorithm questions like Dynamic Progra 5. [Misc](algorithms/miscellaneous) 6. [Sorting](algorithms/sorting) - ### Bookmarks You can find useful links in this repository in the different markdown files. Below is a table of contents. @@ -68,7 +66,6 @@ Feel free to raise new issues, file new PRs and star and fork this repo! :wink: To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) - ## :page_facing_up: License [MIT @ Prabhu Pant](LICENSE) From 5556b7c46de4100edbd2020e03d73c22b92f7ee2 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 29 Dec 2019 21:16:08 +0530 Subject: [PATCH 236/455] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 4df4e4a9..9e789645 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,6 @@ As you can see, the repo is still in its infancy. Here are some key things in th 1. Queue questions 2. Algorithms - 2.1. Dynamic Programming - 2.2. Greedy 3. More questions in data structures, especially for graph, circular linked list, tries, heaps and hash. ## :raised_hand: Contributing From cccb2723d48c7ef87191e959b29f6f6b61799840 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 9 Jan 2020 07:22:35 +0530 Subject: [PATCH 237/455] Added matrix --- ...find_in_row_and_column_wise_sorted_matrix.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 data_structures/matrix/find_in_row_and_column_wise_sorted_matrix.py diff --git a/data_structures/matrix/find_in_row_and_column_wise_sorted_matrix.py b/data_structures/matrix/find_in_row_and_column_wise_sorted_matrix.py new file mode 100644 index 00000000..cd1b07e6 --- /dev/null +++ b/data_structures/matrix/find_in_row_and_column_wise_sorted_matrix.py @@ -0,0 +1,17 @@ +def search(mat, n, x): + + i = 0 + + j = n - 1 + + while i < n and j >=0: + if mat[i][j] == x: + print("Found at - ", i, j) + return 1 + if mat[i][j] > x: + j -= 1 + else: + i += 1 + + print("Element not found") + return 0 From 396bcd5d82706218113d6274fc3fb34f586aab26 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 12 Jan 2020 15:18:00 +0530 Subject: [PATCH 238/455] Matrix question --- data_structures/matrix/find_pair.py | 0 .../matrix/flood_fill_algorithm.py | 23 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 data_structures/matrix/find_pair.py create mode 100644 data_structures/matrix/flood_fill_algorithm.py diff --git a/data_structures/matrix/find_pair.py b/data_structures/matrix/find_pair.py new file mode 100644 index 00000000..e69de29b diff --git a/data_structures/matrix/flood_fill_algorithm.py b/data_structures/matrix/flood_fill_algorithm.py new file mode 100644 index 00000000..d5d3da24 --- /dev/null +++ b/data_structures/matrix/flood_fill_algorithm.py @@ -0,0 +1,23 @@ +# Reference - https://www.geeksforgeeks.org/flood-fill-algorithm-implement-fill-paint/ + +# Dimensions of paint screen +M = 8 +N = 8 + +def flood_fill_util(screen, x, y prev_color, new_color): + if x < 0 or x >= M or y < 0 or y >= N or screen[x][y] != prev_color or screen[x][y] == new_color: + return + + screen[x][y] = new_color + flood_fill_util(screen, x + 1, y, prev_color, new_color) + flood_fill_util(screen, x - 1, y, prev_color, new_color) + flood_fill_util(screen, x, y + 1, prev_color, new_color) + flood_fill_util(screen, x, y - 1, prev_color, new_color) + + +def flood_fill(screen, x, y, new_color): + prev_color = screen[x][y] # Finding the previous color on x and y + flood_fill_util(screen, x, y, prev_color, new_color) + + + From e975b326d0bd3fb1eafc9fcd989773519e5c6aab Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 16 Jan 2020 21:39:14 +0530 Subject: [PATCH 239/455] Update README.md From 9aabe86224b25ca70ac9ad61681b9bb431cd7ebf Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 20 Jan 2020 15:19:19 +0530 Subject: [PATCH 240/455] Create find_common_in_three_arrays.py --- .../array/find_common_in_three_arrays.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 data_structures/array/find_common_in_three_arrays.py diff --git a/data_structures/array/find_common_in_three_arrays.py b/data_structures/array/find_common_in_three_arrays.py new file mode 100644 index 00000000..7c254ef8 --- /dev/null +++ b/data_structures/array/find_common_in_three_arrays.py @@ -0,0 +1,26 @@ +# Find the common elements in three arrays + +def find_common(arr1, arr2, arr3): + i, j, k = 0, 0, 0 + + while i < len(arr1) and j < len(arr2) and k < len(arr3): + if arr1[i] == arr2[j] == arr3[k]: + print(arr1[i]) + i += 1 + j += 1 + k += 1 + + elif arr1[i] < arr2[j]: + i += 1 + + elif arr2[j] < arr3[k]: + j += 1 + + else: + k += 1 + +arr1 = [1,2,3,4,5,6] +arr2 = [5,6,7,8,9] +arr3 = [4,5,6,9,10] + +find_common(arr1, arr2, arr3) From d34e1529b3a8c5f1f8ece2e6b292330423a77978 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 20 Jan 2020 15:38:46 +0530 Subject: [PATCH 241/455] Create find_given_sum_in_array.py --- .../array/find_given_sum_in_array.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 data_structures/array/find_given_sum_in_array.py diff --git a/data_structures/array/find_given_sum_in_array.py b/data_structures/array/find_given_sum_in_array.py new file mode 100644 index 00000000..0aacc5b4 --- /dev/null +++ b/data_structures/array/find_given_sum_in_array.py @@ -0,0 +1,27 @@ +# Find if a given sum exists in an array +# Reference - https://www.geeksforgeeks.org/find-subarray-with-given-sum/ + +def find_sum(arr, s): + curr_sum = arr[0] + start = 0 + n = len(arr) - 1 + + i = 1 + + while i <= n: + + while curr_sum > s and start < i: + curr_sum = curr_sum - arr[start] + start += 1 + + if curr_sum == s: + return "Found between {} and {}".format(start, i - 1) + + curr_sum = curr_sum + arr[i] + i += 1 + + return "Sum not found" + +arr = [15, 2, 4, 8, 9, 5, 10, 23] + +print(find_sum(arr, 6)) From 75c815c771c04201910a84761ff177b5e7e708ff Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 21 Jan 2020 12:54:42 +0530 Subject: [PATCH 242/455] Delete daysofweek.py --- data_structures/array/daysofweek.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 data_structures/array/daysofweek.py diff --git a/data_structures/array/daysofweek.py b/data_structures/array/daysofweek.py deleted file mode 100644 index 2b279f23..00000000 --- a/data_structures/array/daysofweek.py +++ /dev/null @@ -1,18 +0,0 @@ -''' -Given a date, return the corresponding day of the week for that date. -The input is given as three integers representing the day, month and year respectively. -Return the answer as one of the following values {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}. -The given dates are valid dates between the years 1971 and 2100. - -Example 1: -Input: day = 31, month = 8, year = 2019 -Output: "Saturday" -''' - # :type day: int , :type month: int , :type year: int , :rtype: str - -class Solution(object): - def dayOfTheWeek(self, day, month, year): - day_of_week_map = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] - t = [ 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 ] - year -= month < 3 - return day_of_week_map[((year + int(year / 4) - int(year / 100) + int(year / 400) + t[month - 1] + day) % 7)] \ No newline at end of file From b9d84e962a7b0beefca9607d6a406f98199e2430 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 21 Jan 2020 13:49:06 +0530 Subject: [PATCH 243/455] Delete matrix_layer_rotation.py --- .../array/matrix_layer_rotation.py | 88 ------------------- 1 file changed, 88 deletions(-) delete mode 100644 data_structures/array/matrix_layer_rotation.py diff --git a/data_structures/array/matrix_layer_rotation.py b/data_structures/array/matrix_layer_rotation.py deleted file mode 100644 index ef5d36c7..00000000 --- a/data_structures/array/matrix_layer_rotation.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Description: - -Matrix Layer Rotation - -You are given a 2D matrix of dimension mxn and a positive integer r. You have to rotate the -matrix r times and print the resultant matrix. Rotation should be in anti-clockwise direction. -Rotation of a 4x5 matrix is represented by the following figure. Note that in one rotation, -you have to shift elements by one step only. This is shifting the elemment. -Note:- Minimum of m and n will be even. - -Start First Second - 1 2 3 4 2 3 4 5 3 4 5 6 -12 1 2 5 -> 1 2 3 6 -> 2 3 4 7 -11 4 3 6 12 1 4 7 1 2 1 8 -10 9 8 7 11 10 9 8 12 11 10 9 -""" - - -# Function to rotate the sides of the matrix in place. -def matrix_rotate(matrix, m, n, i=0, j=0): - if (m, n) == (1, 1): - return matrix - if (m, n) == (2, 2): - temp = matrix[i][j] - matrix[i][j] = matrix[i + 1][j] - matrix[i + 1][j] = matrix[i + 1][j + 1] - matrix[i + 1][j + 1] = matrix[i + 1][j] - matrix[i + 1][j] = temp - return matrix - else: - temp = matrix[i][j] - # top - for a in range(j, n - j - 1): - matrix[i][a] = matrix[i][a + 1] - matrix[i][n - j - 1] = matrix[i + 1][n - j - 1] - # right - for a in range(i + 1, m - i - 2): - matrix[a][n - 1 - j] = matrix[a + 1][n - 1 - j] - matrix[m - j - 2][n - j - 1] = matrix[m - j - 1][n - j - 1] - # bottom - for a in range(n - j - 1, j, -1): - matrix[m - j - 1][a] = matrix[m - j - 1][a - 1] - matrix[m - j - 1][j] = matrix[m - j - 2][j] - # left - for a in range(m - i - 2, i, -1): - matrix[a][i] = matrix[a - 1][i] - matrix[i + 1][j] = temp - return matrix - - -def driver_code(matrix, r): - m = len(matrix) - n = len(matrix[0]) - i, j = 0, 0 - s = 0 - while (i, j) < (m // 2, n // 2): # Checking for the maximum values of i, j. - for _ in range(r): - s = matrix_rotate(matrix, m, n, i, j) - i += 1 - j += 1 - print_matrix(s) - - -def print_matrix(matrix): - m = len(matrix) - n = len(matrix[0]) - print('\n'.join([' '.join(['{:n}'.format(item) for item in row]) - for row in matrix])) - - -if __name__ == '__main__': - mnr = input().rstrip().split() - - m = int(mnr[0]) - - n = int(mnr[1]) - - r = int(mnr[2]) - - matrix2d = [] - - for _ in range(m): - matrix2d.append(list(map(int, input().rstrip().split()))) - - driver_code(matrix2d, r) - - From 004c3cc63a93bf2a3b11bfde95de34e12c7a1684 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 21 Jan 2020 13:55:25 +0530 Subject: [PATCH 244/455] Update min_product.py --- data_structures/array/min_product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/min_product.py b/data_structures/array/min_product.py index bdf7cbf3..e83cf5e6 100644 --- a/data_structures/array/min_product.py +++ b/data_structures/array/min_product.py @@ -7,7 +7,7 @@ # If there are odd number of negative numbers and no zeros, # the result is simply the product of all -# If there is a zero, then the result is zero +# If there is a zero and al other are positive, then the result is zero # If there are only positive numbers, the the result is # the smallest positive number From b54017fe5bdd74956c145d668f09e473b62c83e8 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 10:44:08 +0530 Subject: [PATCH 245/455] Update mother_vertex.py --- data_structures/graphs/mother_vertex.py | 58 +++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/data_structures/graphs/mother_vertex.py b/data_structures/graphs/mother_vertex.py index bc996c78..40f8ac10 100644 --- a/data_structures/graphs/mother_vertex.py +++ b/data_structures/graphs/mother_vertex.py @@ -1,5 +1,63 @@ # A mother vertex is a vertex such that all other vertices # can be reached by a path from this vertex +# Reference - https://www.geeksforgeeks.org/find-a-mother-vertex-in-a-graph/ +# Time complexity - 2 * O(V + E) = O(V + E) +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def dfs_util(self, v, visited): + visited[v] = True + + for i in self.graph[v]: + if visited[i] == False: + self.dfs_util(i, visited) + + + def add_edge(self, v, w): + self.graph[v].append(w) + + + def find_mother(self): + visited = [False] * self.V + + v = 0 + + for i in range(self.V): + if visited[i] == False: + self.dfs_util(i, visited) + v = i + + # Now check if v is one of the mother vertex + # Reset all the values of visited and do DFS beginning from v + # to check if all the vertices are reachable from it or not + + visited = [False] * self.V + self.dfs_util(v, visited) + + if any(i == False for i in visited): + return -1 + + else: + return v + + +g = Graph(7) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 3) +g.add_edge(4, 1) +g.add_edge(6, 4) +g.add_edge(5, 6) +g.add_edge(5, 2) +g.add_edge(6, 0) + +print("Mother vertex is - ", g.find_mother()) From 72fed7a11a9bb0f03be044f7ab28fcf7bc858faf Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 10:55:04 +0530 Subject: [PATCH 246/455] Create iterative_dfs.py --- data_structures/graphs/iterative_dfs.py | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/graphs/iterative_dfs.py diff --git a/data_structures/graphs/iterative_dfs.py b/data_structures/graphs/iterative_dfs.py new file mode 100644 index 00000000..face3aaf --- /dev/null +++ b/data_structures/graphs/iterative_dfs.py @@ -0,0 +1,37 @@ +# The code is almost same to BFS, the only difference being queue +# is replaced by stack + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def dfs(self, s): + visited = [False] * self.V + + stack = [] + + stack.append(s) + + while stack: + s = stack[-1] + stack.pop() + + if not visited[s]: + print(s, end=' ') + visited[s] = True + + for i in self.graph[s]: + if not visited[i]: + stack.append(i) + + + From 6ffbe5169c7ef81bc400315b05efd9283153ed45 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 11:02:02 +0530 Subject: [PATCH 247/455] Create transpose.py --- data_structures/graphs/transpose.py | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 data_structures/graphs/transpose.py diff --git a/data_structures/graphs/transpose.py b/data_structures/graphs/transpose.py new file mode 100644 index 00000000..02270c55 --- /dev/null +++ b/data_structures/graphs/transpose.py @@ -0,0 +1,44 @@ +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def print_graph(self): + for i in self.graph: + print(i, " --> ", end=" ") + for j in self.graph[i]: + print(j, end=" ") + print() + + + def transpose(self): + g = Graph(self.V) + + for i in self.graph: + for j in self.graph[i]: + g.add_edge(j, i) + + return g + + +g = Graph(5) +g.add_edge(1, 0) +g.add_edge(0, 2) +g.add_edge(2, 1) +g.add_edge(0, 3) +g.add_edge(3, 4) +g.print_graph() + +print('---------') + +t = g.transpose() +t.print_graph() From f59acf175ebbd20862cd6f3493b57e8008f08d63 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 12:50:45 +0530 Subject: [PATCH 248/455] Create bipartite_graph.py --- data_structures/graphs/bipartite_graph.py | 46 +++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 data_structures/graphs/bipartite_graph.py diff --git a/data_structures/graphs/bipartite_graph.py b/data_structures/graphs/bipartite_graph.py new file mode 100644 index 00000000..0c851248 --- /dev/null +++ b/data_structures/graphs/bipartite_graph.py @@ -0,0 +1,46 @@ +# Check for bipartite graph + +# Do a BFS and make source of red color and its neighbour blue +# Keep on doing this. +# If self loop, return false +# If current color == neighbour color, false, else true + +# Reference - https://www.geeksforgeeks.org/bipartite-graph/ + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def is_bipartite(self, s): + # 0 -> color 0 + # 1 -> color 1 + # -1 -> no color assigned + + colors = [-1] * self.V + colors[s] = 1 + + queue = [] + queue.append(s) + + while queue: + u = queue.pop() + + if self.graph[u][v] == 1: # Check for self loop + return False + + # An edge u to v exists and destination is not + # colored + for v in range(self.V): + if self.graph[u][v] == 1 and colors[v] == -1: + colors[v] = 1 - colors[u] + queue.append(v) + + elif self.graph[u][v] == 1 and colors[v] == colors[u]: + return False + + return True From 4d8482186dcf8d32fbe489f17bb62a2184a88d77 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 15:34:02 +0530 Subject: [PATCH 249/455] Create count_paths_between_nodes.py --- .../graphs/count_paths_between_nodes.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 data_structures/graphs/count_paths_between_nodes.py diff --git a/data_structures/graphs/count_paths_between_nodes.py b/data_structures/graphs/count_paths_between_nodes.py new file mode 100644 index 00000000..3b1f71de --- /dev/null +++ b/data_structures/graphs/count_paths_between_nodes.py @@ -0,0 +1,47 @@ +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def count_paths_util(self, u, d, visited, path_count): + visited[u] = True + + if u == d: + path_count[0] += 1 + + else: + i = 0 + for i in range(len(self.graph[u])): + if not visited[self.graph[u][i]]: + self.count_paths_util(self.graph[u][i], d, visited, path_count) + + visited[u] = False + + + def count_paths(self, s, d): + visited = [False] * self.V + path_count = [0] + self.count_paths_util(s, d, visited, path_count) + return path_count[0] + + +g = Graph(4) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(0, 3) +g.add_edge(2, 0) +g.add_edge(2, 1) +g.add_edge(1, 3) + +s = 2 +d = 3 + +print(g.count_paths(s, d)) From fc3eae1c2bd94ebca302622aa0e871e11fac705e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 16:06:40 +0530 Subject: [PATCH 250/455] Create cycle_in_directed_graph.py --- .../graphs/cycle_in_directed_graph.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 data_structures/graphs/cycle_in_directed_graph.py diff --git a/data_structures/graphs/cycle_in_directed_graph.py b/data_structures/graphs/cycle_in_directed_graph.py new file mode 100644 index 00000000..2a2b3253 --- /dev/null +++ b/data_structures/graphs/cycle_in_directed_graph.py @@ -0,0 +1,40 @@ +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def is_cyclic_util(self, v, visited, rec_stack): + visited[v] = True + rec_stack[v] = True + + for neighbour in self.graph[v]: + if visited[neighbour] == False: + if self.is_cyclic_util(neighbour, visited, rec_stack): + return True + + elif rec_stack[neighbour] == True: + return True + + rec_stack[v] = False + return False + + + def is_cyclic(self): + visited = [False] * self.V + rec_stack = [False] * self.V + + for i in range(self.V): + if visited[i] == False: + if self.is_cyclic_util(node, visited, rec_stack) == True: + return True + + return False From 4cfffdbd9293dfed6e560ebeb2a8a10ac9808c3e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 23 Jan 2020 16:17:39 +0530 Subject: [PATCH 251/455] Create cyclic_in_undirected_graph.py --- .../graphs/cyclic_in_undirected_graph.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/graphs/cyclic_in_undirected_graph.py diff --git a/data_structures/graphs/cyclic_in_undirected_graph.py b/data_structures/graphs/cyclic_in_undirected_graph.py new file mode 100644 index 00000000..bb16b122 --- /dev/null +++ b/data_structures/graphs/cyclic_in_undirected_graph.py @@ -0,0 +1,37 @@ +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def is_cyclic_util(self, v, visited, parent): + visited[v] = True + + for i in self.graph[v]: + if visited[i] == False: + if self.is_cyclic_util(i, visited, v): + return True + + elif parent != i: + return True + + return False + + + def is_cyclic(self): + visited = [False] * (self.V) + + for i in range(self.V): + if visited[i] == False: + if self.is_cyclic_util(i, visited, -1): + return True + + return False From 9652add89dc6bd30221c332f04bb99e44c2131ce Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 24 Jan 2020 13:00:53 +0530 Subject: [PATCH 252/455] Create topological_sort.py --- data_structures/graphs/topological_sort.py | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 data_structures/graphs/topological_sort.py diff --git a/data_structures/graphs/topological_sort.py b/data_structures/graphs/topological_sort.py new file mode 100644 index 00000000..d0fb65fa --- /dev/null +++ b/data_structures/graphs/topological_sort.py @@ -0,0 +1,33 @@ +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def topo_sort_util(self, v, visited, stack): + visited[v] = True + + for i in self.graph[v]: + if visited[i] == False: + self.topo_sort_util(i, visited, stack) + + stack.insert(0, v) + + + def topo_sort(self): + visited = [False] * self.V + stack = [] + + for i in range(self.V): + if visited[i] == False: + self.topo_sort_util(i, visited, stack) + + print(stack) From ef7b1e29e141a428c656b80c3b2eff4abbd0a0ab Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 27 Jan 2020 15:15:34 +0530 Subject: [PATCH 253/455] Create root_which_gives_min_height.py --- .../graphs/root_which_gives_min_height.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 data_structures/graphs/root_which_gives_min_height.py diff --git a/data_structures/graphs/root_which_gives_min_height.py b/data_structures/graphs/root_which_gives_min_height.py new file mode 100644 index 00000000..77a738a9 --- /dev/null +++ b/data_structures/graphs/root_which_gives_min_height.py @@ -0,0 +1,56 @@ +# Reference - https://www.geeksforgeeks.org/roots-tree-gives-minimum-height/ + +from collections import defaultdict +from queue import Queue + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + self.degree = [0] * vertices + + + def add_edge(self, v, w): + self.graph[v].append(w) + self.graph[w].append(v) + self.degree[v] += 1 + self.degree[w] += 1 + + + def root_min_height(self): + q = Queue() + + for i in range(self.V): + if self.degree[i] == 1: + q.put(i) + + + while self.V > 2: + for i in range(q.qsize()): + t = q.get() + self.V -= 1 + + # For each neighbour decrease its degree and if it becomes + # leaf, insert into the queue + for j in self.graph[t]: + self.degree[j] -= 1 + if self.degree[j] == 1: + q.put(j) + + + res = list() + while q.qsize() > 0: + res.append(q.get()) + + + return res + +g = Graph(6) +g.add_edge(0, 3) +g.add_edge(1, 3) +g.add_edge(2, 3) +g.add_edge(4, 3) +g.add_edge(5, 4) + +print(g.root_min_height()) From 34029c1c899101fd7e6ff7709dee552c70863f6e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 27 Jan 2020 15:25:12 +0530 Subject: [PATCH 254/455] Create longest_path.py --- data_structures/graphs/longest_path.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 data_structures/graphs/longest_path.py diff --git a/data_structures/graphs/longest_path.py b/data_structures/graphs/longest_path.py new file mode 100644 index 00000000..e3334433 --- /dev/null +++ b/data_structures/graphs/longest_path.py @@ -0,0 +1 @@ +# https://www.geeksforgeeks.org/longest-path-between-any-pair-of-vertices/ From 3818db23a15c06068b77fb75e3dc191b2ad4dd71 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 28 Jan 2020 11:41:20 +0530 Subject: [PATCH 255/455] Create trie.py --- data_structures/trie/trie.py | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 data_structures/trie/trie.py diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py new file mode 100644 index 00000000..c4c533ba --- /dev/null +++ b/data_structures/trie/trie.py @@ -0,0 +1,91 @@ +class TrieNode(): + def __init__(self): + + self.children = {} + self.last = False + +class Trie(): + def __init__(self): + + self.root = TrieNode() + self.word_list = [] + + def formTrie(self, keys): + + for key in keys: + self.insert(key) + + def insert(self, key): + + node = self.root + + for a in list(key): + if not node.children.get(a): + node.children[a] = TrieNode() + + node = node.children[a] + + node.last = True + + def search(self, key): + + node = self.root + found = True + + for a in list(key): + if not node.children.get(a): + found = False + break + + node = node.children[a] + + return node and node.last and found + + def suggestionsRec(self, node, word): + + if node.last: + self.word_list.append(word) + + for a,n in node.children.items(): + self.suggestionsRec(n, word + a) + + def printAutoSuggestions(self, key): + + node = self.root + not_found = False + temp_word = '' + + for a in list(key): + if not node.children.get(a): + not_found = True + break + + temp_word += a + node = node.children[a] + + if not_found: + return 0 + elif node.last and not node.children: + return -1 + + self.suggestionsRec(node, temp_word) + + for s in self.word_list: + print(s) + return 1 + +keys = ["hello", "dog", "hell", "cat", "a", + "hel", "help", "helps", "helping"] +key = "hel" +status = ["Not found", "Found"] + +t = Trie() + +t.formTrie(keys) + +comp = t.printAutoSuggestions(key) + +if comp == -1: + print("No other strings found with this prefix\n") +elif comp == 0: + print("No string found with this prefix\n") From cb23bfffff63f1057b802ca56dc8b7bcde3783c0 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 28 Jan 2020 12:56:32 +0530 Subject: [PATCH 256/455] Create notes.md --- notes.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 notes.md diff --git a/notes.md b/notes.md new file mode 100644 index 00000000..5be5193e --- /dev/null +++ b/notes.md @@ -0,0 +1,123 @@ +# Notes + +## Linked List + +### Advantages over Array + +1. Dynamic size +2. Ease of insertion/deletion + +### Drawbacks + +1. Random access is not allowed +2. Extra memory is required with each pointer +3. Not cache friendly. Since array elements are contiguous locations, there is locality of reference which is not there in case of linked lists. + +### Applications + +1. Implementation of stack and queue and adjacency list representation of graphs +2. Dynamic memory allocation [Why?](https://www.slideshare.net/profansari/linked-list-static-and-dynamic-memory-allocation) +3. Maintaining directory of names +4. Image viewer, where images are linked in slideshows +5. Previos and next page in web browsers +6. Playlist in music players + +--- + +## Circular Linked List + +### Advantages + +1. Any node can be a starting point +2. Easy to go from the last node to the first node + +### Disadvantages + +1. More memory +2. Not easy to reverse the list + +### Applications + +1. Computers use Circular Linked List to cycle through active applications. Basically Round Robin Scheduling algorithm +2. Task queues +3. Snake game on Nokia phones +4. Never ending playlist + +--- + +## Doubly Linked List + +### Advantages + +1. Can be traversed in both directions +2. Deletion is more efficient as we can easily fetch the previous node + +### Disadvantages + +1. Consumes more space because of extra pointer + +[See XOR Linked List](https://www.geeksforgeeks.org/xor-linked-list-a-memory-efficient-doubly-linked-list-set-1/) + +### Applications + +1. Schedulers in operating systems +2. Undo-Redo functionality +3. MRU and LRU in operating systems + +--- + +## Tree + +### Applications + +1. Store hierarchial data +2. Trie are used in autocompletion and suggestion of words +3. BST can be used in searching +4. B-Tree and B+ Trees are used in database indexing + +### Misc + +1. [Advantages of BST over Hash Table](https://www.geeksforgeeks.org/advantages-of-bst-over-hash-table/) +2. [Ternary Search Tree - space efficient Trie](https://www.geeksforgeeks.org/ternary-search-tree/) +3. Heaps are better at finding Min/Max whereas BSTs are finding specific values +4. Insertion in heaps is O(1) whereas it is O(log(n)) for BST. This is the killer feature of heaps +5. Binary heap creation is O(n) whereas it is O(n log(n)) for BST. + +### Advantages of BST over heap + +1. Search for arbitary element is O(log(n)) in BST whereas it is O(n) for heap. [Reference](https://stackoverflow.com/questions/6147242/heap-vs-binary-search-tree-bst) + +--- + +## Heap + +### Applications + +1. Graph algorithms like Djikstra +2. Priority queues + +### Misc + +For differences between Heap and BST - [Reference](https://stackoverflow.com/questions/6147242/heap-vs-binary-search-tree-bst) + +[Why is binary heap preferred over BST for priority queue](https://www.geeksforgeeks.org/why-is-binary-heap-preferred-over-bst-for-priority-queue/) + +--- + +## Graph + + +### Difference between Graph and Tree + +| Graphs | Trees | +| --- | --- | --- | +| No unique node called root | Has a unique root node | +| There can be a cycle | No cycle | +| Network model | Hierarchial model | + +### Applications + +1. Networking +2. Social networks to find friends +3. Maps +4. Finding dependencies (Topological Sort) From 9a29687a304b5d2b6dfe8dee68d0ad49f8f9a77e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 28 Jan 2020 13:52:13 +0530 Subject: [PATCH 257/455] Update notes.md --- notes.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/notes.md b/notes.md index 5be5193e..1220a6ab 100644 --- a/notes.md +++ b/notes.md @@ -121,3 +121,60 @@ For differences between Heap and BST - [Reference](https://stackoverflow.com/que 2. Social networks to find friends 3. Maps 4. Finding dependencies (Topological Sort) +5. Topological sort - + 1. Finding dependencies + 2. Job scheduling among dependent jobs +6. Kosaraju's algorithm - + 1. To find strongly connected components (which are used in social networks) +7. Bipartite Graph - + 1. Student and class scheduling + 2. Stable marriage + 3. Text analyzer to cluster documents + 4. Netflix movie preference algorithm +8. Depth First Search - + 1. For a **weighted** graph, DFS produces Minimum Spanning Tree + 2. Cycle check + 3. Path finding + 4. Topological Sorting + 5. Finding strongly connected components +9. Breadth First Search - + 1. For a **unweighted** graph, BFS produces Minimum Spanning Tree + 2. Used in BitTorrent to find all neighbour nodes + 3. Crawlers in search engine [Why BFS not DFS is used in web crawlers](https://stackoverflow.com/a/20580936/12360506) + 4. Broadcasting in networking + 5. Garbage collection. Breadth First Search is preferred over Depth First Search because of better locality of reference. + 6. Ford-Fulkerson algorithm +10. Minimum Spanning Tree - + 1. Network design (like connecting all offices in a city with the lowest cost of cables) +11. Articulation Point - + 1. Articulation points represent vulnerabilities in a connected network – single points whose failure would split the network into 2 or more disconnected components. They are useful for designing reliable networks. + +--- + +## Stack + +### Application + +1. Expression handling, infix to postfix etc +2. Function calls +3. Parenthesis checking +4. Backtracking + +--- + +## Queue + +### Application + +1. BFS traversal +2. Handling interrupts in operating system +3. IO Buffers, pipes + +--- + +## Priority Queue + +### Application + +1. Prim's algorithm +2. Data compression. Used in Huffman coding From 07b5f44cc5543a06f6dc1bd5b393437b83ff8c6c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 29 Jan 2020 14:41:02 +0530 Subject: [PATCH 258/455] Create count_edges.py --- data_structures/graphs/count_edges.py | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 data_structures/graphs/count_edges.py diff --git a/data_structures/graphs/count_edges.py b/data_structures/graphs/count_edges.py new file mode 100644 index 00000000..f1601542 --- /dev/null +++ b/data_structures/graphs/count_edges.py @@ -0,0 +1,42 @@ +# Use handshaking lemma +# deg(v) = 2|E| +# Time - O(V) + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = [[] for i in range(vertices)] + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def count_edges(self): + s = 0 + + for i in range(self.V): + s += len(self.graph[i]) + + return s // 2 + + +g = Graph(9) +g.add_edge(0, 1 ) +g.add_edge(0, 7 ) +g.add_edge(1, 2 ) +g.add_edge(1, 7 ) +g.add_edge(2, 3 ) +g.add_edge(2, 8 ) +g.add_edge(2, 5 ) +g.add_edge(3, 4 ) +g.add_edge(3, 5 ) +g.add_edge(4, 5 ) +g.add_edge(5, 6 ) +g.add_edge(6, 7 ) +g.add_edge(6, 8 ) +g.add_edge(7, 8 ) + +print(g.count_edges()) From 5b7f8ed993e22186ed1565cb21505a45f6410608 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 29 Jan 2020 14:58:33 +0530 Subject: [PATCH 259/455] Create number_of_triangles.py --- data_structures/graphs/number_of_triangles.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 data_structures/graphs/number_of_triangles.py diff --git a/data_structures/graphs/number_of_triangles.py b/data_structures/graphs/number_of_triangles.py new file mode 100644 index 00000000..aa0a1669 --- /dev/null +++ b/data_structures/graphs/number_of_triangles.py @@ -0,0 +1,30 @@ +# Reference - https://www.geeksforgeeks.org/number-of-triangles-in-a-undirected-graph/ +# Reference - https://www.geeksforgeeks.org/number-of-triangles-in-directed-and-undirected-graphs/ + +# In case of undirected graph - trace(A^3)/6 +# For undirected graph, just check if an edge exists among all the three vertices + +class Graph: + + def __init__(self, vertices, is_directed): + self.V = vertices + self.graph = [[] for i in range(vertices)] + self.is_directed = is_directed + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def count_triangles(self): + nodes = len(self.graph) + count = 0 + + for i in range(nodes): + for j in range(nodes): + for k in range(nodes): + if i != j and j != k and k != i and self.graph[i][j] and self.graph[j][k] and self.graph[k][i]: + count += 1 + + return count // 3 if is_directed else count // 6 From fe202544bdd9c6f34f70209e83074d3c29ae3850 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 29 Jan 2020 16:23:39 +0530 Subject: [PATCH 260/455] Create not_reachable_nodes.py --- data_structures/graphs/not_reachable_nodes.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 data_structures/graphs/not_reachable_nodes.py diff --git a/data_structures/graphs/not_reachable_nodes.py b/data_structures/graphs/not_reachable_nodes.py new file mode 100644 index 00000000..df2e765a --- /dev/null +++ b/data_structures/graphs/not_reachable_nodes.py @@ -0,0 +1,44 @@ +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.V = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def dfs_util(self, v, visited): + visited[v] = True + + for i in self.graph[v]: + if visited[i] == False: + self.dfs_util(i, visited) + + + def count_nodes(self, v): + visited = [False] * self.V + + self.dfs_util(v, visited) + + count = 0 + + for i in range(self.V): + if visited[i] == False: + count += 1 + + return count + +g = Graph(8) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(3, 4) +g.add_edge(4, 5) +g.add_edge(6, 7) + +print(g.count_nodes(0)) From 46d0606fc35156f0c0549bb6e7c447b9b4f81445 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 31 Jan 2020 11:58:58 +0530 Subject: [PATCH 261/455] Create database.md --- bookmarks/database.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 bookmarks/database.md diff --git a/bookmarks/database.md b/bookmarks/database.md new file mode 100644 index 00000000..5a4e2fd3 --- /dev/null +++ b/bookmarks/database.md @@ -0,0 +1 @@ +https://stackoverflow.com/questions/23435361/does-mysql-update-the-index-on-all-inserts-can-i-make-it-update-after-every-x-i From 9f6dedc9b71ce14ceeb4aa8e49ed416b0eed19bb Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 31 Jan 2020 15:18:01 +0530 Subject: [PATCH 262/455] Create reverse_with_special_chars.py --- .../strings/reverse_with_special_chars.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 data_structures/strings/reverse_with_special_chars.py diff --git a/data_structures/strings/reverse_with_special_chars.py b/data_structures/strings/reverse_with_special_chars.py new file mode 100644 index 00000000..6d4aa95b --- /dev/null +++ b/data_structures/strings/reverse_with_special_chars.py @@ -0,0 +1,25 @@ +# Reverse a string making sure that special characters remain +# in their place + +# a#bcd#efg -> g#fed#cba + + +def reverse(s): + i = 0 + j = len(s) - 1 + + while i < j: + if s[i].isalnum() and s[j].isalnum(): + s[i], s[j] = s[j], s[i] + i += 1 + j -= 1 + if not s[i].isalnum(): + i += 1 + if not s[j].isalnum(): + j -= 1 + return ''.join(s) + + +s = 'a#bcd#efg' +print(s) +print(reverse(list(s))) From d42c5946f5ca1b1c98e72b2da75b497f3e396752 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 1 Feb 2020 10:11:44 +0530 Subject: [PATCH 263/455] Change bfs and dfs graph --- data_structures/graphs/bfs.py | 11 +++++++++++ data_structures/graphs/iterative_dfs.py | 25 +++++++++++++++---------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/data_structures/graphs/bfs.py b/data_structures/graphs/bfs.py index 72a0fff6..82bda7d3 100644 --- a/data_structures/graphs/bfs.py +++ b/data_structures/graphs/bfs.py @@ -26,3 +26,14 @@ def bfs(self, s): if visited[i] == False: queue.append(i) visited[i] = True + + +g = Graph() +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(2, 3) +g.add_edge(3, 3) + +g.bfs(0) diff --git a/data_structures/graphs/iterative_dfs.py b/data_structures/graphs/iterative_dfs.py index face3aaf..65c092dc 100644 --- a/data_structures/graphs/iterative_dfs.py +++ b/data_structures/graphs/iterative_dfs.py @@ -5,8 +5,7 @@ class Graph: - def __init__(self, vertices): - self.V = vertices + def __init__(self): self.graph = defaultdict(list) @@ -15,23 +14,29 @@ def add_edge(self, u, v): def dfs(self, s): - visited = [False] * self.V + visited = [False] * len(self.graph) stack = [] stack.append(s) + visited[s] = True while stack: - s = stack[-1] - stack.pop() - - if not visited[s]: - print(s, end=' ') - visited[s] = True + s = stack.pop() + print(s, end=' ') for i in self.graph[s]: - if not visited[i]: + if visited[i] == False: stack.append(i) + visited[i] = True +g = Graph() +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(2, 3) +g.add_edge(3, 3) +g.dfs(0) From b58ee744033b84d74fb69f6ce45b932ecee5d66d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 2 Feb 2020 11:54:21 +0530 Subject: [PATCH 264/455] Add 01 Knapsack --- algorithms/dynamic_programming/01_knapsack.py | 26 +++++ .../dynamic_programming/bit_masking1.py | 99 ------------------- .../dynamic_programming/climbing_stairs.py | 22 ----- algorithms/dynamic_programming/coin_change.py | 26 ----- algorithms/dynamic_programming/dice.py | 24 ----- .../dynamic_programming/edit_distance.py | 31 ------ algorithms/dynamic_programming/index.md | 11 --- .../dynamic_programming/k_palindrome1.py | 65 ------------ .../longest_common_subsequence.py | 23 ----- .../longest_increasing_subsequence.py | 63 ------------ .../longest_palindromic_subsequence.py | 40 -------- .../dynamic_programming/max_subarray.py | 26 ----- algorithms/dynamic_programming/rod_cutting.py | 22 ----- .../dynamic_programming/unique_grid_paths.py | 26 ----- 14 files changed, 26 insertions(+), 478 deletions(-) create mode 100644 algorithms/dynamic_programming/01_knapsack.py delete mode 100644 algorithms/dynamic_programming/bit_masking1.py delete mode 100644 algorithms/dynamic_programming/climbing_stairs.py delete mode 100644 algorithms/dynamic_programming/coin_change.py delete mode 100644 algorithms/dynamic_programming/dice.py delete mode 100644 algorithms/dynamic_programming/edit_distance.py delete mode 100644 algorithms/dynamic_programming/index.md delete mode 100644 algorithms/dynamic_programming/k_palindrome1.py delete mode 100644 algorithms/dynamic_programming/longest_common_subsequence.py delete mode 100644 algorithms/dynamic_programming/longest_increasing_subsequence.py delete mode 100644 algorithms/dynamic_programming/longest_palindromic_subsequence.py delete mode 100644 algorithms/dynamic_programming/max_subarray.py delete mode 100644 algorithms/dynamic_programming/rod_cutting.py delete mode 100644 algorithms/dynamic_programming/unique_grid_paths.py diff --git a/algorithms/dynamic_programming/01_knapsack.py b/algorithms/dynamic_programming/01_knapsack.py new file mode 100644 index 00000000..652c65e9 --- /dev/null +++ b/algorithms/dynamic_programming/01_knapsack.py @@ -0,0 +1,26 @@ +def knapsack(values, weights, total): + total_items = len(weights) + + rows = total_items + 1 + cols = total + 1 + + # rows are the number of items + # columns are the values of weights required + + t = [[0 for i in range(cols)] for i in range(rows)] + + for i in range(1, rows): + for j in range(1, cols): + if j < weights[i-1]: + t[i][j] = t[i-1][j] + else: + t[i][j] = max(t[i-1][j], values[i-1] + t[i-1][j-weights[i-1]]) + + return t[rows-1][cols-1] + + +weights = [1,3,4,5] +values = [1,4,5,7] + +ans = knapsack(values, weights, 7) +print(ans) diff --git a/algorithms/dynamic_programming/bit_masking1.py b/algorithms/dynamic_programming/bit_masking1.py deleted file mode 100644 index b5e3de9b..00000000 --- a/algorithms/dynamic_programming/bit_masking1.py +++ /dev/null @@ -1,99 +0,0 @@ -""" -Consider the below problems statement. - -There are 100 different types of caps each having a unique id from 1 to 100. Also, -there are ‘n’ persons each having a collection of a variable number of caps. -One day all of these persons decide to go in a party wearing a cap but to look unique -they decided that none of them will wear the same type of cap. So, count the total number -of arrangements or ways such that none of them is wearing the same type of cap. - -""" - -# Python program to find number of ways to wear hats -from collections import defaultdict - - -class AssignCap: - - # Initialize variables - def __init__(self): - - self.allmask = 0 - - self.total_caps = 100 - - self.caps = defaultdict(list) - - # Mask is the set of persons, i is the current cap number. - def count_ways_util(self, dp, mask, cap_no): - - # If all persons are wearing a cap so we - # are done and this is one way so return 1 - if mask == self.allmask: - return 1 - - # If not everyone is wearing a cap and also there are no more - # caps left to process, so there is no way, thus return 0; - if cap_no > self.total_caps: - return 0 - - # If we have already solved this subproblem, return the answer. - if dp[mask][cap_no] != -1: - return dp[mask][cap_no] - - # Ways, when we don't include this cap in our arrangement - # or solution set - ways = self.count_ways_util(dp, mask, cap_no + 1) - - # assign ith cap one by one to all the possible persons - # and recur for remaining caps. - if cap_no in self.caps: - - for ppl in self.caps[cap_no]: - - # if person 'ppl' is already wearing a cap then continue - if mask & (1 << ppl): - continue - - # Else assign him this cap and recur for remaining caps with - # new updated mask vector - ways += self.count_ways_util(dp, mask | (1 << ppl), cap_no + 1) - - ways = ways % (10**9 + 7) - - # Save the result and return it - dp[mask][cap_no] = ways - - return dp[mask][cap_no] - - def count_ways(self, N): - - # Reads n lines from standard input for current test case - # create dictionary for cap. cap[i] = list of person having - # cap no i - for ppl in range(N): - - cap_possessed_by_person = map(int, input().strip().split()) - - for i in cap_possessed_by_person: - - self.caps[i].append(ppl) - - # allmask is used to check if all persons - # are included or not, set all n bits as 1 - self.allmask = (1 << N) - 1 - - # Initialize all entries in dp as -1 - dp = [[-1 for j in range(self.total_caps + 1)] for i in range(2 ** N)] - - # Call recursive function countWaysUtil - # result will be in dp[0][1] - print(self.count_ways_util(dp, 0, 1,)) - -# Driver Program - - -def main(): - No_of_people = int(input()) # number of persons in every test case - - AssignCap().count_ways(No_of_people) diff --git a/algorithms/dynamic_programming/climbing_stairs.py b/algorithms/dynamic_programming/climbing_stairs.py deleted file mode 100644 index b47ffa3a..00000000 --- a/algorithms/dynamic_programming/climbing_stairs.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -High Level Description: -You are climbing a stair case. It takes n steps to reach to the top. -Each time you can either climb 1 or 2 steps. In how many distinct ways can you -climb to the top? - -Time Complexity: -O(n) -""" - -def climb_stairs(n): - if n==0 or n==1: - return 1 - first= 1 - second= 1 - ans= 0 - - for i in range(2, n+1): - ans = first + second - second = first - first = ans - return ans \ No newline at end of file diff --git a/algorithms/dynamic_programming/coin_change.py b/algorithms/dynamic_programming/coin_change.py deleted file mode 100644 index fcf8d87b..00000000 --- a/algorithms/dynamic_programming/coin_change.py +++ /dev/null @@ -1,26 +0,0 @@ -# Dynamic Programming Python implementation of Coin -# Change problem -def count(S, m, n): - # We need n+1 rows as the table is constructed - # in bottom up manner using the base case 0 value - # case (n = 0) - table = [[0 for x in range(m)] for x in range(n+1)] - - # Fill the entries for 0 value case (n = 0) - for i in range(m): - table[0][i] = 1 - - # Fill rest of the table entries in bottom up manner - for i in range(1, n+1): - for j in range(m): - - # Count of solutions including S[j] - x = table[i - S[j]][j] if i-S[j] >= 0 else 0 - - # Count of solutions excluding S[j] - y = table[i][j-1] if j >= 1 else 0 - - # total count - table[i][j] = x + y - - return table[n][m-1] diff --git a/algorithms/dynamic_programming/dice.py b/algorithms/dynamic_programming/dice.py deleted file mode 100644 index 4c4ec68f..00000000 --- a/algorithms/dynamic_programming/dice.py +++ /dev/null @@ -1,24 +0,0 @@ -''' -Given n dices each with m faces, numbered from 1 to m, -find the number of ways to get a given sum X. -X is the summation of values on each face when all the dice are thrown. - -''' - -dp = [[-1 for i in range(x+1)] for j in range(n+1)] - - -def num_of_ways(m, n, x): - if x == 0 and n == 0: - return 1 - if x < 0 or n == 0: - return 0 - if dp[n][x] != -1: - return dp[n][x] - - ans = 0 - for i in range(1, m + 1): - ans += num_of_ways(m, n - 1, x - i) - - dp[n][x] = ans - return ans diff --git a/algorithms/dynamic_programming/edit_distance.py b/algorithms/dynamic_programming/edit_distance.py deleted file mode 100644 index dde466a9..00000000 --- a/algorithms/dynamic_programming/edit_distance.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -High Level Description: -Given two words word1 and word2, find the minimum number of operations -required to convert word1 to word2. You have the following 3 operations -permitted on a word: -Insert a character -Delete a character -Replace a character - -Time Complexity: -O(m*n) -""" - - -def edit_dist(str1, str2, m, n): - dp = [[0 for x in range(n+1)] for x in range(m+1)] - - for i in range(m+1): - for j in range(n+1): - if i == 0: - dp[i][j] = j - elif j == 0: - dp[i][j] = i - elif str1[i-1] == str2[j-1]: - dp[i][j] = dp[i-1][j-1] - else: - dp[i][j] = 1 + min(dp[i][j-1], # Insert - dp[i-1][j], # Remove - dp[i-1][j-1]) # Replace - - return dp[m][n] diff --git a/algorithms/dynamic_programming/index.md b/algorithms/dynamic_programming/index.md deleted file mode 100644 index 0a50f2c6..00000000 --- a/algorithms/dynamic_programming/index.md +++ /dev/null @@ -1,11 +0,0 @@ -# Index of dynamic_programming - -* [Climbing Stairs](climbing_stairs.py) -* [Coin Change](coin_change.py) -* [Dice](dice.py) -* [Edit Distance](edit_distance.py) -* [Longest Common Subsequence](longest_common_subsequence.py) -* [Longest Palindromic Subsequence](longest_palindromic_subsequence.py) -* [Max Subarray](max_subarray.py) -* [Rod Cutting](rod_cutting.py) -* [Unique Grid Paths](unique_grid_paths.py) diff --git a/algorithms/dynamic_programming/k_palindrome1.py b/algorithms/dynamic_programming/k_palindrome1.py deleted file mode 100644 index 8c69e5af..00000000 --- a/algorithms/dynamic_programming/k_palindrome1.py +++ /dev/null @@ -1,65 +0,0 @@ -# code to find if given string -# is K-Palindrome or not - -""" -Explanation - -Process all characters one by one staring from either from left or right sides of both strings. -Let us traverse from the right corner, there are two possibilities for every pair of character being traversed. - -If last characters of two strings are same, we ignore last characters and get count for remaining strings. -So we recur for lengths m-1 and n-1 where m is length of str1 and n is length of str2. -If last characters are not same, we consider remove operation on last character of first string and -last character of second string, recursively compute minimum cost for the operations and take minimum of two values. -Remove last char from str1: Recur for m-1 and n. -Remove last char from str2: Recur for m and n-1. -""" - -# Find if given string -# is K-Palindrome or not - - -def is_kpalrec(str1, str2, m, n): - - # If first string is empty, - # the only option is to remove - # all characters of second string - if not m: - return n - - # If second string is empty, - # the only option is to remove - # all characters of first string - if not n: - return m - - # If last characters of two strings - # are same, ignore last characters - # and get count for remaining strings. - if str1[m - 1] == str2[n - 1]: - return isKPalRec(str1, str2, m - 1, n - 1) - - # If last characters are not same, - # 1. Remove last char from str1 and recur for m-1 and n - # 2. Remove last char from str2 and recur for m and n-1 - # Take minimum of above two operations - res = 1 + min(is_kpalrec(str1, str2, m - 1, n), # Remove from str1 - (is_kpalrec(str1, str2, m, n - 1))) # Remove from str2 - - return res - -# Returns true if str is k palindrome. - - -def is_kPal(string, k): - revStr = string[::-1] - l = len(string) - - return (is_kpalrec(string, revStr, l, l) <= k * 2) - - -# Driver program -string = "acdcb" -k = 2 - -print("Yes" if is_kPal(string, k) else "No") diff --git a/algorithms/dynamic_programming/longest_common_subsequence.py b/algorithms/dynamic_programming/longest_common_subsequence.py deleted file mode 100644 index d8a5e66e..00000000 --- a/algorithms/dynamic_programming/longest_common_subsequence.py +++ /dev/null @@ -1,23 +0,0 @@ -''' -We are given two sequences and we -need to find the length of the -longest common subsequence -''' - - -def lcs(S1, S2): - m = len(S1) - n = len(S2) - - LCS = [[-1]*(n + 1) for i in range(m + 1)] - - for i in range(m + 1): - for j in range(n + 1): - if i == 0 or j == 0: - LCS[i][j] = 0 - elif S1[i-1] == S2[j-1]: - LCS[i][j] = LCS[i-1][j-1]+1 - else: - LCS[i][j] = max(LCS[i-1][j], LCS[i][j-1]) - - return LCS[m][n] diff --git a/algorithms/dynamic_programming/longest_increasing_subsequence.py b/algorithms/dynamic_programming/longest_increasing_subsequence.py deleted file mode 100644 index 1a00abf2..00000000 --- a/algorithms/dynamic_programming/longest_increasing_subsequence.py +++ /dev/null @@ -1,63 +0,0 @@ -''' -Problem statement: -given an array of N elements, -return the length of the -longest increasing subsequence -of that array -''' - - -def lis(s, cur_index=0, last_index=-1, cur_length=0, dp=None): - """ - Return length of the longest increasing - subsequence from array s. - - To use, simply call lis(s). The other - parameters will be used in the - recursion - """ - - # Initialize dp dictionary to use in the recursion - if dp == None: - dp = dict() - - # Base case: we've gone through the whole array - if cur_index == len(s): - return cur_length - - if dp.get((last_index, cur_index)) is not None: - return dp.get((last_index, cur_index)) # Return stored value - - ''' - Length of the LIS if we include cur_index - is initialized as -1 because we might not - be able to include it if it is less than - the number at last_index. If last_index is - -1, we can take cur_index, as it will be - the first integer in the possible LIS. - ''' - take = -1 - if last_index == -1 or s[last_index] < s[cur_index]: - take = lis(s, cur_index + 1, cur_index, cur_length + 1, dp) - - # Length of the LIS if we don't include cur_index - not_take = lis(s, cur_index + 1, last_index, cur_length, dp) - - # Return the greatest LIS (include cur_index or not) - dp[(last_index, cur_index)] = max(take, not_take) # Store result in cache - return dp.get((last_index, cur_index)) - - -def main(): - """ Simple test cases """ - t1 = [1, 6, 2, 3, 7, 9, 4, 8, 5] - t2 = [9, 8, 7, 6, 5, 4, 3, 2, 1] - t3 = [-1, -1, -1, -1, -1, -1] - - print('LIS of {}: {}'.format(t1, lis(t1))) # Should be 5 - print('LIS of {}: {}'.format(t2, lis(t2))) # Should be 1 - print('LIS of {}: {}'.format(t3, lis(t3))) # Should be 1 - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/algorithms/dynamic_programming/longest_palindromic_subsequence.py b/algorithms/dynamic_programming/longest_palindromic_subsequence.py deleted file mode 100644 index e0d6f3bd..00000000 --- a/algorithms/dynamic_programming/longest_palindromic_subsequence.py +++ /dev/null @@ -1,40 +0,0 @@ -''' -Question : -Given a string consisting of English alphabets, the task is to count the alphabets in the longest palindromic subsequence. - -For example : -Input: str = "BBABCBCAB" -Output: 7 -"BABCBAB" is the longest palindromic subseuqnce in it. "BBBBB"" and "BBCBB" are also palindromic subsequences of the given sequence, but not the longest ones. - -Source: https://www.geeksforgeeks.org/python-program-for-longest-palindromic-subsequence-dp-12/ -''' - -def lps(str): - n = len(str) - - # Create a table to store results of subproblems - L = [[0 for x in range(n)] for x in range(n)] - - # Strings of length 1 are palindrome of length 1 - for i in range(n): - L[i][i] = 1 - - # Build the table. Note that the lower - # diagonal values of table are - # useless and not filled in the process. - for cl in range(2, n + 1): - for i in range(n-cl + 1): - j = i + cl-1 - if str[i] == str[j] and cl == 2: - L[i][j] = 2 - elif str[i] == str[j]: - L[i][j] = L[i + 1][j-1] + 2 - else: - L[i][j] = max(L[i][j-1], L[i + 1][j]); - - return L[0][n-1] - -# Test inputs -seq = "BBABCBCAB" -print("The length of the LPS is " + str(lps(seq))) diff --git a/algorithms/dynamic_programming/max_subarray.py b/algorithms/dynamic_programming/max_subarray.py deleted file mode 100644 index 422c29c9..00000000 --- a/algorithms/dynamic_programming/max_subarray.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -High Level Description: -Given an integer array nums, find the contiguous subarray (containing at least -one number) which has the largest sum and return its sum. - -Time Complexity: -O(n) -""" - - -# Iterative Solution - Kadane's algorithm -def max_sub_array(arr): - if not arr: - return 0 - - cur_sum = max_sum = arr[0] - for num in arr[1:]: - cur_sum = max(num, cur_sum + num) - max_sum = max(max_sum, cur_sum) - - return max_sum - - - -print max_sub_array([1,2,-100,3,4]) - diff --git a/algorithms/dynamic_programming/rod_cutting.py b/algorithms/dynamic_programming/rod_cutting.py deleted file mode 100644 index 9e807bb0..00000000 --- a/algorithms/dynamic_programming/rod_cutting.py +++ /dev/null @@ -1,22 +0,0 @@ -''' -Given a rod of length n units and an -array of prices that contains prices -of all pieces of size less than n. We -need to find the maximum maximum price -obtainable by cutting the rod and -selling it. -''' -INT_MIN = -32767 - - -def cutRod(price, n): - values = [0 for i in range(n+1)] - values[0] = 0 - - for i in range(1, n+1): - max_value = INT_MIN - for j in range(i): - max_value = max(max_value, price[j] + values[i-j-1]) - values[i] = max_value - - return values[n] diff --git a/algorithms/dynamic_programming/unique_grid_paths.py b/algorithms/dynamic_programming/unique_grid_paths.py deleted file mode 100644 index a5518ba3..00000000 --- a/algorithms/dynamic_programming/unique_grid_paths.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -High Level Description: -A preson is located at the top-left corner of a m x n grid (marked 'Start' in -the diagram below). The preson can only move either down or right at any point -in time. The preson is trying to reach the bottom-right corner of the grid -(marked 'Finish' in the diagram below). -How many possible unique paths are there? - -Time Complexity: -O(m*n) -""" - - -def number_of_paths(m, n): - count = [[0 for x in range(m)] for y in range(n)] - - for i in range(m): - count[i][0] = 1 - - for j in range(n): - count[0][j] = 1 - - for i in range(1, m): - for j in range(n): - count[i][j] = count[i-1][j] + count[i][j-1] - return count[m-1][n-1] From b7d04e814dc2e416ad8e3ebf1673524acb435cce Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 2 Feb 2020 20:06:31 +0530 Subject: [PATCH 265/455] Add dynamic questions --- algorithms/dynamic_programming/coin_change.py | 16 ++++++++++++++++ .../longest_common_subsequence.py | 18 ++++++++++++++++++ .../longest_common_substring.py | 15 +++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 algorithms/dynamic_programming/coin_change.py create mode 100644 algorithms/dynamic_programming/longest_common_subsequence.py create mode 100644 algorithms/dynamic_programming/longest_common_substring.py diff --git a/algorithms/dynamic_programming/coin_change.py b/algorithms/dynamic_programming/coin_change.py new file mode 100644 index 00000000..88056015 --- /dev/null +++ b/algorithms/dynamic_programming/coin_change.py @@ -0,0 +1,16 @@ +# Concept is almost same as 01 Knapsack Problem + +def min_coin(coins, total): + cols = total + 1 + rows = len(coins) + + t = [ [0] if col == 0 else float('inf') for col in range(cols)] for i in range(rows)] + + for i in range(rows): + for j in range(1, cols): + if j < coins[i]: + t[i][j] = t[i-1][j] + else: + t[i][j] = min(t[i-1][j], 1 + t[i][j-coins[i]) + + return t[rows-1][cols-1] diff --git a/algorithms/dynamic_programming/longest_common_subsequence.py b/algorithms/dynamic_programming/longest_common_subsequence.py new file mode 100644 index 00000000..2c60beda --- /dev/null +++ b/algorithms/dynamic_programming/longest_common_subsequence.py @@ -0,0 +1,18 @@ +def lcs(s1, s2): + cols = len(s1) + 1 + rows = len(s2) + 1 + + t = [[0 for i in range(cols)] for i in range(rows)] + + max_length = 0 + + for i in range(1, rows): + for j in range(1, cols): + if s2[i-1] == s1[j-1]: + t[i][j] = 1 + t[i-1][j-1] + else: + t[i][j] = max(t[i-1][j], t[i][j-1]) + + max_length = max(max_length, t[i][j]) + + return max_length diff --git a/algorithms/dynamic_programming/longest_common_substring.py b/algorithms/dynamic_programming/longest_common_substring.py new file mode 100644 index 00000000..7777feb2 --- /dev/null +++ b/algorithms/dynamic_programming/longest_common_substring.py @@ -0,0 +1,15 @@ +def lcs(s1, s2): + cols = len(s1) + 1 + rows = len(s2) + 1 + + t = [[0 for i in range(cols)] for i in range(rows)] + + max_length = 0 + + for i in range(1, rows): + for j in range(1, cols): + if s[i-1] == s[j-1]: + t[i][j] = t[i-1][j-1] + 1 + max_length = max(max_length, t[i][j]) + + return max_length From 5ffc4f7a7da7796ca426f2083f1b3ffe033c9ff4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 5 Feb 2020 15:45:58 +0530 Subject: [PATCH 266/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e789645..35224879 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![logo](logo/logo.png) +![logo](logo/logo.png) # Python Data Structures and Algorithms From 279c93aa6f81ee789a47f3adc0b7b4bd4b788d3f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 11 Feb 2020 14:15:42 +0530 Subject: [PATCH 267/455] Create all_paths_between_two_vertices.py --- .../graphs/all_paths_between_two_vertices.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 data_structures/graphs/all_paths_between_two_vertices.py diff --git a/data_structures/graphs/all_paths_between_two_vertices.py b/data_structures/graphs/all_paths_between_two_vertices.py new file mode 100644 index 00000000..958a2b82 --- /dev/null +++ b/data_structures/graphs/all_paths_between_two_vertices.py @@ -0,0 +1,50 @@ +# Use backtracking +# The only with this approach is that if there is a cycle, then +# it can show infinitely many paths +# Reference - https://www.geeksforgeeks.org/count-possible-paths-two-vertices/ + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = [[] for i in range(vertices)] + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def count_paths_util(self, u, v, visited, counter): + visited[u] = True + + # If the destination vertex is found + if u == v: + counter[0] += 1 + + else: + for i in range(len(self.graph[u])): + if not visited[self.graph[u][i]]: + self.count_paths_util(self.graph[u][i], v, visited, counter) + + visited[u] = False + + + def count_paths(self, u, v): + visited = [False] * self.vertices + + counter = [0] + + self.count_paths_util(u, v, visited, counter) + + return counter[0] + + +g = Graph(4) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(0, 3) +g.add_edge(2, 0) +g.add_edge(2, 1) +g.add_edge(1, 3) + +print(g.count_paths(2, 3)) From 01dcf738f13ef76b70bf62e1788d78d43098b329 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 11 Feb 2020 15:23:30 +0530 Subject: [PATCH 268/455] Create tree_stays_bipartite.py --- .../graphs/tree_stays_bipartite.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 data_structures/graphs/tree_stays_bipartite.py diff --git a/data_structures/graphs/tree_stays_bipartite.py b/data_structures/graphs/tree_stays_bipartite.py new file mode 100644 index 00000000..cda2299a --- /dev/null +++ b/data_structures/graphs/tree_stays_bipartite.py @@ -0,0 +1,56 @@ +# All trees are bipartite graphs +# Reference - https://www.geeksforgeeks.org/maximum-number-edges-added-tree-stays-bipartite-graph/ + +# Traverse the tree (dfs or bfs) and color nodes with two colors and count each like +# count_color1 and count_color2. Then the max edges that the graph can have are +# count_color1 * count_color2, and the max edges of a tree are n-1 + +# Therefore the answer is = count_color1 * count_color2 - (n-1) + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = [[] for i in range(vertices)] + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def bfs(self, s): + visited = [False] * self.vertices + color_count = [0, 0] + + colors = [-1] * self.vertices + colors[s] = 1 + + queue = [] + + queue.append(s) + visited[s] = True + + while queue: + u = queue.pop(0) + + for v in self.graph[u]: + if colors[v] == -1: # This is a tree. So not visited and not colored is same as there is no cycle + colors[v] = 1 - colors[u] + queue.append(v) + color_count[colors[v]] += 1 + visited[v] = True + + # Counting the max number of edges for graph + graph_edges = color_count[0] * color_count[1] + + return graph_edges + + +# Number of tree nodes +n = 5 + +g = Graph(5) +g.add_edge(1, 2) +g.add_edge(1, 3) +g.add_edge(2, 4) +g.add_edge(3, 5) From 56e7b1301f6a388dc27f824a1d18442e6b6f71b4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 16 Feb 2020 09:14:09 +0530 Subject: [PATCH 269/455] Update README.md From b7cab9de7b49b62a91849d458d800517116eca4d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 16 Feb 2020 09:14:33 +0530 Subject: [PATCH 270/455] Update README.md From 81f71e5ec4732f2b5ce8a19245638671c90a1009 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 22:40:18 +0100 Subject: [PATCH 271/455] Add GitHub Action to lint Python code --- .github/workflows/lint_python.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/lint_python.yml diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml new file mode 100644 index 00000000..507beee3 --- /dev/null +++ b/.github/workflows/lint_python.yml @@ -0,0 +1,18 @@ +name: lint_python +on: + pull_request: + push: + # branches: [master] +jobs: + lint_python: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: actions/setup-python@master + - run: pip install black codespell flake8 isort pytest + - run: black . --diff || true + - run: codespell --quiet-level=2 || true # --ignore-words-list="" --skip="" + - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + - run: isort --recursive . || true + - run: pip install -r requirements.txt || true + - run: pytest . || true From 899d4c26790e849a8daf6651870373db6fc92f51 Mon Sep 17 00:00:00 2001 From: cclauss Date: Tue, 25 Feb 2020 22:57:28 +0100 Subject: [PATCH 272/455] Fix typos found by codespell --- CONTRIBUTING.md | 2 +- README.md | 2 +- notes.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f0c24e6..be0d596c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ For filing a PR for a new question, please open a issue first for the same and t ### Bookmarks -The Bookmarks directory is for storing awesome links to articles, videos, slides, talks, etc that are interesting and can help in increasing knowledge for a specific topic. There has been many PRs for adding new links in Bookmarks and most of them refered to either a whole book or DS Algo MOOCs, please refrain from adding them. Here are some points that you must consider before contributing to Bookmarks - +The Bookmarks directory is for storing awesome links to articles, videos, slides, talks, etc that are interesting and can help in increasing knowledge for a specific topic. There has been many PRs for adding new links in Bookmarks and most of them referred to either a whole book or DS Algo MOOCs, please refrain from adding them. Here are some points that you must consider before contributing to Bookmarks - * Don't add a link to a MOOC or course (like DS Algo MIT lectures) diff --git a/README.md b/README.md index 35224879..14069301 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Python Data Structures and Algorithms -This repository contains data structures and algorithms concepts and questions userful for interviews in Python. +This repository contains data structures and algorithms concepts and questions useful for interviews in Python. ## :dart: Objective diff --git a/notes.md b/notes.md index 1220a6ab..ad364f49 100644 --- a/notes.md +++ b/notes.md @@ -19,7 +19,7 @@ 2. Dynamic memory allocation [Why?](https://www.slideshare.net/profansari/linked-list-static-and-dynamic-memory-allocation) 3. Maintaining directory of names 4. Image viewer, where images are linked in slideshows -5. Previos and next page in web browsers +5. Previous and next page in web browsers 6. Playlist in music players --- @@ -85,7 +85,7 @@ ### Advantages of BST over heap -1. Search for arbitary element is O(log(n)) in BST whereas it is O(n) for heap. [Reference](https://stackoverflow.com/questions/6147242/heap-vs-binary-search-tree-bst) +1. Search for arbitrary element is O(log(n)) in BST whereas it is O(n) for heap. [Reference](https://stackoverflow.com/questions/6147242/heap-vs-binary-search-tree-bst) --- From a6ec61b5103aa918cfe3c89e032df4312ab03e3f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:19:12 +0100 Subject: [PATCH 273/455] Fix Python syntax error --- data_structures/doubly_linked_list/doubly_linked_list.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/doubly_linked_list/doubly_linked_list.py b/data_structures/doubly_linked_list/doubly_linked_list.py index 2702ac1a..9feb64b0 100644 --- a/data_structures/doubly_linked_list/doubly_linked_list.py +++ b/data_structures/doubly_linked_list/doubly_linked_list.py @@ -1,7 +1,7 @@ class Node: - def __init__(self, data = None, next, previous = None): + def __init__(self, data = None, next = None, previous = None): self.data = data - self.next = None + self.next = next self.previous = previous class Lista: From db906aff3a12a9326031d81a78febdf16dbe5f43 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:21:05 +0100 Subject: [PATCH 274/455] Fix Python syntax error --- data_structures/matrix/flood_fill_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/matrix/flood_fill_algorithm.py b/data_structures/matrix/flood_fill_algorithm.py index d5d3da24..935bfd4b 100644 --- a/data_structures/matrix/flood_fill_algorithm.py +++ b/data_structures/matrix/flood_fill_algorithm.py @@ -4,7 +4,7 @@ M = 8 N = 8 -def flood_fill_util(screen, x, y prev_color, new_color): +def flood_fill_util(screen, x, y, prev_color, new_color): if x < 0 or x >= M or y < 0 or y >= N or screen[x][y] != prev_color or screen[x][y] == new_color: return From 35a088a0648ea54f3db971b4c74b812b5eefe943 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:22:31 +0100 Subject: [PATCH 275/455] Fix Python syntax error --- data_structures/array/pivot_index.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data_structures/array/pivot_index.py b/data_structures/array/pivot_index.py index dd2a9e21..d15ce1cd 100644 --- a/data_structures/array/pivot_index.py +++ b/data_structures/array/pivot_index.py @@ -2,9 +2,7 @@ def pivot(arr): s = sum(arr) left_sum = 0 for i, x in enumerate(arr): - if left_sum = (s - x - left_sum): + if left_sum == (s - x - left_sum): return i left_sum += x return -1 - - From df9c8a856875ea8bb13cb055258166ce4936e735 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:23:45 +0100 Subject: [PATCH 276/455] Fix Python syntax error --- data_structures/bst/print_ancestor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/bst/print_ancestor.py b/data_structures/bst/print_ancestor.py index 8158d037..b443c559 100644 --- a/data_structures/bst/print_ancestor.py +++ b/data_structures/bst/print_ancestor.py @@ -11,7 +11,7 @@ def print_ancestor_recursive(root, key): return False if root.val == key: return True - if print_ancestor_recursive(root.left, key) || print_ancestor_recursive(root.right, key): + if print_ancestor_recursive(root.left, key) or print_ancestor_recursive(root.right, key): return root.data return False From 7a816e763628b84068c05b0a3fe8d246c7939a94 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:26:51 +0100 Subject: [PATCH 277/455] Comment out Python TokenError --- data_structures/bst/linked_list_to_bst.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data_structures/bst/linked_list_to_bst.py b/data_structures/bst/linked_list_to_bst.py index 4b3a9aca..ac980985 100644 --- a/data_structures/bst/linked_list_to_bst.py +++ b/data_structures/bst/linked_list_to_bst.py @@ -28,5 +28,6 @@ def linked_list_to_bst(head): def ll_to_bst_recur(head, n): if n <= 0: return None - left = ll_to_bst_recur( + # TODO: Fix me! + # left = ll_to_bst_recur( From 2e137da1f36450e76ac289d18185a5b6e4efb470 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:28:29 +0100 Subject: [PATCH 278/455] Use print() function in both Python 2 and Python 3 --- data_structures/linked_list/merge_linked_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/linked_list/merge_linked_list.py b/data_structures/linked_list/merge_linked_list.py index 572f18c4..11220bd8 100644 --- a/data_structures/linked_list/merge_linked_list.py +++ b/data_structures/linked_list/merge_linked_list.py @@ -29,6 +29,6 @@ def merge(l1, l2): ptr = head_merged while ptr: - print ptr.val + print(ptr.val) ptr = ptr.next From 2364edebac1453a1b84aed09bf05e374c87d0130 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:30:01 +0100 Subject: [PATCH 279/455] Use print() function in both Python 2 and Python 3 --- data_structures/stack/stack_using_linked_list.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data_structures/stack/stack_using_linked_list.py b/data_structures/stack/stack_using_linked_list.py index 35323074..794541b5 100644 --- a/data_structures/stack/stack_using_linked_list.py +++ b/data_structures/stack/stack_using_linked_list.py @@ -62,9 +62,9 @@ def pop(self): # Test stack functionality stack.push(e2) stack.push(e3) -print stack.pop().value -print stack.pop().value -print stack.pop().value -print stack.pop() +print(stack.pop().value) +print(stack.pop().value) +print(stack.pop().value) +print(stack.pop()) stack.push(e4) -print stack.pop().value +print(stack.pop().value) From ab69a75a31c304bb0689a29eff308b8dfa0b2c01 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:31:15 +0100 Subject: [PATCH 280/455] Use print() function in both Python 2 and Python 3 --- algorithms/sorting/insertion_sort.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/algorithms/sorting/insertion_sort.py b/algorithms/sorting/insertion_sort.py index b19d9ddd..5d0ec752 100644 --- a/algorithms/sorting/insertion_sort.py +++ b/algorithms/sorting/insertion_sort.py @@ -15,12 +15,11 @@ def insertion_sort(lst): return lst test_data = [5,9,4,27,3,6] -print insertion_sort(test_data) +print(insertion_sort(test_data)) test_data = ['f','b','z','a','x'] -print insertion_sort(test_data) +print(insertion_sort(test_data)) # Resulting output: # [3, 4, 5, 6, 9, 27] # ['a', 'b', 'f', 'x', 'z'] - From 9d4796af65779a4f56d9914b2240b6c96062e8a0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:34:12 +0100 Subject: [PATCH 281/455] Fix Python IndentationError --- data_structures/bst/duplicate_keys.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/data_structures/bst/duplicate_keys.py b/data_structures/bst/duplicate_keys.py index e044b7ce..4e0e5cbf 100644 --- a/data_structures/bst/duplicate_keys.py +++ b/data_structures/bst/duplicate_keys.py @@ -43,9 +43,6 @@ def delete(root, val): if root.val == val: if root.count > 1: root.count -= 1 - else: - - root = Node(5) From 39bee5c57d7a71d4f890390ca5fa253fbabe8417 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:35:35 +0100 Subject: [PATCH 282/455] Fix Python syntax error --- algorithms/dynamic_programming/coin_change.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/dynamic_programming/coin_change.py b/algorithms/dynamic_programming/coin_change.py index 88056015..0f2a8ff7 100644 --- a/algorithms/dynamic_programming/coin_change.py +++ b/algorithms/dynamic_programming/coin_change.py @@ -4,7 +4,7 @@ def min_coin(coins, total): cols = total + 1 rows = len(coins) - t = [ [0] if col == 0 else float('inf') for col in range(cols)] for i in range(rows)] + t = [[ [0] if col == 0 else float('inf') for col in range(cols)] for i in range(rows)] for i in range(rows): for j in range(1, cols): From b86d1756c4153474a34b4e51a8309b5ab85a6b6b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:37:42 +0100 Subject: [PATCH 283/455] Use print() function in both Python 2 and Python 3 --- algorithms/graph/dfs.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/algorithms/graph/dfs.py b/algorithms/graph/dfs.py index fbd33795..4a452536 100644 --- a/algorithms/graph/dfs.py +++ b/algorithms/graph/dfs.py @@ -1,4 +1,5 @@ -# Python program to print DFS traversal for complete graph +# Python program to print DFS traversal for complete graph +from __future__ import print_function from collections import defaultdict # This class represents a directed graph using adjacency @@ -20,7 +21,7 @@ def DFSUtil(self, v, visited): # Mark the current node as visited and print it visited[v]= True - print v, + print(v, end=" ") # Recur for all the vertices adjacent to # this vertex @@ -42,4 +43,4 @@ def DFS(self): # by one for i in range(V): if visited[i] == False: - self.DFSUtil(i, visited) \ No newline at end of file + self.DFSUtil(i, visited) From 264f40f5079b30e9768c537278bc80115c711dfd Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 25 Feb 2020 23:43:57 +0100 Subject: [PATCH 284/455] Fix Python syntax errors --- algorithms/dynamic_programming/coin_change.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algorithms/dynamic_programming/coin_change.py b/algorithms/dynamic_programming/coin_change.py index 0f2a8ff7..96b57648 100644 --- a/algorithms/dynamic_programming/coin_change.py +++ b/algorithms/dynamic_programming/coin_change.py @@ -4,13 +4,13 @@ def min_coin(coins, total): cols = total + 1 rows = len(coins) - t = [[ [0] if col == 0 else float('inf') for col in range(cols)] for i in range(rows)] + t = [[[0] if col == 0 else float('inf') for col in range(cols)] for i in range(rows)] for i in range(rows): for j in range(1, cols): if j < coins[i]: t[i][j] = t[i-1][j] else: - t[i][j] = min(t[i-1][j], 1 + t[i][j-coins[i]) + t[i][j] = min(t[i-1][j], 1 + t[i][j-coins[i]]) return t[rows-1][cols-1] From dbece378ba131cd899ac9ff88194618f4a7e6436 Mon Sep 17 00:00:00 2001 From: tasbihaasim Date: Fri, 28 Feb 2020 20:59:09 +0500 Subject: [PATCH 285/455] Make Adjacency matrix part of the graphs folder --- data_structures/graphs/Adjacency_matrix.py | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 data_structures/graphs/Adjacency_matrix.py diff --git a/data_structures/graphs/Adjacency_matrix.py b/data_structures/graphs/Adjacency_matrix.py new file mode 100644 index 00000000..7895a279 --- /dev/null +++ b/data_structures/graphs/Adjacency_matrix.py @@ -0,0 +1,35 @@ +class Graph: + + def __init__(self, vertices, directed: bool): + self.V = vertices + self.e = 0 + self.d = directed + self.graph = [] + for i in range(self.V): + lst = [0] * self.V + self.graph.append(lst) + + def add_edge(self, ver1, ver2): + if self.d: + self.graph[ver1][ver2] = 1 + else: + self.graph[ver1][ver2] = 1 + self.graph[ver2][ver1] = 1 + + def remove_edge(self, ver1, ver2): + if self.d[ver1][ver2] == 0: + print("No edge between %d and %d" % (ver1, ver2)) + return + if self.d: + self.graph[ver1][ver2] = 0 + else: + self.graph[ver1][ver2] = 0 + self.graph[ver2][ver1] = 0 + + def print_graph(self): + for i in self.graph: + print(i) + + + + From 38889cf10bda1633d457c83ba302c33a002a203c Mon Sep 17 00:00:00 2001 From: owais4321 Date: Fri, 20 Mar 2020 03:45:12 -0700 Subject: [PATCH 286/455] added question description to array datastructure index.md --- data_structures/array/index.md | 110 +++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 11 deletions(-) diff --git a/data_structures/array/index.md b/data_structures/array/index.md index 8b964508..c549554c 100644 --- a/data_structures/array/index.md +++ b/data_structures/array/index.md @@ -1,34 +1,122 @@ # Index of array * [Permumations of Word](permutations_of_word.py) + +Find Permuatation of a given word. * [Common Elements of three sorted arrays](sorted_array_three_common_elements.py) + +Find Common elements in three array given that all three arrays are sorted * [Dutch Flag Problem](dutch_flag_problem.py) + + Given an array containing only 0s, 1s and 2s in a random order, arrange the array such that all 0s come + before 1s which in turn come before all 2s + +Input - [1,2,0,1,2,1,0,1,2,1,0] + +Output - [0,0,0,1,1,1,1,1,2,2,2] * [Partition an array into three parts with equal sum](partition_three_parts_equal_sum.py) -* [Binary search on an Infinite array](binary_search_infinite_array.py) + +Divide an array into three parts and sum all three parst must be same. +* [Binary search on a finite array](binary_search_infinite_array.py) + +Performing binary search on a finite array + * [Largest Element](largest_element.py) -* [Right Place](right_place.py) + +Find out the largest element in an array + * [Rotation](rotation.py) + +Rotate an array for given number such that the number goes to the end of array + +input=[1,2,3,4,5] rotate around + +output= [4,5,1,2,3] * [Find missing number](find_missing_numbers.py) + +find missing number between smallest and largest number in array which are not present in array + +input=[1,1,1,4] +output=[2,3] + * [Three Largest Elements](three_largest_elements.py) + +Find three largest numbers from an array * [Triplet Sum](triplet_sum.py) -* [Max Product](max_product.py) + +Find three elements of an array whose sum is eqaul to a given value + * [Moves to Zero](moves_zeros_to_end.py) + +Given an array move all zeros in arrays to the end. * [Pivot Index](pivot_index.py) + +Find the index of element whose right element when added give the same value. * [Intersection of Two Sorted Arrays](intersection_sorted_array.py) + + find out the common elements from two arrays * [Max Triplet Sum](max_triplet_sum.py) -* [Number of 1's in Sorted Array](number_of_1_in_sorted_array.py) + +Find out maximium sum of any three elements for a given array + * [Square of Sorted Array](square_of_sorted_array.py) -* [Max Consecutive 1's](max_consecutive_ones.py) -* [Max Product Three Elements](max_product_three_elements.py) -* [Kadane Algorithm](kadane_algorithm.py) + +For a given array return an array that contains square of elements. + * [All Numbers Divisible](all_numbers_divisible.py) -* [Duplicates](duplicates.py) + + Find a number in the array such that all the elements in the array are divisible by it + + + * [Majority Element](majority_element.py) + +Find an element in an array which has most occurences * [Find Sum](find_sum.py) + +Find if sum of any elements in array is eqaul to a given number * [Quick Sort](quick_sort.py) -* [Peak Element](peak_element.py) + +### Implement Quick Sort algorithm + +Quicksort Running Time: +Quick sort average case is O(n log n) + each level takes O(n) but splitting the data is O(log n) + O(n) * O(log n) = O(n log n) +Worse case is O(log n2) + if pivot is smallest value, each level is O(n) and splitting the data is O(n) + O(n) * O(n) = O(n2) + * [Union Sorted Array](union_sorted_array.py) -* [Min Product](min_product.py) + +Perform Union operations on two arrays + * [Sort By Parity](sort_by_parity.py) + +Given an array A of non-negative integers, return an array consisting of all the even elements of A, followed by all the odd elements of A. * [Duplicate](duplicate.py) -* [Product of Array Except Self](product_of_array_except_self.py) \ No newline at end of file + + Find duplicate in an array of integers given that the integers are in random order and +not necessarily each integer i is 0 <= i <= N where N = length of array +* [Product of Array Except Self](product_of_array_except_self.py) + +find the product of all elements in an array + +* [Right Place](right_place.py) + +Placing elements at right position in an array +* [Max Product Three Elements](max_product_three_elements.py) + +Find out highest sum of three numbers in an array +* [Max Consecutive 1's](max_consecutive_ones.py) + +Counts max number of one's in an array + +* [Kadane Algorithm](kadane_algorithm.py) + +Implementation of Kadane Algorithm +* [Max Product](max_product.py) +* [Number of 1's in Sorted Array](number_of_1_in_sorted_array.py) +* [Duplicates](duplicates.py) +* [Peak Element](peak_element.py) +* [Min Product](min_product.py) \ No newline at end of file From 6abe444c6c480c7a6c966013791dc0e0a6fa0530 Mon Sep 17 00:00:00 2001 From: Gavin Spearhead Date: Sat, 28 Mar 2020 16:29:20 +0000 Subject: [PATCH 287/455] Update longest_common_substring.py --- algorithms/dynamic_programming/longest_common_substring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/dynamic_programming/longest_common_substring.py b/algorithms/dynamic_programming/longest_common_substring.py index 7777feb2..bf6995ad 100644 --- a/algorithms/dynamic_programming/longest_common_substring.py +++ b/algorithms/dynamic_programming/longest_common_substring.py @@ -8,7 +8,7 @@ def lcs(s1, s2): for i in range(1, rows): for j in range(1, cols): - if s[i-1] == s[j-1]: + if s2[i-1] == s1[j-1]: t[i][j] = t[i-1][j-1] + 1 max_length = max(max_length, t[i][j]) From 817cf18156b86d1d665f4b59d04a216d662baeea Mon Sep 17 00:00:00 2001 From: rogervieiraa Date: Sat, 4 Apr 2020 14:51:55 -0300 Subject: [PATCH 288/455] add number_convertion --- algorithms/math/number_convertion.py | 115 +++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 algorithms/math/number_convertion.py diff --git a/algorithms/math/number_convertion.py b/algorithms/math/number_convertion.py new file mode 100644 index 00000000..533f8ef6 --- /dev/null +++ b/algorithms/math/number_convertion.py @@ -0,0 +1,115 @@ +bases = { + "binary": 2, + "octal": 8, + "decimal": 10, + "hex": 16, + "hexadecimal": 16 +} + +default = 10 + + +def verify_base(x): + """ + Verify if already is an integer + If is not verify if is in the bases + If is not return the default base + """ + try: + return int(x) + except: + if x in bases: + return bases[x] + else: + return default + + +def decimal_value(x): + """ + ord(x) is a function that return the number in asc2 table + we use ord to get the number of an caracter + """ + # TODO verify if in the base exist the character like: + # 'z' doesnt exisist in decimal values + if(x >= '0' and x <= '9'): + return int(x) + elif(x >= 'a' and x <= 'z'): + return int(ord(x) - ord('a') + 10) + elif(x >= 'A' and x <= 'Z'): + return int(ord(x) - ord('A') + 10) + else: + # Error + raise Exception('Number not valid for: ', x) + + +def to_special_caracter(x): + if(x >= 0 and x <= 9): + return str(x) + elif(x > 9): + return chr(ord('a') + x - 10) + else: + raise Exception('Not valid negative number in converter: ', x) + + +def convert(n, from_base, to_base): + """ + This algorithm convert numbers between any base to any base like: + + convert("10",2,10) + ~> "2" + + This function recive 3 parameters + n -> the number + from_base -> base of n | you can pass as number like base 2 or as string like "binary" + to_base -> base of the result | you can pass as number like base 2 or as string like "binary" + + Why the n and the return is an string? + Because bases greater the 10 use leathers to represents the numbers + """ + # TODO verify if number is negative + + n = str(n) + from_base = verify_base(from_base) + to_base = verify_base(to_base) + + # We convert to decimal because is the easy way to convert to all + multi = 1 + decimal_number = 0 + if(from_base == 10): + decimal_number = int(n) + else: + for i in range(len(n) - 1, -1, -1): + decimal_number += (multi * decimal_value(n[i])) + multi *= from_base + + if(to_base == 10): + return str(decimal_number) + + result = "" + + while(decimal_number > 0): + value = decimal_number % to_base + result = to_special_caracter(value) + result + decimal_number = int((decimal_number - value)/to_base) + + return result + + +def test_convert(): + print(convert("1111000111", 2, 8) == "1707") + print(convert("1111000111", 2, 10) == "967") + print(convert("1111000111", 2, 16) == "3c7") + print(convert("1234567", 8, 2) == "1010011100101110111") + print(convert("1234567", 8, 10) == "342391") + print(convert("1234567", 8, 16) == "53977") + print(convert("987123", 10, 2) == "11110000111111110011") + print(convert("987123", 10, 8) == "3607763") + print(convert("987123", 10, 16) == "f0ff3") + print(convert("abcdef", 16, 2) == "101010111100110111101111") + print(convert("abcdef", 16, 8) == "52746757") + print(convert("abcdef", 16, 10) == "11259375") + + print(convert("179", 10, 16) == "b3") + print(convert("b3", 16, 10) == "179") + +test_convert() From 793d958d8a08ac2276c099f2a43a08314f0f8bc3 Mon Sep 17 00:00:00 2001 From: rogervieiraa Date: Sat, 4 Apr 2020 14:58:56 -0300 Subject: [PATCH 289/455] fix issue with negative numbers --- algorithms/math/number_convertion.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/algorithms/math/number_convertion.py b/algorithms/math/number_convertion.py index 533f8ef6..aa7c81a2 100644 --- a/algorithms/math/number_convertion.py +++ b/algorithms/math/number_convertion.py @@ -66,12 +66,16 @@ def convert(n, from_base, to_base): Why the n and the return is an string? Because bases greater the 10 use leathers to represents the numbers """ - # TODO verify if number is negative - n = str(n) from_base = verify_base(from_base) to_base = verify_base(to_base) + if(n[0] == '-'): + n = n[1:] + negative = True + else: + negative = False + # We convert to decimal because is the easy way to convert to all multi = 1 decimal_number = 0 @@ -83,7 +87,11 @@ def convert(n, from_base, to_base): multi *= from_base if(to_base == 10): - return str(decimal_number) + decimal_number = str(decimal_number) + if(negative): + decimal_number = '-' + decimal_number + + return decimal_number result = "" @@ -92,6 +100,9 @@ def convert(n, from_base, to_base): result = to_special_caracter(value) + result decimal_number = int((decimal_number - value)/to_base) + if(negative): + result = '-' + result + return result @@ -112,4 +123,10 @@ def test_convert(): print(convert("179", 10, 16) == "b3") print(convert("b3", 16, 10) == "179") + # Negative Tests + print("Negative Tests") + print(convert("-179", 10, 16) == "-b3") + print(convert("-b3", 16, 10) == "-179") + print(convert("-1111000111", 2, 10) == "-967") + test_convert() From 20be9fd9b6a24065e5d50a3b6788b331dbddf87b Mon Sep 17 00:00:00 2001 From: rogervieiraa Date: Sat, 4 Apr 2020 14:59:46 -0300 Subject: [PATCH 290/455] add corner case 0 --- algorithms/math/number_convertion.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/algorithms/math/number_convertion.py b/algorithms/math/number_convertion.py index aa7c81a2..2d3e2c75 100644 --- a/algorithms/math/number_convertion.py +++ b/algorithms/math/number_convertion.py @@ -70,6 +70,10 @@ def convert(n, from_base, to_base): from_base = verify_base(from_base) to_base = verify_base(to_base) + # Corner case 0 + if(n == "0"): + return n + if(n[0] == '-'): n = n[1:] negative = True From 985d77b426d47ac3fb70be7991898cc6ed5e4e8e Mon Sep 17 00:00:00 2001 From: rogervieiraa Date: Sat, 4 Apr 2020 15:03:35 -0300 Subject: [PATCH 291/455] fix pep8 on comments --- algorithms/math/number_convertion.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/algorithms/math/number_convertion.py b/algorithms/math/number_convertion.py index 2d3e2c75..e119eb9c 100644 --- a/algorithms/math/number_convertion.py +++ b/algorithms/math/number_convertion.py @@ -60,8 +60,9 @@ def convert(n, from_base, to_base): This function recive 3 parameters n -> the number - from_base -> base of n | you can pass as number like base 2 or as string like "binary" - to_base -> base of the result | you can pass as number like base 2 or as string like "binary" + from_base -> base of n | + to_base -> base of the result | + you can pass the bases as number like base 2 or as string like "binary" Why the n and the return is an string? Because bases greater the 10 use leathers to represents the numbers From 3e2263cd7ddd0056d59c66b676fbf595549f2ec6 Mon Sep 17 00:00:00 2001 From: rogervieiraa Date: Sat, 4 Apr 2020 15:05:03 -0300 Subject: [PATCH 292/455] add in the documents --- algorithms/math/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/math/index.md b/algorithms/math/index.md index e84f7095..fc7b2649 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -5,4 +5,4 @@ * [Nth Prime Number](prime.py) * [Sieve of Erastothenes](sieve_of_eratosthenes.py) * [Perfect Square](perfect_square.py) - +* [Number Convertion](number_convertion.py) From 8e0d2b6d8b2cb20deae1252bd1b87461451b29bd Mon Sep 17 00:00:00 2001 From: Tanmoy Mukherjee Date: Wed, 15 Apr 2020 01:59:14 +0530 Subject: [PATCH 293/455] Update maxprod.py --- data_structures/array/max_product.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/data_structures/array/max_product.py b/data_structures/array/max_product.py index e69de29b..81ee1f70 100644 --- a/data_structures/array/max_product.py +++ b/data_structures/array/max_product.py @@ -0,0 +1,16 @@ +def max_product(arr): + n = len(arr) + if n == 0: + return 0 + if n == 1: + return arr[0] + a = arr[0] + b = arr[1] + maxprod = a * b + for i in range(n): + for j in range(i + 1, n): + if (arr[i] * arr[j]) > maxprod: + a = arr[i] + b = arr[j] + maxprod = a * b + return maxprod From bee1ee73669281c9c2910ffafd23da16d72731a4 Mon Sep 17 00:00:00 2001 From: durid17 Date: Sat, 18 Apr 2020 14:54:22 +0400 Subject: [PATCH 294/455] Z_Algorithm --- algorithms/dynamic_programming/Z_Algorithm.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 algorithms/dynamic_programming/Z_Algorithm.py diff --git a/algorithms/dynamic_programming/Z_Algorithm.py b/algorithms/dynamic_programming/Z_Algorithm.py new file mode 100644 index 00000000..6af4c894 --- /dev/null +++ b/algorithms/dynamic_programming/Z_Algorithm.py @@ -0,0 +1,30 @@ +class Z_Algorithm(): + """ + return all occurences of string s in text, returns its indexes starting from zero + delimeter should be charachter which will not occur neither is S nor in text + by default its '$' + """ + @staticmethod + def find_occurrences(s:str , text:str , delimeter = '$'): + return Z_Algorithm.z_function(s + delimeter + text , len(s)) + + @staticmethod + def z_function(text:str , size:int): + l = 0 + r = 0 + z = [0] * len(text) + for i in range(1 , len(text)): + if i <= r: + z[i] = min(r - i + 1 , z[i - l]) + while i + z[i] < len(text) and text[z[i]] == text[i + z[i]]: + z[i] += 1 + + if i + z[i] - 1 > r: + l = i + r = i + z[i] - 1 + + res = [] + for i in range(size , len(text)): + if z[i] == size: + res.append(i - size - 1) + return res \ No newline at end of file From 520e89923c5a50c9f7e5050c8e111500c87245bd Mon Sep 17 00:00:00 2001 From: shotanozadze Date: Mon, 20 Apr 2020 23:19:58 +0400 Subject: [PATCH 295/455] Deque Implementation --- .DS_Store | Bin 0 -> 8196 bytes data_structures/.DS_Store | Bin 0 -> 8196 bytes data_structures/deque/.DS_Store | Bin 0 -> 6148 bytes data_structures/deque/deque.py | 68 ++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 .DS_Store create mode 100644 data_structures/.DS_Store create mode 100644 data_structures/deque/.DS_Store create mode 100644 data_structures/deque/deque.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..796478d40382de070f3963a44c55518e0a16a8ce GIT binary patch literal 8196 zcmeHMUvC>l5T8vAxpQcIX%muEMLJ<2DmAK7InW1G)i^Q5qTpbgG$C!>vv1>^a=Eqc z&PkIH6e017#2Xax#vk=FAR$C~fKLD~RX+kqhzFj^>>sBWJE1~I2(`P??#%7Z%zA&b zGpk(#04a3b^8gb7U|{9c8p7s~!pC{-D+8)$7%4%0fDk;0VHMUP>XX(T8Uc-fMnEH= z5zq+y9}vJZn-}AVb6<|?RwJMhcp?$t`N77@XHN`X`(6}JPya#&j-{S@ zdeAV_L*~%%ka@kj$~LR96L+G56V|QMRnMgjC%o#p@oJ3*MW1fapd4OtVj3=U;TmH; z3P|2*EO>OYZjH{eAa=ZfhQgk-aqX%XxNNh)I)NJrd1YMi^G>{qc8qME+F}u=Vb-mQ zot<3nr71f%liQuLcP?C*p0a0hFYoS}hB5i#Yn2eQ?j5BtiiL`?p?VX!^_|LQxPXDRv^q;#c>18r zlfIBX{rCPgj7Rx${Dt!uOE=fIws+p!eg9KjB9?teX5{yNdmFh7{4Ho+b3^TQ@@;q7 z_bsctaNOAH2Y;WXD;A>X32%x7W2@6hE|=(*Ll z)AWMYVoYzvRd1WttrI<>73$u2*j3wVqs-{T4q@(cNNFJKl~-0G8ZRdJrMi`gnj!Q3 zc@}xG$AYD65e8T(rt76(h2e}F7+mExABq-e7$NP`SzL0$&!w9iRi(B!Ul1HB)RLAS5K;)?&>K<^8~~+p91;u14zWX8LQpRJ z190WUZ*b!a_yc}`4}dqjOJqAOLGnEHHp~HW%xZ_rAJoTEl>0 z;J;*m_Xiu5Wl77il5*=nBU1p#94^a(KJoymV{2K`a;&6O#h5C45L#8}6hkO=+_xDH zS<-T>q*5oL)JbT|LT4yKT8Ex3;Ur2*n$|F27?@^&bN3~gvwIYz^7rEdKWsRD=m5cs z>N@J>ud<*=l&3oNaMUS_e4jxslY@~1i9d#|7+OsnQQCr7&*;rTFQPbudX+(~Q3Ip* z(DuofHfoS;?+I+Uu*YZ9<9x}ClLxj*Pccd}ZILh^ag>_*1nCT-uIA{Y)AhY5-roKs z&dufW^9z<$unOl3kE-o(P>t(xKPuOI5BTg(J#IU?e>V*MNx$yg^O}R&%G#|ki0fX^ z>`7(MZ36P}z8ARRpd9uCH2F z*80Vr8wZD-3C^``)I(G*j2kN{RnW+E98#v^kdr?Q g(YFC*osyPgC2X8`y+#aAI`XaRdf}Lubo00w ZeCKQj`k#A9M z-V+t2fD|}Z;4-&!_WyhMnfd>iq@5Iy0{=<@pRFEOOT1F`*2&AU*EaYQoHZYC8rDHU mh;|H&c8m?%@pTksUE><(y>LtnI`TmW>dydmkx7BSR^SVP1shiY literal 0 HcmV?d00001 diff --git a/data_structures/deque/deque.py b/data_structures/deque/deque.py new file mode 100644 index 00000000..d578c8e2 --- /dev/null +++ b/data_structures/deque/deque.py @@ -0,0 +1,68 @@ +class Deque(): + def __init__(self): + self.data = list() + + def push_front(self, elem): + temp = list() + temp.append(elem) + + for i in self.data: + temp.append(i) + + self.data = temp + + def push_back(self, elem): + self.data.append(elem) + + def pop_front(self): + temp = list() + + for i in range(0, len(self.data)): + if not i==0: + temp.append(self.data[i]) + + self.data = temp + + def pop_back(self): + temp = list() + + for i in range(0, len(self.data)): + if not i==len(self.data)-1: + temp.append(self.data[i]) + + self.data = temp + + def get_first(self): + if(len(self.data)>0): + return self.data[0] + else: + return "Deque is empty" + + def get_last(self): + if(len(self.data)>0): + return self.data[len(self.data)-1] + else: + return "Deque is empty" + + def size(self): + return len(self.data) + + def isEmpty(self): + if len(self.data) == 0: + return True + return False + + def contains(self, elem): + for i in self.data: + if i==elem: + return True + + return False + + def printElems(self): + result = "" + + for i in self.data: + result += str(i) + " | " + + print(result) \ No newline at end of file From 51774fe95eaf5703c9174cfad73a651e50cf1f18 Mon Sep 17 00:00:00 2001 From: Shota Nozadze <48485182+shotanozadze@users.noreply.github.com> Date: Tue, 21 Apr 2020 13:51:10 +0400 Subject: [PATCH 296/455] Delete ds_store --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 796478d40382de070f3963a44c55518e0a16a8ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMUvC>l5T8vAxpQcIX%muEMLJ<2DmAK7InW1G)i^Q5qTpbgG$C!>vv1>^a=Eqc z&PkIH6e017#2Xax#vk=FAR$C~fKLD~RX+kqhzFj^>>sBWJE1~I2(`P??#%7Z%zA&b zGpk(#04a3b^8gb7U|{9c8p7s~!pC{-D+8)$7%4%0fDk;0VHMUP>XX(T8Uc-fMnEH= z5zq+y9}vJZn-}AVb6<|?RwJMhcp?$t`N77@XHN`X`(6}JPya#&j-{S@ zdeAV_L*~%%ka@kj$~LR96L+G56V|QMRnMgjC%o#p@oJ3*MW1fapd4OtVj3=U;TmH; z3P|2*EO>OYZjH{eAa=ZfhQgk-aqX%XxNNh)I)NJrd1YMi^G>{qc8qME+F}u=Vb-mQ zot<3nr71f%liQuLcP?C*p0a0hFYoS}hB5i#Yn2eQ?j5BtiiL`?p?VX!^_|LQxPXDRv^q;#c>18r zlfIBX{rCPgj7Rx${Dt!uOE=fIws+p!eg9KjB9?teX5{yNdmFh7{4Ho+b3^TQ@@;q7 z_bsctaNOAH2Y;WXD;A>X32%x7W2@6hE|=(*Ll z)AWMYVoYzvRd1WttrI<>73$u2*j3wVqs-{T4q@(cNNFJKl~-0G8ZRdJrMi`gnj!Q3 zc@}xG$AYD65e8T(rt76(h2e}F7+mExABq-e7$NP`SzL0$& Date: Wed, 22 Apr 2020 11:33:06 +0400 Subject: [PATCH 297/455] Delete .DS_Store --- data_structures/.DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data_structures/.DS_Store diff --git a/data_structures/.DS_Store b/data_structures/.DS_Store deleted file mode 100644 index e8e8cc9df611b98d9d158f1c9f0b16d2d2b5410d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHM!EVz)5S^t->!w9iRi(B!Ul1HB)RLAS5K;)?&>K<^8~~+p91;u14zWX8LQpRJ z190WUZ*b!a_yc}`4}dqjOJqAOLGnEHHp~HW%xZ_rAJoTEl>0 z;J;*m_Xiu5Wl77il5*=nBU1p#94^a(KJoymV{2K`a;&6O#h5C45L#8}6hkO=+_xDH zS<-T>q*5oL)JbT|LT4yKT8Ex3;Ur2*n$|F27?@^&bN3~gvwIYz^7rEdKWsRD=m5cs z>N@J>ud<*=l&3oNaMUS_e4jxslY@~1i9d#|7+OsnQQCr7&*;rTFQPbudX+(~Q3Ip* z(DuofHfoS;?+I+Uu*YZ9<9x}ClLxj*Pccd}ZILh^ag>_*1nCT-uIA{Y)AhY5-roKs z&dufW^9z<$unOl3kE-o(P>t(xKPuOI5BTg(J#IU?e>V*MNx$yg^O}R&%G#|ki0fX^ z>`7(MZ36P}z8ARRpd9uCH2F z*80Vr8wZD-3C^``)I(G*j2kN{RnW+E98#v^kdr?Q g(YFC*osyPgC2 Date: Wed, 22 Apr 2020 11:33:24 +0400 Subject: [PATCH 298/455] Delete .DS_Store --- data_structures/deque/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data_structures/deque/.DS_Store diff --git a/data_structures/deque/.DS_Store b/data_structures/deque/.DS_Store deleted file mode 100644 index 581a88fc38e6837702b00784b44de149a97e16b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF-`+P474G|Ni-=bw@igZO|yzZLCptH61qr%A_d)5yo;Z~jBO#JODaTz#*#g| zUe9fAigRpczC3Ji&E{q{z=`(GFg2djCw5U82g31;XS=Z%dwbaJHX8`y+#aAI`XaRdf}Lubo00w ZeCKQj`k#A9M z-V+t2fD|}Z;4-&!_WyhMnfd>iq@5Iy0{=<@pRFEOOT1F`*2&AU*EaYQoHZYC8rDHU mh;|H&c8m?%@pTksUE><(y>LtnI`TmW>dydmkx7BSR^SVP1shiY From e44a71a05f19ef94464fca553884fa3d3d679d4b Mon Sep 17 00:00:00 2001 From: tasbihaasim Date: Wed, 22 Apr 2020 17:23:53 +0500 Subject: [PATCH 299/455] Add front and back search --- .../miscellaneous/front_and_back_search.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 algorithms/miscellaneous/front_and_back_search.py diff --git a/algorithms/miscellaneous/front_and_back_search.py b/algorithms/miscellaneous/front_and_back_search.py new file mode 100644 index 00000000..04e129ac --- /dev/null +++ b/algorithms/miscellaneous/front_and_back_search.py @@ -0,0 +1,26 @@ +def front_and_back_search(lst, item): + ''' + args: + lst: an unsorted array of integers + item: data to be found + + return: + item which is found else False + ''' + rear=0 + front=len(lst)-1 + u=None + if rear>front: + return False + else: + while rear<=front: + if item==lst[rear] or item==lst[front]: + u='' + return True ##item found + elif item!=lst[rear] and item!=lst[front]: + if item > lst[rear]: + rear=rear+1 + elif item < lst[front]: + front=front-1 + if u==None: + return False From 4974fbc4a81a57057dbb913321595d8ef5ecd05d Mon Sep 17 00:00:00 2001 From: Rithwik Ediga Lakhamsani Date: Sat, 25 Apr 2020 17:46:14 -0700 Subject: [PATCH 300/455] Add Longest Palindromic Substring --- .../longest_palindromic_substring.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 algorithms/dynamic_programming/longest_palindromic_substring.py diff --git a/algorithms/dynamic_programming/longest_palindromic_substring.py b/algorithms/dynamic_programming/longest_palindromic_substring.py new file mode 100644 index 00000000..251d2e7f --- /dev/null +++ b/algorithms/dynamic_programming/longest_palindromic_substring.py @@ -0,0 +1,57 @@ +def longest_palindromic_substring_DP(s): + + S = [[False for i in range(len(s))] for j in range(len(s))] + + max_palindrome = "" + + for i in range(len(s))[::-1]: + for j in range(i, len(s)): + # if j - 1 < 3, then there is one or two characters between these + # two positions, implying that if s[i] == s[j] + # then that small string is a palindrome + # We check if the above cases is valid or i + # they are larger, we use DP to check the substring + # in between j and i + S[i][j] = s[i] == s[j] and (j - i < 3 or S[i+1][j-1]) + if S[i][j] and j - i + 1 > len(max_palindrome): + max_palindrome = s[i:j+1] + + return max_palindrome + + +def longest_palindromic_substring_expansion(s): + max_palindrome = "" + + for i in range(len(s) * 2 - 1): + if i % 2 == 0: + # This is when you are "on" an actual character + # o = offset, ind = current character + o = 0 + ind = i // 2 + while ind + o < len(s) and ind - o >= 0: + if(s[ind + o] != s[ind - o]): + break + if ind + o - (ind - o) + 1 > len(max_palindrome): + max_palindrome = s[ind-o:ind+o + 1] + o += 1 + else: + # This is when you are "in the middle of" two characters + # o = offset, sind = start char, eind = end char + o = 0 + sind = i // 2 + eind = i // 2 + 1 + while sind - o >= 0 and eind + o < len(s): + if(s[sind - o] != s[eind + o]): + break + if eind + o - (sind - o) + 1 > len(max_palindrome): + max_palindrome = s[sind - o:eind + o + 1] + o += 1 + + return max_palindrome + + +input_string = "abbbacdcaacdca" + +ans_DP = longest_palindromic_substring_DP(input_string) +ans_expansion = longest_palindromic_substring_expansion(input_string) +print("DP Solution: {}, Expansion Solution: {}".format(ans_DP, ans_expansion)) From 53a140dee849ffb7c4dac747e9262cf706ee063d Mon Sep 17 00:00:00 2001 From: chandanatochandu Date: Tue, 28 Apr 2020 15:04:57 +0500 Subject: [PATCH 301/455] KMP Pattern Searching Algorithm --- data_structures/strings/KMP_Pattern_Search.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 data_structures/strings/KMP_Pattern_Search.py diff --git a/data_structures/strings/KMP_Pattern_Search.py b/data_structures/strings/KMP_Pattern_Search.py new file mode 100644 index 00000000..37bfcd2c --- /dev/null +++ b/data_structures/strings/KMP_Pattern_Search.py @@ -0,0 +1,57 @@ +#Python program for KMP Algorithm +def KMP_pattern_search(pattern, text): + P = len(pattern) + Q = len(text) + + # create long_prefix_suffix[] that will hold the longest prefix suffix + # values for pattern + long_prefix_suffix = [0]*P + + # index for pattern[] + j=0 + + # preprocess the pattern (caluclate long_prefix_suffix[] array) + long_Prefix_Suffix_Array(pattern, P, long_prefix_suffix) + + # index for text[] + i=0 + + while i < Q: + if pattern[j] == text[i]: + i += 1 + j += 1 + + if j == P: + print("Pattern found at index " + str(i-j)) + j=long_prefix_suffix[j-1] + + # mismatch after j matches + elif i < Q and pattern[j] != text[i]: + if j != 0: + j=long_prefix_suffix[j-1] + else: + i += 1 + +def long_Prefix_Suffix_Array(pattern, P, long_prefix_suffix): + # length of the previous longest prefix suffix + l=0 + long_prefix_suffix[0]=0 + i=1 + + # the loop calculates long_prefix_suffix[i] for i = 1 to P-1 + while i < P: + if pattern[i] == pattern[l]: + l += 1 + long_prefix_suffix[i] = l + i += 1 + else: + if l != 0: + l=long_prefix_suffix[l-1] + else: + long_prefix_suffix[i] = 0 + i += 1 + +text = "ABABDABACDABABCABAB" +pattern = "ABABCABAB" +KMP_pattern_search(pattern, text) + From 52653e640806621bddcd5cc61d7c069edbd3a8b8 Mon Sep 17 00:00:00 2001 From: lucifermorningstar Date: Sun, 3 May 2020 03:49:11 -0500 Subject: [PATCH 302/455] Bubble Sort Fix --- algorithms/sorting/bubble_sort.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/algorithms/sorting/bubble_sort.py b/algorithms/sorting/bubble_sort.py index 85668cac..7cd5321e 100644 --- a/algorithms/sorting/bubble_sort.py +++ b/algorithms/sorting/bubble_sort.py @@ -1,12 +1,18 @@ -''' +""" Bubble Sort worst time complexity occurs when array is reverse sorted - O(n^2) Best time scenario is when array is already sorted - O(n) -''' +""" + def bubble_sort(array): - n = len(array) + has_swapped = True + + num_of_iterations = 0 - for i in range(n): - for j in range(0, n-i-1): - if array[j] > array[j+1]: - array[j], array[j+1] = array[j+1], array[j] \ No newline at end of file + while has_swapped: + has_swapped = False + for i in range(len(array) - num_of_iterations - 1): + if array[i] > array[i + 1]: + array[i], array[i + 1] = array[i + 1], array[i] + has_swapped = True + num_of_iterations += 1 From 114541e7ef1098ce13e4e08aaef37b607a45cb1b Mon Sep 17 00:00:00 2001 From: lucifermorningstar Date: Sun, 3 May 2020 04:11:20 -0500 Subject: [PATCH 303/455] min_product fix --- data_structures/array/min_product.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/data_structures/array/min_product.py b/data_structures/array/min_product.py index e83cf5e6..01bbfcb9 100644 --- a/data_structures/array/min_product.py +++ b/data_structures/array/min_product.py @@ -7,45 +7,44 @@ # If there are odd number of negative numbers and no zeros, # the result is simply the product of all -# If there is a zero and al other are positive, then the result is zero +# If there is a zero and all other are positive, then the result is zero # If there are only positive numbers, the the result is # the smallest positive number + def find(arr): if len(arr) == 1: return arr[0] - + count_negative = 0 - count_positive = 0 count_zero = 0 max_neg = float('-inf') min_pos = float('inf') - + prod = 1 - + for num in arr: if num == 0: count_zero += 1 continue if num < 0: - count_neg += 1 + count_negative += 1 max_neg = max(max_neg, num) if num > 0: min_pos = min(min_pos, num) - prod = prod * num + prod *= num - if count_zero == len(arr) or (count_neg == 0 and count_zero > 0): + if count_zero == len(arr) or (count_negative == 0 and count_zero > 0): return 0 - - if count_neg == 0: + + if count_negative == 0: return min_pos - if count_neg & 1 == 0 and count_neg != 0: + if count_negative & 1 == 0 and count_negative != 0: prod = int(prod / max_neg) - - return prod + return prod From d16c253747923e1e93ee8222244f36a71d33cce0 Mon Sep 17 00:00:00 2001 From: bnMikheili Date: Sun, 17 May 2020 03:30:23 +0400 Subject: [PATCH 304/455] add counting sort implementation --- algorithms/sorting/counting_sort.py | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 algorithms/sorting/counting_sort.py diff --git a/algorithms/sorting/counting_sort.py b/algorithms/sorting/counting_sort.py new file mode 100644 index 00000000..d9f359c8 --- /dev/null +++ b/algorithms/sorting/counting_sort.py @@ -0,0 +1,35 @@ +""" +High level description: +Counting sort is a sorting technique based on keys between a specific range, +with efective performance on the predetermined range size of the values. +It works by counting the number of objects having distinct key values (kind of hashing). +Then doing some arithmetic to calculate the position of each object in the output sequence. + +Time complexity: +O(n+k) where n is the number of elements in input array and k is the range of input. + +Auxiliary Space: O(n+k) +""" + +def counting_sort(arr): + # Find min and max values + min_value = min(arr) + max_value = max(arr) + + # Count number appearances in the array + counting_arr = [0]*(max_value-min_value+1) + for num in arr: + counting_arr[num-min_value] += 1 + + # Rearrange sequence in the array + index = 0 + for i, count in enumerate(counting_arr): + for _ in range(count): + arr[index] = min_value + i + index += 1 + +test_array = [3, 3, 2, 6, 4, 7, 9, 7, 8] + +counting_sort(test_array) + +print(test_array) From 7ff39c6fbee9f7399cadbe6a181dab5ca5822927 Mon Sep 17 00:00:00 2001 From: beqakd Date: Tue, 19 May 2020 18:44:31 +0400 Subject: [PATCH 305/455] add implementation of MST alghoritm --- algorithms/graph/mst.py | 97 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 algorithms/graph/mst.py diff --git a/algorithms/graph/mst.py b/algorithms/graph/mst.py new file mode 100644 index 00000000..fc1fdeb2 --- /dev/null +++ b/algorithms/graph/mst.py @@ -0,0 +1,97 @@ +# i checked your other py files and decided that i would go for default dict too +# i used same structure as needed for this repository. +from collections import defaultdict +r = range + + +class Graph: + # Class initializer + def __init__(self, vertices): + # num of vertices and our starting graph + + self.vertices = vertices + # Values will be [start_point, end_point, weight] + self.graph = [] + + # Add edge to graph + def add_edge(self, start, end, weight): + value = [start, end, weight] + self.graph.append(value) + + # Simple search alghoritm + def search(self, parent_ranks, index): + if parent_ranks[index] != index: + return self.search(parent_ranks, parent_ranks[index]) + return index + + def union(self, ranks, parent_ranks, fir, sec): + fir, sec = self.search(parent_ranks, fir), self.search( + parent_ranks, sec) + + # 3 steps. ranks lower, higher, same + + if (ranks[fir] > ranks[sec]): + parent_ranks[sec] = fir + + elif (ranks[fir] < ranks[sec]): + parent_ranks[fir] = sec + + elif (ranks[fir] == ranks[sec]): + parent_ranks[sec] = fir + ranks[fir] += 1 + + # run mst alghoritm main part. + + def run_mst(self, ranks, parent_ranks, answer): + edge, index = 0, 0 + + while True: + if ((self.vertices - 1) <= edge): + break + + # Take value + value = self.graph[index] + + # check cycle + fir, sec = self.search(parent_ranks, value[0]), self.search( + parent_ranks, value[1]) + + if fir != sec: + edge += 1 # increase edge + + # append and union + answer.append(value) + self.union(ranks, parent_ranks, fir, sec) + + index += 1 + + def print_graph(self, answer): + for start, end, weight in answer: + print(f"{start} - {end} --> {weight}") + + # Main function for mst alghoritm + def MST(self): + # sort the graph + self.graph = sorted(self.graph, key=lambda item: item[2]) + + # For this alghoritm we need two array. + ranks = [0] * self.vertices + parent_ranks = [_ for _ in r(self.vertices)] + answer = [] + + self.run_mst(ranks, parent_ranks, answer) + self.print_graph(answer) + + +def main(): + g = Graph(4) + g.add_edge(0, 1, 10) + g.add_edge(0, 2, 6) + g.add_edge(0, 3, 5) + g.add_edge(1, 3, 15) + g.add_edge(2, 3, 4) + g.MST() + + +if __name__ == "__main__": + main() From dbeea5eb05d9da00ac0b0bf86bad5f6c23985940 Mon Sep 17 00:00:00 2001 From: beqakd Date: Tue, 19 May 2020 18:48:17 +0400 Subject: [PATCH 306/455] removed extra main --- algorithms/graph/mst.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/algorithms/graph/mst.py b/algorithms/graph/mst.py index fc1fdeb2..a4c08b0e 100644 --- a/algorithms/graph/mst.py +++ b/algorithms/graph/mst.py @@ -81,17 +81,3 @@ def MST(self): self.run_mst(ranks, parent_ranks, answer) self.print_graph(answer) - - -def main(): - g = Graph(4) - g.add_edge(0, 1, 10) - g.add_edge(0, 2, 6) - g.add_edge(0, 3, 5) - g.add_edge(1, 3, 15) - g.add_edge(2, 3, 4) - g.MST() - - -if __name__ == "__main__": - main() From 75468a5b9166bf0276b4b1431b513400df82e270 Mon Sep 17 00:00:00 2001 From: beqakd Date: Tue, 19 May 2020 18:51:08 +0400 Subject: [PATCH 307/455] check for pip8 style --- algorithms/graph/mst.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/graph/mst.py b/algorithms/graph/mst.py index a4c08b0e..930a2211 100644 --- a/algorithms/graph/mst.py +++ b/algorithms/graph/mst.py @@ -1,4 +1,4 @@ -# i checked your other py files and decided that i would go for default dict too +# i checked your other py files and decided that i would go for default dict # i used same structure as needed for this repository. from collections import defaultdict r = range From 716a4ac97fa8c9c476f15e71879e372b999aefa1 Mon Sep 17 00:00:00 2001 From: shotanozadze Date: Fri, 22 May 2020 19:09:07 +0400 Subject: [PATCH 308/455] division factors --- .gitignore | 1 + algorithms/math/divisors.py | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 algorithms/math/divisors.py diff --git a/.gitignore b/.gitignore index c7126040..40202465 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ questions_to_do.txt +.DS_Store diff --git a/algorithms/math/divisors.py b/algorithms/math/divisors.py new file mode 100644 index 00000000..ea923837 --- /dev/null +++ b/algorithms/math/divisors.py @@ -0,0 +1,63 @@ +import math + +class divisors: + + def findAllDivisors(self, n): + result = list() + + for i in range(1, n+1): + if (n%i == 0): + result.append(i) + + return result + + def divisorsCount(self, n): + divs = self.findAllDivisors(n) + return len(divs) + + def oddFactors(self, n): + result = list() + + for i in range(1, n+1): + if (n%i == 0 and i%2==1): + result.append(i) + + return result + + def oddFactorsSum(self, n): + divs = self.evenFactors(n) + return sum(divs) + + def evenFactors(self, n): + result = list() + + for i in range(1, n+1): + if (n%i == 0 and i%2==0): + result.append(i) + + return result + + def evenFactorsSum(self, n): + divs = self.evenFactors(n) + return sum(divs) + + def primeFactors(self, n): + result = list() + + while n % 2 == 0: + result.append(2) + n = n / 2 + + for i in range(3,int(math.sqrt(n))+1,2): + while n % i== 0: + result.append(i) + n = n / i + + if n > 2: + result.append(n) + + return result + + def primeFactorsSum(self, n): + divs = self.primeFactors(n) + return sum(divs) \ No newline at end of file From aa804e3ced753d446931aa21ae140ea1b5f05442 Mon Sep 17 00:00:00 2001 From: mmbhatk Date: Fri, 22 May 2020 21:02:11 +0530 Subject: [PATCH 309/455] Find the sum of number of set bits in a range of numbers --- README.md | 1 + .../bit_manipulation/range_sum_set_bits.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 algorithms/bit_manipulation/range_sum_set_bits.py diff --git a/README.md b/README.md index 14069301..7b205f4e 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ This directory contains various types of algorithm questions like Dynamic Progra 4. [Math](algorithms/math) 5. [Misc](algorithms/miscellaneous) 6. [Sorting](algorithms/sorting) +7. [Bit Manipulation](algorithms/bit_manipulation) ### Bookmarks diff --git a/algorithms/bit_manipulation/range_sum_set_bits.py b/algorithms/bit_manipulation/range_sum_set_bits.py new file mode 100644 index 00000000..6250acf9 --- /dev/null +++ b/algorithms/bit_manipulation/range_sum_set_bits.py @@ -0,0 +1,19 @@ +# Question: Find the sum of number of set bits in all the numbers in the range [1, n]. + +def countBits(n): + + """ Consider a number x and half of the number (x//2). + The binary representation of x has all the digits as + the binary representation of x//2 followed by an additional + digit at the last position. Therefore, we can find the number + of set bits in x by finding the number of set bits in x//2 + and determining whether the last digit in x is 0 or 1. """ + + res = [0] * (n+1) + for i in range(1, n+1): + res[i] = res[i//2] + (i & 1) + return sum(res) + + +# Extension: Find the sum of number of set bits in all the numbers in the range [m, n]. +# Answer: In countBits(m, n), return sum(res) - sum(res[:m]) \ No newline at end of file From 9d3b6ba0c51f8510ca25eae04ec437e0b21f7ac1 Mon Sep 17 00:00:00 2001 From: durid17 Date: Mon, 25 May 2020 15:49:04 +0400 Subject: [PATCH 310/455] SumSegTree --- data_structures/segment_tree/seg_tree_sum.py | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 data_structures/segment_tree/seg_tree_sum.py diff --git a/data_structures/segment_tree/seg_tree_sum.py b/data_structures/segment_tree/seg_tree_sum.py new file mode 100644 index 00000000..ee7481f9 --- /dev/null +++ b/data_structures/segment_tree/seg_tree_sum.py @@ -0,0 +1,42 @@ +class SumSegTree(): + + def __init__(self, n, arr = None): + self._t = [0] * (4 * n) + self._n = n + if arr: self._build(arr, 1 , 0 , n - 1) + + def _build(self, a, v, tl, tr): + if tl == tr: + self._t[v] = a[tl] + else: + tm = (tl + tr) // 2 + self._build(a, v*2, tl, tm) + self._build(a, v*2+1, tm+1, tr) + self._t[v] = self._t[v*2] + self._t[v*2+1] + + def _sum_util(self, v, tl, tr, l, r): + if l > r: return 0 + + if l == tl and r == tr : return self._t[v] + + tm = (tl + tr) // 2 + return self._sum_util(v*2, tl, tm, l, min(r, tm)) + self._sum_util(v*2+1, tm+1, tr, max(l, tm+1), r) + + def _update_util(self, v, tl, tr, pos, new_val): + if tl == tr: + self._t[v] = new_val + else: + tm = (tl + tr) // 2 + if pos <= tm: self._update_util(v*2, tl, tm, pos, new_val) + else: self._update_util(v*2+1, tm+1, tr, pos, new_val) + self._t[v] = self._t[v*2] + self._t[v*2+1] + + def sum(self, l, r): + return self._sum_util(1 , 0 , self._n - 1 , l , r) + + def update(self, pos, new_val): + self._update_util(1 , 0 , self._n - 1 , pos , new_val) + + def add(self, pos, change): + value = self._sum(pos , pos) + self._update_util(1 , 0 , self._n - 1 , pos , value + change) \ No newline at end of file From 4f8199d9d21ffb20371193292b6e0c8528da84a6 Mon Sep 17 00:00:00 2001 From: durid17 Date: Mon, 25 May 2020 16:36:15 +0400 Subject: [PATCH 311/455] MaxSegTree --- data_structures/segment_tree/seg_tree_max.py | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 data_structures/segment_tree/seg_tree_max.py diff --git a/data_structures/segment_tree/seg_tree_max.py b/data_structures/segment_tree/seg_tree_max.py new file mode 100644 index 00000000..eb40f116 --- /dev/null +++ b/data_structures/segment_tree/seg_tree_max.py @@ -0,0 +1,44 @@ +import sys + +class MaxSegTree(): + + def __init__(self, n, arr = None): + self._t = [-sys.maxsize - 1] * (4 * n) + self._n = n + if arr: self._build(arr, 1 , 0 , n - 1) + + def _build(self, a, v, tl, tr): + if tl == tr: + self._t[v] = a[tl] + else: + tm = (tl + tr) // 2 + self._build(a, v*2, tl, tm) + self._build(a, v*2+1, tm+1, tr) + self._t[v] = max(self._t[v*2] ,self._t[v*2+1]) + + def _max_util(self, v, tl, tr, l, r): + if l > r: return -sys.maxsize - 1 + + if l == tl and r == tr : return self._t[v] + + tm = (tl + tr) // 2 + return max(self._max_util(v*2, tl, tm, l, min(r, tm)) ,self._max_util(v*2+1, tm+1, tr, max(l, tm+1), r)) + + def _update_util(self, v, tl, tr, pos, new_val): + if tl == tr: + self._t[v] = new_val + else: + tm = (tl + tr) // 2 + if pos <= tm: self._update_util(v*2, tl, tm, pos, new_val) + else: self._update_util(v*2+1, tm+1, tr, pos, new_val) + self._t[v] = max(self._t[v*2] , self._t[v*2+1]) + + def max_element(self, l, r): + return self._max_util(1 , 0 , self._n - 1 , l , r) + + def update(self, pos, new_val): + self._update_util(1 , 0 , self._n - 1 , pos , new_val) + + def add(self, pos, change): + value = self.max_element(pos , pos) + self._update_util(1 , 0 , self._n - 1 , pos , value + change) \ No newline at end of file From 49d1b54d13f129b9619813f6845cb8d5536ac1d5 Mon Sep 17 00:00:00 2001 From: beqakd Date: Thu, 4 Jun 2020 19:09:19 +0400 Subject: [PATCH 312/455] add dijkstra alghoritm. --- algorithms/graph/dijkstra.py | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 algorithms/graph/dijkstra.py diff --git a/algorithms/graph/dijkstra.py b/algorithms/graph/dijkstra.py new file mode 100644 index 00000000..91dbe362 --- /dev/null +++ b/algorithms/graph/dijkstra.py @@ -0,0 +1,55 @@ +# i checked your other py files and decided that i would go for default dict +# i used same structure as needed for this repository. +from collections import defaultdict +import sys +r = range +# min weight goes for 0 in this case +max_weight = sys.maxsize + + +class Graph: + # Class initializer + def __init__(self, vertices): + # num of vertices and our starting graph + self.vertices = vertices + + # Values will be [[]] two deminsial array with + # columns for start going to rows. + self.graph = [[0] * self.vertices for _ in r(self.vertices)] + self.visited = [0] * self.vertices # to control visited vertices + # for our distances to minimaze them. + self.distances = [max_weight] * self.vertices + + # Add edge to graph start --> end point with specific weight! + def add_edge(self, start, end, weight): + self.graph[start][end] = weight + + def print_dist(self, dist): + for _ in r(self.vertices): + print("vert ", _, "\tdist ", self.distances[_]) + + def dijkstra(self, end_point): + self.distances[end_point] = 0 + + for vert in r(self.vertices): + + # we need to check for minimum but not visited!! + my_min, min_index = max_weight, 0 + for _ in r(self.vertices): + if not self.visited[_]: + if my_min > self.distances[_]: + my_min = self.distances[_] + min_index = _ + + # check the flag for visited + self.visited[min_index] = 1 + + # # iterate and update if needed + for adj in r(self.vertices): + # check for edge and visited + val = self.graph[min_index][adj] + if not self.visited[adj] and val != 0: + # check if needed update + if self.distances[adj] > self.distances[min_index] + val: + self.distances[adj] = self.distances[min_index] + val + self.print_dist(self.distances) From 733df666bfbd9a1009507ba0ce507a9006c95bd4 Mon Sep 17 00:00:00 2001 From: beqakd Date: Fri, 5 Jun 2020 17:20:01 +0400 Subject: [PATCH 313/455] implement of gnome sort algorithm --- algorithms/sorting/gnome_sort.py | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 algorithms/sorting/gnome_sort.py diff --git a/algorithms/sorting/gnome_sort.py b/algorithms/sorting/gnome_sort.py new file mode 100644 index 00000000..444b127d --- /dev/null +++ b/algorithms/sorting/gnome_sort.py @@ -0,0 +1,38 @@ +''' +Gnome sort is not best sorting algorithms but sure it takes its pride. +It has time O(n^2) +''' + + +def gnome_sort(arr): + """ + Examples: + >>> gnome_sort([0, 5, 2, 3, 2]) + [0, 2, 2, 3, 5] + + >>> gnome_sort([]) + [] + >>> gnome_sort([-2, -45, -5]) + [-45, -5, -2] + """ + + # first case + size = len(arr) + + if size <= 1: + return arr + ind = 0 + # while loop + while ind < size: + if ind == 0: + ind += 1 + elif arr[ind] >= arr[ind - 1]: + ind += 1 + else: + # swap + temp = arr[ind - 1] + arr[ind - 1] = arr[ind] + arr[ind] = temp + ind -= 1 + + return arr From 018c3e8ac51f70fd59cf3d2f56602c6af02ba7af Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 7 Jun 2020 13:59:38 +0530 Subject: [PATCH 314/455] Removing auto linting check --- .github/workflows/lint_python.yml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .github/workflows/lint_python.yml diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml deleted file mode 100644 index 507beee3..00000000 --- a/.github/workflows/lint_python.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: lint_python -on: - pull_request: - push: - # branches: [master] -jobs: - lint_python: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: actions/setup-python@master - - run: pip install black codespell flake8 isort pytest - - run: black . --diff || true - - run: codespell --quiet-level=2 || true # --ignore-words-list="" --skip="" - - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - - run: isort --recursive . || true - - run: pip install -r requirements.txt || true - - run: pytest . || true From 79a4faec5c9f78b1a97508c20e2b6af7e99a3ae3 Mon Sep 17 00:00:00 2001 From: durid17 Date: Mon, 8 Jun 2020 13:34:14 +0400 Subject: [PATCH 315/455] Longest Increasing Subsequence --- .../longest_increasing_subsequence.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 algorithms/dynamic_programming/longest_increasing_subsequence.py diff --git a/algorithms/dynamic_programming/longest_increasing_subsequence.py b/algorithms/dynamic_programming/longest_increasing_subsequence.py new file mode 100644 index 00000000..8a9fa822 --- /dev/null +++ b/algorithms/dynamic_programming/longest_increasing_subsequence.py @@ -0,0 +1,13 @@ +def LIS(arr): + n = len(arr) + if n == 0: return 0 + res = 1 + dp = [0] * n + dp[0] = 1 + for i in range(1, n): + dp[i] = 1; + for j in range(0 , i): + if arr[i] > arr[j]: + dp[i] = max(dp[i] , dp[j] + 1) + res = max(res , dp[i]) + return res \ No newline at end of file From 99944fbbf2d4a3556907c922678001feb7d7799e Mon Sep 17 00:00:00 2001 From: cheymonty <45781686+cheymonty@users.noreply.github.com> Date: Fri, 12 Jun 2020 22:57:32 -0400 Subject: [PATCH 316/455] Add delete last occurrence --- .../linked_list/delete_last_occurrence.py | 30 +++++++++++++++++++ data_structures/linked_list/index.md | 1 + 2 files changed, 31 insertions(+) create mode 100644 data_structures/linked_list/delete_last_occurrence.py diff --git a/data_structures/linked_list/delete_last_occurrence.py b/data_structures/linked_list/delete_last_occurrence.py new file mode 100644 index 00000000..c4e9d95c --- /dev/null +++ b/data_structures/linked_list/delete_last_occurrence.py @@ -0,0 +1,30 @@ +class Node(): + + def __init__(self, val): + self.val = val + self.next = None + +def delete_last_occurrence(head, val): + if not head: + return None + + curr = head + prev = None + final_prev = None + final_occ = None + + while curr != None: + if curr.val == val: + final_prev = prev + final_occ = curr + + prev = curr + curr = curr.next + + if final_occ: + if final_prev: + final_prev.next = final_occ.next + else: + head = None + + return head \ No newline at end of file diff --git a/data_structures/linked_list/index.md b/data_structures/linked_list/index.md index 7c598aed..47a0074e 100644 --- a/data_structures/linked_list/index.md +++ b/data_structures/linked_list/index.md @@ -9,3 +9,4 @@ * [Odd-Even Arrangement](odd_even_arrangement.py) * [Merge Linked List](merge_linked_list.py) * [Remove Duplicates](remove_duplicates.py) +* [Delete Last Occurrence](delete_last_occurrence.py) From 48ae026fd5bae7bb9fdd00ca9e7c7ea356b737b1 Mon Sep 17 00:00:00 2001 From: cheymonty <45781686+cheymonty@users.noreply.github.com> Date: Fri, 12 Jun 2020 23:01:09 -0400 Subject: [PATCH 317/455] Add delete last occurrence --- data_structures/linked_list/delete_last_occurrence.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/linked_list/delete_last_occurrence.py b/data_structures/linked_list/delete_last_occurrence.py index c4e9d95c..e76f1d9a 100644 --- a/data_structures/linked_list/delete_last_occurrence.py +++ b/data_structures/linked_list/delete_last_occurrence.py @@ -21,7 +21,9 @@ def delete_last_occurrence(head, val): prev = curr curr = curr.next + if final_occ: + # special case that checks for a 1 node list that equals the val if final_prev: final_prev.next = final_occ.next else: From fc0ed9bf378548b75ecee8b7dd7b257b8bc5c872 Mon Sep 17 00:00:00 2001 From: cheymonty <45781686+cheymonty@users.noreply.github.com> Date: Fri, 12 Jun 2020 23:32:12 -0400 Subject: [PATCH 318/455] Add stack using list --- data_structures/stack/stack_using_list.py | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 data_structures/stack/stack_using_list.py diff --git a/data_structures/stack/stack_using_list.py b/data_structures/stack/stack_using_list.py new file mode 100644 index 00000000..172892dd --- /dev/null +++ b/data_structures/stack/stack_using_list.py @@ -0,0 +1,25 @@ +class Stack(): + """ + Stack follows Last-In-First-Out methodology + """ + + def __init__(self): + self.entries = [] + + def size(self): + return len(self.entries) + + def push(self, val): + self.entries.append(val) + + def pop(self): + if self.size() > 0: + self.entries.pop(self.size() - 1) + + + + + + + + \ No newline at end of file From 4deb0855684b82713eae3a7b7b327a0250ed8c17 Mon Sep 17 00:00:00 2001 From: Gega Darakhvelidze Date: Sun, 14 Jun 2020 22:56:09 +0400 Subject: [PATCH 319/455] prefix_function added --- .../dynamic_programming/prefix_function.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 algorithms/dynamic_programming/prefix_function.py diff --git a/algorithms/dynamic_programming/prefix_function.py b/algorithms/dynamic_programming/prefix_function.py new file mode 100644 index 00000000..c2cd4385 --- /dev/null +++ b/algorithms/dynamic_programming/prefix_function.py @@ -0,0 +1,19 @@ + +def prefix_function(s: str) -> [int]: + """ + The prefix function for string s is defined as an array pi of length n, + where pi[i] is the length of the longest proper prefix of the substring + s[0...i] which is also a suffix of this substring. A proper prefix of a + string is a prefix that is not equal to the string itself. + By definition, pi[0] = 0. + """ + n = len(s) + pi = [0] * n + for i in range(1, n): + j = pi[i - 1] + while (j > 0) and (s[i] != s[j]): + j = pi[j - 1] + if s[i] == s[j]: + j += 1 + pi[i] = j + return pi From 359aeee68af2a1262a29a5c3168e20bbc9d8cb69 Mon Sep 17 00:00:00 2001 From: Gega Darakhvelidze Date: Tue, 16 Jun 2020 17:56:26 +0400 Subject: [PATCH 320/455] prefix_sums added --- algorithms/dynamic_programming/prefix_sums.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 algorithms/dynamic_programming/prefix_sums.py diff --git a/algorithms/dynamic_programming/prefix_sums.py b/algorithms/dynamic_programming/prefix_sums.py new file mode 100644 index 00000000..2a0b70db --- /dev/null +++ b/algorithms/dynamic_programming/prefix_sums.py @@ -0,0 +1,11 @@ +def prefix_sums(ls: [int]) -> [int]: + """ + Returns list of prefix sums for given list of integers. + """ + n = len(ls) + total = 0 + sums = [0] * n + for i in range(n): + total += ls[i] + sums[i] = total + return sums From a9ba564b9e183e45db7c80fab12ae8fcce517b02 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 20 Jun 2020 07:33:19 +0530 Subject: [PATCH 321/455] Update bubble_sort.py --- algorithms/sorting/bubble_sort.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/algorithms/sorting/bubble_sort.py b/algorithms/sorting/bubble_sort.py index 7cd5321e..1c4a24cc 100644 --- a/algorithms/sorting/bubble_sort.py +++ b/algorithms/sorting/bubble_sort.py @@ -3,8 +3,20 @@ Best time scenario is when array is already sorted - O(n) """ - def bubble_sort(array): + n = len(array) + for i in range(n): + for j in range(0, n-i-1): + if array[j] > array[j+1]: + array[j], array[j+1] = array[j+1], array[j] + return array + + +def bubble_sort_optimized(array): + """ + Optimizes on bubble sort by taking care of already swapped cases + Reference - https://github.com/prabhupant/python-ds/pull/346 + """ has_swapped = True num_of_iterations = 0 From 1b37ff4b71be5ac7f3f93646e94b2b98e36e0da0 Mon Sep 17 00:00:00 2001 From: enqidu Date: Wed, 8 Jul 2020 14:48:21 +0400 Subject: [PATCH 322/455] markov chain algorithm --- algorithms/miscellaneous/markov.py | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 algorithms/miscellaneous/markov.py diff --git a/algorithms/miscellaneous/markov.py b/algorithms/miscellaneous/markov.py new file mode 100755 index 00000000..bffe7675 --- /dev/null +++ b/algorithms/miscellaneous/markov.py @@ -0,0 +1,48 @@ +import codecs +import random + +MAX_LETTERS = 2000 + +def readFile(f, mp, k): + seed = '' + mostFreqSeed = seed + mostFreq = 1 + for line in f: + for ch in line: + seed, mostFreq, mostFreqSeed = processSeed(seed, mostFreqSeed, mostFreq, ch, k, mp) + return mostFreqSeed + +def processSeed(seed, mostFreqSeed, mostFreq, ch, k, mp): + seed += ch + if len(seed) == k+1: + oldSeed = seed[:-1] + mp.setdefault(oldSeed, []).append(ch) + if mostFreq < len(mp[oldSeed]): + mostFreq, mostFreqSeed = len(mp[oldSeed]), oldSeed + seed = seed[1:] + return seed, mostFreq, mostFreqSeed + +def generateText(mp, mostFreqSeed): + text, curSeed = mostFreqSeed, mostFreqSeed + while (len(text) < MAX_LETTERS): + ch = random.choice(mp[curSeed]) + text, curSeed = text+ch, curSeed+ch + curSeed = curSeed[1:] + return text + +def main(): + fileName = input("Enter the file name: ") + ".txt" + f = codecs.open(fileName, encoding='utf-8') + k = int(input("Enter the Markov order [1-10]: ")) + assert (k >= 1 and k <= 10) + mp = {} + mostFreqSeed = readFile(f, mp, k) + f.close() + text = generateText(mp, mostFreqSeed) + print(text) + result = codecs.open("result.txt", "w", encoding='utf-8') + result.write(text) + result.close() + +if __name__ == "__main__": + main() \ No newline at end of file From 16129e82716858e8ccf51abe49b1152546039b39 Mon Sep 17 00:00:00 2001 From: vakhokoto Date: Thu, 9 Jul 2020 00:54:37 +0400 Subject: [PATCH 323/455] hamilton dynamic solution for vertices <= 20 added --- .../dynamic_programming/hamilton_cycle.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 algorithms/dynamic_programming/hamilton_cycle.py diff --git a/algorithms/dynamic_programming/hamilton_cycle.py b/algorithms/dynamic_programming/hamilton_cycle.py new file mode 100644 index 00000000..21e2b4ac --- /dev/null +++ b/algorithms/dynamic_programming/hamilton_cycle.py @@ -0,0 +1,27 @@ +import functools + +def hamilton_cycle(graph, n): + height = 1 << n + + dp = [[False for _ in range(n)] for _ in range(height)] + for i in range(n): + dp[1 << i][i] = True + + for i in range(height): + ones, zeros = [], [] + for pos in range(n): + if (1 << pos) & i: + ones.append(pos) + else: + zeros.append(pos) + + for o in ones: + if not dp[i][o]: + continue + + for z in zeros: + if graph[o][z]: + new_val = i + (1 << z) + dp[new_val][z] = True + + return functools.reduce(lambda a, b: a or b, dp[height - 1]) \ No newline at end of file From 2f674efb40f0b9024e4d07f1bc8d877b83f8a768 Mon Sep 17 00:00:00 2001 From: franklindyer Date: Wed, 8 Jul 2020 21:54:22 +0000 Subject: [PATCH 324/455] Added a faster recursive fibonacci algorithm --- algorithms/math/recursive_fibonacci.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/algorithms/math/recursive_fibonacci.py b/algorithms/math/recursive_fibonacci.py index 4094e6b9..c4447a52 100644 --- a/algorithms/math/recursive_fibonacci.py +++ b/algorithms/math/recursive_fibonacci.py @@ -1,7 +1,11 @@ """ - Recursivly compute the Fibonacci sequence + Recursivly compute the Fibonacci sequence using two different methods + main() compares the amount of time taken by each algorithm + rec_fib(n) requires O(Fibo(n)) operations, whereas binary_rec_fib(n) requires less than O(n) """ +import time + def rec_fib(n): if n == 1: return 1 @@ -10,10 +14,19 @@ def rec_fib(n): else: return rec_fib(n-1)+rec_fib(n-2) +def binary_rec_fib(n): + if n == 2 or n == 1: + return 1 + elif n == 0: + return 0 + else: + sgn = n % 2 + return binary_rec_fib((n-sgn)/2+1)**2 - ((-1)**sgn)*binary_rec_fib((n+sgn)/2-1)**2 + def main(): + times = [] n : int = int(input("n := ")) - for i in range(0, n): - print(rec_fib(i)) + print(binary_rec_fib(i)) if __name__ == "__main__": main() From 614d0b0dd57adc0c30f27e68ccb8e121e4efdb08 Mon Sep 17 00:00:00 2001 From: franklindyer Date: Wed, 8 Jul 2020 22:06:12 +0000 Subject: [PATCH 325/455] Fixed a silly typo --- algorithms/math/recursive_fibonacci.py | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms/math/recursive_fibonacci.py b/algorithms/math/recursive_fibonacci.py index c4447a52..c7741977 100644 --- a/algorithms/math/recursive_fibonacci.py +++ b/algorithms/math/recursive_fibonacci.py @@ -26,6 +26,7 @@ def binary_rec_fib(n): def main(): times = [] n : int = int(input("n := ")) + for i in range(0,n): print(binary_rec_fib(i)) if __name__ == "__main__": From b11cac749aa856bb3c98d552193cd3503961f398 Mon Sep 17 00:00:00 2001 From: franklindyer Date: Wed, 8 Jul 2020 22:20:33 +0000 Subject: [PATCH 326/455] Beautified code to adhere to PEP8 standards, and added clarifying comment --- algorithms/math/recursive_fibonacci.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/algorithms/math/recursive_fibonacci.py b/algorithms/math/recursive_fibonacci.py index c7741977..eb319cd9 100644 --- a/algorithms/math/recursive_fibonacci.py +++ b/algorithms/math/recursive_fibonacci.py @@ -1,11 +1,8 @@ """ Recursivly compute the Fibonacci sequence using two different methods - main() compares the amount of time taken by each algorithm rec_fib(n) requires O(Fibo(n)) operations, whereas binary_rec_fib(n) requires less than O(n) """ -import time - def rec_fib(n): if n == 1: return 1 @@ -20,13 +17,16 @@ def binary_rec_fib(n): elif n == 0: return 0 else: + # This recursive step takes advantage of the following two properties of the fibonacci numbers: + # Fibo(2n) = Fibo(n+1)^2 + Fibo(n)^2 + # Fibo(2n+1) = Fibo(n+1)^2 - Fibo(n-1)^2 sgn = n % 2 - return binary_rec_fib((n-sgn)/2+1)**2 - ((-1)**sgn)*binary_rec_fib((n+sgn)/2-1)**2 + return binary_rec_fib((n-sgn)/2 + 1)**2 - ((-1)**sgn) * binary_rec_fib((n+sgn)/2 - 1)**2 def main(): times = [] n : int = int(input("n := ")) - for i in range(0,n): + for i in range(0, n): print(binary_rec_fib(i)) if __name__ == "__main__": From dc27092ed40a74be0e9ba30bae4db5f5c2bc73b1 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 12 Jul 2020 15:26:52 +0530 Subject: [PATCH 327/455] Recursive & Iterative Functions added --- algorithms/math/factorial_iterative.py | 18 ++++++++++++++++++ algorithms/math/factorial_recursive.py | 16 ++++++++++++++++ algorithms/math/index.md | 2 ++ 3 files changed, 36 insertions(+) create mode 100644 algorithms/math/factorial_iterative.py create mode 100644 algorithms/math/factorial_recursive.py diff --git a/algorithms/math/factorial_iterative.py b/algorithms/math/factorial_iterative.py new file mode 100644 index 00000000..d722ec92 --- /dev/null +++ b/algorithms/math/factorial_iterative.py @@ -0,0 +1,18 @@ +#Calculate factorial of a given number using iterative method. + +def factorial(number): + + answer = 1 + + if number == 0: + return 1 + else: + for num in range(1, number+1): + answer = answer * num + return answer + +if __name__ == '__main__': + + enter_number = int(input("Enter a number whose factorial is required : ")) + result = factorial(enter_number) + print(result) \ No newline at end of file diff --git a/algorithms/math/factorial_recursive.py b/algorithms/math/factorial_recursive.py new file mode 100644 index 00000000..ed5f3b38 --- /dev/null +++ b/algorithms/math/factorial_recursive.py @@ -0,0 +1,16 @@ +#Calculate factorial of a given number using recursive method. + +def factorial(number): + + if number == 0 or number == 1: + return 1 + + answer = number * factorial(number - 1) + + return answer + +if __name__ == '__main__': + + enter_number = int(input("Enter a number whose factorial is required : ")) + result = factorial(enter_number) + print(result) \ No newline at end of file diff --git a/algorithms/math/index.md b/algorithms/math/index.md index fc7b2649..76b9dc6a 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -6,3 +6,5 @@ * [Sieve of Erastothenes](sieve_of_eratosthenes.py) * [Perfect Square](perfect_square.py) * [Number Convertion](number_convertion.py) +* [Iterative Factorial] (factorial_iterative.py) +* [Recursive Factorial] (factorial_recursive.py) From 7ce97e41d8bdde6f4b42a5d882a98fec5a3cf11a Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Sun, 12 Jul 2020 15:29:39 +0530 Subject: [PATCH 328/455] index.md file updated --- algorithms/math/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algorithms/math/index.md b/algorithms/math/index.md index 76b9dc6a..d6248d88 100644 --- a/algorithms/math/index.md +++ b/algorithms/math/index.md @@ -6,5 +6,5 @@ * [Sieve of Erastothenes](sieve_of_eratosthenes.py) * [Perfect Square](perfect_square.py) * [Number Convertion](number_convertion.py) -* [Iterative Factorial] (factorial_iterative.py) -* [Recursive Factorial] (factorial_recursive.py) +* [Iterative Factorial](factorial_iterative.py) +* [Recursive Factorial](factorial_recursive.py) From 3d2716642750e9372484c0b87962e879de92afb4 Mon Sep 17 00:00:00 2001 From: Neagu Briana Date: Sun, 26 Jul 2020 00:33:26 +0300 Subject: [PATCH 329/455] Add Palindromic-Tree in data structures --- .../palindromic_tree/palindromic_tree.py | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 data_structures/palindromic_tree/palindromic_tree.py diff --git a/data_structures/palindromic_tree/palindromic_tree.py b/data_structures/palindromic_tree/palindromic_tree.py new file mode 100644 index 00000000..47992793 --- /dev/null +++ b/data_structures/palindromic_tree/palindromic_tree.py @@ -0,0 +1,68 @@ +import typing + + +class Node: + def __init__(self): + self.next: typing.Dict[str, Node] = {} + self.frequency = 0 + self.length = 0 + self.suffix = None + + +class PalindromicTree: + def __init__(self): + self.null_root = Node() + self.imaginary_root = Node() + + self.null_root.length = 0 + self.null_root.suffix = self.imaginary_root + self.imaginary_root.length = -1 + self.imaginary_root.suffix = self.imaginary_root + + self.counter = 0 + self.all_palindromes: list[Node] = [] + self.previous = self.imaginary_root + + def add_letter(self, string, index): + while index - 1 - self.previous.length < 0 or string[index - 1 - self.previous.length] != string[index]: + self.previous = self.previous.suffix + + if self.previous.next.get(string[index]) is not None: + node = self.previous.next.get(string[index]) + node.frequency += 1 + self.previous = node + return + + new_node = Node() + + self.counter += 1 + new_node.frequency = 1 + new_node.length = self.previous.length + 2 + self.previous.next[string[index]] = new_node + + if new_node.length == 1: + new_node.suffix = self.null_root + self.previous = new_node + else: + self.previous = self.previous.suffix + while index - 1 - self.previous.length < 0 or string[index - 1 - self.previous.length] != string[index]: + self.previous = self.previous.suffix + new_node.suffix = self.previous.next[string[index]] + self.previous = new_node + self.all_palindromes.append(new_node) + + def how_many_palindromes(self): + all_nr = 0 + for node in reversed(self.all_palindromes): + node.suffix.frequency += node.frequency + all_nr += node.frequency + print(f"There are {self.counter} unique palindromes and {all_nr} in total") + + +tree = PalindromicTree() + +s = "abaxxaba" +for i in range(len(s)): + tree.add_letter(s, i) +tree.how_many_palindromes() + From 6637d0ad91df599fdf2a3c9ae35db66143ebf004 Mon Sep 17 00:00:00 2001 From: adarsh ghimire Date: Tue, 11 Aug 2020 10:29:50 +0545 Subject: [PATCH 330/455] Spelling fix in index_updater.py --- index_updater.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index_updater.py b/index_updater.py index 7f4778ae..6f4e1bb3 100755 --- a/index_updater.py +++ b/index_updater.py @@ -10,7 +10,7 @@ else: mypath = sys.argv[1] -# Going trought folders and subfolders. +# Going through folders and subfolders. for root, dirs, files in os.walk(mypath): curr_files = list() curr_folder = os.path.basename(root) From 071e068c9cf688e341726df95b6b5a3553e4673e Mon Sep 17 00:00:00 2001 From: adarsh ghimire Date: Tue, 11 Aug 2020 10:55:10 +0545 Subject: [PATCH 331/455] GCD optimized with iterative process --- algorithms/math/greatest_common_divisor.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/algorithms/math/greatest_common_divisor.py b/algorithms/math/greatest_common_divisor.py index d00efe53..53e70f1d 100644 --- a/algorithms/math/greatest_common_divisor.py +++ b/algorithms/math/greatest_common_divisor.py @@ -26,4 +26,10 @@ def gcd(x, y): if y == 0: return x - return gcd(y, x % y) \ No newline at end of file + return gcd(y, x % y) + +# Iterative optimized +def gcd(x, y): + while y != 0: + x, y = y, x % y + return x From 97c1a15ed7bdd226ed84bc22f42a74fb8d0cfa0f Mon Sep 17 00:00:00 2001 From: Subhasmita <2019003860.subhasmita@ug.sharda.ac.in> Date: Wed, 12 Aug 2020 20:18:28 +0530 Subject: [PATCH 332/455] fixed spelling and grammatical errors --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7b205f4e..13793e33 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Python Data Structures and Algorithms -This repository contains data structures and algorithms concepts and questions useful for interviews in Python. +This repository contains questions requiring implementation of data structures and algorithms concepts. It is useful for interviews in Python. ## :dart: Objective @@ -56,12 +56,12 @@ As you can see, the repo is still in its infancy. Here are some key things in th 1. Queue questions 2. Algorithms -3. More questions in data structures, especially for graph, circular linked list, tries, heaps and hash. +3. More questions in data structures, especially for graph, circular linked list, trees, heaps and hash. ## :raised_hand: Contributing Contributions are always welcomed. :smiley: -Feel free to raise new issues, file new PRs and star and fork this repo! :wink: +Feel free to raise new issues, file new PRs. Consider giving it a star and fork this repo! :wink: To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) From cbe04c3b56ebcac1be2354557c5dcc60506eb377 Mon Sep 17 00:00:00 2001 From: bgz30 <44124521+BGZ30@users.noreply.github.com> Date: Fri, 21 Aug 2020 18:37:49 +0200 Subject: [PATCH 333/455] Check power of two --- algorithms/math/power_of_two.py | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 algorithms/math/power_of_two.py diff --git a/algorithms/math/power_of_two.py b/algorithms/math/power_of_two.py new file mode 100644 index 00000000..f21aac10 --- /dev/null +++ b/algorithms/math/power_of_two.py @@ -0,0 +1,34 @@ +""" + This simple code is to check if a given number is a poer of two or not. + Method: + if a number is a power of two, then its binary representation is (2^k). + ex: 4 --> 2^2 --> 100 --> k = 2 + 8 --> 2^3 --> 1000 --> k = 3 + 16--> 2^4 --> 10000 --> k = 4 + + assume that n is a power of two, then (n-1)&(n) will be zero; + ex: + n = 8 --> (1000) , n-1 = 7 ---> (0111) + performing bit (and) operation between both, then n&(n-1) = 0000 + + n = 12 --> (1110) , n-1 = 11 ---> (1011) + performing bit (and) operation between both, then n&(n-1) = 1010 + + Conclusion: + The result of the above bit "and" operation will be zero, ONLY if the given number is a pwoer of two. + + NOTE: + - Since Python considers 0 as "false", then we are gonna return the inversion of the result; i.e. return not(n&(n-1). + - BUT If n = 0, the result will be zero indicating that 0 is a power of 2, wich is not true. + So to fix that, we are going to perform an extra logical "and" operation with the oreginal number. +""" + + +def pow_of_two(n): + return(n and (not(n&(n-1)))) + +for i in range(20): + if pow_of_two(i): + print(f"{i} is a power of 2.") + else: + print(f"{i} is NOT a power of 2.") \ No newline at end of file From 545a78070b936f7f85156c5ac07f8070fe730c83 Mon Sep 17 00:00:00 2001 From: Bassant Gamal <44124521+BGZ30@users.noreply.github.com> Date: Fri, 21 Aug 2020 18:50:53 +0200 Subject: [PATCH 334/455] Update power_of_two.py fixed the binary number in the second example. --- algorithms/math/power_of_two.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algorithms/math/power_of_two.py b/algorithms/math/power_of_two.py index f21aac10..6fcfdb22 100644 --- a/algorithms/math/power_of_two.py +++ b/algorithms/math/power_of_two.py @@ -11,8 +11,8 @@ n = 8 --> (1000) , n-1 = 7 ---> (0111) performing bit (and) operation between both, then n&(n-1) = 0000 - n = 12 --> (1110) , n-1 = 11 ---> (1011) - performing bit (and) operation between both, then n&(n-1) = 1010 + n = 12 --> (1100) , n-1 = 11 ---> (1011) + performing bit (and) operation between both, then n&(n-1) = 1000 Conclusion: The result of the above bit "and" operation will be zero, ONLY if the given number is a pwoer of two. @@ -31,4 +31,4 @@ def pow_of_two(n): if pow_of_two(i): print(f"{i} is a power of 2.") else: - print(f"{i} is NOT a power of 2.") \ No newline at end of file + print(f"{i} is NOT a power of 2.") From 6508237d2a8246a38be45803204d06aa7eb51b09 Mon Sep 17 00:00:00 2001 From: matttatum97 <69768161+matttatum97@users.noreply.github.com> Date: Tue, 25 Aug 2020 12:09:51 -0400 Subject: [PATCH 335/455] Create sum_of_two_integers.py --- .../bit_manipulation/sum_of_two_integers.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 algorithms/bit_manipulation/sum_of_two_integers.py diff --git a/algorithms/bit_manipulation/sum_of_two_integers.py b/algorithms/bit_manipulation/sum_of_two_integers.py new file mode 100644 index 00000000..c8203c5a --- /dev/null +++ b/algorithms/bit_manipulation/sum_of_two_integers.py @@ -0,0 +1,22 @@ +# Question: Calculate the sum of two integers a and b but without the +# use of the operators + and -. + +#Solution +def getSum(a, b): + """ + :type a: int + :type b: int + :rtype: int + """ + + mask = 0xffffffff + diff = 0 + carry = 0 + while b & mask: + diff = a ^ b + carry = trunc(a & b) + carry = carry << 1 + a = diff + b = carry + if b > 0: return (a & mask) + else: return a \ No newline at end of file From 0652520f468039873fd1a33bfc55e146a4afd9ff Mon Sep 17 00:00:00 2001 From: Yukti Khosla <44090430+Yukti-09@users.noreply.github.com> Date: Sun, 30 Aug 2020 11:00:32 +0530 Subject: [PATCH 336/455] Create transpose_matrix.py --- data_structures/array/transpose_matrix.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 data_structures/array/transpose_matrix.py diff --git a/data_structures/array/transpose_matrix.py b/data_structures/array/transpose_matrix.py new file mode 100644 index 00000000..c7abb7f4 --- /dev/null +++ b/data_structures/array/transpose_matrix.py @@ -0,0 +1,14 @@ +class Solution: + def transpose(self, A: List[List[int]]) -> List[List[int]]: + l=[] + i=0 + while(i!=len(A[0])): + x=[] + j=0 + while(j Date: Wed, 16 Sep 2020 18:15:51 +0530 Subject: [PATCH 337/455] Update misc.md --- bookmarks/misc.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/misc.md b/bookmarks/misc.md index 4bb89d2f..341a8684 100644 --- a/bookmarks/misc.md +++ b/bookmarks/misc.md @@ -15,3 +15,5 @@ This is a list of misc links that may be useful when learning or researching dat - https://machinelearningmastery.com - https://stackoverflow.com/questions/10631326/difference-between-select-into-and-insert-into-from-old-table + +- https://stackoverflow.com/a/33419662/6111200 From 98422fb8c13c29d525b34d0becfa5cde687045a7 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 16 Sep 2020 18:16:21 +0530 Subject: [PATCH 338/455] Update misc.md --- bookmarks/misc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookmarks/misc.md b/bookmarks/misc.md index 341a8684..dbb88192 100644 --- a/bookmarks/misc.md +++ b/bookmarks/misc.md @@ -16,4 +16,4 @@ This is a list of misc links that may be useful when learning or researching dat - https://stackoverflow.com/questions/10631326/difference-between-select-into-and-insert-into-from-old-table -- https://stackoverflow.com/a/33419662/6111200 +- Why SSL are not issued for IP address - https://stackoverflow.com/a/33419662/6111200 From 8b4a0685df475c087c2ca440065b19c2d439a103 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 27 Oct 2020 14:25:01 +0530 Subject: [PATCH 339/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 13793e33..c076e8a4 100644 --- a/README.md +++ b/README.md @@ -67,4 +67,4 @@ To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) ## :page_facing_up: License -[MIT @ Prabhu Pant](LICENSE) +[MIT](LICENSE) From fbe77052450c65a4031893e82fefac572b888131 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 27 Oct 2020 14:27:25 +0530 Subject: [PATCH 340/455] Update square_of_sorted_array.py --- data_structures/array/square_of_sorted_array.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/data_structures/array/square_of_sorted_array.py b/data_structures/array/square_of_sorted_array.py index 88ef6c87..1bebb758 100644 --- a/data_structures/array/square_of_sorted_array.py +++ b/data_structures/array/square_of_sorted_array.py @@ -26,8 +26,3 @@ def square(arr): j += 1 return ans - - - - - From cda8d2016aaf93d72518333dd58fd8edb3cfac85 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 27 Oct 2020 14:31:29 +0530 Subject: [PATCH 341/455] Added question and answer --- data_structures/array/max_product_three_elements.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data_structures/array/max_product_three_elements.py b/data_structures/array/max_product_three_elements.py index 0d31fd53..5883172e 100644 --- a/data_structures/array/max_product_three_elements.py +++ b/data_structures/array/max_product_three_elements.py @@ -1,3 +1,6 @@ +# Q - Find the max product of three elements of an array +# A - Find the max 3 numbers and 2 min numbers. Then find the max of (min1*min2*max1, max1*max2*max3) + import sys def product(arr): From 652caac783fac0a933a49c728e0dd10a930b6b5f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 27 Oct 2020 14:33:16 +0530 Subject: [PATCH 342/455] Fix the name of the file Change the extension of the file from pyt (not a Python file) to py --- ...eck_divide_in_two_halves.pyt => check_divide_in_two_halves.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename data_structures/binary_trees/{check_divide_in_two_halves.pyt => check_divide_in_two_halves.py} (100%) diff --git a/data_structures/binary_trees/check_divide_in_two_halves.pyt b/data_structures/binary_trees/check_divide_in_two_halves.py similarity index 100% rename from data_structures/binary_trees/check_divide_in_two_halves.pyt rename to data_structures/binary_trees/check_divide_in_two_halves.py From c91dda1874083b414e0c718fdd12aad411146a34 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 4 Jan 2021 12:14:41 +0530 Subject: [PATCH 343/455] Update misc.md --- bookmarks/misc.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/misc.md b/bookmarks/misc.md index dbb88192..2afa94e6 100644 --- a/bookmarks/misc.md +++ b/bookmarks/misc.md @@ -17,3 +17,5 @@ This is a list of misc links that may be useful when learning or researching dat - https://stackoverflow.com/questions/10631326/difference-between-select-into-and-insert-into-from-old-table - Why SSL are not issued for IP address - https://stackoverflow.com/a/33419662/6111200 + +- PATCH vs PUT https://stackoverflow.com/questions/28459418/use-of-put-vs-patch-methods-in-rest-api-real-life-scenarios/39338329#39338329 From 6e8b81eb52a6340e5375798d0a55f796fde94bfc Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 13 Jan 2021 09:30:34 +0530 Subject: [PATCH 344/455] Update articles.md --- bookmarks/articles.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/articles.md b/bookmarks/articles.md index a2b8e1ca..81c00863 100644 --- a/bookmarks/articles.md +++ b/bookmarks/articles.md @@ -55,3 +55,5 @@ This is a list of articles that may be useful for algorithms and data structures - https://www.ultravioletsoftware.com/single-post/2017/03/23/An-introduction-into-the-WSGI-ecosystem - https://jwt.io/introduction/ + +- https://khashtamov.com/en/how-to-become-a-data-engineer/ From 27ce2622793f4951ae166414a2a2cfbf011ddece Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 20 Jan 2021 19:22:47 +0530 Subject: [PATCH 345/455] Delete videos.md --- bookmarks/videos.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 bookmarks/videos.md diff --git a/bookmarks/videos.md b/bookmarks/videos.md deleted file mode 100644 index 0ac8813e..00000000 --- a/bookmarks/videos.md +++ /dev/null @@ -1,9 +0,0 @@ -# Videos - -This is a list of video links that may be useful for algorithms and data structures learning. - -## Links: - -- https://www.youtube.com/watch?v=mSzUb7f47qk - -- https://www.youtube.com/user/mycodeschool \ No newline at end of file From 79206a4bca47c265e23d4e4baee24e7c5fe63c3c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 22 Feb 2021 18:53:39 +0530 Subject: [PATCH 346/455] Remove index updater --- index_updater.py | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100755 index_updater.py diff --git a/index_updater.py b/index_updater.py deleted file mode 100755 index 6f4e1bb3..00000000 --- a/index_updater.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os - -# Terminal parameters. -if len(sys.argv[1:]) == 0: - print('Please, give a path') - sys.exit(1) -else: - mypath = sys.argv[1] - -# Going through folders and subfolders. -for root, dirs, files in os.walk(mypath): - curr_files = list() - curr_folder = os.path.basename(root) - - for name in files: - if name.endswith('.py') and not name == '__init__.py' and not dirs: - curr_files.append(name) - - # If we have files, write "index.md" - if curr_files: - with open(os.path.join(root, 'index.md'), mode='w') as md_file: - md_file.write('# Index of {}\n\n'.format(curr_folder)) - for line in curr_files: - file_name = line.split('.')[0].replace('_',' ').title() - md_file.write('* [' + file_name + '](' +line + ')\n') From 4130ae411b963bbbf3655645927d845012864dcf Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 22 Feb 2021 18:55:14 +0530 Subject: [PATCH 347/455] Remove logo and emoticons --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c076e8a4..cdbc6a72 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,12 @@ -![logo](logo/logo.png) - # Python Data Structures and Algorithms This repository contains questions requiring implementation of data structures and algorithms concepts. It is useful for interviews in Python. -## :dart: Objective +## Objective The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: -## :file_folder: Structure of the repository +## Structure of the repository As of now, the repository contains 3 main directories: [**Bookmarks**](bookmarks), [**Data Structures**](data_structures) and [**Algorithms**](algorithms). @@ -50,7 +48,7 @@ You can find useful links in this repository in the different markdown files. Be | Videos | [Click Here](bookmarks/videos.md) | | Misc. | [Click Here](bookmarks/misc.md) | -## :clipboard: Things need to be done +## Things need to be done As you can see, the repo is still in its infancy. Here are some key things in the to-do. @@ -58,13 +56,13 @@ As you can see, the repo is still in its infancy. Here are some key things in th 2. Algorithms 3. More questions in data structures, especially for graph, circular linked list, trees, heaps and hash. -## :raised_hand: Contributing +## Contributing Contributions are always welcomed. :smiley: Feel free to raise new issues, file new PRs. Consider giving it a star and fork this repo! :wink: To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) -## :page_facing_up: License +## License [MIT](LICENSE) From a3c864c4807b709c64e5688055a762d99e3288b3 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 22 Feb 2021 19:01:08 +0530 Subject: [PATCH 348/455] Remove emoticons from contributing.md --- CONTRIBUTING.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be0d596c..7fb881f7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ This is a project that is for the community and its true essence is only possible when it is community driven. -Please feel free to contribute to this project and be a part of this. Anything from raising issues to adding new features or even a typo in documentations, all are welcome. Please report issues here [https://github.com/prabhupant/python-ds/issues](https://github.com/prabhupant/python-ds/issues). It is also recommended to go through the Contributions Best Practices below to help organize contributions :smiley: +Please feel free to contribute to this project and be a part of this. Anything from raising issues to adding new features or even a typo in documentations, all are welcome. Please report issues here [https://github.com/prabhupant/python-ds/issues](https://github.com/prabhupant/python-ds/issues). It is also recommended to go through the Contributions Best Practices below to help organize contributions ## Contributions Best Practices @@ -18,7 +18,7 @@ Please feel free to contribute to this project and be a part of this. Anything f ### Issues -Feel free to open up any issue in the repository, whether it is about code improvements or bug fixes or documentation. You can also use any label you want to associate with the issue. Please provide a clear description of the issue while filing it :smiley: +Feel free to open up any issue in the repository, whether it is about code improvements or bug fixes or documentation. You can also use any label you want to associate with the issue. Please provide a clear description of the issue while filing it. ### Code Styling Guide @@ -26,9 +26,9 @@ Python follows a Pep8 styling. Styling the code according to it makes it univers ### Questions -While there are infinite number of data structure and algorithm questions, it is impossible to collect all of them here. So please add only those questions that are either unique or tricky or have some mind blowing approach to solve them. Also, try not to file a PR for a question which is already present in the repo. Interesting questions and implementations are always welcomed :wink: +While there are infinite number of data structure and algorithm questions, it is impossible to collect all of them here. So please add only those questions that are either unique or tricky or have some mind blowing approach to solve them. Also, try not to file a PR for a question which is already present in the repo. Interesting questions and implementations are always welcomed. -For filing a PR for a new question, please open a issue first for the same and then reference it in the PR. For example, let's say you want to add a new question called "find max element in array". So first head over to the issues tab and create a new issue called "New question: find max element in array". Then if you want to work on it, please mention it in the description. After you are done writing the code and ready to file a PR, refer to the issue number in the PR description. Let's say the issue number was #23. So in the PR description, it should be "Fixes #23". That's it! :smiley: +For filing a PR for a new question, please open a issue first for the same and then reference it in the PR. For example, let's say you want to add a new question called "find max element in array". So first head over to the issues tab and create a new issue called "New question: find max element in array". Then if you want to work on it, please mention it in the description. After you are done writing the code and ready to file a PR, refer to the issue number in the PR description. Let's say the issue number was #23. So in the PR description, it should be "Fixes #23". That's it! ### Bookmarks @@ -36,13 +36,13 @@ The Bookmarks directory is for storing awesome links to articles, videos, slides * Don't add a link to a MOOC or course (like DS Algo MIT lectures) -* Ask yourself "Is the link interesting enough that someone will really love it?" or "Is it something that an interviewer might ask in the interview to test you?" or "Is it some common or amazing thing people don't have enough knowledge about?". If yes to any of them, then sure, quickly file the PR :wink: +* Ask yourself "Is the link interesting enough that someone will really love it?" or "Is it something that an interviewer might ask in the interview to test you?" or "Is it some common or amazing thing people don't have enough knowledge about?". If yes to any of them, then sure, quickly file the PR. * If an article has more than one part, be sure to refer to the first only in the PR. ## How To Contribute? -You can add anything to the repo as long as it is related to programming and increasing knowledge :smiley: +You can add anything to the repo as long as it is related to programming and increasing knowledge. 0. Firstly, fork the repo to your GitHub account. Just to get familiar with some terms, this will be the `origin`. To state `origin` and `upstream` explicitly, @@ -80,13 +80,13 @@ $ git push origin max-number-in-array 6. Write a good brief description and refer to the issue (if any) and submit the PR. -7. Now wait for the approval :smiley: +7. Now wait for the approval. ## Join The Development Before you join the development, please fork and clone the repository to your local machine and explore it. Don't worry nothing will happen, atmost some code might not work :wink: -Feel free to contribute and be a part of this endeavour :beers: +Feel free to contribute and be a part of this endeavour. From 0894eea3d945b400c2b454a779a3698347dd5b3d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 23 Feb 2021 11:50:04 +0530 Subject: [PATCH 349/455] remove logo --- logo/logo.png | Bin 9910 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 logo/logo.png diff --git a/logo/logo.png b/logo/logo.png deleted file mode 100644 index 28749cb76889825a2f93f55013728fad2adaabec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9910 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 From 0114e599616382e0ba770fede9c332984c5f8f06 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 24 Feb 2021 17:16:57 +0530 Subject: [PATCH 350/455] Added peak element --- data_structures/array/peak_element.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/data_structures/array/peak_element.py b/data_structures/array/peak_element.py index e69de29b..29d8b1f2 100644 --- a/data_structures/array/peak_element.py +++ b/data_structures/array/peak_element.py @@ -0,0 +1,22 @@ +# A peak element is an element such that both of its neighbours are smaller than it +# In case of corner elements, consider only one neighbour + + +def peak(arr, low, high): + n = len(arr) + + while low <= high: + mid = low + (high - low) / 2 + mid = int(mid) + + if (mid == 0 or arr[mid-1] <= arr[mid]) and (mid == n-1 or arr[mid+1] <= arr[mid]): + return(arr[mid]) + + elif mid > 0 and arr[mid-1] > arr[mid]: + high = mid - 1 + + else: + low = mid + 1 + +arr = [1, 3, 20, 4, 1, 0] +print(peak(arr, 0, len(arr) - 1)) \ No newline at end of file From a6375c3e60a46aaa2e710f819196f2df7b88d521 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 25 Feb 2021 08:17:26 +0530 Subject: [PATCH 351/455] Modified duplicates --- data_structures/array/duplicate.py | 16 +++++++++++++--- data_structures/array/duplicates.py | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/data_structures/array/duplicate.py b/data_structures/array/duplicate.py index ad4a3fa5..1e4f6291 100644 --- a/data_structures/array/duplicate.py +++ b/data_structures/array/duplicate.py @@ -1,6 +1,12 @@ # Find duplicate in an array of integers given that the integers are in random order and # not necessarily each integer i is 0 <= i <= N where N = length of array +# Solution - use tortoise and hare algorithm. The tortoise pointer moves slower while the hare pointer +# moves faster + +# Note: this array will always contain a duplicate number due to the pigeonhole principle. You are trying to fit +# N different numbers in an array of size N - 1 so one number will be repeated + def duplicate(arr): tortoise = arr[0] hare = arr[0] @@ -11,10 +17,14 @@ def duplicate(arr): if tortoise == hare: break - ptr1 = nums[0] + ptr1 = arr[0] ptr2 = tortoise while ptr1 != ptr2: - ptr1 = nums[ptr1] - ptr2 = nums[ptr2] + ptr1 = arr[ptr1] + ptr2 = arr[ptr2] return ptr1 + + +arr = [3,5,1,2,4,5] +print(duplicate(arr)) \ No newline at end of file diff --git a/data_structures/array/duplicates.py b/data_structures/array/duplicates.py index 04940c0e..a146efba 100644 --- a/data_structures/array/duplicates.py +++ b/data_structures/array/duplicates.py @@ -4,5 +4,5 @@ def duplicate(arr): if arr[abs(x) - 1] < 0: res.append(abs(x)) else: - nums[abs(x) - 1] *= -1 + arr[abs(x) - 1] *= -1 return res From 53a1e37f81fde93665d1d8aa861053343e810d80 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 25 Feb 2021 08:17:48 +0530 Subject: [PATCH 352/455] Add rotation --- data_structures/array/rotation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/array/rotation.py b/data_structures/array/rotation.py index 36b9db0b..c89ab715 100644 --- a/data_structures/array/rotation.py +++ b/data_structures/array/rotation.py @@ -14,14 +14,14 @@ def rotate(arr, d): while 1: k = j + d if k >= n: - k = k -n + k -= n if k == i: break arr[j] = arr[k] j = k arr[j] = temp - + arr = [1,2,3,4,5] -rotate(arr, 1) +rotate(arr, 3) print(arr) From 1911e7069e8425fa8d4cbdf5c0044f7b8bb48fec Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 26 Feb 2021 17:40:37 +0530 Subject: [PATCH 353/455] Add program description --- data_structures/array/majority_element.py | 9 +++++++++ data_structures/array/moves_zeros_to_end.py | 3 +++ 2 files changed, 12 insertions(+) diff --git a/data_structures/array/majority_element.py b/data_structures/array/majority_element.py index 511902dd..457686ad 100644 --- a/data_structures/array/majority_element.py +++ b/data_structures/array/majority_element.py @@ -1,3 +1,7 @@ +# The only prerequisite condition of this algorithm is that the array +# definitely contains a majority element, otherwise it will just return +# the last element + def majority(arr): maj_index = 0 count = 1 @@ -11,3 +15,8 @@ def majority(arr): count = 1 return arr[maj_index] + + +arr = [3, 3, 1,5,6,8,3,0,7] + +print(majority(arr)) \ No newline at end of file diff --git a/data_structures/array/moves_zeros_to_end.py b/data_structures/array/moves_zeros_to_end.py index 036c5cd8..c5589961 100644 --- a/data_structures/array/moves_zeros_to_end.py +++ b/data_structures/array/moves_zeros_to_end.py @@ -1,3 +1,6 @@ +# Move all zeros in an array to the end + + def move(arr): count = 0 for a in arr: From b3a66193cddf0bcb0e30493e505ec291647d49c8 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 28 Feb 2021 12:31:13 +0530 Subject: [PATCH 354/455] New array questions --- data_structures/array/equilibrium_index.py | 23 +++++++++++ data_structures/array/even_more_than_odd.py | 16 ++++++++ data_structures/array/min_swaps.py | 39 +++++++++++++++++++ .../array/rearrange_positive_negative.py | 23 +++++++++++ 4 files changed, 101 insertions(+) create mode 100644 data_structures/array/equilibrium_index.py create mode 100644 data_structures/array/even_more_than_odd.py create mode 100644 data_structures/array/min_swaps.py create mode 100644 data_structures/array/rearrange_positive_negative.py diff --git a/data_structures/array/equilibrium_index.py b/data_structures/array/equilibrium_index.py new file mode 100644 index 00000000..2b1d0601 --- /dev/null +++ b/data_structures/array/equilibrium_index.py @@ -0,0 +1,23 @@ +# Find the equilibrium index of an array. An equilibrium index is such that +# the sum of elements to the left of it is equal to sum of elements to the right +# of it + +def find_equi(arr): + total_sum = sum(arr) + + left_sum = 0 + + for i, num in enumerate(arr): + + total_sum -= num + + if left_sum == total_sum: + return i + + left_sum += num + + return -1 + + +arr = [-7, 1, 5, 2, -4, 3, 0] +print(find_equi(arr)) diff --git a/data_structures/array/even_more_than_odd.py b/data_structures/array/even_more_than_odd.py new file mode 100644 index 00000000..62735d9c --- /dev/null +++ b/data_structures/array/even_more_than_odd.py @@ -0,0 +1,16 @@ +# Rearrange an array such that numbers at even indexes are greater than numbers +# at odd indexes + +def rearrange(arr): + for i in range(1, len(arr)): + if i % 2 == 0: + if arr[i] > arr[i-1]: + arr[i-1], arr[i] = arr[i], arr[i-1] + else: + if arr[i] < arr[i-1]: + arr[i-1], arr[i] = arr[i], arr[i-1] + print(arr) + + +arr = [ 1, 3, 2, 2, 5 ] +rearrange(arr) \ No newline at end of file diff --git a/data_structures/array/min_swaps.py b/data_structures/array/min_swaps.py new file mode 100644 index 00000000..3fdd13a7 --- /dev/null +++ b/data_structures/array/min_swaps.py @@ -0,0 +1,39 @@ +# Minimum swaps required to bring all elements less than or equal to k together + +def min_swaps(arr, k): + # First find out how many elements are there which are less than or + # equal to k + count = 0 + for i in arr: + if i <= k: + count += 1 + + # This count defines a window - inside this window all our elements should + # be placed + # Find the count of bad elements - elements which are more than k and that will be + # our starting answer as we will have to swap them out + bad = 0 + for i in range(0, count): + if arr[i] > k: + bad += 1 + + ans = bad + j = count + + for i in range(0, len(arr)): + if j == len(arr): + break + + if arr[i] > k: + bad -= 1 # because we have moved the bad element out of the window + + if arr[j] > k: + bad += 1 + + ans = min(bad, ans) + j += 1 + + print('answer - ', ans) + +arr = [2,7,9,5,8,7,4] +min_swaps(arr, 5) \ No newline at end of file diff --git a/data_structures/array/rearrange_positive_negative.py b/data_structures/array/rearrange_positive_negative.py new file mode 100644 index 00000000..ab1b971c --- /dev/null +++ b/data_structures/array/rearrange_positive_negative.py @@ -0,0 +1,23 @@ +# Rearragne positive and negative numbers in an array such that they appear +# alternately. If there are more numbers of any one kind, put them at the end + +def rearrange(arr): + i = -1 + + for j in range(len(arr)): + if arr[j] < 0: + i += 1 # maintaining index of the last negative number + arr[j], arr[i] = arr[i], arr[j] + + pos = i + 1 # index of first positive number + neg = 0 # index of first negative number + + while pos < len(arr) and neg < pos and arr[neg] < 0: + arr[pos], arr[neg] = arr[neg], arr[pos] + pos += 1 + neg += 2 + + print(arr) + +arr = [-1, 2, -3, 4, 5, 6, -7, 8, 9] +rearrange(arr) \ No newline at end of file From 90c562fd475bddbd1b2a3d0a051c0361c6cffd45 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 1 Mar 2021 18:55:00 +0530 Subject: [PATCH 355/455] Add bipartite graph --- data_structures/graphs/bipartite_graph.py | 56 +++++++++++++++++++---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/data_structures/graphs/bipartite_graph.py b/data_structures/graphs/bipartite_graph.py index 0c851248..a1ebb149 100644 --- a/data_structures/graphs/bipartite_graph.py +++ b/data_structures/graphs/bipartite_graph.py @@ -7,6 +7,12 @@ # Reference - https://www.geeksforgeeks.org/bipartite-graph/ +# A bipartite graph is a graph whose vertices can be divided into two disjoint sets U and V +# such that every edge connects a vertex in U to one in V. Also, a bipartite graph does not +# contain any odd length cycles + +# Also, a graph with no edge is a bipartite graph - https://math.stackexchange.com/a/53947 + from collections import defaultdict class Graph: @@ -16,31 +22,61 @@ def __init__(self, vertices): self.graph = defaultdict(list) + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def bfs(self, s): + visited = [False] * self.V + queue = [] + queue.append(s) + visited[s] = True + + while queue: + s = queue.pop(0) + print(s, end=' ') + + for i in self.graph[s]: + if not visited[i]: + visited[i] = True + queue.append(i) + + def is_bipartite(self, s): - # 0 -> color 0 - # 1 -> color 1 + # 0 -> color 0 (blue) + # 1 -> color 1 (red) # -1 -> no color assigned colors = [-1] * self.V - colors[s] = 1 + colors[s] = 1 # Color soure vertex red queue = [] queue.append(s) while queue: - u = queue.pop() + s = queue.pop(0) - if self.graph[u][v] == 1: # Check for self loop + if s in self.graph[s]: # Check for self loop return False # An edge u to v exists and destination is not # colored - for v in range(self.V): - if self.graph[u][v] == 1 and colors[v] == -1: - colors[v] = 1 - colors[u] - queue.append(v) + for i in self.graph[s]: + if colors[i] == -1: + colors[i] = 1 - colors[s] + queue.append(i) - elif self.graph[u][v] == 1 and colors[v] == colors[u]: + elif colors[i] == colors[s]: return False return True + + +g = Graph(5) +g.add_edge(0, 1) +g.add_edge(1, 2) +g.add_edge(2, 3) +g.add_edge(3, 4) +g.add_edge(4, 0) +print(g.is_bipartite(0)) \ No newline at end of file From 58232f3f95037d080131636cd74ba9b0cce54d21 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 4 Mar 2021 08:40:29 +0530 Subject: [PATCH 356/455] Modified iterative dfs to work for disconnected vertices --- data_structures/graphs/iterative_dfs.py | 51 ++++++++++++++----------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/data_structures/graphs/iterative_dfs.py b/data_structures/graphs/iterative_dfs.py index 65c092dc..d150c9cb 100644 --- a/data_structures/graphs/iterative_dfs.py +++ b/data_structures/graphs/iterative_dfs.py @@ -5,7 +5,8 @@ class Graph: - def __init__(self): + def __init__(self, vertices): + self.vertices = vertices self.graph = defaultdict(list) @@ -13,30 +14,36 @@ def add_edge(self, u, v): self.graph[u].append(v) - def dfs(self, s): - visited = [False] * len(self.graph) + def dfs(self): + visited = [False] * self.vertices - stack = [] + for s in range(self.vertices): + if not visited[s]: + visited[s] = True + + stack = [] + stack.append(s) - stack.append(s) - visited[s] = True + while stack: + s = stack.pop() + print(s, end=' ') - while stack: - s = stack.pop() - print(s, end=' ') + for i in self.graph[s]: + if visited[i] == False: + stack.append(i) + visited[i] = True - for i in self.graph[s]: - if visited[i] == False: - stack.append(i) - visited[i] = True +# g = Graph() +# g.add_edge(0, 1) +# g.add_edge(0, 2) +# g.add_edge(1, 2) +# g.add_edge(2, 0) +# g.add_edge(2, 3) +# g.add_edge(3, 3) +g = Graph(5) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(3, 4) -g = Graph() -g.add_edge(0, 1) -g.add_edge(0, 2) -g.add_edge(1, 2) -g.add_edge(2, 0) -g.add_edge(2, 3) -g.add_edge(3, 3) - -g.dfs(0) +g.dfs() From 4979d39c02179c6deb6125058971bbb00c4ea43c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 4 Mar 2021 08:40:44 +0530 Subject: [PATCH 357/455] Add count trees --- data_structures/graphs/count_trees.py | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 data_structures/graphs/count_trees.py diff --git a/data_structures/graphs/count_trees.py b/data_structures/graphs/count_trees.py new file mode 100644 index 00000000..84841062 --- /dev/null +++ b/data_structures/graphs/count_trees.py @@ -0,0 +1,46 @@ +# Count the number of tress in a graph (forest) + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[v].append(u) + self.graph[u].append(v) + + + def count_trees(self): + visited = [False] * self.vertices + count = 0 + + for s in range(self.vertices): + if not visited[s]: + visited[s] = True + stack = [] + stack.append(s) + count += 1 + + while stack: + print(stack) + s = stack.pop() + + for i in self.graph[s]: + if not visited[i]: + visited[i] = True + stack.append(i) + + return count + + +g = Graph(5) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(3, 4) + +print('Count of trees - ', g.count_trees()) + From e5a98ba51a959892dced8a525ad9c5b800f263f8 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 4 Mar 2021 09:12:16 +0530 Subject: [PATCH 358/455] Add levels of nodes --- data_structures/graphs/level_of_nodes.py | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 data_structures/graphs/level_of_nodes.py diff --git a/data_structures/graphs/level_of_nodes.py b/data_structures/graphs/level_of_nodes.py new file mode 100644 index 00000000..31d01618 --- /dev/null +++ b/data_structures/graphs/level_of_nodes.py @@ -0,0 +1,45 @@ +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def print_levels(self, s): + levels = [None] * self.vertices + levels[s] = 0 + queue = [] + queue.append(s) + + while queue: + s = queue.pop(0) + + for i in self.graph[s]: + if not levels[i]: + levels[i] = levels[s] + 1 + queue.append(i) + + levels[0] = 0 + + print('Node \t Level') + for node, level in enumerate(levels): + print(f'{node} \t {level}') + +g = Graph(8) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 3) +g.add_edge(1, 4) +g.add_edge(1, 5) +g.add_edge(2, 5) +g.add_edge(2, 6) +g.add_edge(6, 7) +g.print_levels(0) + \ No newline at end of file From 16f7b5439f1c7501a3aa17df7c0b7bae7bdf00b1 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 6 Mar 2021 09:22:29 +0530 Subject: [PATCH 359/455] Remove check and update statement for source node --- data_structures/graphs/level_of_nodes.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/data_structures/graphs/level_of_nodes.py b/data_structures/graphs/level_of_nodes.py index 31d01618..7190341c 100644 --- a/data_structures/graphs/level_of_nodes.py +++ b/data_structures/graphs/level_of_nodes.py @@ -22,12 +22,10 @@ def print_levels(self, s): s = queue.pop(0) for i in self.graph[s]: - if not levels[i]: + if levels[i] == None: levels[i] = levels[s] + 1 queue.append(i) - - levels[0] = 0 - + print('Node \t Level') for node, level in enumerate(levels): print(f'{node} \t {level}') @@ -42,4 +40,4 @@ def print_levels(self, s): g.add_edge(2, 6) g.add_edge(6, 7) g.print_levels(0) - \ No newline at end of file + From 9eb88425822b6da4d7bd673a124c13fbe6f17523 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 9 Mar 2021 15:20:13 +0530 Subject: [PATCH 360/455] Add print in dfs --- data_structures/graphs/dfs.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/data_structures/graphs/dfs.py b/data_structures/graphs/dfs.py index b6608f2b..6af4a6cc 100644 --- a/data_structures/graphs/dfs.py +++ b/data_structures/graphs/dfs.py @@ -7,7 +7,8 @@ def __init__(self): def add_edge(self, u, v): - self.graph[u].append[v] + self.graph[u].append(v) + self.graph[v].append(u) def dfs_util(self, v, visited): @@ -22,3 +23,13 @@ def dfs_util(self, v, visited): def dfs(self, v): visited = [False] * (len(self.graph)) self.dfs_util(v, visited) + + +g = Graph() +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(0, 3) +g.add_edge(1, 4) +g.add_edge(2, 5) +g.add_edge(3, 6) +print(g.dfs(0)) From b2ca87d6eb0a3828f0beb49bf1eabbc801b85f35 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 6 Apr 2021 17:01:51 +0530 Subject: [PATCH 361/455] New graph questions --- .../graphs/min_edges_between_two_vertices.py | 52 ++++++++++++ .../graphs/print_all_paths_between_nodes.py | 50 ++++++++++++ data_structures/graphs/same_path.py | 80 +++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 data_structures/graphs/min_edges_between_two_vertices.py create mode 100644 data_structures/graphs/print_all_paths_between_nodes.py create mode 100644 data_structures/graphs/same_path.py diff --git a/data_structures/graphs/min_edges_between_two_vertices.py b/data_structures/graphs/min_edges_between_two_vertices.py new file mode 100644 index 00000000..13456d5f --- /dev/null +++ b/data_structures/graphs/min_edges_between_two_vertices.py @@ -0,0 +1,52 @@ +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def find_min_edges(self, u, v): + visited = [False] * self.vertices + distance = [0] * self.vertices + queue = [] + + queue.append(u) + visited[u] = True + + while queue: + s = queue.pop(0) + + for i in self.graph[s]: + if visited[i] == False: + distance[i] = distance[s] + 1 + queue.append(i) + visited[i] = True + + return distance[v] + + +g = Graph(9) + +g.add_edge(0, 1) +g.add_edge(0, 7) +g.add_edge(1, 7) +g.add_edge(1, 2) +g.add_edge(2, 3) +g.add_edge(2, 5) +g.add_edge(2, 8) +g.add_edge(3, 4) +g.add_edge(3, 5) +g.add_edge(4, 5) +g.add_edge(5, 6) +g.add_edge(6, 7) +g.add_edge(7, 8) + +print(g.find_min_edges(0, 5)) diff --git a/data_structures/graphs/print_all_paths_between_nodes.py b/data_structures/graphs/print_all_paths_between_nodes.py new file mode 100644 index 00000000..cbd04abf --- /dev/null +++ b/data_structures/graphs/print_all_paths_between_nodes.py @@ -0,0 +1,50 @@ +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def print_path(self, s, d, visited, path): + visited[s] = True + path.append(s) + + if s == d: + print(path) + + else: + for i in self.graph[s]: + if visited[i] == False: + self.print_path(i, d, visited, path) + + path.pop() + visited[s] = False + + + def print_all_paths(self, s, d): + visited = [False] * self.vertices + path = [] + self.print_path(s, d, visited, path) + + +g = Graph(4) + +g.add_edge(0, 3) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 3) +g.add_edge(2, 0) +g.add_edge(2, 1) + +s = 2 +d = 3 + +print(f'Paths from {s} to {d} are - ') +g.print_all_paths(s, d) \ No newline at end of file diff --git a/data_structures/graphs/same_path.py b/data_structures/graphs/same_path.py new file mode 100644 index 00000000..127c1b86 --- /dev/null +++ b/data_structures/graphs/same_path.py @@ -0,0 +1,80 @@ +# Check if two nodes are on the same path in a tree. Use DFS and the concept of intime and outtime. +# Intime - time when a node is visited for the first time +# Outtime - time when a node is visited for the second time after all its children have been visited +# For any pair of node if they are on the same path - +# intime[u] < intime[v] and outtime[u] > outtime[v] + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + self.intime = None + self.outtime = None + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def dfs(self): + visited = [False] * self.vertices + intime = [0] * self.vertices + outtime = [0] * self.vertices + timer = 0 + num_children_visited = [0] * self.vertices + + for s in range(self.vertices): + if not visited[s]: + visited[s] = True + + stack = [] + stack.append(s) + + while stack: + s = stack.pop() + timer += 1 + intime[s] = timer + + print(s) + + for i in self.graph[s]: + if visited[i] == False: + stack.append(i) + visited[i] = True + num_children_visited[s] += 1 + + if num_children_visited[i] == len(self.graph[i]): + timer += 1 + outtime[i] = timer + + print('intime - ', intime) + print('outtime - ', outtime) + print('num_children_visited - ', num_children_visited) + self.intime = intime + self.outtime = outtime + + + def check_same_path(self, u, v): + if (self.intime[u] < self.intime[v] and self.outtime[u] > self.outtime[v]) or \ + (self.intime[v] < self.intime[u] and self.outtime[v] > self.outtime[u]): + return True + return False + + +g = Graph(7) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(0, 3) +g.add_edge(1, 4) +g.add_edge(2, 5) +g.add_edge(3, 6) + +g.dfs() + +print('Same path - ', g.check_same_path(0, 6)) +print(g.graph[6]) \ No newline at end of file From 38906557a2f63c7342d240c974b349797fbe4851 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 6 Apr 2021 17:39:11 +0530 Subject: [PATCH 362/455] Add min number of operations --- .../graphs/min_number_of_operations.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 data_structures/graphs/min_number_of_operations.py diff --git a/data_structures/graphs/min_number_of_operations.py b/data_structures/graphs/min_number_of_operations.py new file mode 100644 index 00000000..7d783e30 --- /dev/null +++ b/data_structures/graphs/min_number_of_operations.py @@ -0,0 +1,54 @@ +""" +Minimum number of operations required to transform a number x to y +Valid operations - multiplication by 2, subtraction by 1 +Ex - x = 4, y = 7 +1. 4 * 2 = 8 +2. 8 - 1 = 7 +Answer = 2 +""" + + +from collections import defaultdict + + +class Node: + + + def __init__(self, value, level): + self.value = value + self.level = level + + +def min_steps(x, y): + node_x = Node(x, 0) + + visited = [] + queue = [] + queue.append(node_x) + + while queue: + s = queue.pop(0) + + if s.value == y: + return s.level + + visited.append(s.value) + + if s.value * 2 == y or s.value - 1 == y: + return s.level + 1 + + # If not visited already, add its children + + if s.value * 2 not in visited: + new_node = Node(s.value * 2, s.level + 1) + queue.append(new_node) + + if s.value - 1 not in visited: + new_node = Node(s.value - 1, s.level + 1) + queue.append(new_node) + + +x = 2 +y = 5 + +print(min_steps(x, y)) \ No newline at end of file From 9ad3c9aee7d5c8a3db77d17f7802878388b090b4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 7 Apr 2021 08:45:01 +0530 Subject: [PATCH 363/455] Refactored comments --- data_structures/graphs/bipartite_graph.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/data_structures/graphs/bipartite_graph.py b/data_structures/graphs/bipartite_graph.py index a1ebb149..0296de6e 100644 --- a/data_structures/graphs/bipartite_graph.py +++ b/data_structures/graphs/bipartite_graph.py @@ -1,17 +1,19 @@ -# Check for bipartite graph +""" +Check for bipartite graph -# Do a BFS and make source of red color and its neighbour blue -# Keep on doing this. -# If self loop, return false -# If current color == neighbour color, false, else true +Do a BFS and make source of red color and its neighbour blue +Keep on doing this. +If self loop, return false +If current color == neighbour color, false, else true -# Reference - https://www.geeksforgeeks.org/bipartite-graph/ +Reference - https://www.geeksforgeeks.org/bipartite-graph/ -# A bipartite graph is a graph whose vertices can be divided into two disjoint sets U and V -# such that every edge connects a vertex in U to one in V. Also, a bipartite graph does not -# contain any odd length cycles +A bipartite graph is a graph whose vertices can be divided into two disjoint sets U and V +such that every edge connects a vertex in U to one in V. Also, a bipartite graph does not +contain any odd length cycles -# Also, a graph with no edge is a bipartite graph - https://math.stackexchange.com/a/53947 +Also, a graph with no edge is a bipartite graph - https://math.stackexchange.com/a/53947 +""" from collections import defaultdict From f0b8d79eca5a1583933431357e43257fbab61bee Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 7 Apr 2021 08:58:22 +0530 Subject: [PATCH 364/455] max_edges_to_make_bipartite.py --- .../graphs/max_edges_to_make_bipartite.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 data_structures/graphs/max_edges_to_make_bipartite.py diff --git a/data_structures/graphs/max_edges_to_make_bipartite.py b/data_structures/graphs/max_edges_to_make_bipartite.py new file mode 100644 index 00000000..9b42fb82 --- /dev/null +++ b/data_structures/graphs/max_edges_to_make_bipartite.py @@ -0,0 +1,60 @@ +""" +Find the max edges that can be added to a tree so that it stays a bipartite graph + +keep count of nodes of each color - say count_color1, count_color2 +These nodes can be connected in count_color1 x count_color2 ways = max no of edges of a bipartite graph +Also, a tree has n-1 edges +So answer = (count_color1 x count_color2) - (n - 1) + +If the answer comes negative, then its impossible to add any edge because of odd cycles +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def bfs(self, s): + count_color0 = 0 + count_color1 = 0 + + colors = [-1] * self.vertices + colors[s] = 1 + count_color1 += 1 + + queue = [] + queue.append(s) + + while queue: + s = queue.pop(0) + + for i in self.graph[s]: + if colors[i] == -1: + colors[i] = 1 - colors[s] + if colors[i] == 0: + count_color0 += 1 + else: + count_color1 += 1 + queue.append(i) + + ans = (count_color0 * count_color1) - (self.vertices - 1) + return ans if ans > 0 else 0 + + +g = Graph(5) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 3) +g.add_edge(2, 4) + +print(g.bfs(0)) \ No newline at end of file From f844c64b75834bc67669a3eb069c00b572ffa3f3 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 8 Apr 2021 17:43:56 +0530 Subject: [PATCH 365/455] Add directed cycle cycle check iterative --- .../cycle_in_directed_graph_iterative.py | 53 +++++++++++++++++++ data_structures/graphs/iterative_dfs.py | 6 +-- 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 data_structures/graphs/cycle_in_directed_graph_iterative.py diff --git a/data_structures/graphs/cycle_in_directed_graph_iterative.py b/data_structures/graphs/cycle_in_directed_graph_iterative.py new file mode 100644 index 00000000..b20b8002 --- /dev/null +++ b/data_structures/graphs/cycle_in_directed_graph_iterative.py @@ -0,0 +1,53 @@ +from collections import defaultdict + + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def dfs(self): + visited = [False] * self.vertices + recursion_stack = [False] * self.vertices + stack = [] + + for s in range(self.vertices): + if visited[s] == False: + visited[s] = True + recursion_stack[s] = True + + stack.append(s) + + while stack: + s = stack.pop() + + recursion_stack[s] = True + + for i in self.graph[s]: + if visited[i] == False: + stack.append(i) + visited[i] = True + recursion_stack[i] = True + elif recursion_stack[i] == True: + return "Contains Cycle" + + recursion_stack[s] = False + + return "No cycle" + + +g = Graph(4) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(2, 3) +g.add_edge(3, 3) +print(g.dfs()) \ No newline at end of file diff --git a/data_structures/graphs/iterative_dfs.py b/data_structures/graphs/iterative_dfs.py index d150c9cb..c2eb7169 100644 --- a/data_structures/graphs/iterative_dfs.py +++ b/data_structures/graphs/iterative_dfs.py @@ -16,12 +16,12 @@ def add_edge(self, u, v): def dfs(self): visited = [False] * self.vertices + stack = [] for s in range(self.vertices): - if not visited[s]: + if visited[s] == False: visited[s] = True - stack = [] stack.append(s) while stack: @@ -34,7 +34,7 @@ def dfs(self): visited[i] = True -# g = Graph() +# g = Graph(4) # g.add_edge(0, 1) # g.add_edge(0, 2) # g.add_edge(1, 2) From 1702373f324b4a56430725407614a20969c14f33 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 8 Apr 2021 18:13:50 +0530 Subject: [PATCH 366/455] Refactored code and add cycle in directed graph using colors --- .../cycle_in_directed_graph_iterative.py | 12 ++-- .../cycle_in_directed_graph_using_colors.py | 60 +++++++++++++++++++ ..._graph.py => cycle_in_undirected_graph.py} | 0 .../cycle_in_undirected_graph_iterative.py | 0 .../cycle_in_undirected_graph_union_find.py | 6 ++ 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 data_structures/graphs/cycle_in_directed_graph_using_colors.py rename data_structures/graphs/{cyclic_in_undirected_graph.py => cycle_in_undirected_graph.py} (100%) create mode 100644 data_structures/graphs/cycle_in_undirected_graph_iterative.py create mode 100644 data_structures/graphs/cycle_in_undirected_graph_union_find.py diff --git a/data_structures/graphs/cycle_in_directed_graph_iterative.py b/data_structures/graphs/cycle_in_directed_graph_iterative.py index b20b8002..cc0b3cd2 100644 --- a/data_structures/graphs/cycle_in_directed_graph_iterative.py +++ b/data_structures/graphs/cycle_in_directed_graph_iterative.py @@ -18,12 +18,12 @@ def dfs(self): recursion_stack = [False] * self.vertices stack = [] - for s in range(self.vertices): - if visited[s] == False: - visited[s] = True - recursion_stack[s] = True + for v in range(self.vertices): + if visited[v] == False: + visited[v] = True + recursion_stack[v] = True - stack.append(s) + stack.append(v) while stack: s = stack.pop() @@ -38,7 +38,7 @@ def dfs(self): elif recursion_stack[i] == True: return "Contains Cycle" - recursion_stack[s] = False + recursion_stack[v] = False return "No cycle" diff --git a/data_structures/graphs/cycle_in_directed_graph_using_colors.py b/data_structures/graphs/cycle_in_directed_graph_using_colors.py new file mode 100644 index 00000000..44dfb5ac --- /dev/null +++ b/data_structures/graphs/cycle_in_directed_graph_using_colors.py @@ -0,0 +1,60 @@ +""" +Using three colors - white, gray and black +White - vertices that are not processed (inital state of all vertices) +Gray - vertices that are in DFS +Black - fully traversed vertices (i.e its progenies are also done) + +If while traversing any adjacent node is colored Gray, that means cycle exists +""" + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def detect_cycle(self): + color = ['white'] * self.vertices + visited = [False] * self.vertices + + stack = [] + + for v in range(self.vertices): + if color[v] == 'white': + color[v] = 'gray' + + stack.append(v) + + while stack: + s = stack.pop() + + for i in self.graph[s]: + if color[i] == 'white': + stack.append(i) + color[i] = 'gray' + elif color[i] == 'gray': + return "Cycle detected" + + color[v] = 'black' + + return "Cycle not present" + + +g = Graph(4) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(2, 3) +g.add_edge(3, 3) +# g.add_edge(0, 1) +# g.add_edge(0, 2) +# g.add_edge(1, 3) +print(g.detect_cycle()) \ No newline at end of file diff --git a/data_structures/graphs/cyclic_in_undirected_graph.py b/data_structures/graphs/cycle_in_undirected_graph.py similarity index 100% rename from data_structures/graphs/cyclic_in_undirected_graph.py rename to data_structures/graphs/cycle_in_undirected_graph.py diff --git a/data_structures/graphs/cycle_in_undirected_graph_iterative.py b/data_structures/graphs/cycle_in_undirected_graph_iterative.py new file mode 100644 index 00000000..e69de29b diff --git a/data_structures/graphs/cycle_in_undirected_graph_union_find.py b/data_structures/graphs/cycle_in_undirected_graph_union_find.py new file mode 100644 index 00000000..b1904365 --- /dev/null +++ b/data_structures/graphs/cycle_in_undirected_graph_union_find.py @@ -0,0 +1,6 @@ +""" +This method cannot be used in Directed graph because of the direction of the edge. +In a union of set containing element A and B, you cannot specify whether A is going to B +or vice versa +""" + From 66b0a6428dfeaab23f6eeff3b28bada68eb3f427 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 8 Apr 2021 18:43:21 +0530 Subject: [PATCH 367/455] cyclic graphs --- .../cycle_in_undirected_graph_iterative.py | 8 +++ .../cycle_in_undirected_graph_union_find.py | 53 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/data_structures/graphs/cycle_in_undirected_graph_iterative.py b/data_structures/graphs/cycle_in_undirected_graph_iterative.py index e69de29b..3a1124ec 100644 --- a/data_structures/graphs/cycle_in_undirected_graph_iterative.py +++ b/data_structures/graphs/cycle_in_undirected_graph_iterative.py @@ -0,0 +1,8 @@ +""" +This is almost same as the iterative one for directed graph but we cannot use the +concept of recursion stack here because in directed graphs, there is defined path to +traverse but in undirected its possible that an edge (or a path) can be traversed +infite number of times. + +Instead check for parents. If a parent of a node is visited and +""" \ No newline at end of file diff --git a/data_structures/graphs/cycle_in_undirected_graph_union_find.py b/data_structures/graphs/cycle_in_undirected_graph_union_find.py index b1904365..e8e0af42 100644 --- a/data_structures/graphs/cycle_in_undirected_graph_union_find.py +++ b/data_structures/graphs/cycle_in_undirected_graph_union_find.py @@ -4,3 +4,56 @@ or vice versa """ +from collections import defaultdict + + +class Graph: + + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def union(self, parent, x, y): + parent[x] = y + + + def find_parent(self, parent, i): + if parent[i] == -1: + return i + else: + return self.find_parent(parent, parent[i]) + + + def check_cyclic(self): + parent = [-1] * self.vertices + + for i in self.graph.keys(): + for j in self.graph[i]: + x = self.find_parent(parent, i) + y = self.find_parent(parent, j) + + if x == y: + return "Cyclic" + + self.union(parent, x, y) + + return "Not cyclic" + + +g = Graph(4) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(2, 3) +g.add_edge(3, 3) +# g.add_edge(0, 1) +# g.add_edge(0, 2) +# g.add_edge(1, 3) +print(g.check_cyclic()) \ No newline at end of file From bb279df2d55dcddbfad04d10edbf96c275e5674d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 9 Apr 2021 17:31:59 +0530 Subject: [PATCH 368/455] Add bellman ford --- data_structures/graphs/bellman_ford.py | 101 +++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 data_structures/graphs/bellman_ford.py diff --git a/data_structures/graphs/bellman_ford.py b/data_structures/graphs/bellman_ford.py new file mode 100644 index 00000000..35c6522d --- /dev/null +++ b/data_structures/graphs/bellman_ford.py @@ -0,0 +1,101 @@ +""" +Bellman Ford algorithm is used to find the single source shortest path in a weighted directed graph. +Example - find the shortest path from node A to F + +Advantages of this algorithm over Djikstra's - +1. Bellman Ford also works for negative weight edges +2. Also finds negative weight cycles in a graph + +Disvantage - +1. Slower than Dijsktra's + +** Idea (https://www.youtube.com/watch?v=-mOEd_3gTK0&t) + +0. Shortest path can be found as - +if distance[v] > distance[u] + weight(u, v), then the right side is the shorter path +1. Mark parent and the new weight each time this is run +2. Do this V-1 times. In the first iteration, the algorithm will find the shortest path between the source +and source's neighbours +3. In the second, between source and source's neighbours' neighbours and so on (V - 1) times +4. Do this again. If in this Vth iteration, the weights of path decrease, then there is a negative cycle in the +graph + +Time complexity - O(V * E) +Space complexity - O(V) +""" + +from collections import defaultdict + +class Edge: + + def __init__(self, source, dest, weight): + self.source = source + self.dest = dest + self.weight = weight + + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + self.edges = {} + + + def add_edge(self, u, v, weight): + self.graph[u].append(v) + self.edges[(u, v)] = Edge(u, v, weight) + + + def bellman_ford(self, source, destination): + parent = [-1] * self.vertices + distance = [float("inf")] * self.vertices + + parent[source] = source + distance[source] = source + + for (u, v) in self.edges: + wt = self.edges[(u, v)].weight + + if distance[v] > distance[u] + wt: + distance[v] = distance[u] + wt + parent[v] = u + + # Now for the Vth iteration, check for the negative cycle + + negative_cycle_present = False + + for (u, v) in self.edges: + wt = self.edges[(u, v)].weight + if distance[v] > distance[u] + wt: + print('h - ', u, v) + negative_cycle_present = True + break + + if negative_cycle_present: + print('Contains negative cycle') + else: + print('No negative cycle') + + # Printing the shortest path from source to destination + + while True: + print(f'{destination}', end=' ') + destination = parent[destination] + + if destination == source: + break + + +g = Graph(5) + +g.add_edge(0, 1, 4) +g.add_edge(0, 2, 5) +g.add_edge(0, 3, 8) +g.add_edge(1, 2, -3) +g.add_edge(2, 4, 4) +g.add_edge(3, 4, 2) +g.add_edge(4, 3, 1) + +g.bellman_ford(0, 3) \ No newline at end of file From f98921fab34afdd36383ffadf4e015b577659b0b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 12 Apr 2021 10:22:45 +0530 Subject: [PATCH 369/455] Add max edges to add to DAG --- .../max_edges_that_can_be_added_to_dag.py | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 data_structures/graphs/max_edges_that_can_be_added_to_dag.py diff --git a/data_structures/graphs/max_edges_that_can_be_added_to_dag.py b/data_structures/graphs/max_edges_that_can_be_added_to_dag.py new file mode 100644 index 00000000..acad5380 --- /dev/null +++ b/data_structures/graphs/max_edges_that_can_be_added_to_dag.py @@ -0,0 +1,81 @@ +""" +Find the max number of edges that can be added to a Directed Acyclic Graph such that +it remains a DAG. + +Solution - +The trick is to add all edges from left to right. Now adding any edge from right to left +will make the graph cyclic because that edge's counterpart will exist from left-to-right. +Hence a cycle will be formed. + +1. Topologically sort all the edges +2. If edge is not there left to right, create the edge +3. Count the number of edges added + +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def topological_sort_util(self, v, visited, stack): + visited[v] = True + + for i in self.graph[v]: + if visited[i] == False: + self.topological_sort_util(i, visited, stack) + + stack.insert(0, v) + + + def topological_sort(self): + visited = [False] * self.vertices + stack = [] + + for i in range(self.vertices): + if visited[i] == False: + self.topological_sort_util(i, visited, stack) + + return stack + + + def max_edges(self): + topo = self.topological_sort() + visited = [False] * self.vertices + count = 0 + + for i in topo: + vertex = topo[i] + # Mark the connected vertices visited + for j in self.graph[vertex]: + visited[j] = True + + # Print the unmarked nodes from topo + for j in range(i+1, len(topo)): + if visited[topo[j]] == False: + print(f"{vertex} -> {topo[j]}") + count += 1 + + visited[topo[j]] = False + + print('Maximum edges that can be added - ', count) + + +g = Graph(6) +g.add_edge(5, 2) +g.add_edge(5, 0) +g.add_edge(4, 0) +g.add_edge(4, 1) +g.add_edge(2, 3) +g.add_edge(3, 1) + +g.max_edges() \ No newline at end of file From 600c8457bfedd2ef46c774342a7c30d6d5806dee Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 12 Apr 2021 12:52:39 +0530 Subject: [PATCH 370/455] Add DAG shortest and longest path --- data_structures/graphs/dag_longest_path.py | 71 ++++++++++++++++++ data_structures/graphs/dag_shortest_path.py | 79 +++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 data_structures/graphs/dag_longest_path.py create mode 100644 data_structures/graphs/dag_shortest_path.py diff --git a/data_structures/graphs/dag_longest_path.py b/data_structures/graphs/dag_longest_path.py new file mode 100644 index 00000000..796c43da --- /dev/null +++ b/data_structures/graphs/dag_longest_path.py @@ -0,0 +1,71 @@ +""" +The idea is similar to DAG Shortest Path. Only the comparision part changes +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v, w): + self.graph[u].append((v, w)) + + + def topological_sort_util(self, vertex, visited, stack): + visited[vertex] = True + + for v, weight in self.graph[vertex]: + if visited[v] == False: + self.topological_sort_util(v, visited, stack) + + stack.insert(0, vertex) + + + def topological_sort(self): + visited = [False] * self.vertices + stack = [] + + for v in range(self.vertices): + if visited[v] == False: + self.topological_sort_util(v, visited, stack) + + return stack + + + def longest_path(self, s): + stack = self.topological_sort() + + distance = [-float("inf")] * self.vertices + distance[s] = 0 + + while stack: + i = stack.pop(0) + + for vertex, weight in self.graph[i]: + if distance[vertex] < distance[i] + weight: + distance[vertex] = distance[i] + weight + + for i in range(self.vertices): + print(f"{s} -> {i} = {distance[i]}") + + +g = Graph(6) +g.add_edge(0, 1, 5) +g.add_edge(0, 2, 3) +g.add_edge(1, 3, 6) +g.add_edge(1, 2, 2) +g.add_edge(2, 4, 4) +g.add_edge(2, 5, 2) +g.add_edge(2, 3, 7) +g.add_edge(3, 5, 1) +g.add_edge(3, 4, -1) +g.add_edge(4, 5, -2) + +source = 0 + +g.longest_path(source) \ No newline at end of file diff --git a/data_structures/graphs/dag_shortest_path.py b/data_structures/graphs/dag_shortest_path.py new file mode 100644 index 00000000..36bebda4 --- /dev/null +++ b/data_structures/graphs/dag_shortest_path.py @@ -0,0 +1,79 @@ +""" +Find shortest path from source vertex to all vertices + +In general, Bellaman-Ford and Dijkstra can be used to find shortest path. But for +DAG, we can improvise + +Bellman-Ford: O(V*E), Dijsktra: O(E+VlogV) + +For DAG, using Topological sort will solve this problem in O(V+E). We are using Topo +sort because it lays out a graph in its linear representation according to the paths. +Hence we can proceed in this order to find shortest path +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v, w): + self.graph[u].append((v, w)) + + + def topological_sort_util(self, vertex, visited, stack): + visited[vertex] = True + + for v, weight in self.graph[vertex]: + if visited[v] == False: + self.topological_sort_util(v, visited, stack) + + stack.insert(0, vertex) + + + def topological_sort(self): + visited = [False] * self.vertices + stack = [] + + for v in range(self.vertices): + if visited[v] == False: + self.topological_sort_util(v, visited, stack) + + return stack + + + def shortest_path(self, s): + stack = self.topological_sort() + + distance = [float("inf")] * self.vertices + distance[s] = 0 + + while stack: + i = stack.pop(0) + + for vertex, weight in self.graph[i]: + if distance[vertex] > distance[i] + weight: + distance[vertex] = distance[i] + weight + + for i in range(self.vertices): + print(f"{s} -> {i} = {distance[i]}") + + +g = Graph(6) +g.add_edge(0, 1, 5) +g.add_edge(0, 2, 3) +g.add_edge(1, 3, 6) +g.add_edge(1, 2, 2) +g.add_edge(2, 4, 4) +g.add_edge(2, 5, 2) +g.add_edge(2, 3, 7) +g.add_edge(3, 4, -1) +g.add_edge(4, 5, -2) + +source = 0 + +g.shortest_path(source) \ No newline at end of file From 0635e65a1112563552a6136e5afbd6e1840fb7e4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 13 Apr 2021 17:57:31 +0530 Subject: [PATCH 371/455] Fix BFS --- data_structures/graphs/bfs.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/data_structures/graphs/bfs.py b/data_structures/graphs/bfs.py index 82bda7d3..67722def 100644 --- a/data_structures/graphs/bfs.py +++ b/data_structures/graphs/bfs.py @@ -2,8 +2,9 @@ class Graph: - def __init__(self): + def __init__(self, vertices): self.graph = defaultdict(list) + self.vertices = vertices def add_edge(self, u, v): @@ -11,29 +12,31 @@ def add_edge(self, u, v): def bfs(self, s): - visited = [False] * len(self.graph) + visited = [False] * self.vertices queue = [] queue.append(s) visited[s] = True + bfs = [] + while queue: s = queue.pop(0) print(s, end=' ') - for i in self.graph[s]: if visited[i] == False: queue.append(i) visited[i] = True +g = Graph(6) -g = Graph() -g.add_edge(0, 1) -g.add_edge(0, 2) -g.add_edge(1, 2) -g.add_edge(2, 0) -g.add_edge(2, 3) -g.add_edge(3, 3) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 3) +g.add_edge(0, 3) +g.add_edge(2, 4) +g.add_edge(3, 4) +g.add_edge(3, 5) g.bfs(0) From 3e6f90d07a97468f8bc63980ee505fb621b4ede6 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 13 Apr 2021 18:15:45 +0530 Subject: [PATCH 372/455] Add description --- data_structures/graphs/level_of_nodes.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data_structures/graphs/level_of_nodes.py b/data_structures/graphs/level_of_nodes.py index 7190341c..c453fa95 100644 --- a/data_structures/graphs/level_of_nodes.py +++ b/data_structures/graphs/level_of_nodes.py @@ -1,3 +1,10 @@ +""" +Level is the distance of a node from a source node. This concept can be used to find +the distance between 2 nodes in an unweighted graph as well. A simple BFS traversal +between these 2 nodes will give the level and level will always be the shortest distance +between nodes. +""" + from collections import defaultdict class Graph: @@ -39,5 +46,4 @@ def print_levels(self, s): g.add_edge(2, 5) g.add_edge(2, 6) g.add_edge(6, 7) -g.print_levels(0) - +g.print_levels(0) \ No newline at end of file From d6051d2d6457643d580b8423892e2f70ac0b23fc Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 13 Apr 2021 18:16:03 +0530 Subject: [PATCH 373/455] Add shortest path --- .../graphs/shortest_path_unweighted_graph.py | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 data_structures/graphs/shortest_path_unweighted_graph.py diff --git a/data_structures/graphs/shortest_path_unweighted_graph.py b/data_structures/graphs/shortest_path_unweighted_graph.py new file mode 100644 index 00000000..ca5cd60b --- /dev/null +++ b/data_structures/graphs/shortest_path_unweighted_graph.py @@ -0,0 +1,68 @@ +""" +Find the shortest path between two nodes in an unweighted undirected graph. Remember this +is about finding the shortest path, not the shortest distance. For shortest +distance you can simply calculate the level of nodes from the source vertex +and that will give the answer. For shortest path, use the concept of parents of +Bellman-Ford algorithm. + +Simply do a BFS and keep track of parents of each node. Then recursively print the +parents of destination node until the source node. +""" + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def bfs(self, s): + parent = [-1] * self.vertices + visited = [False] * self.vertices + visited[s] = True + queue = [] + queue.append(s) + + while queue: + s = queue.pop(0) + + for i in self.graph[s]: + if visited[i] == False: + queue.append(i) + parent[i] = s + visited[i] = True + + return parent + + + def shortest_path(self, source, dest): + parent = self.bfs(source) + + while True: + print(dest, end=' ') + dest = parent[dest] + + if dest == source: + break + + +g = Graph(8) +g.add_edge(0, 1) +g.add_edge(0, 3) +g.add_edge(1, 2) +g.add_edge(3, 4) +g.add_edge(3, 7) +g.add_edge(4, 5) +g.add_edge(4, 6) +g.add_edge(4, 7) +g.add_edge(5, 6) +g.add_edge(6, 7) + +g.shortest_path(0, 7) \ No newline at end of file From a0e470a7acbf9d8e1de961498ecbb226a050e3f9 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 14 Apr 2021 12:45:45 +0530 Subject: [PATCH 374/455] Add comments --- data_structures/graphs/count_edges.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/data_structures/graphs/count_edges.py b/data_structures/graphs/count_edges.py index f1601542..6b9d1f87 100644 --- a/data_structures/graphs/count_edges.py +++ b/data_structures/graphs/count_edges.py @@ -1,6 +1,12 @@ -# Use handshaking lemma -# deg(v) = 2|E| -# Time - O(V) +""" +Count the number of edges in an undirected graph + +Use Handshaking Lemma (Note: Handshaking Lemma is only for undirected graph) + +For all v in V, deg(v) = 2|E| +""" + +Time - O(V) class Graph: @@ -39,4 +45,4 @@ def count_edges(self): g.add_edge(6, 8 ) g.add_edge(7, 8 ) -print(g.count_edges()) +print(g.count_edges()) \ No newline at end of file From 2f87807aef8a8a65b7777db7d3c7c7c885566d9d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 14 Apr 2021 12:50:29 +0530 Subject: [PATCH 375/455] Add comments --- data_structures/graphs/count_trees.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/data_structures/graphs/count_trees.py b/data_structures/graphs/count_trees.py index 84841062..28033ee9 100644 --- a/data_structures/graphs/count_trees.py +++ b/data_structures/graphs/count_trees.py @@ -1,4 +1,10 @@ -# Count the number of tress in a graph (forest) +""" +Count the number of trees in a forest + +A forest is a collection of trees. Do a DFS. If any vertex if not reachable +from any other, then it means it is not a part of that subgraph (tree). Hence +it is a different tree, so increment the count +""" from collections import defaultdict @@ -42,5 +48,4 @@ def count_trees(self): g.add_edge(0, 2) g.add_edge(3, 4) -print('Count of trees - ', g.count_trees()) - +print('Count of trees - ', g.count_trees()) \ No newline at end of file From 42a6240bfaad46e6b23319d3338be9a588f7d54e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 14 Apr 2021 18:14:37 +0530 Subject: [PATCH 376/455] Add question --- .../cycle_in_undirected_graph_iterative.py | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/data_structures/graphs/cycle_in_undirected_graph_iterative.py b/data_structures/graphs/cycle_in_undirected_graph_iterative.py index 3a1124ec..53bca95d 100644 --- a/data_structures/graphs/cycle_in_undirected_graph_iterative.py +++ b/data_structures/graphs/cycle_in_undirected_graph_iterative.py @@ -4,5 +4,57 @@ traverse but in undirected its possible that an edge (or a path) can be traversed infite number of times. -Instead check for parents. If a parent of a node is visited and -""" \ No newline at end of file +Instead check for parents (which means vertex fro which you reached the current vertex). +If a vertex is visited and you are not coming to this vertex from the current "source" vertex +(source - vertex from which DFS has started), then it means that in the same DFS chain, there is +another path to reach this vertex - hence a cycle +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def dfs(self): + visited = [False] * self.vertices + parent = [-1] * self.vertices + + stack = [] + + for v in range(self.vertices): + if visited[v] == False: + visited[v] = True + + stack.append(v) + + while stack: + s = stack.pop() + + for i in self.graph[s]: + if visited[i] == False: + parent[i] = s + stack.append(i) + visited[i] = True + elif parent[s] != i: + return "Contains Cycle" + + return "No cycle" + + +g = Graph(5) +g.add_edge(1, 0) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(0, 3) +g.add_edge(3, 4) +print(g.dfs()) \ No newline at end of file From 5fe1373e4e20e8b08845b7dbae85b619ab66e04a Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 14 Apr 2021 18:42:51 +0530 Subject: [PATCH 377/455] Add check if graph is tree --- .../graphs/check_if_graph_is_tree.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 data_structures/graphs/check_if_graph_is_tree.py diff --git a/data_structures/graphs/check_if_graph_is_tree.py b/data_structures/graphs/check_if_graph_is_tree.py new file mode 100644 index 00000000..90ed3425 --- /dev/null +++ b/data_structures/graphs/check_if_graph_is_tree.py @@ -0,0 +1,59 @@ +""" +A graph is a tree if - +1. It does not contain cycles +2. The graph is connected + +Do DFS and see if every vertex can be visited from a source vertex and check for cycle +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def is_tree(self, s): + visited = [False] * self.vertices + parent = [-1] * self.vertices + stack = [] + + visited[s] = True + no_of_visited = 1 + stack.append(s) + + while stack: + s = stack.pop() + + for i in self.graph[s]: + if visited[i] == False: + parent[i] = s + visited[i] = True + stack.append(i) + no_of_visited += 1 + elif parent[s] != i: + return "Not a tree" + + if no_of_visited == self.vertices: + return "Graph is Tree" + else: + return "Not a tree" + + +g = Graph(7) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 3) +g.add_edge(2, 4) +g.add_edge(4, 5) +g.add_edge(1, 6) + +print(g.is_tree(0)) \ No newline at end of file From 469a9bff4af81789c05a5a5add569062fa171e09 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 15 Apr 2021 11:55:26 +0530 Subject: [PATCH 378/455] Add sink nodes --- data_structures/graphs/count_sink_nodes.py | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 data_structures/graphs/count_sink_nodes.py diff --git a/data_structures/graphs/count_sink_nodes.py b/data_structures/graphs/count_sink_nodes.py new file mode 100644 index 00000000..7cce157f --- /dev/null +++ b/data_structures/graphs/count_sink_nodes.py @@ -0,0 +1,31 @@ +""" +Count the number of sink nodes + +Sink nodes are the nodes without any outgoing edge + +Solution - +vertices contains the total number of edges and graph is an adjacency list. +Simply subtract the vertices and len(graph) +""" + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def count_sink_nodes(self): + return self.vertices - len(self.graph) + + +g = Graph(3) +g.add_edge(0, 1) +g.add_edge(0, 2) +print(g.count_sink_nodes()) \ No newline at end of file From 941bb7992d8a2159760008058500b7babf729092 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 15 Apr 2021 11:55:35 +0530 Subject: [PATCH 379/455] Update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cdbc6a72..ec31aa8c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Python Data Structures and Algorithms -This repository contains questions requiring implementation of data structures and algorithms concepts. It is useful for interviews in Python. +No non-sense solutions to common Data Structure and Algorithm interview questions in Python. ## Objective -The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! :smiley: +The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! ## Structure of the repository @@ -58,8 +58,8 @@ As you can see, the repo is still in its infancy. Here are some key things in th ## Contributing -Contributions are always welcomed. :smiley: -Feel free to raise new issues, file new PRs. Consider giving it a star and fork this repo! :wink: +Contributions are always welcomed. +Feel free to raise new issues, file new PRs. Consider giving it a star and fork this repo! To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) From a6c75eaac88b0b53ae74cd24ca600428b4cf5263 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 15 Apr 2021 17:19:04 +0530 Subject: [PATCH 380/455] Two cliques --- data_structures/graphs/two_cliques.py | 75 +++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 data_structures/graphs/two_cliques.py diff --git a/data_structures/graphs/two_cliques.py b/data_structures/graphs/two_cliques.py new file mode 100644 index 00000000..4eefba9c --- /dev/null +++ b/data_structures/graphs/two_cliques.py @@ -0,0 +1,75 @@ +""" +Find if a graph can be divided into two cliques + +A clique is a subgraph such that all vertices in it are completely +connected with each other + +Solution - +A bipartite graph is a graph which can be divided into two sets U and V such +that every edge from u or v has a destination in the other. +So take the complement of the graph (create edge where there is none, and destroy +edges where present) and if the complement is a bipartite, it means that there are edges +in U and V that connect each other. So complement's complement (i.e the original graph) will +not have these edges and hence it can be divided into two clique +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.cgraph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def is_bipartite(self): + colors = [-1] * self.vertices + queue = [] + + for v in range(self.vertices): + if colors[v] == -1: + colors[v] = 1 + + queue.append(v) + + while queue: + s = queue.pop(0) + + for i in self.cgraph[s]: + if colors[i] == -1: + colors[i] = 1 - colors[s] + queue.append(i) + + elif colors[i] == colors[s]: + return False + + return True + + + def make_complement(self): + for src, dest in self.graph.items(): + for v in range(self.vertices): + if v not in dest and src != v: + self.cgraph[src].append(v) + self.cgraph[v].append(src) + + + def two_cliques(self): + self.make_complement() + return self.is_bipartite() + + +g = Graph(5) +g.add_edge(0, 3) +g.add_edge(3, 4) +g.add_edge(0, 1) +g.add_edge(1, 2) +g.add_edge(2, 0) +print(g.two_cliques()) \ No newline at end of file From 3e7c26038805dfca32a263b7ef2613fd0da72599 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 18 Apr 2021 14:33:28 +0530 Subject: [PATCH 381/455] Added kosaraju's algorithm --- data_structures/graphs/kosaraju_algorithm.py | 80 +++++++++++++------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/data_structures/graphs/kosaraju_algorithm.py b/data_structures/graphs/kosaraju_algorithm.py index cfc2a2b0..cd446c1a 100644 --- a/data_structures/graphs/kosaraju_algorithm.py +++ b/data_structures/graphs/kosaraju_algorithm.py @@ -1,7 +1,13 @@ -# Reference - https://www.geeksforgeeks.org/strongly-connected-components/ +""" +Reference - https://www.geeksforgeeks.org/strongly-connected-components/ -# This is used to find all the strongly connected components and does DFS -# 2 times. +Algorithm - https://youtu.be/RpgcYiky7uw + +This is used to find all the strongly connected components and does DFS +2 times. + +Note: A single vertex is also strongly connected +""" from collections import defaultdict @@ -9,7 +15,7 @@ class Graph: def __init__(self, vertices): - self.V = vertices + self.vertices = vertices self.graph = defaultdict(list) @@ -17,49 +23,67 @@ def add_edge(self, u, v): self.graph[u].append(v) - def dfs_util(self, v, visited): + def fill_time(self, v, visited, stack): visited[v] = True - print(v, end=' ') for i in self.graph[v]: if visited[i] == False: - self.dfs_util(i, visited) + self.fill_time(i, visited, stack) + stack = stack.append(v) - def fill_order(self, v, visited, stack): + + def dfs(self, v, visited): visited[v] = True + print(v, end=' ') + for i in self.graph[v]: if visited[i] == False: - self.fill_order(i, visited, stack) - stack.append(v) + self.dfs(i, visited) - - def get_transpose(self): - g = Graph(self.V) + + def create_tranpose(self): + tgraph = Graph(self.vertices) for i in self.graph: for j in self.graph[i]: - g.add_edge(j, i) - - return g + tgraph.add_edge(j, i) + return tgraph + def kosaraju(self): + visited = [False] * self.vertices stack = [] - visited = [False] * self.V - for i in range(self.V): - if visited[i] == False: - self.fill_order(i, visited, stack) + for v in range(self.vertices): + if visited[v] == False: + self.fill_time(v, visited, stack) - gr = self.get_transpose() + tgraph = self.create_tranpose() + visited = [False] * self.vertices - visited = [False] * self.V + print('stack - ', stack) while stack: - i = stack.pop() - if visited[i] == False: - gr.dfs_util(i, visited) - print() - - + s = stack.pop() + + if visited[s] == False: + tgraph.dfs(s, visited) + print() + + +g = Graph(11) +g.add_edge(0, 1) +g.add_edge(2, 0) +g.add_edge(1, 2) +g.add_edge(1, 3) +g.add_edge(3, 4) +g.add_edge(4, 5) +g.add_edge(5, 3) +g.add_edge(6, 5) +g.add_edge(6, 7) +g.add_edge(7, 8) +g.add_edge(8, 9) +g.add_edge(9, 10) +g.kosaraju() \ No newline at end of file From 8834704dbdf69e3ac322218e6df2ac1fa4008bac Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 18 Apr 2021 14:39:32 +0530 Subject: [PATCH 382/455] Add connected components undirected graph --- .../connected_components_undirected_graphs.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 data_structures/graphs/connected_components_undirected_graphs.py diff --git a/data_structures/graphs/connected_components_undirected_graphs.py b/data_structures/graphs/connected_components_undirected_graphs.py new file mode 100644 index 00000000..feb3dce4 --- /dev/null +++ b/data_structures/graphs/connected_components_undirected_graphs.py @@ -0,0 +1,46 @@ +from collections import defaultdict + + +class Graph: + + def __init__(self, vertices): + self.vertices = vertices + self.graph = defaultdict(list) + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def dfs(self, v, temp, visited): + visited[v] = True + temp.append(v) + + for i in self.graph[v]: + if visited[i] == False: + temp = self.dfs(i, temp, visited) + + return temp + + + def connected_components(self): + visited = [False] * self.vertices + cc = [] + + for i in range(self.vertices): + if visited[i] == False: + temp = [] + cc.append(self.dfs(i, temp, visited)) + + return cc + + +g = Graph(5) +g.add_edge(0, 1) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(0, 3) +g.add_edge(3, 4) + +print(g.connected_components()) \ No newline at end of file From 54cdebaf032197fb41396a841395f054a62c9f97 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 19 Apr 2021 17:23:23 +0530 Subject: [PATCH 383/455] Remove TODO from binary tree --- data_structures/binary_trees/TO_DO | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 data_structures/binary_trees/TO_DO diff --git a/data_structures/binary_trees/TO_DO b/data_structures/binary_trees/TO_DO deleted file mode 100644 index cb734cb7..00000000 --- a/data_structures/binary_trees/TO_DO +++ /dev/null @@ -1,2 +0,0 @@ -1. Max width of a binary tree -2. Total width of a binary tree From ec052e90f9a08da46935662ebac40fed91fef709 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 20 Apr 2021 14:09:51 +0530 Subject: [PATCH 384/455] Delete index --- data_structures/binary_trees/index.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 data_structures/binary_trees/index.md diff --git a/data_structures/binary_trees/index.md b/data_structures/binary_trees/index.md deleted file mode 100644 index 4f749eae..00000000 --- a/data_structures/binary_trees/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Index of binary_trees - -* [Symmetric Binary Tree](symmetric_binary_tree.py) From 505c3b41101d4149e9752c5a618a41f6cf703070 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 20 Apr 2021 16:07:39 +0530 Subject: [PATCH 385/455] boundary traversal --- .../binary_trees/boundary_traversal.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/data_structures/binary_trees/boundary_traversal.py b/data_structures/binary_trees/boundary_traversal.py index 760a6342..a4f08c00 100644 --- a/data_structures/binary_trees/boundary_traversal.py +++ b/data_structures/binary_trees/boundary_traversal.py @@ -15,8 +15,6 @@ def print_leaves(root): print_leaves(root.right) -# To ensure top down, print before calling for other -# To ensure bottom up, print after calling def print_left_boundary(root): if root: @@ -30,6 +28,11 @@ def print_left_boundary(root): def print_right_boundary(root): + """ + The traversal here will be from top to bottom because + this will be called after finishing the left side which is + top-to-bottom traversal + """ if root: if root.right: print_right_boundary(root.right) @@ -47,3 +50,14 @@ def print_boundary(root): print_leaves(root.left) print_leaves(root.right) print_right_boundary(root.right) + + +root = Node(20) +root.left = Node(8) +root.left.left = Node(4) +root.left.right = Node(12) +root.left.right.left = Node(10) +root.left.right.right = Node(14) +root.right = Node(22) +root.right.right = Node(25) +print_boundary(root) \ No newline at end of file From eaf5678fecdd14962bb0657c1c6d56323614abcd Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 21 Apr 2021 08:41:49 +0530 Subject: [PATCH 386/455] Add function call in check cousins --- data_structures/binary_trees/check_cousin.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/data_structures/binary_trees/check_cousin.py b/data_structures/binary_trees/check_cousin.py index 6453eed4..a65b95c8 100644 --- a/data_structures/binary_trees/check_cousin.py +++ b/data_structures/binary_trees/check_cousin.py @@ -34,3 +34,19 @@ def is_cousin(root, a, b): return True else: return False + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(4) +root.left.right = Node(5) +root.left.right.right = Node(15) +root.right.left = Node(6) +root.right.right = Node(7) +root.right.left.right = Node(8) + +node1 = root.left.right +node2 = root.right.right + +print(is_cousin(root, node1, node2)) \ No newline at end of file From 6a0a08e919a77b7d7e50cbaa9a8df4c9b5434e2e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 21 Apr 2021 09:49:23 +0530 Subject: [PATCH 387/455] Add implementation --- .../check_divide_in_two_halves.py | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/data_structures/binary_trees/check_divide_in_two_halves.py b/data_structures/binary_trees/check_divide_in_two_halves.py index df4f71b3..828138d2 100644 --- a/data_structures/binary_trees/check_divide_in_two_halves.py +++ b/data_structures/binary_trees/check_divide_in_two_halves.py @@ -1,8 +1,10 @@ -# Check if removing an edge of a binary tree can divide -# the tree in two equal halves +""" +Check if removing an edge of a binary tree can divide +the tree in two equal halves -# Count the number of nodes, say n. Then traverse the tree -# in bottom up manner and check if n - s = s +Solution - Count the number of nodes, say n. Then traverse the tree +in bottom up manner and find the size of every subtree (s). Check if n - s = s +""" class Node: @@ -31,5 +33,15 @@ def check_util(root, n): def check(root): - n = count(rot) + n = count(root) return check_util(root, n) + + +root = Node(5) +root.left = Node(1) +root.right = Node(6) +root.left.left = Node(3) +root.right.left = Node(7) +root.right.right = Node(4) + +print(check(root)) \ No newline at end of file From adddf51b3a076a3ebbecb5dd988406356a5196cb Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 22 Apr 2021 17:13:44 +0530 Subject: [PATCH 388/455] Add question --- data_structures/binary_trees/boundary_traversal.py | 8 +++++++- data_structures/binary_trees/check_if_graph_is_tree.py | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) delete mode 100644 data_structures/binary_trees/check_if_graph_is_tree.py diff --git a/data_structures/binary_trees/boundary_traversal.py b/data_structures/binary_trees/boundary_traversal.py index a4f08c00..706970f1 100644 --- a/data_structures/binary_trees/boundary_traversal.py +++ b/data_structures/binary_trees/boundary_traversal.py @@ -1,3 +1,9 @@ +""" +Print the boundary traversal of a binary tree + +Boundary traversal - root, left (top-down), bottom, right (bottom-up) +""" + class Node: def __init__(self, val): @@ -21,7 +27,7 @@ def print_left_boundary(root): if root.left: print(root.val, end=' ') print_left_boundary(root.left) - + elif root.right: print(root.val, end=' ') print_left_boundary(root.right) diff --git a/data_structures/binary_trees/check_if_graph_is_tree.py b/data_structures/binary_trees/check_if_graph_is_tree.py deleted file mode 100644 index 8b137891..00000000 --- a/data_structures/binary_trees/check_if_graph_is_tree.py +++ /dev/null @@ -1 +0,0 @@ - From d59296d4ec3ce63969cfea2148ea2e3243d2fd29 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 22 Apr 2021 18:44:37 +0530 Subject: [PATCH 389/455] Modifications --- data_structures/binary_trees/check_cousin.py | 25 +++++++++++++------ .../binary_trees/check_full_binary_tree.py | 19 ++++++++++---- .../binary_trees/check_if_path_exists.py | 7 +++--- data_structures/binary_trees/traversals.py | 15 +++++++++++ 4 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 data_structures/binary_trees/traversals.py diff --git a/data_structures/binary_trees/check_cousin.py b/data_structures/binary_trees/check_cousin.py index a65b95c8..c1f83d16 100644 --- a/data_structures/binary_trees/check_cousin.py +++ b/data_structures/binary_trees/check_cousin.py @@ -1,4 +1,11 @@ -# Check if two nodes are cousin or not +""" +Check if two nodes are cousin or not + +Condition for being cousin - +1. Level is same +2. They are not siblings + +""" class Node: @@ -11,22 +18,26 @@ def __init__(self, val): def level(root, node, lev): if not root: return 0 + if root == node: return lev - l = level(root.left, node, lev + 1) - + l = level(root.left, node, lev+1) + if not l == 0: return l - l = level(root.right, node, lev + 1) + l = level(root.right, node, lev+1) def is_sibling(root, a, b): - if root is None: - return 0 + if not root: + return False - return ( (root.left == a and root.right == b) or (root.left == b and root.right == a) or is_sibling(root.left, a, b) or is_sibling(root.right, a, b) ) + return (root.left == a and root.right == b) or \ + (root.right == b and root.left == a) or \ + is_sibling(root.left, a, b) or \ + is_sibling(root.right, a, b) def is_cousin(root, a, b): diff --git a/data_structures/binary_trees/check_full_binary_tree.py b/data_structures/binary_trees/check_full_binary_tree.py index 23c03f16..2498a4e6 100644 --- a/data_structures/binary_trees/check_full_binary_tree.py +++ b/data_structures/binary_trees/check_full_binary_tree.py @@ -1,4 +1,6 @@ -# A full binary tree is one which has 0 or 2 children only +""" +A full binary tree is a tree which has either 0 children or 2 children +""" class Node: @@ -9,14 +11,21 @@ def __init__(self, val): def check(root): - if root is None: + if not root: return True - if root.left is None and root.right is None: + if not root.left and not root.right: return True - if root.left is not None and root.right is not None: + if root.left and root.right: return check(root.left) and check(root.right) - return False +root = Node(0) +root.left = Node(1) +root.right = Node(2) + +if check(root): + print('True') +else: + print("False") \ No newline at end of file diff --git a/data_structures/binary_trees/check_if_path_exists.py b/data_structures/binary_trees/check_if_path_exists.py index be05f876..c6e33e5b 100644 --- a/data_structures/binary_trees/check_if_path_exists.py +++ b/data_structures/binary_trees/check_if_path_exists.py @@ -1,8 +1,7 @@ -# Check if a given path exists in a tree - -# Traverse the tree in preorder fashion and keep matching the node -# value to the index of the given path +""" +Given a path in an array form, check if this path leads to a leaf node +""" class Node: def __init__(self, val): diff --git a/data_structures/binary_trees/traversals.py b/data_structures/binary_trees/traversals.py new file mode 100644 index 00000000..5c26eb39 --- /dev/null +++ b/data_structures/binary_trees/traversals.py @@ -0,0 +1,15 @@ +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +class Tree: + + def __init__(self, root): + self.root = root + + + def inorder() From 015e49899c890710191ed61188fc4460203e190d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 26 Apr 2021 10:52:47 +0530 Subject: [PATCH 390/455] Add height of tree --- .../binary_trees/height_of_tree.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 data_structures/binary_trees/height_of_tree.py diff --git a/data_structures/binary_trees/height_of_tree.py b/data_structures/binary_trees/height_of_tree.py new file mode 100644 index 00000000..cd082f1f --- /dev/null +++ b/data_structures/binary_trees/height_of_tree.py @@ -0,0 +1,35 @@ +""" +Find the height of a binary tree + +Height - (max of left height and right height) + 1 +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def height(root): + if not root: + return 0 + + else: + lheight = height(root.left) + rheight = height(root.right) + + return 1 + max(lheight, rheight) + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(7) +root.left.right = Node(6) +root.right.left = Node(5) +root.right.right = Node(4) +root.right.right.right = Node(40) + +print(height(root)) \ No newline at end of file From 397a53a5c0ddc84815007366b2cc3e8b96ad9aa1 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 26 Apr 2021 11:13:49 +0530 Subject: [PATCH 391/455] Add comments --- data_structures/binary_trees/diameter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/binary_trees/diameter.py b/data_structures/binary_trees/diameter.py index da1726b7..7c84ccd6 100644 --- a/data_structures/binary_trees/diameter.py +++ b/data_structures/binary_trees/diameter.py @@ -16,9 +16,9 @@ def height(root, ans): lheight = height(root.left, ans) rheight = height(root.right, ans) - ans[0] = max(ans[0], 1 + lheight + rheight) + ans[0] = max(ans[0], 1 + lheight + rheight) # This is for diameter - return 1 + max(lheight, rheight) + return 1 + max(lheight, rheight) # This is for height def diameter(root): From 253002b86bb2dfde0ab34be2158afb76a2b22162 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 26 Apr 2021 11:14:23 +0530 Subject: [PATCH 392/455] Add comments --- data_structures/binary_trees/longest_path_with_same_value.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/binary_trees/longest_path_with_same_value.py b/data_structures/binary_trees/longest_path_with_same_value.py index 288bbf95..6c285fd7 100644 --- a/data_structures/binary_trees/longest_path_with_same_value.py +++ b/data_structures/binary_trees/longest_path_with_same_value.py @@ -1,3 +1,7 @@ +""" +Find the longest path in the tree with the same value +""" + class Node: def __init__(self, val): From 213e225e0235004ea8c41a8813b193ad2c5bf15b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 26 Apr 2021 12:00:03 +0530 Subject: [PATCH 393/455] Add new questions --- .../binary_trees/print_path_to_a_node.py | 10 ++-- ...ree.py => print_spiral_tree_two_stacks.py} | 0 data_structures/binary_trees/spiral_tree.py | 56 +++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) rename data_structures/binary_trees/{print_spiral_tree.py => print_spiral_tree_two_stacks.py} (100%) create mode 100644 data_structures/binary_trees/spiral_tree.py diff --git a/data_structures/binary_trees/print_path_to_a_node.py b/data_structures/binary_trees/print_path_to_a_node.py index 3e1ece97..7202dbc6 100644 --- a/data_structures/binary_trees/print_path_to_a_node.py +++ b/data_structures/binary_trees/print_path_to_a_node.py @@ -6,21 +6,19 @@ def __init__(self, val): self.right = None -def has_path(root, arr, x): +def has_path(root, stack, x): if not root: return False - arr.append(root.val) + stack.append(root.val) if root.val == x: return True - if has_path(root.left, arr, x) or has_path(root.right, arr, x): + if has_path(root.left, stack, x) or has_path(root.right, stack, x): return True - # If the required node is not in the left or right subtree, remove - # the parent node from where the fork starts - arr.pop() + stack.pop() return False diff --git a/data_structures/binary_trees/print_spiral_tree.py b/data_structures/binary_trees/print_spiral_tree_two_stacks.py similarity index 100% rename from data_structures/binary_trees/print_spiral_tree.py rename to data_structures/binary_trees/print_spiral_tree_two_stacks.py diff --git a/data_structures/binary_trees/spiral_tree.py b/data_structures/binary_trees/spiral_tree.py new file mode 100644 index 00000000..e8505384 --- /dev/null +++ b/data_structures/binary_trees/spiral_tree.py @@ -0,0 +1,56 @@ +""" +Do level order traversal of a tree in spiral form +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def height(root): + if not root: + return 0 + + lheight = height(root.left) + rheight = height(root.right) + + return 1 + max(lheight, rheight) + + +def print_spiral(root): + h = height(root) + + left_to_right = False + + for i in range(1, h+1): + print_level(root, i, left_to_right) + left_to_right = not left_to_right + + +def print_level(root, level, left_to_right): + if not root: + return + + if level == 1: + print(root.val, end=' ') + elif level > 1: + if left_to_right: + print_level(root.left, level-1, left_to_right) + print_level(root.right, level-1, left_to_right) + else: + print_level(root.right, level-1, left_to_right) + print_level(root.left, level-1, left_to_right) + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(7) +root.left.right = Node(6) +root.right.left = Node(5) +root.right.right = Node(4) + +print_spiral(root) \ No newline at end of file From 8764dc8f5c3ded1b5f3eef583268b474ab529bfd Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 26 Apr 2021 12:39:00 +0530 Subject: [PATCH 394/455] Add perfect tree --- data_structures/binary_trees/perfect_tree.py | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 data_structures/binary_trees/perfect_tree.py diff --git a/data_structures/binary_trees/perfect_tree.py b/data_structures/binary_trees/perfect_tree.py new file mode 100644 index 00000000..68c1dfe0 --- /dev/null +++ b/data_structures/binary_trees/perfect_tree.py @@ -0,0 +1,47 @@ +""" +Check if a given binary tree is perfect or not +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def find_depth(node): + d = 0 + while node: + d += 1 + node = node.left + return d + + +def is_perfect_util(root, d, level=0): + if not root: + return True + + if not root.left and not root.right: + return d == level + 1 + + if not root.left or not root.right: + return False + + return is_perfect_util(root.left, d, level+1) and is_perfect_util(root.right, d, level+1) + + +def is_perfect(root): + depth = find_depth(root) + return is_perfect_util(root, depth) + + +root = Node(10) +root.left = Node(20) +root.right = Node(30) +root.left.left = Node(40) +root.left.right = Node(50) +root.right.left = Node(60) +root.right.right = Node(70) + +print(is_perfect(root)) \ No newline at end of file From 547a2a06d21ce26871f4a2003a4f0beb087a8d77 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 27 Apr 2021 13:00:28 +0530 Subject: [PATCH 395/455] Add views --- data_structures/binary_trees/left_view.py | 38 +++++++ data_structures/binary_trees/right_view.py | 42 ++++++++ data_structures/binary_trees/top_view.py | 52 +++++++++ .../binary_trees/vertical_traversal.py | 102 ++++++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 data_structures/binary_trees/left_view.py create mode 100644 data_structures/binary_trees/right_view.py create mode 100644 data_structures/binary_trees/top_view.py create mode 100644 data_structures/binary_trees/vertical_traversal.py diff --git a/data_structures/binary_trees/left_view.py b/data_structures/binary_trees/left_view.py new file mode 100644 index 00000000..63cdbf9d --- /dev/null +++ b/data_structures/binary_trees/left_view.py @@ -0,0 +1,38 @@ +""" +Print left view of a binary tree +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def left_view_util(root, max_level, level): + if not root: + return + + if max_level[0] < level: + print(root.val) + max_level[0] = level + + left_view_util(root.left, max_level, level+1) + left_view_util(root.right, max_level, level+1) + + +def left_view(root): + max_level = [0] + left_view_util(root, max_level, 1) + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(4) +root.left.left.left = Node(5) +root.left.left.left.left = Node(6) +root.right.right = Node(7) +root.right.right.right = Node(8) +left_view(root) \ No newline at end of file diff --git a/data_structures/binary_trees/right_view.py b/data_structures/binary_trees/right_view.py new file mode 100644 index 00000000..cc6aa796 --- /dev/null +++ b/data_structures/binary_trees/right_view.py @@ -0,0 +1,42 @@ +""" +Print right view of a binary tree + +The idea behind using max_level[0] is that - +1. Its value when changes will be reflected in every recursion call +2. We are visiting right side first. So this acts as a check that that level was done +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def right_view_util(root, max_level, level): + if not root: + return + + if max_level[0] < level: + print(root.val) + max_level[0] = level + + right_view_util(root.right, max_level, level+1) + right_view_util(root.left, max_level, level+1) + + +def right_view(root): + max_level = [0] + right_view_util(root, max_level, 1) + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(4) +root.left.right = Node(5) +root.right.left = Node(6) +root.right.right = Node(7) +root.right.left.right = Node(8) +right_view(root) \ No newline at end of file diff --git a/data_structures/binary_trees/top_view.py b/data_structures/binary_trees/top_view.py new file mode 100644 index 00000000..565e9e00 --- /dev/null +++ b/data_structures/binary_trees/top_view.py @@ -0,0 +1,52 @@ +""" +Print the top view of a binary tree + +Almost like vertical traversal +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + self.col = None + + +def top_view(root): + if not root: + return + + queue = [] + col = 0 + d = {} + + queue.append(root) + root.col = col + + while queue: + root = queue.pop(0) + col = root.col + + if col not in d: + d[col] = root.val + + if root.left: + queue.append(root.left) + root.left.col = col - 1 + if root.right: + queue.append(root.right) + root.right.col = col + 1 + + for i in sorted(d): + print(d[i], end=" ") + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.right = Node(4) +root.left.right.right = Node(5) +root.left.right.right.right = Node(6) + +top_view(root) \ No newline at end of file diff --git a/data_structures/binary_trees/vertical_traversal.py b/data_structures/binary_trees/vertical_traversal.py new file mode 100644 index 00000000..344a546f --- /dev/null +++ b/data_structures/binary_trees/vertical_traversal.py @@ -0,0 +1,102 @@ +""" +Print vertical view of a binary tree + + 1 + / \ + 2 3 + / \ / \ + 4 5 6 7 + / \ + 8 9 + + +The output of print this tree vertically will be: +4 +2 +1 5 6 +3 8 +7 +9 + +source - https://www.geeksforgeeks.org/print-binary-tree-vertical-order-set-2/ +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + self.col = None + + +def print_vertical_util(root, col, d): + if not root: + return + + if col in d: + d[col].append(root.val) + else: + d[col] = [root.val] + + print_vertical_util(root.left, col-1, d) + print_vertical_util(root.right, col+1, d) + + +def print_vertical(root): + d = {} + col = 0 + + print_vertical_util(root, col, d) + + for k, v in sorted(d.items()): + for i in v: + print(i, end=' ') + print() + + +def print_vertical_iterative(root): + queue = [] + col = 0 + d = {} + + queue.append(root) + root.col = col + + while queue: + root = queue.pop(0) + col = root.col + + if col not in d: + d[col] = [root.val] + else: + d[col].append(root.val) + + if root.left: + queue.append(root.left) + root.left.col = col - 1 + if root.right: + queue.append(root.right) + root.right.col = col + 1 + + for k, v in sorted(d.items()): + for i in v: + print(i, end=' ') + print() + + + +root = Node(1) +root.left = Node(2) +root.right = Node(3) +root.left.left = Node(4) +root.left.right = Node(5) +root.right.left = Node(6) +root.right.right = Node(7) +root.right.left.right = Node(8) +root.right.right.right = Node(9) + +print_vertical(root) + +print("Iterative solution - ") +print_vertical_iterative(root) \ No newline at end of file From b6d135f510e2cc772cdf34f8d8564744bb93aca7 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 28 Apr 2021 13:30:09 +0530 Subject: [PATCH 396/455] add comments --- data_structures/bst/second_largest_in_bst.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/data_structures/bst/second_largest_in_bst.py b/data_structures/bst/second_largest_in_bst.py index 598b36bb..334a3dd6 100644 --- a/data_structures/bst/second_largest_in_bst.py +++ b/data_structures/bst/second_largest_in_bst.py @@ -1,3 +1,14 @@ +""" +There can be two condition for finding the second largest element in a BST + +1. If right subtree does not exist, find the largest on the left side +Otherwise, +2. If right exists but right's left and right's right do not, that means +you are currently at the second largest element + +Move to right +""" + class Node: def __init__(self, val): From 0bfea10c8a919be75eca512345b2a89985cb486d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 28 Apr 2021 20:14:38 +0530 Subject: [PATCH 397/455] Remove index --- data_structures/bst/index.md | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 data_structures/bst/index.md diff --git a/data_structures/bst/index.md b/data_structures/bst/index.md deleted file mode 100644 index 97a6320f..00000000 --- a/data_structures/bst/index.md +++ /dev/null @@ -1,31 +0,0 @@ -# Index of BST - -* [Deletion](deletion.py) -* [Sorted Array To BST](sorted_array_to_bst.py) -* [Print Left Node](print_left_node.py) -* [Diameter](diameter.py) -* [BFS](bfs.py) -* [Check if BT is BST](check_if_bt_if_bst.py) -* [Trim BST](trim_bst.py) -* [BT to BST](bt_to_bst.py) -* [Binary Search Tree](binary_search_tree.py) -* [Convert BST to Right Node Tree](convert_bst_to_right_node_tree.py) -* [kth largest in BST](kth_largest_in_bst.py) -* [Range Sum](range_sum.py) -* [DFS Iterative](dfs_iterative.py) -* [Print Ancestor](print_ancestor.py) -* [Min Max Value in BST](min_max_value_in_bst.py) -* [Check BT is Subtree of another BT](check_bt_is_subtree_of_another_bt.py) -* [Ceil](ceil.py) -* [Closest Element](closest_element.py) -* [kth smallest in BST](kth_smallest_in_bst.py) -* [Insertion Iterative](insertion_iterative.py) -* [Lowest Common Ancestor](lowest_common_ancestor.py) -* [DFS Recursion](dfs_recursion.py) -* [Search](search.py) -* [Insertion Recursive](insertion_recursive.py) -* [Duplicate Keys](duplicate_keys.py) -* [Merge Sum](merge_sum.py) -* [Linked List to BST](linked_list_to_bst.py) -* [Reverse Inorder Traversal](reverse_inorder_traversal.py) -* [Average of Levels](average_of_levels.py) From bf82d5cb426318a075654910fba9d81c18a570f4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 29 Apr 2021 18:21:28 +0530 Subject: [PATCH 398/455] Add comments --- data_structures/bst/duplicate_keys.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/data_structures/bst/duplicate_keys.py b/data_structures/bst/duplicate_keys.py index 4e0e5cbf..ba8b6123 100644 --- a/data_structures/bst/duplicate_keys.py +++ b/data_structures/bst/duplicate_keys.py @@ -1,3 +1,11 @@ +""" +Create a BST such that it can have duplicate nodes. +Technically BST cannot have duplicate nodes. The work around is to +have a counter associated with every node. Increment its count whenever +there is a duplicate. If the count goes to zero, delete that node +""" + + class Node(): def __init__(self, val): From 09edf53c5f4676eb66c448b27f885e0600456350 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 29 Apr 2021 18:34:26 +0530 Subject: [PATCH 399/455] Complete duplicate keys by adding deletion --- data_structures/bst/duplicate_keys.py | 37 +++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/data_structures/bst/duplicate_keys.py b/data_structures/bst/duplicate_keys.py index ba8b6123..a09dc2c1 100644 --- a/data_structures/bst/duplicate_keys.py +++ b/data_structures/bst/duplicate_keys.py @@ -45,12 +45,41 @@ def insert(root, val): return root +def min_value_node(root): + curr = root + while curr: + curr = curr.left + return curr.val + + def delete(root, val): if not root: - return - if root.val == val: + return None + + if val < root.val: + root.left = delete(root.left, val) + elif val > root.val: + root.right = delete(root.right, val) + else: if root.count > 1: root.count -= 1 + else: + # check if left node is None + if not root.left: + temp = root.right + root = None + return temp + # chec if right node is None + if not root.right: + temp = root.left + root = None + return temp + + temp = min_value_node(root.right) + root.val = temp.val + root.right = delete(root.right, temp.val) + + return root root = Node(5) @@ -61,3 +90,7 @@ def delete(root, val): insert(root, 10) inorder(root) + +print("After deletion") +root = delete(root, 8) +inorder(root) \ No newline at end of file From 2fc7e45577c53d103e90e1fb5de631126e157445 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 30 Apr 2021 12:26:58 +0530 Subject: [PATCH 400/455] Add comments --- data_structures/bst/kth_largest_in_bst.py | 8 ++++++++ data_structures/bst/kth_smallest_in_bst.py | 8 ++++++++ data_structures/bst/print_ancestor.py | 3 --- data_structures/bst/trim_bst.py | 6 +++++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/data_structures/bst/kth_largest_in_bst.py b/data_structures/bst/kth_largest_in_bst.py index 1a013baf..e96eb84c 100644 --- a/data_structures/bst/kth_largest_in_bst.py +++ b/data_structures/bst/kth_largest_in_bst.py @@ -1,3 +1,11 @@ +""" +Print the kth largest element in a BST + +The inorder traversal gives elements of BST in ascending order. Do reverse inorder +(Right-Node-Left) and print the kth element +""" + + class Node(): def __init__(self, val): diff --git a/data_structures/bst/kth_smallest_in_bst.py b/data_structures/bst/kth_smallest_in_bst.py index aefa1345..26131ee1 100644 --- a/data_structures/bst/kth_smallest_in_bst.py +++ b/data_structures/bst/kth_smallest_in_bst.py @@ -1,3 +1,11 @@ +""" +Print the kth smallest number in BST + +The inorder traversal of BST gives elements in ascending order. So do inorder, +keep count and return the kth value +""" + + class Node(): def __init__(self, val): diff --git a/data_structures/bst/print_ancestor.py b/data_structures/bst/print_ancestor.py index b443c559..b065efa0 100644 --- a/data_structures/bst/print_ancestor.py +++ b/data_structures/bst/print_ancestor.py @@ -14,6 +14,3 @@ def print_ancestor_recursive(root, key): if print_ancestor_recursive(root.left, key) or print_ancestor_recursive(root.right, key): return root.data return False - - - diff --git a/data_structures/bst/trim_bst.py b/data_structures/bst/trim_bst.py index 31a17422..1ba86545 100644 --- a/data_structures/bst/trim_bst.py +++ b/data_structures/bst/trim_bst.py @@ -1,3 +1,7 @@ +""" +Trim a BST so that all elements lie within a given high and low range +""" + class Node(): def __init__(self, val): @@ -12,7 +16,7 @@ def trim(root, L, R): if root.val > R: return trim(root.left, L, R) if root.val < L: - return trim(root. right, L, R) + return trim(root.right, L, R) root.left = trim(root.left, L, R) root.right = trim(root.right, L, R) return root From f454f57eeee84b7efefa973f35fb7a24d9cf6be5 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 6 May 2021 09:43:56 +0530 Subject: [PATCH 401/455] Add comments --- data_structures/graphs/print_all_paths_between_nodes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_structures/graphs/print_all_paths_between_nodes.py b/data_structures/graphs/print_all_paths_between_nodes.py index cbd04abf..0b370237 100644 --- a/data_structures/graphs/print_all_paths_between_nodes.py +++ b/data_structures/graphs/print_all_paths_between_nodes.py @@ -24,6 +24,8 @@ def print_path(self, s, d, visited, path): if visited[i] == False: self.print_path(i, d, visited, path) + # If path from this node does not lead to the destination, remove it + # from the path stack and mark it as not visited path.pop() visited[s] = False From 25e8966ea638866c13ca937c3e858fd28d067aab Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 6 May 2021 16:59:56 +0530 Subject: [PATCH 402/455] Add min degree --- .../graphs/min_nodes_to_reach_all_nodes.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 data_structures/graphs/min_nodes_to_reach_all_nodes.py diff --git a/data_structures/graphs/min_nodes_to_reach_all_nodes.py b/data_structures/graphs/min_nodes_to_reach_all_nodes.py new file mode 100644 index 00000000..d60f6f9b --- /dev/null +++ b/data_structures/graphs/min_nodes_to_reach_all_nodes.py @@ -0,0 +1,11 @@ +""" +We are given a DAG. Find the smallest set of vertices from which all +nodes in the graph are reachable. It's guaranteed that a unique solution exists. + +Solution - +The crux of the question is that - +1. If any node has an indegree > 1 (i.e it is reachable from any other node), then it means +in a connected graph it will be possible to reach here if its parent node also has an indegree +2. So the min will be the set of nodes with indegree = 0 +""" + From fafcfab9a6b528834fbfb74f7f3e4e4fa5cb0662 Mon Sep 17 00:00:00 2001 From: RK Date: Mon, 10 May 2021 10:36:45 +0530 Subject: [PATCH 403/455] fixed bug in line 20 and simplified code for creating graph --- data_structures/graphs/Adjacency_matrix.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/data_structures/graphs/Adjacency_matrix.py b/data_structures/graphs/Adjacency_matrix.py index 7895a279..f173bc37 100644 --- a/data_structures/graphs/Adjacency_matrix.py +++ b/data_structures/graphs/Adjacency_matrix.py @@ -4,10 +4,7 @@ def __init__(self, vertices, directed: bool): self.V = vertices self.e = 0 self.d = directed - self.graph = [] - for i in range(self.V): - lst = [0] * self.V - self.graph.append(lst) + self.graph = [[0 for i in range(vertices)] for j in range(vertices)] def add_edge(self, ver1, ver2): if self.d: @@ -17,7 +14,7 @@ def add_edge(self, ver1, ver2): self.graph[ver2][ver1] = 1 def remove_edge(self, ver1, ver2): - if self.d[ver1][ver2] == 0: + if self.graph[ver1][ver2] == 0: print("No edge between %d and %d" % (ver1, ver2)) return if self.d: @@ -30,6 +27,11 @@ def print_graph(self): for i in self.graph: print(i) - - +if __name__=="__main__": + g1 = Graph(3,0) + g1.add_edge(0,0) + g1.add_edge(1,1) + g1.add_edge(2,2) + g1.remove_edge(2,1) + g1.print_graph() From eb8ea1471c3f9473776ec6ba9bf95a52f3a36864 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 10 May 2021 18:02:12 +0530 Subject: [PATCH 404/455] New changes --- README.md | 4 ++++ data_structures/graphs/dijsktra_algorithm.py | 0 2 files changed, 4 insertions(+) create mode 100644 data_structures/graphs/dijsktra_algorithm.py diff --git a/README.md b/README.md index ec31aa8c..b5a68823 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ No non-sense solutions to common Data Structure and Algorithm interview question ## Objective +There are a plenty of resources when it comes to interview preparations on the internet. What prompted me to create this project was the dissimilarity across different approaches and the infused complexity of the code. + +Feel free to contribute but please follow the Contributing Guidelines as I want to maintain the uniformity of the implementation of data structures and algorithms. Last time around, people bombarded with me with Pull Requests, Issues and Emails insisting me to merge their changes + The open source community has helped me a lot during my interview preparations and studies while I was in my undergrad. I always wanted to give something back to the community. In my endeavour to contribute something back, I will be uploading data structures and algorithms questions in Python in this repo. Feel free to contribute and get in touch! ## Structure of the repository diff --git a/data_structures/graphs/dijsktra_algorithm.py b/data_structures/graphs/dijsktra_algorithm.py new file mode 100644 index 00000000..e69de29b From cbe2097711a3fc34aad779a263d8ab8c26b33a53 Mon Sep 17 00:00:00 2001 From: Rohan Krishna Ullas <71774184+Kakarot-2000@users.noreply.github.com> Date: Tue, 18 May 2021 15:39:41 +0530 Subject: [PATCH 405/455] Updated balanced_expression.py to fix bugs --- data_structures/stack/balanced_expression.py | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/data_structures/stack/balanced_expression.py b/data_structures/stack/balanced_expression.py index 784666c0..60e3c506 100644 --- a/data_structures/stack/balanced_expression.py +++ b/data_structures/stack/balanced_expression.py @@ -1,24 +1,30 @@ -# simple program to check if an expression is balanced using stack stack = [] def checkBalanced(expr): for i in expr: if i == "{" or i == "[" or i == "(": stack.append(i) elif i == "}" or i == "]" or i == ")": - temp = stack.pop() - if i == "}" and temp != "{": + if not stack: return False - elif i == "]" and temp != "[": + top = stack.pop() + if i == "}" and top != "{": return False - elif i == ")" and temp != "(": + elif i == "]" and top != "[": return False + elif i == ")" and top != "(": + return False + else: + print("Invalid Expression") + return False - return True + if not len(stack): + return True + else: + return False # main function expr = input() -result = checkBalanced(expr) -if result: - print("Expression is balanced") +if not checkBalanced(expr): + print("Not Balanced") else: - print("Expression is not balanced") + print('Balanced') From a8954614d2128f40a50fb9e932be37a671b68d4e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 2 Jun 2021 09:34:14 +0530 Subject: [PATCH 406/455] Add array to bt --- .../binary_trees/array_to_binary_tree.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 data_structures/binary_trees/array_to_binary_tree.py diff --git a/data_structures/binary_trees/array_to_binary_tree.py b/data_structures/binary_trees/array_to_binary_tree.py new file mode 100644 index 00000000..9057b163 --- /dev/null +++ b/data_structures/binary_trees/array_to_binary_tree.py @@ -0,0 +1,37 @@ +""" +Convert an array to a binary tree + +Sample input - +[1,2,3,4,5,null,6,7,null,null,null,null,8] + +Note - +if a tree has N nodes and is complete, then the no of internal +nodes can be (N-1) / 2 +""" + +class Node: + + def __init__(self, val): + self.val = val + self.left = None + self.right = None + + +def create_tree(arr): + curr_ptr = 0 + child_ptr = 0 + + root = Node(arr[0]) + curr_node = root + + while i < (len(arr) - 1)/2: + curr_ptr = arr[i] + child_ptr = i + 1 + + left_child = arr[child_ptr] + right_child = arr[child_ptr + 1] + + curr_node.left = Node(left_child) + curr_node.right = Node(right_child) + + From 9e8e9ca35ef876cf7543ef068f3dc9cca000a758 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 4 Jun 2021 18:52:03 +0530 Subject: [PATCH 407/455] Update first_repeating_char.py --- data_structures/array/first_repeating_char.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/first_repeating_char.py b/data_structures/array/first_repeating_char.py index 2ba272eb..89477411 100644 --- a/data_structures/array/first_repeating_char.py +++ b/data_structures/array/first_repeating_char.py @@ -1,4 +1,4 @@ -# Find the first character in a string without using extra space +# Find the first repeated character in a string without using extra space # With extra space its simple. Just check for the element in a hash map # If present, then it is the recurrent char From e522e65b070759ba0bb0f5672e6d3566dea77b63 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 4 Jun 2021 20:21:41 +0530 Subject: [PATCH 408/455] Update cycle_in_undirected_graph_iterative.py --- data_structures/graphs/cycle_in_undirected_graph_iterative.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/graphs/cycle_in_undirected_graph_iterative.py b/data_structures/graphs/cycle_in_undirected_graph_iterative.py index 53bca95d..565cedde 100644 --- a/data_structures/graphs/cycle_in_undirected_graph_iterative.py +++ b/data_structures/graphs/cycle_in_undirected_graph_iterative.py @@ -4,7 +4,7 @@ traverse but in undirected its possible that an edge (or a path) can be traversed infite number of times. -Instead check for parents (which means vertex fro which you reached the current vertex). +Instead check for parents (which means vertex from which you reached the current vertex). If a vertex is visited and you are not coming to this vertex from the current "source" vertex (source - vertex from which DFS has started), then it means that in the same DFS chain, there is another path to reach this vertex - hence a cycle @@ -57,4 +57,4 @@ def dfs(self): g.add_edge(2, 0) g.add_edge(0, 3) g.add_edge(3, 4) -print(g.dfs()) \ No newline at end of file +print(g.dfs()) From bca7a225fa8bb9f2fba312a4c27ac4e6b98eff65 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 7 Jun 2021 08:38:36 +0530 Subject: [PATCH 409/455] Update topics.md --- bookmarks/topics.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookmarks/topics.md b/bookmarks/topics.md index bf8c7be2..d1d54010 100644 --- a/bookmarks/topics.md +++ b/bookmarks/topics.md @@ -14,4 +14,6 @@ This is a list of links to topics that may be helpful in learning or researching - https://stackoverflow.com/questions/40200413/sessions-vs-token-based-authentication -- https://stackoverflow.com/questions/15678406/when-to-use-myisam-and-innodb \ No newline at end of file +- https://stackoverflow.com/questions/15678406/when-to-use-myisam-and-innodb + +- https://www.bigocheatsheet.com/ From 40a29e79ce1b1fa78cb0a4b9995d4342bca642c4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 7 Jun 2021 10:31:07 +0530 Subject: [PATCH 410/455] add heap --- data_structures/heap/max_heap.py | 152 +++++++++++++++++++++++++++++++ data_structures/heap/min_heap.py | 0 2 files changed, 152 insertions(+) create mode 100644 data_structures/heap/max_heap.py create mode 100644 data_structures/heap/min_heap.py diff --git a/data_structures/heap/max_heap.py b/data_structures/heap/max_heap.py new file mode 100644 index 00000000..3061e2d3 --- /dev/null +++ b/data_structures/heap/max_heap.py @@ -0,0 +1,152 @@ +""" +Thing to remember - +* index of parent = i / 2 +* index of left child = 2i + 1 +* index of right child = 2i + 2 +""" + +import sys + +class MaxHeap: + + def __init__(self, maxsize): + self.maxsize = maxsize + self.size = 0 # current number of elements in the heap + self.heap = [0] * self.maxsize + self.front = 0 + + + def parent(self, pos): + return pos // 2 + + + def left_child(self, pos): + return 2*pos + 1 + + + def right_child(self, pos): + return 2*pos + 2 + + + def mid_index(self): + return self.size // 2 + + + def last_index(self): + return self.size - 1 + + + def is_leaf(self, pos): + """ + Every node that is after the middle index of the heap + is a leaf node because their children cannot exist as the + index of children are twice their index as those indexes + do not exist in the heap + """ + if self.mid_index() <= pos <= self.last_index(): + return True + return False + + + def is_empty(self): + if self.size == 0 and not self.heap[0]: + return True + return False + + + def insert(self, value): + if self.is_empty(): # if the heap is empty + self.heap[self.front] = value + self.size += 1 + return + + if self.size >= self.maxsize: # if max size has been reached + return + + self.size += 1 + self.heap[self.last_index()] = value + + curr = self.last_index() + + # While inserting the element in the heap we have to + # make sure that the inserted element is always smaller + # than its parent. So basically here we are adjusting the + # position of the parent + while self.heap[curr] > self.heap[self.parent(curr)]: + self.swap(curr, self.parent(curr)) + curr = self.parent(curr) + + + def max_heapify(self, pos): + """ + This function will run whenever a node is non-leaf + node and smaller than its childen + """ + if not self.is_leaf(pos): + left = self.heap[self.left_child(pos)] + right = self.heap[self.right_child(pos)] + curr = self.heap[pos] + + if curr < left or curr < right: + + if left > right: + self.swap(pos, self.left_child(pos)) + self.max_heapify(self.left_child(pos)) + else: + self.swap(pos, self.right_child(pos)) + self.max_heapify(self.right_child(pos)) + + + def swap(self, x, y): + self.heap[x], self.heap[y] = self.heap[y], self.heap[x] + + + def pop_max(self): + max_element = self.heap[self.front] # max element is always at the front + self.heap[self.front] = self.heap[self.last_index()] # placing last element at the front + self.heap[self.last_index()] = 0 + self.size -= 1 # decrease size as one element has been popped + self.max_heapify(self.front) # heapify the heap again + return max_element + + + def print(self): + """ + Priting in inorder + """ + for i in range(0, self.mid_index() + 1): + parent = self.heap[i] + left = self.heap[self.left_child(i)] + right = self.heap[self.right_child(i)] + + print(f"Parent: {self.heap[i]}") + + if left: + print(f"Left child: {left}") + if right: + print(f"Right child: {right}") + + +if __name__ == '__main__': + max_heap = MaxHeap(15) + max_heap.insert(5) + max_heap.insert(3) + max_heap.insert(17) + max_heap.insert(10) + max_heap.insert(84) + max_heap.insert(19) + max_heap.insert(6) + max_heap.insert(22) + max_heap.insert(9) + + max_heap.print() + + print('Max element is - ', max_heap.pop_max()) + + + max_heap.print() + + print('Max element is - ', max_heap.pop_max()) + + + diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py new file mode 100644 index 00000000..e69de29b From b76544e65806cb80ab6c3263651464d5a840e432 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 7 Jun 2021 17:42:26 +0530 Subject: [PATCH 411/455] Add code for min and max heap --- data_structures/heap/max_heap.py | 17 +---- data_structures/heap/min_heap.py | 122 +++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 13 deletions(-) diff --git a/data_structures/heap/max_heap.py b/data_structures/heap/max_heap.py index 3061e2d3..29fcef70 100644 --- a/data_structures/heap/max_heap.py +++ b/data_structures/heap/max_heap.py @@ -5,8 +5,6 @@ * index of right child = 2i + 2 """ -import sys - class MaxHeap: def __init__(self, maxsize): @@ -17,7 +15,7 @@ def __init__(self, maxsize): def parent(self, pos): - return pos // 2 + return (pos) // 2 def left_child(self, pos): @@ -49,7 +47,7 @@ def is_leaf(self, pos): def is_empty(self): - if self.size == 0 and not self.heap[0]: + if self.size == 0: return True return False @@ -88,7 +86,8 @@ def max_heapify(self, pos): curr = self.heap[pos] if curr < left or curr < right: - + + # This check is only to prevent out-of-index error if left > right: self.swap(pos, self.left_child(pos)) self.max_heapify(self.left_child(pos)) @@ -140,13 +139,5 @@ def print(self): max_heap.insert(9) max_heap.print() - print('Max element is - ', max_heap.pop_max()) - - max_heap.print() - - print('Max element is - ', max_heap.pop_max()) - - - diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py index e69de29b..069524d4 100644 --- a/data_structures/heap/min_heap.py +++ b/data_structures/heap/min_heap.py @@ -0,0 +1,122 @@ +""" +See max_heap.py for more detailed comments +""" + +class MinHeap: + + + def __init__(self, maxsize): + self.maxsize = maxsize + self.size = 0 + self.first = 0 + self.heap = [0] * self.maxsize + + + def is_empty(self): + return self.size == 0 + + + def is_leaf(self, pos): + if self.mid_index() <= pos <= self.last_index(): + return True + return False + + + def parent(self, pos): + return pos // 2 + + + def left_child(self, pos): + return 2*pos + 1 + + + def right_child(self, pos): + return 2*pos + 2 + + + def last_index(self): + return self.size - 1 + + + def mid_index(self): + return self.size // 2 + + + def swap(self, x, y): + self.heap[x], self.heap[y] = self.heap[y], self.heap[x] + + + def pop_min(self): + min_element = self.heap[self.first] + self.heap[self.first] = self.heap[self.last_index()] + self.heap[self.last_index()] = 0 + self.size -= 1 + self.min_heapify(self.first) + return min_element + + + def min_heapify(self, pos): + if not self.is_leaf(pos): + left = self.heap[self.left_child(pos)] + right = self.heap[self.right_child(pos)] + curr = self.heap[pos] + + if curr > left or curr > right: + + if left > right: + self.swap(pos, self.left_child(pos)) + self.min_heapify(self.left_child(pos)) + else: + self.swap(pos, self.right_child(pos)) + self.min_heapify(self.right_child(pos)) + + + def insert(self, element): + if self.is_empty(): + self.heap[self.first] = element + self.size += 1 + return + + if self.size >= self.maxsize: + return + + self.size += 1 + self.heap[self.last_index()] = element + + curr = self.last_index() + + while self.heap[curr] < self.heap[self.parent(curr)]: + self.swap(curr, self.parent(curr)) + curr = self.parent(curr) + + + def print(self): + for i in range(0, self.mid_index() + 1): + parent = self.heap[i] + left = self.heap[self.left_child(i)] + right = self.heap[self.right_child(i)] + + print(f"Parent: {self.heap[i]}") + + if left: + print(f"Left child: {left}") + if right: + print(f"Right child: {right}") + + +if __name__ == '__main__': + min_heap = MinHeap(15) + min_heap.insert(5) + min_heap.insert(3) + min_heap.insert(17) + min_heap.insert(10) + min_heap.insert(84) + min_heap.insert(19) + min_heap.insert(6) + min_heap.insert(22) + min_heap.insert(9) + + min_heap.print() + print(min_heap.heap) + print('Min element is - ', min_heap.pop_min()) + min_heap.print() From 1dd751bc3e99148a82c9ca034f80985e6531a0ca Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 7 Jun 2021 17:47:21 +0530 Subject: [PATCH 412/455] add heap using library functions --- data_structures/heap/heap_using_heapq.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 data_structures/heap/heap_using_heapq.py diff --git a/data_structures/heap/heap_using_heapq.py b/data_structures/heap/heap_using_heapq.py new file mode 100644 index 00000000..0ee5410a --- /dev/null +++ b/data_structures/heap/heap_using_heapq.py @@ -0,0 +1,23 @@ +""" +Heap in python using heapq library function + +Note: by default, heapq creates a min-heap. To make it a +max-heap, add items after multiplying them by -1 +""" + +from heapq import heappop, heappush, heapify + +heap = [] +heapify(heap) + +heappush(heap, 10) +heappush(heap, 11) +heappush(heap, 2) +heappush(heap, 4) +heappush(heap, 14) +heappush(heap, 1) + +print('first element - ', heap[0]) +print('popping min element - ', heappop(heap)) +print('first element - ', heap[0]) + From 936d1734791ef509f4b807693e67f10c13e369d4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 8 Jun 2021 06:33:10 +0530 Subject: [PATCH 413/455] Add array indexes --- data_structures/heap/heap_using_heapq.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data_structures/heap/heap_using_heapq.py b/data_structures/heap/heap_using_heapq.py index 0ee5410a..7e28d109 100644 --- a/data_structures/heap/heap_using_heapq.py +++ b/data_structures/heap/heap_using_heapq.py @@ -21,3 +21,6 @@ print('popping min element - ', heappop(heap)) print('first element - ', heap[0]) +# Heap prints as an array and can be access using indexes +print(heap) +print(heap[2]) From 440cec21054a5a5e77c265882fd32fdfecaa12b4 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 8 Jun 2021 06:33:28 +0530 Subject: [PATCH 414/455] Add median of infinite stream --- .../heap/median_of_infinite_stream.py | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 data_structures/heap/median_of_infinite_stream.py diff --git a/data_structures/heap/median_of_infinite_stream.py b/data_structures/heap/median_of_infinite_stream.py new file mode 100644 index 00000000..9ce834a8 --- /dev/null +++ b/data_structures/heap/median_of_infinite_stream.py @@ -0,0 +1,95 @@ +""" +Awesome explanation - https://youtu.be/1LkOrc-Le-Y + +Median is the middle element in a sorted array. The stream of input +integers can be in any order and we will have to store the integers in +such a way that the stream is maintained in an increasing order. + +So the main idea is that take an array and divide it into two parts of +equal length and the median will be as follows - + +* if the total number of integers in the stream is even, then both part will +have the same length. Hence the median will be the average of last element of the first +part (i.e max element of the first part) and the first element of the second part (i.e +min element of the second part) + +* if total number of integers in the stream is odd, add the extra element in the first part. +In this case, the median will be the last element of the first part + +Now we just have to maintain the order of both the parts of the array. Since we want the max +element from the first part, we can use a max heap there. And we can use min heap for the second +part as we need the min element from the second part + +Time complexity: + if the size of stream is N, we will have to iterate N times. LogN because insertion in heap + takes this much time. O(1) for getting the max or min element + + N * LogN +""" + +from heapq import heappush, heappop, heapify + +class MedianStream: + + def __init__(self): + self.stream = [] + self.min_heap = [] + self.max_heap = [] + heapify(self.max_heap) + heapify(self.min_heap) + self.curr_median = None + + + def add_number(self, num): + """ + min heap length <= maxheap length <= min heap length + 1 + """ + self.stream.append(num) + + if len(self.max_heap) == len(self.min_heap) == 0: + self.curr_median = num + + if len(self.max_heap) > len(self.min_heap): + if num < self.curr_median: + max_popped = -1 * heappop(self.max_heap) + heappush(self.min_heap, max_popped) + heappush(self.max_heap, -1 * num) + self.find_median('avg') + else: + heappush(self.min_heap, num) + self.find_median('avg') + else: + if num > self.curr_median: + # num will go to the min heap and the min element + # of min heap will go the max heap + min_popped = heappop(self.min_heap) + heappush(self.max_heap, -1 * min_popped) + heappush(self.min_heap, num) + self.find_median('max') + + else: + # num will go to the max heap + heappush(self.max_heap, -1 * num) + self.find_median('max') + + + def find_median(self, how): + if how == 'max': + self.curr_median = -1 * self.max_heap[0] + elif how == 'avg': + self.curr_median = (self.min_heap[0] + (-1 * self.max_heap[0])) / 2 + + +x = MedianStream() + +num = input() + +while num != 'q': + if num == 's': + print('Stream of integers - ', x.stream) + else: + num = int(num) + x.add_number(num) + print('Median - ', x.curr_median) + + num = input() From b6bf29a82abbdda4c4cd1a62ec80cf147780f25c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 8 Jun 2021 09:13:03 +0530 Subject: [PATCH 415/455] add heap questions --- .../heap/kth_largest_element_in_stream.py | 61 +++++++++++++++++++ data_structures/heap/sum_elements_range.py | 24 ++++++++ 2 files changed, 85 insertions(+) create mode 100644 data_structures/heap/kth_largest_element_in_stream.py create mode 100644 data_structures/heap/sum_elements_range.py diff --git a/data_structures/heap/kth_largest_element_in_stream.py b/data_structures/heap/kth_largest_element_in_stream.py new file mode 100644 index 00000000..dfc278e4 --- /dev/null +++ b/data_structures/heap/kth_largest_element_in_stream.py @@ -0,0 +1,61 @@ +""" +Use a priority queue - min heap + +as soon as the stream reaches a length of K, start finding the number + +Since we are using a priority queue (min heap), the minimum number will be +at the first index. O(1) time to extract it + +We have to make sure that the length of the stream does not go above K because +we to find the kth largest element which in terms of this heap means the smallest +element. For example lets say we have K = 4. So as soon as the stream reaches a +length of 4, we start to find the 4th largest number. Now as we are maintaining the +length of the array at 4, 4th largest number will mean the smallest number. Using this +we are designing the program. + +If the number entered in the stream is less than the current min, we dont take it as it +wont affect the result. +""" + +from heapq import heapify, heappop, heappush + +class Stream: + + def __init__(self, k): + self.heap = [] + self.stream = [] + self.k = k + self.curr_min = None + heapify(self.heap) + + + def insert(self, x): + self.stream.append(x) + + if len(self.heap) < self.k: # when the heap is empty or size is less than K + heappush(self.heap, x) + self.curr_min = self.heap[0] + else: + if x > self.curr_min: + heappop(self.heap) # remove the curr min element + heappush(self.heap, x) # insert x + self.curr_min = self.heap[0] + + + def find_kth_max(self): + if len(self.heap) == self.k: + print(f'{self.k}th max number - {self.heap[0]}') + +k = 3 +x = Stream(k) + +num = input() + +while num != 'q': + if num == 's': + print(f'Stream - {x.stream} | K - {k}') + else: + num = int(num) + x.insert(num) + x.find_kth_max() + num = input() diff --git a/data_structures/heap/sum_elements_range.py b/data_structures/heap/sum_elements_range.py new file mode 100644 index 00000000..4a3b6645 --- /dev/null +++ b/data_structures/heap/sum_elements_range.py @@ -0,0 +1,24 @@ +""" +Find the sum of elements between k1th and k2th smallest elements +""" + +from heapq import heappush, heapify, heappop + +heap = [20, 8, 22, 4, 12, 10, 14] +k1 = 3 +k2 = 6 + +heapify(heap) + +# extracting min k1 times + +for i in range(k1): + heappop(heap) + +# now do extract min k2 - (k1 + 1) times +s = 0 + +for i in range(k2 - k1 - 1): + s += heappop(heap) + +print(s) From 65e797eb93624988b9d58e74c5af0f11530d4389 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 8 Jun 2021 10:06:42 +0530 Subject: [PATCH 416/455] new question --- ...s_that_can_searched_using_binary_search.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 data_structures/array/number_of_elements_that_can_searched_using_binary_search.py diff --git a/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py b/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py new file mode 100644 index 00000000..b1889522 --- /dev/null +++ b/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py @@ -0,0 +1,52 @@ +""" +In an input of unsorted integer array, find the number of elements +that can be searched using binary search + +The idea is the an element is binary searchable if the elements to the +left of it are smaller than it and the elements to the right of it +are bigger than it + +So maintain two arrays - left_max and right_min such that in i'th index - + +* left_max[i] contains the max element between 0 and i-1 (left to right movement) +* right_min[i] contains the min element between n-1 and i+1 (right to left movement) + +Now for every element in the array, if its index its i, then it is binary searchable +if left_max[i] < arr[i] < right_min[i] +""" +import sys + +def get_searchable_numbers(arr, n): + left_max = [None] * n + right_min = [None] * n + + left_max[0] = float('-inf') + right_min[n-1] = float('inf') + + for i in range(1, n): + left_max[i] = max(left_max[i-1], arr[i-1]) + + for i in range(len(arr) - 2, -1, -1): + right_min[i] = min(right_min[i+1], arr[i+1]) + + res = [] + count = 0 + + for i in range(0, n): + num = arr[i] + left = left_max[i] + right = right_min[i] + + if left < num < right: + res.append(num) + count += 1 + + return count, res + + +if __name__ == '__main__': + #arr = [5,1,4,3,6,8,10,7,9] + arr = [4,1,3,9,8,10,11] + count, res = get_searchable_numbers(arr, len(arr)) + + print(count, res) From 179ef490f8c233445a78b1d2de8a5c9d471b0055 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 9 Jun 2021 20:53:59 +0530 Subject: [PATCH 417/455] add hash --- .../longest_subarray_sum_divisible_by_k.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 data_structures/hash/longest_subarray_sum_divisible_by_k.py diff --git a/data_structures/hash/longest_subarray_sum_divisible_by_k.py b/data_structures/hash/longest_subarray_sum_divisible_by_k.py new file mode 100644 index 00000000..4d691f59 --- /dev/null +++ b/data_structures/hash/longest_subarray_sum_divisible_by_k.py @@ -0,0 +1,55 @@ +""" +Find the longest subarray in an array whose sum is ` +divisible by k + +source - https://www.geeksforgeeks.org/longest-subarray-sum-divisible-k/ + +The idea is that we create a new array mod_arr where we mod_arr[i] = +sum(arr[0]...arr[i]) % k. So basically this array tells us that upto this +point in the input array, if we take sum of numbers till index i, that sum will +be divisible by k + +We will be creating a hash table for this to store the mod results + +Now, lets say x = sum(arr[0]...arr[i]) % k = mod_arr[i]. If + +1. if we find x == 0, increment length by 1 +2. if x not in hash, create it and store (x, index of x) +3. if x in hash: + this tells us that upto this point, where the remainder of sum of numbers + till this point divided by k is x, that remainder we already saw before as it + exists in the hash. So if we ignore the first dont consider the first occurence of x + and remove that from the sum, then this sum will be divisible by k (because subtracting remainder + from a number makes it divisible). + Now find the max length of such case as + if length = max(length, (i - index(x)) +""" + +def find_length(arr, k): + hash_table = {} + mod_arr = [] + s = 0 + length = 0 + start, end = 0, 0 + + for i in range(0, len(arr)): + s += arr[i] + mod_arr.append(s % k) + + for i in range(0, len(mod_arr)): + if mod_arr[i] == 0: + length += 1 + else: + if mod_arr[i] not in hash_table: + hash_table[mod_arr[i]] = i + else: + if length < (i - mod_arr[i]): + length = i - mod_arr[i] + start = mod_arr[i] + end = i - 1 # i-1 because the current number is not to considered as it makes the sum not divisible by k + + return length, arr[start:end+1] + + +arr = [ 2, 7, 6, 1, 4, 5 ] +print(find_length(arr, 3)) From 45a32a8822c421cf58bb75fb6324da0fae69174c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Jun 2021 08:01:04 +0530 Subject: [PATCH 418/455] Add longest consecutuve subsequence --- .../hash/longest_consecutive_subsequence.py | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 data_structures/hash/longest_consecutive_subsequence.py diff --git a/data_structures/hash/longest_consecutive_subsequence.py b/data_structures/hash/longest_consecutive_subsequence.py new file mode 100644 index 00000000..742ef4b7 --- /dev/null +++ b/data_structures/hash/longest_consecutive_subsequence.py @@ -0,0 +1,45 @@ +""" +Given an array of integers, find the length of the longest sub-sequence +such that elements in the subsequence are consecutive integers, the +consecutive numbers can be in any order. + +The idea is to store all the elements in a set first. Then as we are iterating +over the array, we check two things - +1. a number x can be a starting number in a sequence if x-1 is not present in the +set. If this is the case, create a loop and check how many elements from x to x+j are +in the set +2. if x -1 is there in the set, do nothing as this number is not a starting element +and must have been considered in a different sequence +""" + +def find_seq(arr, n): + s = set() + + for num in arr: + s.add(num) + + ans = 0 + elements = [] + + for i in range(n): + temp = [] + + if arr[i] - 1 not in s: + j = arr[i] + + while j in s: + temp.append(j) + j += 1 + + if j - arr[i] > ans: + ans = j - arr[i] + elements = temp.copy() + + return ans, elements + + +arr = [36, 41, 56, 35, 44, 33, 34, 92, 43, 32, 42] + +ans, elements = find_seq(arr, len(arr)) +print('Length - ', ans) +print('Elements - ', elements) From e0cffcfdefa4af9ad4689d3bcd6972842f75ea7d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Jun 2021 09:18:16 +0530 Subject: [PATCH 419/455] moved code around --- .../longest_consecutive_subsequence.py | 0 ...gest_increasing_consecutive_subsequence.py | 26 +++++++++++++++++++ .../longest_subarray_sum_divisible_by_k.py | 0 data_structures/hash/hash_table.py | 0 4 files changed, 26 insertions(+) rename {data_structures/hash => algorithms/dynamic_programming}/longest_consecutive_subsequence.py (100%) create mode 100644 algorithms/dynamic_programming/longest_increasing_consecutive_subsequence.py rename {data_structures/hash => algorithms/dynamic_programming}/longest_subarray_sum_divisible_by_k.py (100%) create mode 100644 data_structures/hash/hash_table.py diff --git a/data_structures/hash/longest_consecutive_subsequence.py b/algorithms/dynamic_programming/longest_consecutive_subsequence.py similarity index 100% rename from data_structures/hash/longest_consecutive_subsequence.py rename to algorithms/dynamic_programming/longest_consecutive_subsequence.py diff --git a/algorithms/dynamic_programming/longest_increasing_consecutive_subsequence.py b/algorithms/dynamic_programming/longest_increasing_consecutive_subsequence.py new file mode 100644 index 00000000..c272820c --- /dev/null +++ b/algorithms/dynamic_programming/longest_increasing_consecutive_subsequence.py @@ -0,0 +1,26 @@ +""" +Find the longest increasing consecutive subsequence in an array + +Idea - + +create a dictionary 'seq' and start iterating over the array + +1. if arr[i] - 1 exists in the array, length = length + seq[arr[i] - 1] +2. else, seq[i] = 1 +""" + +def find_seq(arr): + seq = {} + count = 0 + + for num in arr: + if num - 1 in seq: + seq[num] = seq[num - 1] + 1 + count = max(count, seq[num]) + else: + seq[num] = 1 + + return count + +arr = [6, 7, 8, 3, 4, 5, 9, 10] +print(find_seq(arr)) diff --git a/data_structures/hash/longest_subarray_sum_divisible_by_k.py b/algorithms/dynamic_programming/longest_subarray_sum_divisible_by_k.py similarity index 100% rename from data_structures/hash/longest_subarray_sum_divisible_by_k.py rename to algorithms/dynamic_programming/longest_subarray_sum_divisible_by_k.py diff --git a/data_structures/hash/hash_table.py b/data_structures/hash/hash_table.py new file mode 100644 index 00000000..e69de29b From 246f5272eddfe72317dcbfe4fb031654b59ca2c0 Mon Sep 17 00:00:00 2001 From: pratikscfr Date: Thu, 10 Jun 2021 11:50:34 +0530 Subject: [PATCH 420/455] Added Partition Sum Problem --- .../dynamic_programming/partition_sum.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 algorithms/dynamic_programming/partition_sum.py diff --git a/algorithms/dynamic_programming/partition_sum.py b/algorithms/dynamic_programming/partition_sum.py new file mode 100644 index 00000000..ff8cddcf --- /dev/null +++ b/algorithms/dynamic_programming/partition_sum.py @@ -0,0 +1,46 @@ +# A Dynamic Programming based +# Python3 program to partition problem + +# Returns true if arr[] can be partitioned +# in two subsets of equal sum, otherwise false +def findPartiion(arr, n) : + Sum = 0 + + # Calculate sum of all elements + for i in range(n) : + Sum += arr[i] + if (Sum % 2 != 0) : + return 0 + part = [0] * ((Sum // 2) + 1) + + # Initialize the part array as 0 + for i in range((Sum // 2) + 1) : + part[i] = 0 + + # Fill the partition table in bottom up manner + for i in range(n) : + + # the element to be included + # in the sum cannot be + # greater than the sum + for j in range(Sum // 2, arr[i] - 1, -1) : + + # check if sum - arr[i] + # could be formed + # from a subset + # using elements + # before index i + if (part[j - arr[i]] == 1 or j == arr[i]) : + part[j] = 1 + + return part[Sum // 2] + +# Drive code +arr = [ 1, 3, 3, 2, 3, 2 ] +n = len(arr) + +# Function call +if (findPartiion(arr, n) == 1) : + print("Can be divided into two subsets of equal sum") +else : + print("Can not be divided into two subsets of equal sum") From 2c7103f5170e7139f1ae59023d190d04ec09fa72 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 10 Jun 2021 18:00:57 +0530 Subject: [PATCH 421/455] Add file for hash table --- data_structures/hash/hash_table.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/data_structures/hash/hash_table.py b/data_structures/hash/hash_table.py index e69de29b..c1c05ced 100644 --- a/data_structures/hash/hash_table.py +++ b/data_structures/hash/hash_table.py @@ -0,0 +1,29 @@ +""" +Create a hash table from scratch. Use chaining for hash collision +""" + +class HashTable: + + + def __init__(self): + self.hash_table = + + + def check_collision(self): + pass + + + def add_to_linked_list(self): + pass + + + def insert(self): + pass + + + def delete(self): + pass + + + def get(self): + pass From 800eb1d1c48c9d71164bcbb0875d36ff6d81e516 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 11 Jun 2021 09:28:28 +0530 Subject: [PATCH 422/455] Fix issues and bugs and add comments --- .../graphs/all_paths_between_two_vertices.py | 2 +- data_structures/graphs/bellman_ford.py | 12 ++-- ...n_directed_graph_using_colors_recursive.py | 58 +++++++++++++++++ data_structures/graphs/kosaraju_algorithm.py | 3 +- .../max_edges_that_can_be_added_to_dag.py | 4 +- data_structures/graphs/mother_vertex.py | 10 +-- .../graphs/root_which_gives_min_height.py | 12 ++-- data_structures/graphs/same_path.py | 14 ++-- data_structures/graphs/same_path_recursive.py | 65 +++++++++++++++++++ 9 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 data_structures/graphs/cycle_in_directed_graph_using_colors_recursive.py create mode 100644 data_structures/graphs/same_path_recursive.py diff --git a/data_structures/graphs/all_paths_between_two_vertices.py b/data_structures/graphs/all_paths_between_two_vertices.py index 958a2b82..3632d36e 100644 --- a/data_structures/graphs/all_paths_between_two_vertices.py +++ b/data_structures/graphs/all_paths_between_two_vertices.py @@ -1,5 +1,5 @@ # Use backtracking -# The only with this approach is that if there is a cycle, then +# The only poroblem with this approach is that if there is a cycle, then # it can show infinitely many paths # Reference - https://www.geeksforgeeks.org/count-possible-paths-two-vertices/ diff --git a/data_structures/graphs/bellman_ford.py b/data_structures/graphs/bellman_ford.py index 35c6522d..2901613e 100644 --- a/data_structures/graphs/bellman_ford.py +++ b/data_structures/graphs/bellman_ford.py @@ -55,12 +55,14 @@ def bellman_ford(self, source, destination): parent[source] = source distance[source] = source - for (u, v) in self.edges: - wt = self.edges[(u, v)].weight + for i in range(self.vertices - 1): # Doing V - 1 times to find shortest distance - if distance[v] > distance[u] + wt: - distance[v] = distance[u] + wt - parent[v] = u + for (u, v) in self.edges: + wt = self.edges[(u, v)].weight + + if distance[v] > distance[u] + wt: + distance[v] = distance[u] + wt + parent[v] = u # Now for the Vth iteration, check for the negative cycle diff --git a/data_structures/graphs/cycle_in_directed_graph_using_colors_recursive.py b/data_structures/graphs/cycle_in_directed_graph_using_colors_recursive.py new file mode 100644 index 00000000..c4a687ed --- /dev/null +++ b/data_structures/graphs/cycle_in_directed_graph_using_colors_recursive.py @@ -0,0 +1,58 @@ +""" +Using three colors - white, gray and black +White - vertices that are not processed (inital state of all vertices) +Gray - vertices that are in DFS +Black - fully traversed vertices (i.e its progenies are also done) + +If while traversing any adjacent node is colored Gray, that means cycle exists +""" + +from collections import defaultdict + +class Graph: + + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + + + def dfs(self, vertex, colors): + colors[vertex] = 'Gray' + + for v in self.graph[vertex]: + + if colors[v] == 'Gray': + return True + + elif colors[v] == 'White' and self.dfs(v, colors) == True: + return True + + colors[vertex] = 'Black' + return False + + + def is_cyclic(self): + colors = ['White'] * self.vertices + + for vertex in self.graph.keys(): + if colors[vertex] == 'White': + if self.dfs(vertex, colors) == True: + return True + + return False + + +g = Graph(4) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(1, 2) +g.add_edge(2, 0) +g.add_edge(2, 3) +g.add_edge(3, 3) + +print(g.is_cyclic()) \ No newline at end of file diff --git a/data_structures/graphs/kosaraju_algorithm.py b/data_structures/graphs/kosaraju_algorithm.py index cd446c1a..99277672 100644 --- a/data_structures/graphs/kosaraju_algorithm.py +++ b/data_structures/graphs/kosaraju_algorithm.py @@ -14,6 +14,7 @@ class Graph: + def __init__(self, vertices): self.vertices = vertices self.graph = defaultdict(list) @@ -63,8 +64,6 @@ def kosaraju(self): tgraph = self.create_tranpose() visited = [False] * self.vertices - print('stack - ', stack) - while stack: s = stack.pop() diff --git a/data_structures/graphs/max_edges_that_can_be_added_to_dag.py b/data_structures/graphs/max_edges_that_can_be_added_to_dag.py index acad5380..f4ba0900 100644 --- a/data_structures/graphs/max_edges_that_can_be_added_to_dag.py +++ b/data_structures/graphs/max_edges_that_can_be_added_to_dag.py @@ -11,6 +11,8 @@ 2. If edge is not there left to right, create the edge 3. Count the number of edges added +source - https://www.geeksforgeeks.org/maximum-edges-can-added-dag-remains-dag/ + """ from collections import defaultdict @@ -53,7 +55,7 @@ def max_edges(self): visited = [False] * self.vertices count = 0 - for i in topo: + for i in range(len(topo)): vertex = topo[i] # Mark the connected vertices visited for j in self.graph[vertex]: diff --git a/data_structures/graphs/mother_vertex.py b/data_structures/graphs/mother_vertex.py index 40f8ac10..794c88ee 100644 --- a/data_structures/graphs/mother_vertex.py +++ b/data_structures/graphs/mother_vertex.py @@ -1,9 +1,11 @@ -# A mother vertex is a vertex such that all other vertices -# can be reached by a path from this vertex +""" +A mother vertex is a vertex such that all other vertices +can be reached by a path from this vertex -# Reference - https://www.geeksforgeeks.org/find-a-mother-vertex-in-a-graph/ +Reference - https://www.geeksforgeeks.org/find-a-mother-vertex-in-a-graph/ -# Time complexity - 2 * O(V + E) = O(V + E) +Time complexity - 2 * O(V + E) = O(V + E) +""" from collections import defaultdict diff --git a/data_structures/graphs/root_which_gives_min_height.py b/data_structures/graphs/root_which_gives_min_height.py index 77a738a9..7a079196 100644 --- a/data_structures/graphs/root_which_gives_min_height.py +++ b/data_structures/graphs/root_which_gives_min_height.py @@ -1,4 +1,7 @@ -# Reference - https://www.geeksforgeeks.org/roots-tree-gives-minimum-height/ +""" +Find the node in an undirected graph which gives the minimum height +Reference - https://www.geeksforgeeks.org/roots-tree-gives-minimum-height/ +""" from collections import defaultdict from queue import Queue @@ -22,10 +25,10 @@ def root_min_height(self): q = Queue() for i in range(self.V): - if self.degree[i] == 1: + if self.degree[i] == 1: # To identify leaf nodes q.put(i) - - + + # now move inwards from the leaf node while self.V > 2: for i in range(q.qsize()): t = q.get() @@ -38,7 +41,6 @@ def root_min_height(self): if self.degree[j] == 1: q.put(j) - res = list() while q.qsize() > 0: res.append(q.get()) diff --git a/data_structures/graphs/same_path.py b/data_structures/graphs/same_path.py index 127c1b86..82219691 100644 --- a/data_structures/graphs/same_path.py +++ b/data_structures/graphs/same_path.py @@ -1,8 +1,10 @@ -# Check if two nodes are on the same path in a tree. Use DFS and the concept of intime and outtime. -# Intime - time when a node is visited for the first time -# Outtime - time when a node is visited for the second time after all its children have been visited -# For any pair of node if they are on the same path - -# intime[u] < intime[v] and outtime[u] > outtime[v] +""" +Check if two nodes are on the same path in a tree. Use DFS and the concept of intime and outtime. +Intime - time when a node is visited for the first time +Outtime - time when a node is visited for the second time after all its children have been visited +For any pair of node if they are on the same path - +intime[u] < intime[v] and outtime[u] > outtime[v] +""" from collections import defaultdict @@ -40,8 +42,6 @@ def dfs(self): timer += 1 intime[s] = timer - print(s) - for i in self.graph[s]: if visited[i] == False: stack.append(i) diff --git a/data_structures/graphs/same_path_recursive.py b/data_structures/graphs/same_path_recursive.py new file mode 100644 index 00000000..3b2087aa --- /dev/null +++ b/data_structures/graphs/same_path_recursive.py @@ -0,0 +1,65 @@ +""" +Check if two nodes are on the same path in a undirected graph. Use DFS and the concept of intime and outtime. +Intime - time when a node is visited for the first time +Outtime - time when a node is visited for the second time after all its children have been visited +For any pair of node if they are on the same path - +intime[u] < intime[v] and outtime[u] > outtime[v] +""" + +from collections import defaultdict + +class Graph: + + def __init__(self, vertices): + self.graph = defaultdict(list) + self.vertices = vertices + + + def add_edge(self, u, v): + self.graph[u].append(v) + self.graph[v].append(u) + + + def dfs(self, vertex, intime, outtime, timer, visited): + visited[vertex] = True + timer += 1 + intime[vertex] = timer + + for v in self.graph[vertex]: + if visited[v] == False: + self.dfs(v, intime, outtime, timer, visited) + + timer += 1 + outtime[vertex] = timer + + + def on_same_path(self, u, v): + intime = [-1] * self.vertices + outtime = [-1] * self.vertices + timer = 0 + visited = [False] * self.vertices + + for vertex in self.graph: + if visited[vertex] == False: + self.dfs(vertex, intime, outtime, timer, visited) + + + if (intime[u] < intime[v] and outtime[u] > outtime[v]) \ + or (intime[v] < intime[u] and outtime[v] > outtime[u]): + return True + return False + + +g = Graph(9) +g.add_edge(0, 1) +g.add_edge(0, 2) +g.add_edge(2, 5) +g.add_edge(1, 3) +g.add_edge(1, 4) +g.add_edge(4, 6) +g.add_edge(4, 7) +g.add_edge(4, 8) + +print(g.on_same_path(0, 4)) +print(g.on_same_path(1, 8)) +print(g.on_same_path(1, 5)) \ No newline at end of file From e05e57e703bd0df915f72a6d8d51842950d7a5ae Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 12 Jun 2021 15:59:12 +0530 Subject: [PATCH 423/455] added new question --- ...subarray_with_no_pairsum_divisible_by_k.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 algorithms/dynamic_programming/longest_subarray_with_no_pairsum_divisible_by_k.py diff --git a/algorithms/dynamic_programming/longest_subarray_with_no_pairsum_divisible_by_k.py b/algorithms/dynamic_programming/longest_subarray_with_no_pairsum_divisible_by_k.py new file mode 100644 index 00000000..844b5611 --- /dev/null +++ b/algorithms/dynamic_programming/longest_subarray_with_no_pairsum_divisible_by_k.py @@ -0,0 +1,54 @@ +""" +Find the longest subarray in the input array such that the pairwise sum of +the elements of this subarray is not divisible by K + +The idea is - +How can we tell that two numbers x and y will make a pairsum that will be +divisible by K just by looking at their remainders? There can be two conditions + +1. It will be only possible if the sum of the remainders when x and y are +divided by K is equal to K. As the sum of the remainders cannot exceed K +so if it reaches K then it means that the sum of those numbers will also be +divisible by K +0 < (X%K) + (Y%K) <= K + +2. If arr[i] % k == 0 and there is also an element j such that arr[j] % k == 0 +and 0 exists in the hash (i.e hash[j] = True) +""" + +def find_subarray(arr, k): + """ + True means divisible by k + """ + start, end = 0, 0 + max_start, max_end = 0, 0 + + n = len(arr) + mod_arr = [0] * n + + mod_arr[arr[0] % k] = mod_arr[arr[0] % k] + 1 + + for i in range(1, n): + mod = arr[i] % k + + while (mod_arr[k - mod] != 0) or (mod == 0 and mod_arr[mod] != 0): + mod_arr[arr[start] % k] = mod_arr[arr[start] % k] - 1 + start += 1 + + mod_arr[mod] = mod_arr[mod] + 1 + end += 1 + + if (end - start) > (max_end - max_start): + max_end = end + max_start = start + + print(f'Max size is {max_end - max_start}') + + for i in (max_start, max_end + 1): + print(arr[i], end=" ") + + +arr = [3, 7, 1, 9, 2] +k = 3 +find_subarray(arr, k) + From a5b56bbf76075c6b4fd19becaefe4c978d84e5d9 Mon Sep 17 00:00:00 2001 From: pratikscfr Date: Sun, 13 Jun 2021 21:04:08 +0530 Subject: [PATCH 424/455] changed casing --- .../dynamic_programming/partition_sum.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/algorithms/dynamic_programming/partition_sum.py b/algorithms/dynamic_programming/partition_sum.py index ff8cddcf..c07b79f6 100644 --- a/algorithms/dynamic_programming/partition_sum.py +++ b/algorithms/dynamic_programming/partition_sum.py @@ -3,18 +3,18 @@ # Returns true if arr[] can be partitioned # in two subsets of equal sum, otherwise false -def findPartiion(arr, n) : - Sum = 0 +def find_partiion(arr, n) : + sum = 0 # Calculate sum of all elements for i in range(n) : - Sum += arr[i] - if (Sum % 2 != 0) : + sum += arr[i] + if (sum % 2 != 0) : return 0 - part = [0] * ((Sum // 2) + 1) + part = [0] * ((sum // 2) + 1) # Initialize the part array as 0 - for i in range((Sum // 2) + 1) : + for i in range((sum // 2) + 1) : part[i] = 0 # Fill the partition table in bottom up manner @@ -23,7 +23,7 @@ def findPartiion(arr, n) : # the element to be included # in the sum cannot be # greater than the sum - for j in range(Sum // 2, arr[i] - 1, -1) : + for j in range(sum // 2, arr[i] - 1, -1) : # check if sum - arr[i] # could be formed @@ -33,14 +33,14 @@ def findPartiion(arr, n) : if (part[j - arr[i]] == 1 or j == arr[i]) : part[j] = 1 - return part[Sum // 2] + return part[sum // 2] # Drive code arr = [ 1, 3, 3, 2, 3, 2 ] n = len(arr) # Function call -if (findPartiion(arr, n) == 1) : +if (find_partiion(arr, n) == 1) : print("Can be divided into two subsets of equal sum") else : print("Can not be divided into two subsets of equal sum") From 13621d82012fcbdea4420eea1945ce35e65984fb Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 15 Jun 2021 08:48:22 +0530 Subject: [PATCH 425/455] Cleaned code --- algorithms/greedy/__init__.py | 1 - algorithms/greedy/activity_selection.py | 31 ++++++++++++++++++------- algorithms/greedy/index.md | 1 - 3 files changed, 23 insertions(+), 10 deletions(-) delete mode 100644 algorithms/greedy/__init__.py delete mode 100644 algorithms/greedy/index.md diff --git a/algorithms/greedy/__init__.py b/algorithms/greedy/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/algorithms/greedy/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/algorithms/greedy/activity_selection.py b/algorithms/greedy/activity_selection.py index 8dbd822f..374ad563 100644 --- a/algorithms/greedy/activity_selection.py +++ b/algorithms/greedy/activity_selection.py @@ -4,15 +4,30 @@ #s[]--> An array that contains start time of all activities #f[] --> An array that contains finish time of all activities -def print_max_activities(s, f): - n = len(f) - # the first activity is always selected +def find_activities(arr): + n = len(arr) + selected = [] + + arr.sort(key = lambda x: x[1]) + i = 0 - print(i, end=' ') - # for the rest - for j in range(n): - if s[j] >= f[i]: - print(j, end=' ') + # since it is a greedy algorithm, the first acitivity is always + # selected because it is the most optimal choice at that point + selected.append(arr[i]) + + for j in range(1, n): + start_time_next_activity = arr[j][0] + end_time_prev_activity = arr[i][1] + + if start_time_next_activity >= end_time_prev_activity: + selected.append(arr[j]) i = j + + return selected + + +arr = [[5, 9], [1, 2], [3, 4], [0, 6],[5, 7], [8, 9]] +print(find_activities(arr)) + diff --git a/algorithms/greedy/index.md b/algorithms/greedy/index.md deleted file mode 100644 index d9b79484..00000000 --- a/algorithms/greedy/index.md +++ /dev/null @@ -1 +0,0 @@ -# Index of Greedy \ No newline at end of file From ede7c4dd1babe732e8dac3c5121e2c60b28d28a8 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 15 Jun 2021 10:20:48 +0530 Subject: [PATCH 426/455] Add questions --- algorithms/dynamic_programming/coin_change.py | 39 +++++++++++++------ algorithms/greedy/min_platforms.py | 37 ++++++++++++++++++ 2 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 algorithms/greedy/min_platforms.py diff --git a/algorithms/dynamic_programming/coin_change.py b/algorithms/dynamic_programming/coin_change.py index 96b57648..7b9cbe26 100644 --- a/algorithms/dynamic_programming/coin_change.py +++ b/algorithms/dynamic_programming/coin_change.py @@ -1,16 +1,33 @@ -# Concept is almost same as 01 Knapsack Problem -def min_coin(coins, total): +def min_coins(coins, total): cols = total + 1 - rows = len(coins) - t = [[[0] if col == 0 else float('inf') for col in range(cols)] for i in range(rows)] + min_coins = [float('inf')] * (total + 1) + coins_used = [-1] * (total + 1) - for i in range(rows): - for j in range(1, cols): - if j < coins[i]: - t[i][j] = t[i-1][j] - else: - t[i][j] = min(t[i-1][j], 1 + t[i][j-coins[i]]) + min_coins[0] = 0 # to form 0, we need 0 coins - return t[rows-1][cols-1] + for i in range(0, len(coins)): + for j in range(1, len(min_coins)): + if coins[i] > j: # if the coin value is more than j (curr total), ignore it + continue + + if (1 + min_coins[j - coins[i]]) < min_coins[j]: + min_coins[j] = 1 + min_coins[j - coins[i]] + coins_used[j] = i + + # finding which coins were used + picked_coins = [] + while total > 0: + index_of_coin_used = coins_used[total] + coin = coins[index_of_coin_used] + picked_coins.append(coin) + total -= coin + + print('Min coins needed - ', min_coins[-1]) + print('Coins used - ', picked_coins) + +total = 11 +coins = [9, 6, 5, 1] + +min_coins(coins, total) diff --git a/algorithms/greedy/min_platforms.py b/algorithms/greedy/min_platforms.py new file mode 100644 index 00000000..fd372f0a --- /dev/null +++ b/algorithms/greedy/min_platforms.py @@ -0,0 +1,37 @@ +""" +Given the arrival and departure times of buses at a station +find the min number of platforms that must be there +""" + + +def find_platforms(arrival, departure): + n = len(arrival) + + arrival.sort() + departure.sort() + + i = 1 + j = 0 + + ans = 1 # atleast one platform is required + plat = 1 + + while i < n and j < n: + if arrival[i] <= departure[j]: + plat += 1 + i += 1 + + elif arrival[i] > departure[j]: + plat -= 1 + j += 1 + + ans = max(ans, plat) + + + return ans + + +arr = [900, 940, 950, 1100, 1500, 1800] +dep = [910, 1200, 1120, 1130, 1900, 2000] + +print(find_platforms(arr, dep)) From 3c2597ffa0113acb5877d77baab21b8f0a2c3d3a Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 16 Jun 2021 08:40:40 +0530 Subject: [PATCH 427/455] Added cost of tiling --- algorithms/greedy/cost_of_tiles.py | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 algorithms/greedy/cost_of_tiles.py diff --git a/algorithms/greedy/cost_of_tiles.py b/algorithms/greedy/cost_of_tiles.py new file mode 100644 index 00000000..05fde8da --- /dev/null +++ b/algorithms/greedy/cost_of_tiles.py @@ -0,0 +1,45 @@ +""" +Find the min cost of tiles to cover a floor. +Floor is represented by 2D array where - +* = tile already placed +. = no tile + +tiles available are 1*1 and 1*2 and their costs +are A and B + +Source - https://www.geeksforgeeks.org/minimize-cost-to-cover-floor-using-tiles-of-dimensions-11-and-12/ +""" + +def cost(arr, A, B): + n = len(arr) + m = len(arr[0]) + + ans = 0 + + for i in range(n): + j = 0 + + while j < m: + if arr[i][j] == '*': # tile is already there + j += 1 + continue + + if j == m - 1: # if j is pointing to last tile, you can use only 1*1 tile + ans += A + else: + if arr[i][j+1] == '.': + ans += min(2 * A, B) + j += 1 + else: + ans += A + + j += 1 + + print('Cost of tiling is - ', ans) + +arr = [ [ '.', '.', '*' ], + [ '.', '*', '*' ] ] + +A, B = 2, 10 + +cost(arr, A, B) From 1342be014357df0816f9e3b105ebadeff5d94323 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 20 Jun 2021 15:48:33 +0530 Subject: [PATCH 428/455] Remove graph --- algorithms/graph/bfs.py | 49 ---------------- algorithms/graph/dfs.py | 46 --------------- algorithms/graph/dijkstra.py | 55 ------------------ algorithms/graph/find_all_paths.py | 32 ----------- algorithms/graph/index.md | 4 -- algorithms/graph/mst.py | 83 ---------------------------- algorithms/graph/topological_sort.py | 33 ----------- 7 files changed, 302 deletions(-) delete mode 100644 algorithms/graph/bfs.py delete mode 100644 algorithms/graph/dfs.py delete mode 100644 algorithms/graph/dijkstra.py delete mode 100644 algorithms/graph/find_all_paths.py delete mode 100644 algorithms/graph/index.md delete mode 100644 algorithms/graph/mst.py delete mode 100644 algorithms/graph/topological_sort.py diff --git a/algorithms/graph/bfs.py b/algorithms/graph/bfs.py deleted file mode 100644 index 6c64f75f..00000000 --- a/algorithms/graph/bfs.py +++ /dev/null @@ -1,49 +0,0 @@ -# Python3 Program to print BFS traversal -# from a given source vertex. BFS(int s) -# traverses vertices reachable from s. -from collections import defaultdict - -# This class represents a directed graph -# using adjacency list representation -class Graph: - - # Constructor - def __init__(self): - - # default dictionary to store graph - self.graph = defaultdict(list) - - # function to add an edge to graph - def addEdge(self,u,v): - self.graph[u].append(v) - - # Function to print a BFS of graph - def BFS(self, s): - - # Mark all the vertices as not visited - visited = [False] * (len(self.graph)) - - # Create a queue for BFS - queue = [] - - # Mark the source node as - # visited and enqueue it - queue.append(s) - visited[s] = True - - while queue: - - # Dequeue a vertex from - # queue and print it - s = queue.pop(0) - print (s, end = " ") - - # Get all adjacent vertices of the - # dequeued vertex s. If a adjacent - # has not been visited, then mark it - # visited and enqueue it - for i in self.graph[s]: - if visited[i] == False: - queue.append(i) - visited[i] = True - \ No newline at end of file diff --git a/algorithms/graph/dfs.py b/algorithms/graph/dfs.py deleted file mode 100644 index 4a452536..00000000 --- a/algorithms/graph/dfs.py +++ /dev/null @@ -1,46 +0,0 @@ -# Python program to print DFS traversal for complete graph -from __future__ import print_function -from collections import defaultdict - -# This class represents a directed graph using adjacency -# list representation -class Graph: - - # Constructor - def __init__(self): - - # default dictionary to store graph - self.graph = defaultdict(list) - - # function to add an edge to graph - def addEdge(self,u,v): - self.graph[u].append(v) - - # A function used by DFS - def DFSUtil(self, v, visited): - - # Mark the current node as visited and print it - visited[v]= True - print(v, end=" ") - - # Recur for all the vertices adjacent to - # this vertex - for i in self.graph[v]: - if visited[i] == False: - self.DFSUtil(i, visited) - - - # The function to do DFS traversal. It uses - # recursive DFSUtil() - def DFS(self): - V = len(self.graph) #total vertices - - # Mark all the vertices as not visited - visited =[False]*(V) - - # Call the recursive helper function to print - # DFS traversal starting from all vertices one - # by one - for i in range(V): - if visited[i] == False: - self.DFSUtil(i, visited) diff --git a/algorithms/graph/dijkstra.py b/algorithms/graph/dijkstra.py deleted file mode 100644 index 91dbe362..00000000 --- a/algorithms/graph/dijkstra.py +++ /dev/null @@ -1,55 +0,0 @@ -# i checked your other py files and decided that i would go for default dict -# i used same structure as needed for this repository. -from collections import defaultdict -import sys -r = range -# min weight goes for 0 in this case -max_weight = sys.maxsize - - -class Graph: - # Class initializer - def __init__(self, vertices): - # num of vertices and our starting graph - self.vertices = vertices - - # Values will be [[]] two deminsial array with - # columns for start going to rows. - self.graph = [[0] * self.vertices for _ in r(self.vertices)] - self.visited = [0] * self.vertices # to control visited vertices - # for our distances to minimaze them. - self.distances = [max_weight] * self.vertices - - # Add edge to graph start --> end point with specific weight! - def add_edge(self, start, end, weight): - self.graph[start][end] = weight - - def print_dist(self, dist): - for _ in r(self.vertices): - print("vert ", _, "\tdist ", self.distances[_]) - - def dijkstra(self, end_point): - self.distances[end_point] = 0 - - for vert in r(self.vertices): - - # we need to check for minimum but not visited!! - my_min, min_index = max_weight, 0 - for _ in r(self.vertices): - if not self.visited[_]: - if my_min > self.distances[_]: - my_min = self.distances[_] - min_index = _ - - # check the flag for visited - self.visited[min_index] = 1 - - # # iterate and update if needed - for adj in r(self.vertices): - # check for edge and visited - val = self.graph[min_index][adj] - if not self.visited[adj] and val != 0: - # check if needed update - if self.distances[adj] > self.distances[min_index] + val: - self.distances[adj] = self.distances[min_index] + val - self.print_dist(self.distances) diff --git a/algorithms/graph/find_all_paths.py b/algorithms/graph/find_all_paths.py deleted file mode 100644 index 9152bf2a..00000000 --- a/algorithms/graph/find_all_paths.py +++ /dev/null @@ -1,32 +0,0 @@ -''' -find all the possible paths in a directed cyclic graph from -a start point to a end point. -''' - - - - -def find_all_paths(graph, start, end, path=[]): - path = path + [start] - if start == end: - return [path] - if start not in graph.keys(): - return [] - paths = [] - for node in graph[start]: - if node not in path: #to prevent cyclic rotations - newpaths = find_all_paths(graph, node, end, path) - #print(newpaths) - for newpath in newpaths: - paths.append(newpath) - return paths - - -graph={1:[2,4], - 2:[3], - 4:[5], - 3:[5] - } - -for i in graph.keys(): - print(i,'to 5',find_all_paths(graph,i,5)) diff --git a/algorithms/graph/index.md b/algorithms/graph/index.md deleted file mode 100644 index e5197adc..00000000 --- a/algorithms/graph/index.md +++ /dev/null @@ -1,4 +0,0 @@ -# Index of graph - -* dfs.py -* bfs.py diff --git a/algorithms/graph/mst.py b/algorithms/graph/mst.py deleted file mode 100644 index 930a2211..00000000 --- a/algorithms/graph/mst.py +++ /dev/null @@ -1,83 +0,0 @@ -# i checked your other py files and decided that i would go for default dict -# i used same structure as needed for this repository. -from collections import defaultdict -r = range - - -class Graph: - # Class initializer - def __init__(self, vertices): - # num of vertices and our starting graph - - self.vertices = vertices - # Values will be [start_point, end_point, weight] - self.graph = [] - - # Add edge to graph - def add_edge(self, start, end, weight): - value = [start, end, weight] - self.graph.append(value) - - # Simple search alghoritm - def search(self, parent_ranks, index): - if parent_ranks[index] != index: - return self.search(parent_ranks, parent_ranks[index]) - return index - - def union(self, ranks, parent_ranks, fir, sec): - fir, sec = self.search(parent_ranks, fir), self.search( - parent_ranks, sec) - - # 3 steps. ranks lower, higher, same - - if (ranks[fir] > ranks[sec]): - parent_ranks[sec] = fir - - elif (ranks[fir] < ranks[sec]): - parent_ranks[fir] = sec - - elif (ranks[fir] == ranks[sec]): - parent_ranks[sec] = fir - ranks[fir] += 1 - - # run mst alghoritm main part. - - def run_mst(self, ranks, parent_ranks, answer): - edge, index = 0, 0 - - while True: - if ((self.vertices - 1) <= edge): - break - - # Take value - value = self.graph[index] - - # check cycle - fir, sec = self.search(parent_ranks, value[0]), self.search( - parent_ranks, value[1]) - - if fir != sec: - edge += 1 # increase edge - - # append and union - answer.append(value) - self.union(ranks, parent_ranks, fir, sec) - - index += 1 - - def print_graph(self, answer): - for start, end, weight in answer: - print(f"{start} - {end} --> {weight}") - - # Main function for mst alghoritm - def MST(self): - # sort the graph - self.graph = sorted(self.graph, key=lambda item: item[2]) - - # For this alghoritm we need two array. - ranks = [0] * self.vertices - parent_ranks = [_ for _ in r(self.vertices)] - answer = [] - - self.run_mst(ranks, parent_ranks, answer) - self.print_graph(answer) diff --git a/algorithms/graph/topological_sort.py b/algorithms/graph/topological_sort.py deleted file mode 100644 index ea214d0d..00000000 --- a/algorithms/graph/topological_sort.py +++ /dev/null @@ -1,33 +0,0 @@ -from collections import defaultdict - - -def topological_sort(graph: dict) -> list: - """Provides the topologically sorted nodes of a graph in a list. Takes input as a dictionary, - where the key is a node and the value is a list of the nodes that the key is a source node for.""" - - # Keeps track of the "degree" of a node; once this reaches 0, we push it onto the output. - leading_in = defaultdict(lambda: 0) - - for key, values in graph.items(): - if key not in leading_in.keys(): - leading_in[key] = 0 - for node in values: - leading_in[node] += 1 - - queue = [] - output = [] - - for node, degree in leading_in.items(): - if degree == 0: - queue.append(node) - output.append(node) - - while queue: - node = queue.pop(0) - for destination in graph.get(node, []): - leading_in[destination] -= 1 - if leading_in[destination] == 0: - queue.append(destination) - output.append(destination) - - return output From c68b97f6e3622ecffa2806a4fde99c82f9cd079a Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 23 Jun 2021 08:14:30 +0530 Subject: [PATCH 429/455] Remove index files --- data_structures/circular_linked_list/index.md | 5 ----- data_structures/queue/index.md | 3 --- 2 files changed, 8 deletions(-) delete mode 100644 data_structures/circular_linked_list/index.md delete mode 100644 data_structures/queue/index.md diff --git a/data_structures/circular_linked_list/index.md b/data_structures/circular_linked_list/index.md deleted file mode 100644 index a14e9993..00000000 --- a/data_structures/circular_linked_list/index.md +++ /dev/null @@ -1,5 +0,0 @@ -# Index of circular linked list - -* [Check Circular Linked List](check_circular_linked_list.py) -* [Delete](delete.py) -* [Traversal](traversal.py) diff --git a/data_structures/queue/index.md b/data_structures/queue/index.md deleted file mode 100644 index 8506ea63..00000000 --- a/data_structures/queue/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Index of Queue - -[Queue](queue.py) \ No newline at end of file From 6e222610c8537c476c61566d79ce945c3cda639e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 24 Jun 2021 09:29:58 +0530 Subject: [PATCH 430/455] Remove index from graphs --- data_structures/graphs/index.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 data_structures/graphs/index.md diff --git a/data_structures/graphs/index.md b/data_structures/graphs/index.md deleted file mode 100644 index 7baba1cf..00000000 --- a/data_structures/graphs/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Index of graphs - -* [Adjacency List](adjacency_list.py) From 4dc760fd8d07df815c17b96a89372ef1909e7eea Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 1 Jul 2021 18:47:50 +0530 Subject: [PATCH 431/455] Add docstring --- data_structures/binary_trees/check_perfect_binary_tree.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data_structures/binary_trees/check_perfect_binary_tree.py b/data_structures/binary_trees/check_perfect_binary_tree.py index c3f76281..5768717b 100644 --- a/data_structures/binary_trees/check_perfect_binary_tree.py +++ b/data_structures/binary_trees/check_perfect_binary_tree.py @@ -1,5 +1,7 @@ -# A binary tree is perfect if all the internal nodes have 2 children and -# all the leaves are at the same level +""" +A binary tree is perfect if all the internal nodes have 2 children and +all the leaves are at the same level +""" class Node: From 3322d66c59220c17ecf9f456fc49ae09e30f8133 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 1 Jul 2021 19:11:16 +0530 Subject: [PATCH 432/455] Bug fix --- data_structures/binary_trees/identical_trees.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_trees/identical_trees.py b/data_structures/binary_trees/identical_trees.py index 1d81cef3..bacc0614 100644 --- a/data_structures/binary_trees/identical_trees.py +++ b/data_structures/binary_trees/identical_trees.py @@ -13,6 +13,6 @@ def identical(root1, root2): return True if root1 is not None and root2 is not None: - return root1.val == root2. val and identical(root1.left, root2.left) and identical(root1.right, root2.right) + return root1.val == root2.val and identical(root1.left, root2.left) and identical(root1.right, root2.right) return False From d9da92f29bd23163c069a58f4126d90e5bb2d0d7 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 2 Jul 2021 08:31:44 +0530 Subject: [PATCH 433/455] Remove print statement --- data_structures/graphs/bellman_ford.py | 1 - 1 file changed, 1 deletion(-) diff --git a/data_structures/graphs/bellman_ford.py b/data_structures/graphs/bellman_ford.py index 2901613e..49aabe8a 100644 --- a/data_structures/graphs/bellman_ford.py +++ b/data_structures/graphs/bellman_ford.py @@ -71,7 +71,6 @@ def bellman_ford(self, source, destination): for (u, v) in self.edges: wt = self.edges[(u, v)].weight if distance[v] > distance[u] + wt: - print('h - ', u, v) negative_cycle_present = True break From d414f3498e93cdbb51ab685a0f98b8d4ea9767fc Mon Sep 17 00:00:00 2001 From: "A.H" <73077907+ahcodes@users.noreply.github.com> Date: Fri, 2 Jul 2021 21:15:34 +0530 Subject: [PATCH 434/455] Minor alteration of a sentence. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b5a68823..1286c6c4 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Contains all data structure questions categorised into sub-directories like stac ### Algorithms -This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is like - +This directory contains various types of algorithm questions like Dynamic Programming, Sorting, Greedy, etc. The current structure of this directory is as follows: 1. [Dynamic Programming](algorithms/dynamic_programming) 2. [Graphs](algorithms/graph) From 27b802be136a035acc9ec4f3663d52cebe407e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tadej=20Glin=C5=A1ek?= Date: Mon, 19 Jul 2021 16:51:25 +0200 Subject: [PATCH 435/455] Fixed a bug in permutations_of_word.py --- data_structures/array/permutations_of_word.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/permutations_of_word.py b/data_structures/array/permutations_of_word.py index c0085b54..e5eb8998 100644 --- a/data_structures/array/permutations_of_word.py +++ b/data_structures/array/permutations_of_word.py @@ -6,7 +6,7 @@ def permutation(lst): l = [] for i in range(len(lst)): m = lst[i] - rem_lst = lst[:i] + lst[i+i:] + rem_lst = lst[:i] + lst[i+1:] for p in permutation(rem_lst): l.append([m] + p) return l From 70d2852bd4a2f752b2b9f2b7475fb8b7206450a7 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Wed, 25 Aug 2021 10:10:00 +0530 Subject: [PATCH 436/455] Add comments for Kadane's algorithm --- data_structures/array/kadane_algorithm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/data_structures/array/kadane_algorithm.py b/data_structures/array/kadane_algorithm.py index f2fee2d3..19824af5 100644 --- a/data_structures/array/kadane_algorithm.py +++ b/data_structures/array/kadane_algorithm.py @@ -1,3 +1,12 @@ +""" +Kadane's algorithm is used to find the maximum contiguous sum in an array. +The logic is simple. Take the first element in the sum and then find current max num. +Curr max = max(arr[i], curr_max + arr[i]) - we add this number if it increases the sum, +otherwise we take the number if it is more than the sum + +Then keep track of max of this value +""" + def max_sum(arr): max_so_far = arr[0] curr_max = arr[0] From 9220f3ec5739e70ca3ae38cfa2e5d1d366338a9d Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 26 Aug 2021 16:34:01 +0530 Subject: [PATCH 437/455] add comments --- data_structures/array/number_of_1_in_sorted_array.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data_structures/array/number_of_1_in_sorted_array.py b/data_structures/array/number_of_1_in_sorted_array.py index 79689872..bfcfda50 100644 --- a/data_structures/array/number_of_1_in_sorted_array.py +++ b/data_structures/array/number_of_1_in_sorted_array.py @@ -1,4 +1,8 @@ -# The array is sorted in decreasing order +""" +Count the number of 1s in a sorted array +Instead of linearly searching the array to find the first occurence, +do a binary search to find the first 0 +""" def count(arr): start = 0 From 7bb1eb02fa933d8508594df1a20a0e1794317768 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 26 Aug 2021 16:35:49 +0530 Subject: [PATCH 438/455] Correct the logic --- .../number_of_elements_that_can_searched_using_binary_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py b/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py index b1889522..9137db3c 100644 --- a/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py +++ b/data_structures/array/number_of_elements_that_can_searched_using_binary_search.py @@ -9,7 +9,7 @@ So maintain two arrays - left_max and right_min such that in i'th index - * left_max[i] contains the max element between 0 and i-1 (left to right movement) -* right_min[i] contains the min element between n-1 and i+1 (right to left movement) +* right_min[i] contains the min element between i+1 and n-1 (right to left movement) Now for every element in the array, if its index its i, then it is binary searchable if left_max[i] < arr[i] < right_min[i] From f6beedd2f3cbc116b7b07a05a261faf6846d9e5f Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 27 Aug 2021 12:04:29 +0530 Subject: [PATCH 439/455] adjust formatting --- .../largest_rectangle_area_in_histogram.py | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/data_structures/stack/largest_rectangle_area_in_histogram.py b/data_structures/stack/largest_rectangle_area_in_histogram.py index bee42b5b..86ac073d 100644 --- a/data_structures/stack/largest_rectangle_area_in_histogram.py +++ b/data_structures/stack/largest_rectangle_area_in_histogram.py @@ -1,8 +1,7 @@ ''' Largest rectangle area in a histogram:: -Find the largest rectangular area possible in a given histogram where the largest rectangle can be made of a number of contiguous bars. For simplicity, assume that all bars have same width and the width is 1 unit. - - +Find the largest rectangular area possible in a given histogram where the largest rectangle can be made of a number of contiguous bars. +For simplicity, assume that all bars have same width and the width is 1 unit. ''' def max_area_histogram(histogram): @@ -12,36 +11,30 @@ def max_area_histogram(histogram): max_area = 0 # Initialize max area index = 0 - while index < len(histogram): - + + while index < len(histogram): if (not stack) or (histogram[stack[-1]] <= histogram[index]): stack.append(index) index += 1 - - else: - top_of_stack = stack.pop() - area = (histogram[top_of_stack] * ((index - stack[-1] - 1) if stack else index)) - max_area = max(max_area, area) while stack: - top_of_stack = stack.pop() - area = (histogram[top_of_stack] * ((index - stack[-1] - 1) if stack else index)) max_area = max(max_area, area) - return max_area + + hist = [4, 7, 1, 8, 4, 9, 5] print("Maximum area is", - max_area_histogram(hist)) +max_area_histogram(hist)) From f81517515b5f6911c2fecd7abd7f062141d982a2 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 4 Sep 2021 18:40:47 +0530 Subject: [PATCH 440/455] refactored --- .../stack/largest_rectangle_area_in_histogram.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/data_structures/stack/largest_rectangle_area_in_histogram.py b/data_structures/stack/largest_rectangle_area_in_histogram.py index 86ac073d..6aa55947 100644 --- a/data_structures/stack/largest_rectangle_area_in_histogram.py +++ b/data_structures/stack/largest_rectangle_area_in_histogram.py @@ -19,16 +19,12 @@ def max_area_histogram(histogram): index += 1 else: top_of_stack = stack.pop() - area = (histogram[top_of_stack] * - ((index - stack[-1] - 1) - if stack else index)) + area = (histogram[top_of_stack] * ((index - stack[-1] - 1) if stack else index)) max_area = max(max_area, area) while stack: top_of_stack = stack.pop() - area = (histogram[top_of_stack] * - ((index - stack[-1] - 1) - if stack else index)) + area = (histogram[top_of_stack] * ((index - stack[-1] - 1) if stack else index)) max_area = max(max_area, area) From 2cfccd1a7e8476f8f1eb30ca17d9f83036929756 Mon Sep 17 00:00:00 2001 From: sterben04 Date: Mon, 4 Oct 2021 21:02:55 +0530 Subject: [PATCH 441/455] Added unique-char-check --- data_structures/strings/unique_char_check.py | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 data_structures/strings/unique_char_check.py diff --git a/data_structures/strings/unique_char_check.py b/data_structures/strings/unique_char_check.py new file mode 100644 index 00000000..3af3083c --- /dev/null +++ b/data_structures/strings/unique_char_check.py @@ -0,0 +1,24 @@ +""" +Question +You are given a string S, check if all characters are unique. + +SAMPLE INPUT 1 +abcd +SAMPLE OUTPUT 1 +True + +SAMPLE INPUT 2 +aabc +SAMPLE OUTPUT 2 +False +""" +from collections import Counter +def unique_char_check(S): + character_count = Counter(S) + + if len(character_count) == len(S): + return True + return False + +S = input() +print(unique_char_check(S)) \ No newline at end of file From 565278fc4a63213684c73bef2b99feeccd69f09e Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 15 Oct 2021 12:10:50 +0530 Subject: [PATCH 442/455] Remove init from data structures --- data_structures/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 data_structures/__init__.py diff --git a/data_structures/__init__.py b/data_structures/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/data_structures/__init__.py +++ /dev/null @@ -1 +0,0 @@ - From dde44bc8d0e740a83a3b08f754d3ae86dff9ea3b Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 15 Oct 2021 12:13:44 +0530 Subject: [PATCH 443/455] remove init from algorithms dir --- algorithms/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 algorithms/__init__.py diff --git a/algorithms/__init__.py b/algorithms/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/algorithms/__init__.py +++ /dev/null @@ -1 +0,0 @@ - From f4b55227e97e4a8dacd43e4694099d57995d0424 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 24 Oct 2021 08:48:28 +0530 Subject: [PATCH 444/455] Update License full name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1286c6c4..fc10b02b 100644 --- a/README.md +++ b/README.md @@ -69,4 +69,4 @@ To follow the guidelines, refer to [Contributing.md](CONTRIBUTING.md) ## License -[MIT](LICENSE) +[MIT License](LICENSE) From 99dfc16d82aea6bdfdc1aff4d77cc52664912d56 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sun, 24 Oct 2021 08:50:24 +0530 Subject: [PATCH 445/455] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc10b02b..7c05260f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Python Data Structures and Algorithms -No non-sense solutions to common Data Structure and Algorithm interview questions in Python. +No non-sense solutions to common Data Structure and Algorithm interview questions in Python. Follows a consistent approach throughout problems. ## Objective From 6b7ad5611109697873e5b6000b907f9cd8c01c5c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Thu, 7 Apr 2022 09:52:48 +0530 Subject: [PATCH 446/455] Add WebSockets vs XMPP --- bookmarks/articles.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookmarks/articles.md b/bookmarks/articles.md index 81c00863..ccdd64e2 100644 --- a/bookmarks/articles.md +++ b/bookmarks/articles.md @@ -57,3 +57,5 @@ This is a list of articles that may be useful for algorithms and data structures - https://jwt.io/introduction/ - https://khashtamov.com/en/how-to-become-a-data-engineer/ + +- https://blog.mirrorfly.com/xmpp-vs-websockets-instant-messaging-protocol-comparison/ From 6d7079c5d922d905ca1c0f8bc9a4ca366e7dd1d2 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 4 Oct 2022 06:57:20 +0530 Subject: [PATCH 447/455] Added comments --- data_structures/bst/average_of_levels.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/bst/average_of_levels.py b/data_structures/bst/average_of_levels.py index 5028cf58..273c18d6 100644 --- a/data_structures/bst/average_of_levels.py +++ b/data_structures/bst/average_of_levels.py @@ -1,3 +1,7 @@ +""" +Find the mathematical average of all levels of a BST +""" + import collections class Node(): From b971f2a931ed4850727c1441353fe1294cecd1ac Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 4 Oct 2022 06:58:19 +0530 Subject: [PATCH 448/455] Update check_circular_linked_list.py --- .../circular_linked_list/check_circular_linked_list.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/circular_linked_list/check_circular_linked_list.py b/data_structures/circular_linked_list/check_circular_linked_list.py index 6a72e6e7..4da76507 100644 --- a/data_structures/circular_linked_list/check_circular_linked_list.py +++ b/data_structures/circular_linked_list/check_circular_linked_list.py @@ -1,3 +1,7 @@ +""" +Check if a linked list is a circular linked list +""" + class Node(): def __init__(self, val): From f835c9a71361d5cbba995df926b08ae980cb52c5 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 4 Oct 2022 06:58:41 +0530 Subject: [PATCH 449/455] Delete index.md --- data_structures/doubly_linked_list/index.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 data_structures/doubly_linked_list/index.md diff --git a/data_structures/doubly_linked_list/index.md b/data_structures/doubly_linked_list/index.md deleted file mode 100644 index 0a7d6f6d..00000000 --- a/data_structures/doubly_linked_list/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Index of doubly_linked_list - -* [Doubly Linked List](doubly_linked_list.py) From a21f390fc06b0432bda509b5199335075a593723 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 4 Oct 2022 06:59:30 +0530 Subject: [PATCH 450/455] Rename Adjacency_matrix.py to adjacency_matrix.py --- .../graphs/{Adjacency_matrix.py => adjacency_matrix.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename data_structures/graphs/{Adjacency_matrix.py => adjacency_matrix.py} (100%) diff --git a/data_structures/graphs/Adjacency_matrix.py b/data_structures/graphs/adjacency_matrix.py similarity index 100% rename from data_structures/graphs/Adjacency_matrix.py rename to data_structures/graphs/adjacency_matrix.py From f3305bc4c55f02c69e1d03f50be0472bb30f6d89 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Mon, 1 Apr 2024 19:33:02 +0530 Subject: [PATCH 451/455] Fix infinite array search --- data_structures/array/binary_search_infinite_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/array/binary_search_infinite_array.py b/data_structures/array/binary_search_infinite_array.py index 6eff9207..1db83e07 100644 --- a/data_structures/array/binary_search_infinite_array.py +++ b/data_structures/array/binary_search_infinite_array.py @@ -23,7 +23,7 @@ def search(arr, val): high = 1 while temp < val: - low = 0 + low = high high = 2 * high temp = arr[high] From f17ce1b59f23feb58778491151b095c4c52e6013 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 2 Apr 2024 11:06:54 +0530 Subject: [PATCH 452/455] Some fixes --- data_structures/array/duplicate.py | 12 ++++++------ data_structures/array/find_given_sum_in_array.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/data_structures/array/duplicate.py b/data_structures/array/duplicate.py index 1e4f6291..4838b1aa 100644 --- a/data_structures/array/duplicate.py +++ b/data_structures/array/duplicate.py @@ -17,13 +17,13 @@ def duplicate(arr): if tortoise == hare: break - ptr1 = arr[0] - ptr2 = tortoise - while ptr1 != ptr2: - ptr1 = arr[ptr1] - ptr2 = arr[ptr2] + tortoise = arr[0] + + while tortoise != hare: + tortoise = arr[tortoise] + hare = arr[hare] - return ptr1 + return hare arr = [3,5,1,2,4,5] diff --git a/data_structures/array/find_given_sum_in_array.py b/data_structures/array/find_given_sum_in_array.py index 0aacc5b4..e3adcfcb 100644 --- a/data_structures/array/find_given_sum_in_array.py +++ b/data_structures/array/find_given_sum_in_array.py @@ -24,4 +24,4 @@ def find_sum(arr, s): arr = [15, 2, 4, 8, 9, 5, 10, 23] -print(find_sum(arr, 6)) +print(find_sum(arr, 6)) \ No newline at end of file From ef23195057a1721eea41d39e0bdbd4c52b5640ea Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Tue, 2 Apr 2024 15:49:12 +0530 Subject: [PATCH 453/455] Small fixes --- data_structures/array/peak_element.py | 3 +-- data_structures/array/square_of_sorted_array.py | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/data_structures/array/peak_element.py b/data_structures/array/peak_element.py index 29d8b1f2..ded661b0 100644 --- a/data_structures/array/peak_element.py +++ b/data_structures/array/peak_element.py @@ -6,8 +6,7 @@ def peak(arr, low, high): n = len(arr) while low <= high: - mid = low + (high - low) / 2 - mid = int(mid) + mid = (high - low) // 2 if (mid == 0 or arr[mid-1] <= arr[mid]) and (mid == n-1 or arr[mid+1] <= arr[mid]): return(arr[mid]) diff --git a/data_structures/array/square_of_sorted_array.py b/data_structures/array/square_of_sorted_array.py index 1bebb758..68f196b9 100644 --- a/data_structures/array/square_of_sorted_array.py +++ b/data_structures/array/square_of_sorted_array.py @@ -1,3 +1,8 @@ +""" +Find the square of all the numbers of a sorted array such that after finding the square of the sorted array, the +resultant array containing the squared numbers remains sorted +""" + def square(arr): n = len(arr) j = 0 From 27124b9b77a18a2d3e89c262311286a1d9c2910c Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Fri, 5 Apr 2024 15:51:52 +0530 Subject: [PATCH 454/455] Convert camelCase to snake_case --- data_structures/deque/deque.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/deque/deque.py b/data_structures/deque/deque.py index d578c8e2..85c7dd2c 100644 --- a/data_structures/deque/deque.py +++ b/data_structures/deque/deque.py @@ -47,7 +47,7 @@ def get_last(self): def size(self): return len(self.data) - def isEmpty(self): + def is_empty(self): if len(self.data) == 0: return True return False @@ -59,7 +59,7 @@ def contains(self, elem): return False - def printElems(self): + def print_elements(self): result = "" for i in self.data: From 35d3556a992ceccc5b925afa892fae3ba01a0e81 Mon Sep 17 00:00:00 2001 From: Prabhu Pant Date: Sat, 6 Apr 2024 13:13:16 +0530 Subject: [PATCH 455/455] Add comments --- data_structures/linked_list/delete_last_occurrence.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/linked_list/delete_last_occurrence.py b/data_structures/linked_list/delete_last_occurrence.py index e76f1d9a..80951ab0 100644 --- a/data_structures/linked_list/delete_last_occurrence.py +++ b/data_structures/linked_list/delete_last_occurrence.py @@ -1,3 +1,7 @@ +""" +Delete last occurence of a number in linked list. +""" + class Node(): def __init__(self, val):