From 42a08f1ababdc2ddd1d9ba1335f5e6062700163a Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 24 Jul 2019 08:38:33 -0500 Subject: [PATCH 001/189] Added example for i18n in java --- .../datetime/DurationVsPeriod.java | 18 ++++++++++++-- .../certification/i18n/DataFormatExample.java | 21 ++++++++++++++++ .../i18n/NumberFormatExample.java | 21 ++++++++++++++++ .../examples/certification/i18n/Zoo.java | 12 ++++++++++ .../examples/certification/i18n/ZooOpen.java | 24 +++++++++++++++++++ .../MultiThreadWExecutor.java | 0 src/main/resources/zoo_en.properties | 2 ++ src/main/resources/zoo_fr.properties | 2 ++ 8 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/eprogrammerz/examples/certification/i18n/DataFormatExample.java create mode 100644 src/main/java/com/eprogrammerz/examples/certification/i18n/NumberFormatExample.java create mode 100644 src/main/java/com/eprogrammerz/examples/certification/i18n/Zoo.java create mode 100644 src/main/java/com/eprogrammerz/examples/certification/i18n/ZooOpen.java rename src/main/java/com/eprogrammerz/examples/threading/{ => concurrency}/MultiThreadWExecutor.java (100%) create mode 100644 src/main/resources/zoo_en.properties create mode 100644 src/main/resources/zoo_fr.properties diff --git a/src/main/java/com/eprogrammerz/examples/certification/datetime/DurationVsPeriod.java b/src/main/java/com/eprogrammerz/examples/certification/datetime/DurationVsPeriod.java index 8d4b82c..6341362 100644 --- a/src/main/java/com/eprogrammerz/examples/certification/datetime/DurationVsPeriod.java +++ b/src/main/java/com/eprogrammerz/examples/certification/datetime/DurationVsPeriod.java @@ -1,7 +1,8 @@ package com.eprogrammerz.examples.certification.datetime; -import java.time.Duration; -import java.time.Period; +import java.time.*; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalUnit; public class DurationVsPeriod { public static void main(String[] args) { @@ -13,5 +14,18 @@ public static void main(String[] args) { System.out.println(dp1); System.out.println(dp2); + + System.out.println(ZonedDateTime.now()); + System.out.println(ZonedDateTime.now(ZoneId.of("Australia/Sydney"))); + + System.out.println(Period.of(1,2,3)); // P1Y2M3D + System.out.println(Period.ofWeeks(3)); // P21D + System.out.println(Period.ofMonths(13)); // P13M + + Duration d = Duration.of(20, ChronoUnit.MINUTES); + System.out.println(d); // PT20M + + LocalDate now = LocalDate.now(); +// System.out.println(now.plus(d)); // Unsupported unit: Seconds } } diff --git a/src/main/java/com/eprogrammerz/examples/certification/i18n/DataFormatExample.java b/src/main/java/com/eprogrammerz/examples/certification/i18n/DataFormatExample.java new file mode 100644 index 0000000..1d00144 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/certification/i18n/DataFormatExample.java @@ -0,0 +1,21 @@ +package com.eprogrammerz.examples.certification.i18n; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.util.Date; + +public class DataFormatExample { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2019, 7, 8); + LocalTime time = LocalTime.of(14,59); + LocalDateTime dateTime = LocalDateTime.of(date, time); + + DateTimeFormatter shortF = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT); + DateTimeFormatter mediumF = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); + System.out.println(shortF.format(dateTime)); // 7/8/19 2:59 PM + System.out.println(mediumF.format(dateTime)); // Jul 8, 2019 2:59:00 PM + } +} diff --git a/src/main/java/com/eprogrammerz/examples/certification/i18n/NumberFormatExample.java b/src/main/java/com/eprogrammerz/examples/certification/i18n/NumberFormatExample.java new file mode 100644 index 0000000..fd5d0c8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/certification/i18n/NumberFormatExample.java @@ -0,0 +1,21 @@ +package com.eprogrammerz.examples.certification.i18n; + +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +public class NumberFormatExample { + public static void main(String[] args) throws ParseException { + NumberFormat nf = NumberFormat.getCurrencyInstance(); + int price = 40; + System.out.println(nf.format(price)); // $40.00 + + nf = NumberFormat.getCurrencyInstance(new Locale("np")); + System.out.println(nf.format(price)); // suppose to print in rupees + + String amt = "$92,807.99"; + NumberFormat cf = NumberFormat.getCurrencyInstance(); + double value = (double) cf.parse(amt); + System.out.println(value); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/certification/i18n/Zoo.java b/src/main/java/com/eprogrammerz/examples/certification/i18n/Zoo.java new file mode 100644 index 0000000..5f4938c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/certification/i18n/Zoo.java @@ -0,0 +1,12 @@ +package com.eprogrammerz.examples.certification.i18n; + +import java.util.ListResourceBundle; + +public class Zoo extends ListResourceBundle { + @Override + protected Object[][] getContents() { + return new Object[][] { + {"default", "Default"} + }; + } +} diff --git a/src/main/java/com/eprogrammerz/examples/certification/i18n/ZooOpen.java b/src/main/java/com/eprogrammerz/examples/certification/i18n/ZooOpen.java new file mode 100644 index 0000000..6849d4c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/certification/i18n/ZooOpen.java @@ -0,0 +1,24 @@ +package com.eprogrammerz.examples.certification.i18n; + +import java.util.Locale; +import java.util.ResourceBundle; + +public class ZooOpen { + public static void main(String[] args) { + Locale us = new Locale("en", "US"); + Locale france = new Locale("fr", "FR"); + + printProps(us); + + System.out.println(); + + printProps(france); + } + + private static void printProps(Locale locale) { + ResourceBundle rb = ResourceBundle.getBundle("zoo", locale); + System.out.println(rb.getString("hello")); + System.out.println(rb.getString("open")); +// System.out.println(rb.getString("default")); // this fails since there java Zoo.java can't be loaded with zoo! it has to be package.ClassName + } +} diff --git a/src/main/java/com/eprogrammerz/examples/threading/MultiThreadWExecutor.java b/src/main/java/com/eprogrammerz/examples/threading/concurrency/MultiThreadWExecutor.java similarity index 100% rename from src/main/java/com/eprogrammerz/examples/threading/MultiThreadWExecutor.java rename to src/main/java/com/eprogrammerz/examples/threading/concurrency/MultiThreadWExecutor.java diff --git a/src/main/resources/zoo_en.properties b/src/main/resources/zoo_en.properties new file mode 100644 index 0000000..0db7b0b --- /dev/null +++ b/src/main/resources/zoo_en.properties @@ -0,0 +1,2 @@ +hello=Hello +open=The Zoo is Open \ No newline at end of file diff --git a/src/main/resources/zoo_fr.properties b/src/main/resources/zoo_fr.properties new file mode 100644 index 0000000..cd347a5 --- /dev/null +++ b/src/main/resources/zoo_fr.properties @@ -0,0 +1,2 @@ +hello=Bonjour +open=Le zoo est ouvert \ No newline at end of file From 8029864fef94ca3122e5ad59317d515aff6de123 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 24 Jul 2019 08:39:30 -0500 Subject: [PATCH 002/189] example for concurrency in java --- .../concurrency/FinishUpAllThread.java | 62 +++++++++++++++++++ .../concurrency/MultiThreadWExecutor.java | 2 +- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/eprogrammerz/examples/threading/concurrency/FinishUpAllThread.java diff --git a/src/main/java/com/eprogrammerz/examples/threading/concurrency/FinishUpAllThread.java b/src/main/java/com/eprogrammerz/examples/threading/concurrency/FinishUpAllThread.java new file mode 100644 index 0000000..118a866 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/threading/concurrency/FinishUpAllThread.java @@ -0,0 +1,62 @@ +package com.eprogrammerz.examples.threading.concurrency; + +import java.util.concurrent.*; + +public class FinishUpAllThread { + public static void testExecutorService() throws InterruptedException { + ExecutorService es = Executors.newFixedThreadPool(10); + + for (int i = 0; i < 5; i++) { + es.execute(new Thread(() -> { + try { + Thread.sleep(15000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Thread -> " + Thread.currentThread().getName()); + })); + } + + es.awaitTermination(10, TimeUnit.SECONDS); + + System.out.println("Done executing all threads . . ."); + if (!es.isShutdown()) { + System.out.println("Shutting down executor . . ."); + es.shutdown(); // graceful shutdown of the service + } + } + + public static void main(String[] args) throws InterruptedException { +// testExecutorService(); + testWithJoin(); + } + + public static void testWithJoin() throws InterruptedException { + Runnable r = () -> { + try { + Thread.sleep(15000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Thread -> " + Thread.currentThread().getName()); + }; + + Thread t1 = new Thread(r); + Thread t2 = new Thread(r); + Thread t3 = new Thread(r); + Thread t4 = new Thread(r); + + t1.start(); + t2.start(); + t3.start(); + t4.start(); + + // join all threads to the main thread i.e. before joining t2 to main thread, t1 should + // have been joined + t1.join(); + t2.join(); + t3.join(); + t4.join(); + System.out.println("Done with all threads!"); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/threading/concurrency/MultiThreadWExecutor.java b/src/main/java/com/eprogrammerz/examples/threading/concurrency/MultiThreadWExecutor.java index 1398f74..f240e54 100644 --- a/src/main/java/com/eprogrammerz/examples/threading/concurrency/MultiThreadWExecutor.java +++ b/src/main/java/com/eprogrammerz/examples/threading/concurrency/MultiThreadWExecutor.java @@ -1,4 +1,4 @@ -package com.eprogrammerz.examples.threading; +package com.eprogrammerz.examples.threading.concurrency; import org.junit.Test; From a14db0270cf547ae841eaefc1e9a968f1aebf6e4 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 31 Jul 2019 14:57:03 -0500 Subject: [PATCH 003/189] Added example for self referential problem --- .../ds/custom/trie/ProductCategoryTest.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java new file mode 100644 index 0000000..c7994d5 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java @@ -0,0 +1,112 @@ +package com.eprogrammerz.examples.ds.custom.trie; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +class ProductCategory { + List findByCategory(List products, String categoryName) { + if (categoryProducts == null) { + createCategoryProductsMap(products); + } + return categoryProducts.get(categoryName); + } + + private void createCategoryProductsMap(List products) { + this.categoryProducts = new HashMap<>(); + + for (Product product: products) { + Category category = product.getCategory(); + + List existing = this.categoryProducts.get(category.getName()); + + if (existing == null) { + List newList = new ArrayList<>(); + newList.add(product); + + this.categoryProducts.put(category.getName(), newList); + } else { + existing.add(product); + } + } + + } + + private Map> categoryProducts = null; +} + +public class ProductCategoryTest { + + + /** + * Category + * | + * ------------------------------------------ + * | | | + * Sports Electronics Apparel + * | | | + * ---------------------- --------------- ----------------------------- + * | | | | | | | + * Jersey Footware TV Phone Shirts Pants Atheltic + * | + * ------------------------ + * | | + * Yoga Outdoor + */ + @Test + public void testProductsByCategory() { + Category jersey = new Category(10, "Jersey", null); + Category footware = new Category(11, "Footware", null); + Category c1 = new Category(1, "Sports", Arrays.asList(jersey, footware)); + + Category tv = new Category(12, "TV", null); + Category phone = new Category(13, "Phone", null); + Category c3 = new Category(3, "Electronics", Arrays.asList(tv, phone)); + + + Category c2 = new Category(2, "Apparel", null); + + Product p1 = new Product(1, "Nike Air Max 97", c1); + Product p2 = new Product(2, "Nike T-Shirt", c2); + Product p3 = new Product(3, "Jordon 97", c1); + Product p4 = new Product(4, "Iphone 97", c3); + Product p5 = new Product(5, "Samsung Washer and Dryer", c3); + Product pJersey = new Product(6, "Barcelan", jersey); + Product pFootware = new Product(7, "Nike Air", footware); + + List products = Arrays.asList(p1, p2, p3, p4, p5, pJersey, pFootware); + + + ProductCategory pc = new ProductCategory(); + + List apparels = pc.findByCategory(products, c2.getName()); + System.out.println(apparels); + + List sports = pc.findByCategory(products, c1.getName()); + System.out.println(sports); + + assertEquals(4, sports.size()); + } +} + + +@Data +@AllArgsConstructor +class Product { + private int id; + private String name; + private Category category; +} + +@Data +@AllArgsConstructor +class Category { + private int id; + private String name; + + List subCategories; +} \ No newline at end of file From 8753c6252aece8248477a8a63b9e5d82cf287dbf Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 2 Sep 2019 18:58:36 -0500 Subject: [PATCH 004/189] Update solution to rotate matrix in place --- .../algorithm/general/MatrixRotation.java | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/MatrixRotation.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/MatrixRotation.java index b91ffcd..1b2379f 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/general/MatrixRotation.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/MatrixRotation.java @@ -1,20 +1,60 @@ package com.eprogrammerz.examples.algorithm.general; +import org.junit.Test; + /** * Created by 542596 on 3/5/2017. */ public class MatrixRotation { - public static void main(String[] args) { + + + /** + * You are given an n x n 2D matrix representing an image. + * + * Rotate the image by 90 degrees (clockwise). + * + * @param matrix + */ + public void rotateMatrix(int[][] matrix) { + int n = matrix.length; + for (int r = 0; r < n / 2; r++) { + for (int c = r; c < n - 1 - r; c++) { + int temp = matrix[r][c]; + // left to top + matrix[r][c] = matrix[n - 1 - c][r]; + // bottom to left + matrix[n - 1 - c][r] = matrix[n - 1 -r][n - 1 - c]; + // right to bottom + matrix[n - 1 - r][n - 1 - c] = matrix[c][n - 1 - r]; + // top to right + matrix[c][n - 1 - r] = temp; + } + } + } + + @Test + public void testRotateMatrix() { int[][] twoD = new int[][]{ /*{1,2}, {3,4}*/ - {1,2,3}, + /*{1,2,3}, {4,5,6}, - {7,8,9} + {7,8,9}*/ + {1,2,3,4}, + {6,7,8,9}, + {10,11,12,13}, + {14,15,16,17} }; - flipMatrix(twoD); - for(int i = 0; i< twoD.length; i++) { - for(int j = 0; j Date: Tue, 17 Sep 2019 19:48:54 -0500 Subject: [PATCH 005/189] Added example for linkedlist operation --- .../custom/linkedList/KReverseLinkedList.java | 113 ++++++++++++++++++ .../ds/custom/linkedList/ListNode.java | 15 +++ .../ds/custom/linkedList/ListUtil.java | 17 +++ .../linkedList/RemoveNthNodeFromLast.java | 69 +++++++++++ .../ds/custom/linkedList/ReverseListII.java | 111 +++++++++++++++++ .../ds/custom/linkedList/RotateList.java | 73 +++++++++++ .../ds/custom/linkedList/SwapPair.java | 51 ++++++++ .../ds/custom/trie/ProductCategoryTest.java | 75 +++++++++--- 8 files changed, 507 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/KReverseLinkedList.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListNode.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListUtil.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RemoveNthNodeFromLast.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RotateList.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/KReverseLinkedList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/KReverseLinkedList.java new file mode 100644 index 0000000..421144e --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/KReverseLinkedList.java @@ -0,0 +1,113 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * Given a singly linked list and an integer K, reverses the nodes of the + * + * list K at a time and returns modified linked list. + * + * NOTE : The length of the list is divisible by K + * Example : + * + * Given linked list 1 -> 2 -> 3 -> 4 -> 5 -> 6 and K=2, + * + * You should return 2 -> 1 -> 4 -> 3 -> 6 -> 5 + * + * Try to solve the problem using constant extra space. + */ +public class KReverseLinkedList { + public ListNode reverseList(ListNode head, int k) { + + ListNode current = head; + ListNode previous = null; + ListNode next = null; + + if (isGroup(current, k)) { + int count = k; + while (count-- > 0 && current != null) { + next = current.next; + current.next = previous; + previous = current; + current = next; + } + } else { + return head; + } + + if (current != null) { + if (isGroup(current, k)) { + head.next = reverseList(current, k); + } else { + head.next = next; + } + } + return previous == null ? current: previous; + } + + private boolean isGroup(ListNode node, int k) { + int count = 0; + while (node != null) { + count++; + node = node.next; + if (count == k) return true; + } + return false; + } + + @Test + public void testReverse1() { + // 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 ->8 -> 9 + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + + ListNode res = reverseList(n1, 2); // 2 -> 1 -> 4 -> 3 -> 6 -> 5 -> 8 -> 7 -> 9 + assertEquals("2 -> 1 -> 4 -> 3 -> 6 -> 5 -> 8 -> 7 -> 9", printList(res)); + } + + @Test + public void testReverse2() { + // 1 -> 2 -> 3 -> 4 -> 5 + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + + ListNode res = reverseList(n1, 3); // 3 -> 2 -> 1 -> 4 -> 5 + assertEquals("3 -> 2 -> 1 -> 4 -> 5", printList(res)); + } + + @Test + public void testReverse3() { + // 1 -> 2 + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + n1.next = n2; + + ListNode res = reverseList(n1, 3); // 1 -> 2 + assertEquals("1 -> 2", printList(res)); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListNode.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListNode.java new file mode 100644 index 0000000..7882ec8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListNode.java @@ -0,0 +1,15 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +public class ListNode { + int val; + ListNode next; + + ListNode(int val) { + this.val = val; + } + + @Override + public String toString() { + return "(" + val + ")"; + } +} \ No newline at end of file diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListUtil.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListUtil.java new file mode 100644 index 0000000..ed15899 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ListUtil.java @@ -0,0 +1,17 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +public class ListUtil { + + public static String printList(ListNode res) { + StringBuilder sb = new StringBuilder(); + if (res == null) return sb.toString(); + + while (res.next != null) { + sb.append(res.val); + sb.append(" -> "); + res = res.next; + } + sb.append(res.val); + return sb.toString(); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RemoveNthNodeFromLast.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RemoveNthNodeFromLast.java new file mode 100644 index 0000000..73ebd65 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RemoveNthNodeFromLast.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +public class RemoveNthNodeFromLast { + public ListNode removeNthFromEnd(ListNode head, int n) { + ListNode node = head; + + ListNode fast = head; + for (int i = 0; i < n; i++) { + fast = fast.next; + } + + while (fast != null && fast.next != null) { + node = node.next; + fast = fast.next; + } + + if (fast == null) { + head = head.next; + } else { + + node.next = node.next != null ? node.next.next : null; + } + + return head; + } + + @Test + public void testRemoveNthFromEnd1() { +// 1 -> 2 -> 3 -> 4 -> 5 -> 6 + ListNode head = new ListNode(1); + ListNode node1 = new ListNode(2); + ListNode node2 = new ListNode(3); + ListNode node3 = new ListNode(4); + ListNode node4 = new ListNode(5); + head.next = node1; + node1.next = node2; + node2.next = node3; + node3.next = node4; + + ListNode res = removeNthFromEnd(head, 2); + assertEquals("1 -> 2 -> 3 -> 5", printList(res)); + } + + + @Test + public void testRemoveNthFromEnd2() { + // 1 -> 2 + ListNode head = new ListNode(1); + ListNode node1 = new ListNode(2); + head.next = node1; + + ListNode res = removeNthFromEnd(head, 2); + assertEquals("2", printList(res)); + } + + @Test + public void testRemoveNthFromEnd3() { + // 1 -> 2 + ListNode head = new ListNode(1); + + ListNode res = removeNthFromEnd(head, 1); + assertEquals("", printList(res)); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java new file mode 100644 index 0000000..26e1fc8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java @@ -0,0 +1,111 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import java.util.List; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * Reverse a linked list from position m to n. Do it in-place and in one-pass. + * + * For example: + * Given 1->2->3->4->5->NULL, m = 2 and n = 4, + * + * return 1->4->3->2->5->NULL. + */ +public class ReverseListII { + public ListNode reverseBetween(ListNode head, int m, int n) { + if (head.next == null) return head; + + /** + * Get first half f1 (0 -> m - 1) + * Traverse and create reversed list (m -> n) mid + * f1.next = mid + */ + + ListNode tracker = head; + ListNode f1Tail = head; + + ListNode resultHead = tracker; + for (int i = 1; i < m; i++) { + f1Tail = tracker; + tracker = tracker.next; + } + + + ListNode next = tracker.next; + + ListNode midHead = tracker; + midHead.next = null; + + ListNode midTail = tracker; + for (int i = m; i < n; i++) { + ListNode temp = midHead; + ListNode nextTemp = next.next; + midHead = next; + midHead.next = temp; + next = nextTemp; + } + + midTail.next = next; + f1Tail.next = midHead; + + return resultHead; + } + + public ListNode reverse(ListNode node) { + if (node == null) return null; + + ListNode current = node; + + ListNode next = current.next; + + current.next = null; + + while (next != null) { + ListNode temp = next.next; + next.next = current; + current = next; + next = temp; + } + return current; + } + + @Test + public void testReverse() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + + ListNode res = reverseBetween(n1, 2, 4); + assertEquals("1 -> 4 -> 3 -> 2 -> 5 -> 6 -> 7 -> 8 -> 9", printList(res)); + } + + @Test + public void testReverse2() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + n1.next = n2; + n2.next = n3; + + ListNode res = reverseBetween(n1, 2 ,3); + assertEquals("1 -> 3 -> 2", printList(res)); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RotateList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RotateList.java new file mode 100644 index 0000000..7f2db62 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/RotateList.java @@ -0,0 +1,73 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class RotateList { + public ListNode rotateRight(ListNode A, int B) { + // find size so that we can find the node for the head in resulting list + int size = getSize(A); + + ListNode node = A; + ListNode prev = node; + ListNode firstHalf = prev; + + for (int i = 0; i < size; i++) { + prev = node; // prev = 3 + node = node.next; // node = 4 + int newIdx = (i + B + 1) % size; + if (newIdx == 0) { + break; + } + } + prev.next = null; + ListNode half = node; + ListNode head = node; + + if (half != null) { + while (half.next != null) { + half = half.next; + } + half.next = firstHalf; + } else { + head = firstHalf; + } + + return head; + } + + private int getSize(ListNode node) { + ListNode n = node; + int size = 0; + while (n != null) { + size++; + n = n.next; + } + return size; + } + + @Test + public void testRotateRight() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + + ListNode res = rotateRight(n1, 3); // (7)(8)(9)(1)(2)(3)(4)(5)(6) + assertEquals(7, res.val); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java new file mode 100644 index 0000000..2926af6 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java @@ -0,0 +1,51 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +public class SwapPair { + public ListNode swapPairs(ListNode A) { + // temp = current.next + // prev.next = current.next + // current.next = prev + // current = temp + + ListNode prev = null; + ListNode head = A.next; + if (head == null) return A; + + ListNode current = A; + while (current != null && current.next != null) { + + ListNode temp = current.next; + current.next = current.next.next; + temp.next = current; + if (prev != null) prev.next = temp; + prev = current; + current = current.next; + } + return head; + } + + @Test + public void testSwapPair() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + ListNode node = swapPairs(n1); + System.out.println(node); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java index c7994d5..0d6ceeb 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java @@ -8,16 +8,34 @@ import static org.junit.Assert.assertEquals; -class ProductCategory { +class ProductService { List findByCategory(List products, String categoryName) { if (categoryProducts == null) { createCategoryProductsMap(products); } - return categoryProducts.get(categoryName); + List cProducts = categoryProducts.get(categoryName); + + List result = new ArrayList<>(); + + if (cProducts != null && cProducts.size() > 0) { + result.addAll(cProducts); + } + Category category = categoryMap.get(categoryName); + if (category != null) { + List subCategories = category.getSubCategories(); + if (subCategories != null) { + for (Category c : subCategories) { + List subProducts = findByCategory(products, c.getName()); + result.addAll(subProducts); + } + } + } + return result; } private void createCategoryProductsMap(List products) { this.categoryProducts = new HashMap<>(); + this.categoryMap = new HashMap<>(); for (Product product: products) { Category category = product.getCategory(); @@ -32,11 +50,27 @@ private void createCategoryProductsMap(List products) { } else { existing.add(product); } + populateCategoryMap(category); } } + private void populateCategoryMap(Category category) { + if (!categoryMap.containsKey(category.getName())) { + categoryMap.put(category.getName(), category); + + List subCategories = category.getSubCategories(); + + if (subCategories != null) { + for (Category subCategory: subCategories) { + populateCategoryMap(subCategory); + } + } + } + } + private Map> categoryProducts = null; + private Map categoryMap = null; } public class ProductCategoryTest { @@ -51,7 +85,7 @@ public class ProductCategoryTest { * | | | * ---------------------- --------------- ----------------------------- * | | | | | | | - * Jersey Footware TV Phone Shirts Pants Atheltic + * Jersey Footware TV Phone Shirts Pants Athletic * | * ------------------------ * | | @@ -61,35 +95,42 @@ public class ProductCategoryTest { public void testProductsByCategory() { Category jersey = new Category(10, "Jersey", null); Category footware = new Category(11, "Footware", null); - Category c1 = new Category(1, "Sports", Arrays.asList(jersey, footware)); + Category sports = new Category(1, "Sports", Arrays.asList(jersey, footware)); Category tv = new Category(12, "TV", null); Category phone = new Category(13, "Phone", null); - Category c3 = new Category(3, "Electronics", Arrays.asList(tv, phone)); + Category electronics = new Category(3, "Electronics", Arrays.asList(tv, phone)); - Category c2 = new Category(2, "Apparel", null); + Category shirts = new Category(14, "Shirts", null); + Category pants = new Category(15, "Panys", null); + Category yoga = new Category(20, "Yoga", null); + Category outdoor = new Category(21, "Outdoor", null); + Category athletic = new Category(16, "Athletic", Arrays.asList(yoga, outdoor)); + Category apparel = new Category(2, "Apparel", Arrays.asList(shirts, pants, athletic)); - Product p1 = new Product(1, "Nike Air Max 97", c1); - Product p2 = new Product(2, "Nike T-Shirt", c2); - Product p3 = new Product(3, "Jordon 97", c1); - Product p4 = new Product(4, "Iphone 97", c3); - Product p5 = new Product(5, "Samsung Washer and Dryer", c3); + Product p1 = new Product(1, "Nike Air Max 97", sports); + Product p2 = new Product(2, "Nike T-Shirt", apparel); + Product p3 = new Product(3, "Jordon 97", sports); + Product p4 = new Product(4, "Iphone 97", electronics); + Product p5 = new Product(5, "Samsung Washer and Dryer", electronics); Product pJersey = new Product(6, "Barcelan", jersey); Product pFootware = new Product(7, "Nike Air", footware); + Product luluman = new Product(8, "Yoga Pants", yoga); - List products = Arrays.asList(p1, p2, p3, p4, p5, pJersey, pFootware); + List products = Arrays.asList(p1, p2, p3, p4, p5, pJersey, pFootware, luluman); - ProductCategory pc = new ProductCategory(); + ProductService pc = new ProductService(); - List apparels = pc.findByCategory(products, c2.getName()); + List apparels = pc.findByCategory(products, apparel.getName()); System.out.println(apparels); + assertEquals(2, apparels.size()); - List sports = pc.findByCategory(products, c1.getName()); - System.out.println(sports); + List sportsProducts = pc.findByCategory(products, sports.getName()); + System.out.println(sportsProducts); - assertEquals(4, sports.size()); + assertEquals(4, sportsProducts.size()); } } From 03f95abf4beaf328688e2d44273d9da9ec9f3195 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 17 Sep 2019 19:52:49 -0500 Subject: [PATCH 006/189] Added example for priority queue and deque --- .../general/StudentPriorityQueue.java | 98 +++++++++++++++++++ .../general/UniqueElementInSubArr.java | 70 +++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/StudentPriorityQueue.java create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/UniqueElementInSubArr.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/StudentPriorityQueue.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/StudentPriorityQueue.java new file mode 100644 index 0000000..47cdc52 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/StudentPriorityQueue.java @@ -0,0 +1,98 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +/** + * Find order in which student can be served! + * Criterion: + * 1. Highest GPA first + * 2. If same gpa, alphabetic order + * 3. If same name, id ascending + */ + +public class StudentPriorityQueue { + @Test + public void testGetStudents() { + Priorities priorities = new Priorities(); + + List events = Arrays.asList( + "ENTER John 3.75 50", + "ENTER Mark 3.8 24", + "ENTER Shafaet 3.7 35", + "SERVED", + "SERVED", + "ENTER Samiha 3.85 36", + "SERVED", + "ENTER Ashley 3.9 42", + "ENTER Maria 3.6 46", + "ENTER Anik 3.95 49", + "ENTER Dan 3.95 50", + "SERVED"); + List toBeServed = Arrays.asList("Dan", "Ashley", "Shafaet", "Maria"); + assertEquals(toBeServed, priorities.getStudents(events).stream().map(Student::getName).collect(Collectors.toList())); + } +} + +class Student { + private int id; + private String name; + private double cgpa; + + Student(int id, String name, double cgpa) { + this.id = id; + this.name = name; + this.cgpa = cgpa; + } + + public int getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public double getCGPA() { + return this.cgpa; + } +} + +class Priorities { + List getStudents(List events) { + Comparator c = (s1, s2) -> { + double diff = s2.getCGPA() - s1.getCGPA(); + if (diff > 0) { + return 1; + } else if (diff < 0) { + return -1; + } + int nameComp = s1.getName().compareTo(s2.getName()); + if (nameComp == 0) return s1.getId() - s2.getId(); + + return nameComp; + }; + Queue queue = new PriorityQueue<>(c); + for (String event : events) { + if (event.startsWith("ENTER")) { + String[] parts = event.split(" "); + String name = parts[1]; + double cgpa = Double.valueOf(parts[2]); + int id = Integer.valueOf(parts[3]); + queue.add(new Student(id, name, cgpa)); + } else { + queue.poll(); + } + } + + List result = new ArrayList<>(); + while (!queue.isEmpty()){ + result.add(queue.poll()); + } + return result; + } +} diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/UniqueElementInSubArr.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/UniqueElementInSubArr.java new file mode 100644 index 0000000..59ddb4f --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/UniqueElementInSubArr.java @@ -0,0 +1,70 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * you are given N integers. You need to find the maximum number of unique integers among all the possible contiguous subarrays of size M. + * + * Sample Input + * + * 6 3 + * 5 3 5 2 3 2 + * Sample Output + * + * 3 + * + */ +public class UniqueElementInSubArr { + + public int maxElementSubArr(int[] arr, int m) { + // deque so that element can be removed from first and added at last + Deque deque = new ArrayDeque<>(); + + // map to track elem count + Map map = new HashMap<>(); + + int res = 0; + + for (int elem : arr) { + deque.addLast(elem); + + if (map.containsKey(elem)) { + map.put(elem, map.get(elem) + 1); + } else { + map.put(elem, 1); + } + + // if we get to the window size, then need to adjust list and map + if (deque.size() == m) { + if (map.size() > res) { + res = map.size(); + } + int head = deque.removeFirst(); + int newCount = map.get(head) - 1; + if (newCount == 0) { + map.remove(head); + } else { + map.put(head, newCount); + } + } + } + + return res; + } + + @Test + public void testMaxElementSubArr() { + int[] input1 = new int[] {5, 3, 5, 2, 3, 2}; + assertEquals(3, maxElementSubArr(input1, 3)); + + int[] input2 = new int[] {1, 2, 3}; + assertEquals(3, maxElementSubArr(input2, 3)); + + int[] input3 = new int[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + assertEquals(1, maxElementSubArr(input3, 3)); + } +} From 046993e75621bfed0f56ccc5feecfc3becf0d3e1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 17 Sep 2019 19:54:56 -0500 Subject: [PATCH 007/189] Better version for integer to english --- .../crackingCoding/IntEnglishV2.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/crackingCoding/IntEnglishV2.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/crackingCoding/IntEnglishV2.java b/src/main/java/com/eprogrammerz/examples/algorithm/crackingCoding/IntEnglishV2.java new file mode 100644 index 0000000..0034d5c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/crackingCoding/IntEnglishV2.java @@ -0,0 +1,64 @@ +package com.eprogrammerz.examples.algorithm.crackingCoding; + +import org.junit.Test; + +import java.util.TreeMap; + +import static org.junit.Assert.assertEquals; + +public class IntEnglishV2 { + private final static TreeMap DEFAULTS = new TreeMap<>(); + + static { + DEFAULTS.put(1, "One"); + DEFAULTS.put(2, "Two"); + DEFAULTS.put(3, "Three"); + DEFAULTS.put(4, "Four"); + DEFAULTS.put(5, "Five"); + DEFAULTS.put(6, "Six"); + DEFAULTS.put(7, "Seven"); + DEFAULTS.put(8, "Eight"); + DEFAULTS.put(9, "Nine"); + DEFAULTS.put(10, "Ten"); + DEFAULTS.put(11, "Eleven"); + DEFAULTS.put(12, "Twelve"); + DEFAULTS.put(13, "Thirteen"); + DEFAULTS.put(14, "Fourteen"); + DEFAULTS.put(15, "Fifteen"); + DEFAULTS.put(16, "Sixteen"); + DEFAULTS.put(17, "Seventeen"); + DEFAULTS.put(18, "Eighteen"); + DEFAULTS.put(19, "Nineteen"); + DEFAULTS.put(20, "Twenty"); + DEFAULTS.put(30, "Thirty"); + DEFAULTS.put(40, "Forty"); + DEFAULTS.put(50, "Fifty"); + DEFAULTS.put(60, "Sixty"); + DEFAULTS.put(70, "Seventy"); + DEFAULTS.put(80, "Eighty"); + DEFAULTS.put(90, "Ninety"); + DEFAULTS.put(100, "Hundred"); + DEFAULTS.put(1000, "Thousand"); + DEFAULTS.put(100000, "Million"); + } + + public String translate(int val) { + int floor = DEFAULTS.floorKey(val); + if (floor == val) { + return DEFAULTS.get(val); + } + int multiplier = val / floor; + return (val > 100 ? DEFAULTS.get(multiplier) + " " : "") + DEFAULTS.get(floor) + " " + translate(val - floor * multiplier); + } + + @Test + public void testMapIntToString() { + assertEquals("Twelve Thousand Three Hundred Forty Five", translate(12345)); + assertEquals("One Hundred Eleven", translate(111)); + assertEquals("Two Hundred Eleven", translate(211)); + assertEquals("One Hundred Twenty Four", translate(124)); + assertEquals("One Hundred Forty Four", translate(144)); + assertEquals("One Thousand One Hundred Twenty Four", translate(1124)); + assertEquals("Nine Thousand Two Hundred Twenty Four", translate(9224)); + } +} From 1a4b5129415cf497db475c7cd884b869d9fcc201 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 17 Sep 2019 19:57:00 -0500 Subject: [PATCH 008/189] Added solution for partioning with equal sum and shortest unsorted continuous sub array --- .../leetcode/PartitionWEqualSum.java | 102 ++++++++++++++++++ .../leetcode/ShortestUnsortedConArr.java | 101 +++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PartitionWEqualSum.java create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestUnsortedConArr.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PartitionWEqualSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PartitionWEqualSum.java new file mode 100644 index 0000000..92a539f --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PartitionWEqualSum.java @@ -0,0 +1,102 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +/** + * Given an array A of integers, return true if and only if we can partition the array into three non-empty parts with equal sums. + *

+ * Formally, we can partition the array if we can find indexes i+1 < j with (A[0] + A[1] + ... + A[i] == A[i+1] + A[i+2] + ... + A[j-1] == A[j] + A[j-1] + ... + A[A.length - 1]) + *

+ *

+ *

+ * Example 1: + *

+ * Input: [0,2,1,-6,6,-7,9,1,2,0,1] + * Output: true + * Explanation: 0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1 + */ +public class PartitionWEqualSum { + /** + * O(n^2) - time + * @param arr + * @return + */ + public boolean canThreePartsEqualSum(int[] arr) { + // find sum to index i, see if rest of array can be divided into two to find target sum + int sum = 0; + for (int n : arr) { + sum += n; + } + + int p1 = 0; + + for (int i = 0; i < arr.length - 1; i++) { + p1 += arr[i]; + sum -= arr[i]; + if (canTwoPartsEqualSum(arr, i + 1, p1, sum)) return true; + } + + return false; + } + + private boolean canTwoPartsEqualSum(int[] arr, int startIdx, int target, int sum) { + int p2 = 0; + for (int i = startIdx; i < arr.length; i++) { + p2 += arr[i]; + sum -= arr[i]; + if (p2 == target && sum == target) return true; + } + return false; + } + + @Test + public void testCanThreePartsEqualSum() { + assertTrue(canThreePartsEqualSum(new int[]{0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1})); + assertFalse(canThreePartsEqualSum(new int[]{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1})); + assertTrue(canThreePartsEqualSum(new int[]{3, 3, 6, 5, -2, 2, 5, 1, -9, 4})); + assertTrue(canThreePartsEqualSum(new int[]{18, 12, -18, 18, -19, -1, 10, 10})); + assertTrue(canThreePartsEqualSum(new int[]{2, 8, 15, -5, 0, 9, -3, 4})); + + } + + + /** + * O(n) - time + * @param arr + * @return + */ + public boolean canThreePartsEqualSumBetter(int[] arr) { + // find sum to index i, see if rest of array can be divided into two to find target sum + int sum = 0; + for (int n : arr) { + sum += n; + } + + if (sum % 3 != 0) return false; + + int partSum = sum / 3; + int tempSum = 0; + int count = 0; + for (int n: arr) { + tempSum += n; + if (partSum == tempSum) { + count++; + tempSum = 0; + } + } + return count == 3; + } + + @Test + public void testCanThreePartsEqualSumBetter() { + assertTrue(canThreePartsEqualSumBetter(new int[]{0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1})); + assertFalse(canThreePartsEqualSumBetter(new int[]{0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1})); + assertTrue(canThreePartsEqualSumBetter(new int[]{3, 3, 6, 5, -2, 2, 5, 1, -9, 4})); + assertTrue(canThreePartsEqualSumBetter(new int[]{18, 12, -18, 18, -19, -1, 10, 10})); + assertTrue(canThreePartsEqualSumBetter(new int[]{2, 8, 15, -5, 0, 9, -3, 4})); + + } +} diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestUnsortedConArr.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestUnsortedConArr.java new file mode 100644 index 0000000..20f299b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestUnsortedConArr.java @@ -0,0 +1,101 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too. + * + * You need to find the shortest such subarray and output its length. + * + * Example 1: + * Input: [2, 6, 4, 8, 10, 9, 15] + * Output: 5 + * Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted in ascending order. + */ +public class ShortestUnsortedConArr { + /** + * O(nlogn) - Time + * O(n) - space + * @param nums + * @return + */ + public int findUnsortedSubarray(int[] nums) { + int[] temp = Arrays.copyOf(nums, nums.length); + Arrays.sort(temp); + + int start = -1; + int end = -1; + + for (int i = 0; i < nums.length; i++) { + if (nums[i] != temp[i]) { + if (start == -1) { + start = i; + } + end = i; + } + } + if (start == -1) return 0; + + return (end - start) + 1; + } + + @Test + public void testFindUnsortedSubArray() { + assertEquals(5, findUnsortedSubarray(new int[] {2, 6, 4, 8, 10, 9, 15})); + assertEquals(0, findUnsortedSubarray(new int[] {1, 2, 4, 8, 10, 15})); + assertEquals(0, findUnsortedSubarray(new int[] {1, 2, 2, 8, 10, 15})); + assertEquals(4, findUnsortedSubarray(new int[] {1, 3, 2, 3, 2, 15})); + assertEquals(2, findUnsortedSubarray(new int[] {1, 3, 2, 3, 3, 15})); + assertEquals(4, findUnsortedSubarray(new int[] {1, 3, 2, 2, 2})); + assertEquals(3, findUnsortedSubarray(new int[] {2, 3, 3, 2, 4})); + assertEquals(3, findUnsortedSubarray(new int[] {1, 2, 4, 5, 3})); + } + + /** + * O(n) - Time + * O(1) - space + * + * @param nums + * @return + */ + public int findUnsortedSubarrayBetter(int[] nums) { + int len = nums.length - 1; + int start = -1; + int end = -2; + + int max = nums[0]; + int min = nums[len]; + + for (int i = 1; i < nums.length; i++) { + if (nums[i] < max) { + end = i; + } else if (nums[i] > max) { + max = nums[i]; + } + + if (nums[len - i] > min) { + start = len - i; + } else if (nums[len - i] < min) { + min = nums[len - i]; + } + } + + return (end - start) + 1; + } + + @Test + public void testFindUnsortedSubArrayBetter() { + assertEquals(5, findUnsortedSubarrayBetter(new int[] {2, 6, 4, 8, 10, 9, 15})); + assertEquals(0, findUnsortedSubarrayBetter(new int[] {1, 2, 4, 8, 10, 15})); + assertEquals(0, findUnsortedSubarrayBetter(new int[] {1, 2, 2, 8, 10, 15})); + assertEquals(4, findUnsortedSubarrayBetter(new int[] {1, 3, 2, 3, 2, 15})); + assertEquals(2, findUnsortedSubarrayBetter(new int[] {1, 3, 2, 3, 3, 15})); + assertEquals(4, findUnsortedSubarrayBetter(new int[] {1, 3, 2, 2, 2})); + assertEquals(3, findUnsortedSubarrayBetter(new int[] {2, 3, 3, 2, 4})); + assertEquals(3, findUnsortedSubarrayBetter(new int[] {1, 2, 4, 5, 3})); + } +} From fd297187c55519cda1f8bbd5b08117e14fbe12c4 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 17 Sep 2019 21:26:23 -0500 Subject: [PATCH 009/189] Added solution to flatten tree in place --- .../algorithm/trees/FlattenBinaryTree.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/FlattenBinaryTree.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/FlattenBinaryTree.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/FlattenBinaryTree.java new file mode 100644 index 0000000..a55ffc2 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/FlattenBinaryTree.java @@ -0,0 +1,85 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Given a binary tree, flatten it to a linked list in-place. + */ +public class FlattenBinaryTree { + /** + * Do dfs + * once updated stack with child nodes, update traverse node with current node as right node + * @param root + */ + public void flatten(TreeNode root) { + if (root == null) return; + + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + + if (node.right != null) { + stack.push(node.right); + } + + if (node.left != null) { + stack.push(node.left); + } + + if (node != root) { + root.right = node; + root.left = null; + root = root.right; + } + } + } + + + /** + * 6 + * / \ + * 3 7 + * / \ \ + * 2 5 1 + * \ + * 10 + *

+ * 6 -> 3 -> 2 -> 5 -> 7 -> 1 -> 10 + */ + + @Test + public void testPathSum() { + TreeNode root = new TreeNode(6); + root.left = new TreeNode(3); + root.right = new TreeNode(7); + + root.right.right = new TreeNode(1); + + root.left.left = new TreeNode(2); + root.left.right = new TreeNode(5); + root.right.right.right = new TreeNode(10); + + flatten(root); + + assertEquals(6, root.val); + + assertNull(root.left); + assertEquals(3, root.right.val); + + + assertNull(root.right.left); + assertEquals(2, root.right.right.val); + + assertNull(root.right.right.left); + assertEquals(5, root.right.right.right.val); + + assertNull(root.right.right.right.right.left); + assertEquals(7, root.right.right.right.right.val); + } +} From c832025c84f7a7d0e7543c60404c14c430cb5b8c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 21 Sep 2019 21:18:23 -0500 Subject: [PATCH 010/189] Added solution for spiral matrix --- .../algorithm/leetcode/SpiralMatrixII.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrixII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrixII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrixII.java new file mode 100644 index 0000000..7344eb9 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrixII.java @@ -0,0 +1,50 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class SpiralMatrixII { + public int[][] generateMatrix(int n) { + int[][] m = new int[n][n]; + int val = 0; + for (int i = 0; i <= (n / 2); i++) { + int row = i; + int col = i; + // top + for (; col < n - i; col++) { + m[row][col] = ++val; + } + + col--; + row++; + // right + for (; row < n - i; row++) { + m[row][col] = ++val; + } + + // bottom + row--; + col--; + for (; col >= i; col--) { + m[row][col] = ++val; + } + + // left + row--; + col++; + for (; row > i; row--) { + m[row][col] = ++val; + } + } + return m; + } + + @Test + public void test() { + int[][] matrix = generateMatrix(3); + int[][] expected = new int[][]{{1, 2, 3}, {8, 9, 4}, {7, 6, 5}}; + assertThat(matrix, is(expected)); + } +} From 0841d4a1e3dec5f222d7483f681bb592f7971597 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 22 Sep 2019 09:47:10 -0500 Subject: [PATCH 011/189] Added solution for spiral traversal of matrix --- .../algorithm/leetcode/SpiralMatrix.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrix.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrix.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrix.java new file mode 100644 index 0000000..da7ae30 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SpiralMatrix.java @@ -0,0 +1,76 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +/** + * Given a matrix of order m x n, return spiral traversal of the matrix. + */ +public class SpiralMatrix { + public List spiralOrder(int[][] matrix) { + + List l = new ArrayList<>(); + + + if (matrix == null) return l; + + int rowStart = 0; + int rowEnd = matrix.length - 1; + int colStart = 0; + int colEnd = matrix[0].length - 1; + + + boolean[][] visited = new boolean[matrix.length][matrix[0].length]; + + while (rowStart <= rowEnd && colStart <= colEnd) { + for (int i = colStart; i <= colEnd && !visited[rowStart][i]; i++) { + l.add(matrix[rowStart][i]); + visited[rowStart][i] = true; + } + + rowStart++; + for (int i = rowStart; i <= rowEnd && !visited[i][colEnd]; i++) { + l.add(matrix[i][colEnd]); + visited[i][colEnd] = true; + } + colEnd--; + for (int i = colEnd; i >= colStart && !visited[rowEnd][i]; i--) { + l.add(matrix[rowEnd][i]); + visited[rowEnd][i] = true; + } + + rowEnd--; + for (int i = rowEnd; i >= rowStart && !visited[i][colStart]; i--) { + l.add(matrix[i][colStart]); + visited[i][colStart] = true; + } + colStart++; + } + + return l; + } + + @Test + public void test1() { + int[][] arr = new int[][]{{1, 2, 3}, {8, 9, 4}, {7, 6, 5}}; + List expected = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); + assertThat(spiralOrder(arr), is(expected)); + } + + @Test + public void test2() { + int[][] arr = new int[][]{ + {1, 2, 3, 10}, + {8, 9, 4, 11}, + {7, 6, 5, 12} + }; + List expected = Arrays.asList(1, 2, 3, 10, 11, 12, 5, 6, 7, 8, 9, 4); + assertThat(spiralOrder(arr), is(expected)); + } +} From b59defe5b42917d7d354a3fd623ca7310e6213b8 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 22 Sep 2019 09:52:27 -0500 Subject: [PATCH 012/189] Added solution for seaching matrix --- .../algorithm/leetcode/Search2DMatrix.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Search2DMatrix.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Search2DMatrix.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Search2DMatrix.java new file mode 100644 index 0000000..475cecb --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Search2DMatrix.java @@ -0,0 +1,121 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: + * + * - Integers in each row are sorted from left to right. + * - The first integer of each row is greater than the last integer of the previous row. + */ +public class Search2DMatrix { + public boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false; + + // int[] firstRow = matrix[0]; + // int[] lastRow = matrix[matrix.length - 1]; + + // if (firstRow) + // find row in which target falls using bs + // search target in that row + int start = 0; + int end = matrix.length - 1; + + while (start <= end) { + int mid = start + (end - start) / 2; + int[] row = matrix[mid]; + + if (row[0] <= target && target <= row[row.length - 1]) { + return bs(row, target); + } else if (row[0] > target) { + end = mid - 1; + } else { + start = mid + 1; + } + } + + return false; + } + + private boolean bs(int[] arr, int target) { + int start = 0; + int end = arr.length - 1; + + while (start <= end) { + int mid = start + (end - start) / 2; + + if (arr[mid] == target) { + return true; + } else if (arr[mid] < target) { + start = mid + 1; + } else { + end = mid - 1; + } + } + return false; + } + + @Test + public void test1() { + int[][] matrix = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8,9}}; + assertTrue(searchMatrix(matrix, 3)); + assertTrue(searchMatrix(matrix, 6)); + assertFalse(searchMatrix(matrix, 10)); + assertFalse(searchMatrix(matrix, -1)); + } + + @Test + public void test2() { + int[][] matrix = new int[][]{ + {} + }; + assertFalse(searchMatrix(matrix, 10)); + } + + /** + * Better version + * @param matrix + * @param target + * @return + */ + public boolean searchMatrixBetter(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false; + + // start from bottom left corner + // if less than current, do row-- + // if greater, then col++ + + int row = matrix.length - 1; + int col = 0; + while (row >=0 && col < matrix[0].length) { + if (matrix[row][col] == target) return true; + + if (matrix[row][col] > target) { + row--; + } else { + col++; + } + } + return false; + } + + @Test + public void test3() { + int[][] matrix = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8,9}}; + assertTrue(searchMatrixBetter(matrix, 3)); + assertTrue(searchMatrixBetter(matrix, 6)); + assertFalse(searchMatrixBetter(matrix, 10)); + assertFalse(searchMatrixBetter(matrix, -1)); + } + + @Test + public void test4() { + int[][] matrix = new int[][]{ + {} + }; + assertFalse(searchMatrixBetter(matrix, 10)); + } +} From 7c878d9eed73926809d69b240edb9896768f2217 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 22 Sep 2019 20:36:03 -0500 Subject: [PATCH 013/189] Added solution for sorting linkedlist --- .../ds/custom/linkedList/SortLinkedList.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java new file mode 100644 index 0000000..a2d841d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java @@ -0,0 +1,104 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + + +import org.junit.Test; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * Sort a linked list in O(n log n) time using constant space complexity. + * + * Example 1: + * + * Input: 4->2->1->3 + * Output: 1->2->3->4 + */ +public class SortLinkedList { + public ListNode sortList(ListNode head) { + if (head == null || head.next == null) return head; + + ListNode left = findMid(head); + + ListNode right = left.next; + left.next = null; + left = head; + + left = sortList(head); + right = sortList(right); + + // now merge left and right + ListNode dummy = new ListNode( - 1); + ListNode runner = dummy; + + while (left != null && right != null) { + if (left.val <= right.val) { + runner.next = left; + runner = runner.next; + left = left.next; + } else { + runner.next = right; + runner = runner.next; + right = right.next; + } + } + + if (left != null) { + runner.next = left; + } + + if (right != null) { + runner.next = right; + } + + return dummy.next; + } + + private ListNode findMid(ListNode head) { + if (head == null || head.next == null) return head; + ListNode slow = head; + ListNode fast = head.next; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + @Test + public void test1() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(8); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(6); + ListNode n6 = new ListNode(5); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(2); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + + ListNode res = sortList(n1); + assertEquals("1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9", printList(res)); + } + + @Test + public void test2() { + ListNode n1 = new ListNode(3); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(1); + n1.next = n2; + n2.next = n3; + + ListNode res = sortList(n1); + assertEquals("1 -> 2 -> 3", printList(res)); + } +} From d5f2b981e3a21cac7460787e3a73a249901c25fa Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 24 Sep 2019 16:35:30 -0500 Subject: [PATCH 014/189] Added solution to find days of week after n days --- .../algorithm/general/DaysOfWeek.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/DaysOfWeek.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/DaysOfWeek.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/DaysOfWeek.java new file mode 100644 index 0000000..425faee --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/DaysOfWeek.java @@ -0,0 +1,27 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class DaysOfWeek { + private List daysInWeek = Arrays.asList("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); + public String findNextDay(String day, int k) { + if (day == null) return null; + + int idx = daysInWeek.indexOf(day); + + return daysInWeek.get((idx + k) % 7); + } + + @Test + public void test() { + assertEquals("Fri", findNextDay("Wed", 2)); + assertEquals("Sat", findNextDay("Wed", 3)); + assertEquals("Sun", findNextDay("Wed", 4)); + assertEquals("Mon", findNextDay("Wed", 5)); + } +} From b86b2a6f68c5d8553185878e1502b879abdb3ed4 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 26 Sep 2019 18:45:48 -0500 Subject: [PATCH 015/189] Added solution to merge list --- .../algorithm/general/MergeSortList.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/MergeSortList.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/MergeSortList.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/MergeSortList.java new file mode 100644 index 0000000..a973935 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/MergeSortList.java @@ -0,0 +1,53 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.core.Is.is; + +/** + * Merge sort + */ +public class MergeSortList { + public void sort(List l) { + if (l == null || l.size() == 1) return; + int mid = l.size() / 2; + List left = new ArrayList<>(l.subList(0, mid)); + List right = new ArrayList<>(l.subList(mid, l.size())); + + sort(left); + sort(right); + merge(left, right, l); + } + + private void merge(List left, List right, List list) { + int leftIndex = 0; + int rightIndex = 0; + int listIndex = 0; + + while (leftIndex < left.size() && rightIndex < right.size()) { + if (left.get(leftIndex) < right.get(rightIndex)) { + list.set(listIndex++, left.get(leftIndex++)); + } else { + list.set(listIndex++, right.get(rightIndex++)); + } + } + while (leftIndex < left.size()) { + list.set(listIndex++, left.get(leftIndex++)); + } + while (rightIndex < right.size()) { + list.set(listIndex++, right.get(rightIndex++)); + } + } + + @Test + public void test1() { + List actual = Arrays.asList(1,4,3,2,7,5,6,8); + sort(actual); + assertThat(actual, is(Arrays.asList(1,2,3,4,5,6,7,8))); + } +} From 318b3e0524ac6769fc25e531b826b352252b4849 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 30 Sep 2019 18:08:04 -0500 Subject: [PATCH 016/189] Added solution to merge k lists --- .../custom/linkedList/MergeKSortedList.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MergeKSortedList.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MergeKSortedList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MergeKSortedList.java new file mode 100644 index 0000000..c03c82c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MergeKSortedList.java @@ -0,0 +1,114 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import java.util.PriorityQueue; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +public class MergeKSortedList { + public ListNode mergeKLists(ListNode[] lists) { + if (lists == null || lists.length == 0) return null; + + return mergeKLists(lists, 0, lists.length - 1); + } + + private ListNode mergeKLists(ListNode[] lists, int start, int end) { + if (end == start) + return lists[end]; + int mid = start + (end - start) / 2; + ListNode a = mergeKLists(lists, start, mid); + ListNode b = mergeKLists(lists, mid + 1, end); + return mergeTwoList(a, b); + } + + private ListNode mergeTwoList(ListNode l1, ListNode l2) { + if (l1 == null) return l2; + if (l2 == null) return l1; + + ListNode dummy = new ListNode(-1); + ListNode runner = dummy; + + while (l1 != null && l2 != null) { + if (l1.val > l2.val) { + runner.next = l2; + runner = runner.next; + l2 = l2.next; + } else { + runner.next = l1; + runner = runner.next; + l1 = l1.next; + } + } + + if (l1 != null) { + runner.next = l1; + } + + if (l2 != null) { + runner.next = l2; + } + return dummy.next; + } + + @Test + public void test() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(3); + ListNode n3 = new ListNode(8); + n1.next = n2; + n2.next = n3; + + ListNode m1 = new ListNode(2); + ListNode m2 = new ListNode(4); + m1.next = m2; + + ListNode[] lists = new ListNode[] { n1, m1}; + ListNode res = mergeKLists(lists); + assertEquals("1 -> 2 -> 3 -> 4 -> 8", printList(res)); + } + + public ListNode mergeKListsPQ(ListNode[] lists) { + if (lists == null || lists.length == 0) return null; + + PriorityQueue pq = new PriorityQueue<>((n1, n2) -> n1.val - n2.val); + + ListNode dummy = new ListNode(-1); + ListNode runner = dummy; + + for (int i = 0; i < lists.length; i++) { + if (lists[i] != null) { + pq.add(lists[i]); + } + } + + while (!pq.isEmpty()) { + ListNode node = pq.poll(); + runner.next = node; + runner = runner.next; + + if (node.next != null) { + pq.add(node.next); + } + } + return dummy.next; + } + + @Test + public void testBetter() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(3); + ListNode n3 = new ListNode(8); + n1.next = n2; + n2.next = n3; + + ListNode m1 = new ListNode(2); + ListNode m2 = new ListNode(4); + m1.next = m2; + + ListNode[] lists = new ListNode[] { n1, m1}; + ListNode res = mergeKListsPQ(lists); + assertEquals("1 -> 2 -> 3 -> 4 -> 8", printList(res)); + } +} From 096f64151c09a84ab506b86581f0dcdf2673ec9c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 2 Oct 2019 07:59:30 -0500 Subject: [PATCH 017/189] Added solution to find path to sum, foresting and palindrome check --- .../trees/DeleteNodesAndReturnForest.java | 80 ++++++++++++ .../examples/algorithm/trees/PathToSum.java | 14 ++- .../ds/custom/linkedList/PalindromeCheck.java | 116 ++++++++++++++++++ 3 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/DeleteNodesAndReturnForest.java create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PalindromeCheck.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/DeleteNodesAndReturnForest.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/DeleteNodesAndReturnForest.java new file mode 100644 index 0000000..d6bcf30 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/DeleteNodesAndReturnForest.java @@ -0,0 +1,80 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class DeleteNodesAndReturnForest { + public List delNodes(TreeNode root, int[] to_delete) { + + List l = new ArrayList<>(); + if (root == null) return l; + delNodes(root, to_delete, l); + return l; + } + + private void delNodes(TreeNode root, int[] toDelete, List l) { + if (root == null) return; + if (!isToDelete(toDelete, root.val)) { + l.add(root); + } + + Queue q = new LinkedList<>(); + q.add(root); + + while (!q.isEmpty()) { + TreeNode node = q.poll(); + if (isToDelete(toDelete, root.val)) { + delNodes(node.left, toDelete, l); + delNodes(node.right, toDelete, l); + } + else { + if (node.left != null) { + if (isToDelete(toDelete, node.left.val)) { + TreeNode temp = node.left; + node.left = null; + delNodes(temp.left, toDelete, l); + delNodes(temp.right, toDelete, l); + } else { + q.add(node.left); + } + + } + + if (node.right != null) { + if (isToDelete(toDelete, node.right.val)) { + TreeNode temp = node.right; + node.right = null; + delNodes(temp.left, toDelete, l); + delNodes(temp.right, toDelete, l); + } else { + q.add(node.right); + } + + } + } + + } + } + + private boolean isToDelete(int[] toDelete, int val) { + for (int n : toDelete) { + if (n == val) return true; + } + return false; + } + + @Test + public void test1() { + TreeNode n1 = new TreeNode(1); + n1.left = new TreeNode(2); + n1.right = new TreeNode(3); + n1.right.right = new TreeNode(4); + + List forest = delNodes(n1, new int[] {2,1}); + System.out.println(forest); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java index 6700046..9e6dcef 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java @@ -6,7 +6,9 @@ import java.util.Arrays; import java.util.List; +import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; /** * Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum. @@ -31,15 +33,15 @@ public class PathToSum { public List> pathSum(TreeNode root, int target) { List> paths = new ArrayList<>(); - pathSum(root, target, paths, new ArrayList<>(), 0); + pathSum(root, target, paths, new ArrayList<>()); return paths; } - private void pathSum(TreeNode root, int target, List> paths, List path, int sum) { + private void pathSum(TreeNode root, int target, List> paths, List path) { if (root == null) return; if (root.left == null && root.right == null) { - if (sum + root.val == target) { + if (root.val == target) { path.add(root.val); paths.add(new ArrayList<>(path)); @@ -49,8 +51,8 @@ private void pathSum(TreeNode root, int target, List> paths, List< } path.add(root.val); - pathSum(root.left, target, paths, path, sum + root.val); - pathSum(root.right, target, paths, path, sum + root.val); + pathSum(root.left, target - root.val, paths, path); + pathSum(root.right, target - root.val, paths, path); path.remove(path.size() - 1); } @@ -82,7 +84,7 @@ public void testPathSum() { // add right node to rightest node on last level root.right.right.right = new TreeNode(10); List> actual2 = pathSum(root, 24); - assertEquals(Arrays.asList(Arrays.asList(6, 7, 1, 10)), actual2); + assertThat(actual2, contains(Arrays.asList(6, 7, 1, 10))); } } diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PalindromeCheck.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PalindromeCheck.java new file mode 100644 index 0000000..83d9144 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PalindromeCheck.java @@ -0,0 +1,116 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +public class PalindromeCheck { + public boolean isPalindrome(ListNode head) { + if (head == null) return false; + boolean isEven = isEven(head); + + ListNode mid = mid(head); + + ListNode l2 = mid.next; + mid.next = null; + ListNode l1 = reverse(head); + + if (!isEven) l1 = l1.next; + + while (l1 != null && l2 != null) { + if (l1.val != l2.val) return false; + l1 = l1.next; + l2 = l2.next; + } + + if (l1 != null || l2 != null) return false; + return true; + } + + private ListNode reverse(ListNode node) { + if (node == null) return node; + ListNode prev = null; + while (node != null) { + ListNode temp = node.next; + node.next = prev; + prev = node; + node = temp; + } + return prev; + } + + private boolean isEven(ListNode node) { + if (node == null) return false; + + ListNode slow = node; + ListNode fast = node.next; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return fast != null; + } + + private ListNode mid(ListNode node) { + if (node == null) return null; + + ListNode slow = node; + ListNode fast = node.next; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + @Test + public void testPalindrome1() { + // 7 -> 2 -> 5 -> 3 -> 5 -> 2 -> 7 + ListNode head = new ListNode(7); + ListNode node1 = new ListNode(2); + ListNode node2 = new ListNode(5); + ListNode node3 = new ListNode(3); + ListNode node4 = new ListNode(5); + ListNode node5 = new ListNode(2); + ListNode node6 = new ListNode(7); + head.next = node1; + node1.next = node2; + node2.next = node3; + node3.next = node4; + node4.next = node5; + node5.next = node6; + + assertTrue(isPalindrome(head)); + } + + @Test + public void testPalindrome2() { + // 7 -> 2 -> 2 -> 7 + ListNode head = new ListNode(7); + ListNode node1 = new ListNode(2); + ListNode node2 = new ListNode(2); + ListNode node3 = new ListNode(7); + head.next = node1; + node1.next = node2; + node2.next = node3; + + assertTrue(isPalindrome(head)); + } + + @Test + public void testPalindrome3() { + // 7 -> 2 -> 2 -> 7 + ListNode head = new ListNode(7); + ListNode node1 = new ListNode(2); + ListNode node2 = new ListNode(2); + ListNode node3 = new ListNode(5); + head.next = node1; + node1.next = node2; + node2.next = node3; + + assertFalse(isPalindrome(head)); + } +} From c0bb4d958bbb3e6f69faee1c64e82194311c89a8 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 2 Oct 2019 08:00:32 -0500 Subject: [PATCH 018/189] Added solution for pascal traiangle --- .../algorithm/leetcode/PascalTriangle.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PascalTriangle.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PascalTriangle.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PascalTriangle.java new file mode 100644 index 0000000..35c3e09 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PascalTriangle.java @@ -0,0 +1,48 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; +import org.w3c.dom.ls.LSException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + + +public class PascalTriangle { + public List> generate(int numRows) { + + List> r = new ArrayList<>(); + if (numRows == 0) return r; + + List r1 = Collections.singletonList(1); + r.add(r1); + if (numRows == 1) { + return r; + } + + for (int rn = 2; rn <= numRows; rn++) { + List row = new ArrayList<>(); + row.add(1); + for (int i = 1, s = 0; i < rn - 1; i++, s++) { + int ith = r.get(rn - 2).get(s) + r.get(rn - 2).get(s + 1); + row.add(ith); + } + row.add(1); + r.add(row); + } + return r; + } + + @Test + public void testGenerate() { + List> actual = generate(5); + List> expected = asList(asList(1), asList(1,1), asList(1,2,1),asList(1,3,3,1), asList(1,4,6,4,1)); + assertThat(actual, is(expected)); + } +} From 7140e1dc3bbe9cdd0bff3c8386f2d9d19d6e73d2 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 2 Oct 2019 18:16:04 -0500 Subject: [PATCH 019/189] Added solution to add numbers represented by linked list --- .../ds/custom/linkedList/SumList.java | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SumList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SumList.java index 3816d82..d3ddf78 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SumList.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SumList.java @@ -2,8 +2,11 @@ import org.junit.Test; +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + public class SumList { - private Node sumList(Node h1, Node h2) { + public Node sumList(Node h1, Node h2) { Node result = null; Node carrier = null; @@ -69,4 +72,69 @@ public void testSumList() { } // prints 219 } + + /** + * You are given two non-empty linked lists representing two non-negative integers. + * The digits are stored in reverse order and each of their nodes contain a single digit. + * Add the two numbers and return it as a linked list. + * + * You may assume the two numbers do not contain any leading zero, except the number 0 itself. + * + * Example: + * + * Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) + * Output: 7 -> 0 -> 8 + * Explanation: 342 + 465 = 807. + * @param l1 + * @param l2 + * @return + */ + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + int carry = 0; + + ListNode result = new ListNode(-1); + + ListNode last = result; + + while(l1 != null || l2 != null) { + int x = l1 != null ? l1.val : 0; + int y = l2 != null ? l2.val : 0; + int sum = x + y + carry; + + if (l1 != null) l1 = l1.next; + if (l2 != null) l2 = l2.next; + carry = sum / 10; + sum = sum % 10; + + last.next = new ListNode(sum); + last = last.next; + } + + if(carry != 0) { + last.next = new ListNode(carry); + } + return result.next; + } + + @Test + public void testSumList2() { + // 617 + // presented in reverse order 7 -> 1 -> 6 + ListNode n1 = new ListNode(7); + ListNode n2 = new ListNode(1); + ListNode n3 = new ListNode(6); + n1.next = n2; + n2.next = n3; + + // 295 + // 5 -> 9 -> 2 + ListNode na = new ListNode(5); + ListNode nb = new ListNode(9); + ListNode nc = new ListNode(2); + na.next = nb; + nb.next = nc; + + ListNode sum = addTwoNumbers(n1, na); // 912 + assertEquals("2 -> 1 -> 9", printList(sum)); + } } From bbf210d7bf0243ff4b43ff033325ea5534514ad4 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 2 Oct 2019 18:39:05 -0500 Subject: [PATCH 020/189] Added solution for adding nums represented by strings --- .../algorithm/leetcode/AddStrings.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AddStrings.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AddStrings.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AddStrings.java new file mode 100644 index 0000000..73688df --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AddStrings.java @@ -0,0 +1,53 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class AddStrings { + /** + * Add numbers represented by strings + * 123 + 980 = 1103 + * @param num1 + * @param num2 + * @return + */ + public String addStrings(String num1, String num2) { + StringBuilder sb1 = new StringBuilder(num1).reverse(); + StringBuilder sb2 = new StringBuilder(num2).reverse(); + StringBuilder sb = new StringBuilder(); + + int n1 = 0; + int n2 = 0; + int carry = 0; + + + while (n1 < sb1.length() || n2 < sb2.length()) { + int x = n1 < sb1.length() ? sb1.charAt(n1) - 48 : 0; + int y = n2 < sb2.length() ? sb2.charAt(n2) - 48 : 0; + + int sum = x + y + carry; + + carry = sum / 10; + sum = sum % 10; + + sb.append(sum); + + n1++; + n2++; + } + + if (carry > 0) { + sb.append(carry); + } + + return sb.reverse().toString(); + } + + @Test + public void test() { + assertEquals("1110", addStrings("123", "987")); + assertEquals("218", addStrings("120", "98")); + assertEquals("107", addStrings("98", "9")); + } +} From a1ad05d57743f89a847ce1a98b1e6846e0dfe844 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 3 Oct 2019 19:25:46 -0500 Subject: [PATCH 021/189] Added solution for super ugly num --- .../algorithm/leetcode/SuperUglyNumber.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SuperUglyNumber.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SuperUglyNumber.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SuperUglyNumber.java new file mode 100644 index 0000000..da798f1 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SuperUglyNumber.java @@ -0,0 +1,54 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.PriorityQueue; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * Write a program to find the nth super ugly number. + * + * Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. + * + * Example: + * + * Input: n = 12, primes = [2,7,13,19] + * Output: 32 + * Explanation: [1,2,4,7,8,13,14,16,19,26,28,32] is the sequence of the first 12 + * super ugly numbers given primes = [2,7,13,19] of size 4. + */ +public class SuperUglyNumber { + public int nthSuperUglyNumber(int n, int[] primes) { + PriorityQueue q = new PriorityQueue<>(); + for (int prime: primes) { + q.add((long) prime); + } + if (primes.length == 1) { + return (int) Math.pow(primes[0], n - 1); + } + int count = 1; + long ugly = 1; + while (count < n) { + ugly = q.poll(); + + if (ugly != q.peek()) { + count++; + for (int prime: primes) { + long potentialUgly = prime * ugly; + q.add(potentialUgly); + } + } + + } + return (int) ugly; + } + + @Test + public void test() { + assertEquals(32, nthSuperUglyNumber(12, new int[] {2, 7, 13, 19})); + assertEquals(2, nthSuperUglyNumber(2, new int[] {2})); + } +} From 240b4bd7a74b646daf3ae7fa90f0690595e690af Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 3 Oct 2019 19:35:09 -0500 Subject: [PATCH 022/189] Added solution to uglynumberII --- .../algorithm/general/UglyNumberII.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/UglyNumberII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/UglyNumberII.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/UglyNumberII.java new file mode 100644 index 0000000..04bb172 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/UglyNumberII.java @@ -0,0 +1,53 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +/** + * Write a program to find the n-th ugly number. + *

+ * Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. + *

+ * Example: + *

+ * Input: n = 10 + * Output: 12 + * Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers + */ +public class UglyNumberII { + private List factors = Arrays.asList(2L, 3L, 5L); + + public int nthUglyNumber(int n) { + if (n <= 3) return n; + + PriorityQueue pq = new PriorityQueue<>(factors); + + + int count = 1; + long ugly = 1; + while (count < n) { + ugly = pq.poll(); + + if (ugly != pq.peek()) { + count++; + + for (long factor : factors) { + pq.add(factor * ugly); + } + } + } + + return (int) ugly; + } + + @Test + public void test1() { + int ugly = nthUglyNumber(10); + assertEquals(12, ugly); + } +} From eddd08aa10243f5e0ee47e87ca214dcfadba7eed Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 8 Oct 2019 19:45:40 -0500 Subject: [PATCH 023/189] Added solution to insert A's to make it even --- .../algorithm/general/MaxInsertOfA.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/MaxInsertOfA.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxInsertOfA.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxInsertOfA.java new file mode 100644 index 0000000..a0326e4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxInsertOfA.java @@ -0,0 +1,48 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Insert max a into string str so that they will 2 consecutive a + * if str has more than 2 a's, then return -1 + */ +public class MaxInsertOfA { + public int countMaxInsert(String str) { + int count = 0; + int aCount = 0; + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch == 'a') { + aCount++; + if (aCount > 2) return -1; + } else { + if (aCount == 2) { + aCount = 0; + } else if (aCount > 0) { + count += aCount; + aCount = 0; + } else { + count += 2; + aCount = 0; + } + } + } + if (str.charAt(str.length() - 1) != 'a') { + count += 2; + } else { + count += (2 - aCount); + } + return count; + } + + @Test + public void test() { + assertEquals(3, countMaxInsert("aabab")); + assertEquals(2, countMaxInsert("aababa")); + assertEquals(8, countMaxInsert("dog")); + assertEquals(0, countMaxInsert("aa")); + assertEquals(-1, countMaxInsert("baaaa")); + } +} From 9dd0dbc62342f5e0658bd283e0a7aefb2a74c748 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 8 Oct 2019 19:46:20 -0500 Subject: [PATCH 024/189] Added solution to find max num by inserting 5 --- .../algorithm/general/MaxPossibleValue.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/MaxPossibleValue.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxPossibleValue.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxPossibleValue.java new file mode 100644 index 0000000..2e8b467 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxPossibleValue.java @@ -0,0 +1,63 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; + +/** + * return max possible value of n by inserting 5 + * + * for example: 0 -> 50 + * 2345 -> 52345 + * -99 -> -599 + * -23 -> -235 + */ +public class MaxPossibleValue { + public int maxPossibleValue(int n) { + if (n == 0) return 50; + if (n < 0) return (-1) * findValue(-n, false); + return findValue(n, true); + } + + private int findValue(int n, boolean isMax) { + Stack stack = new Stack<>(); + while (n != 0) { + stack.push(n % 10); + n /= 10; + } + + int num = 0; + boolean added = false; + while (!stack.isEmpty()) { + int digit = stack.pop(); + if (!added) { + if (isMax && digit <= 5) { + num = num * 10 + 5; + added = true; + } + + if (!isMax && digit > 5) { + num = num * 10 + 5; + added = true; + } + } + num = num * 10 + digit; + } + + if (!added) num = num * 10 + 5; + + return num; + } + + @Test + public void test() { + assertEquals(5268, maxPossibleValue(268)); + assertEquals(50, maxPossibleValue(0)); + assertEquals(550, maxPossibleValue(50)); + assertEquals(6750, maxPossibleValue(670)); + assertEquals(9995, maxPossibleValue(999)); + assertEquals(-5999, maxPossibleValue(-999)); + } +} From 99a49dadc9d6034f6f1ba13d4b84e58e8575a4e2 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 8 Oct 2019 19:47:28 -0500 Subject: [PATCH 025/189] Added solution to find max sum of pair with same digit sum --- .../general/NumWithEqualDigitSum.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/NumWithEqualDigitSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/NumWithEqualDigitSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/NumWithEqualDigitSum.java new file mode 100644 index 0000000..651b448 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/NumWithEqualDigitSum.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * given an array of integers, return max sum of pair whose digits sums to equals + */ +public class NumWithEqualDigitSum { + public int findMaxSum(int[] nums) { + Map> nList = new HashMap<>(); + for (int n: nums) { + int sum = findDigitSum(n); + List list = nList.get(sum); + if (list == null) { + list = new ArrayList<>(); + list.add(n); + nList.put(sum, list); + } else { + list.add(n); + } + } + + int maxSum = Integer.MIN_VALUE; + for (int key: nList.keySet()) { + List list = nList.get(key); + if (list.size() >= 2) { + int sum = list.size() == 2 ? list.get(0) + list.get(1) : findMaxSum(list); + if (sum > maxSum) maxSum = sum; + } + } + return maxSum == Integer.MIN_VALUE ? -1 : maxSum; + } + + private int findMaxSum(List l) { + int maxSum = Integer.MIN_VALUE; + for (int i = 0; i < l.size() - 1; i++) { + for (int j = i + 1; j < l.size(); j++) { + int sum = l.get(i) + l.get(j); + if (sum > maxSum) { + maxSum = sum; + } + } + } + return maxSum; + } + + private int findDigitSum(int n) { + int sum = 0; + while (n != 0) { + sum += n % 10; + n /= 10; + } + return sum; + } + + @Test + public void test() { + assertEquals(93, findMaxSum(new int[] {51, 17, 71, 42})); + assertEquals(102, findMaxSum(new int[] {42, 33, 60})); + assertEquals(-1, findMaxSum(new int[] {51, 32, 43})); + } +} From 078ccd41ede142250858a4988cc1a19bcb3dd756 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 08:29:30 -0500 Subject: [PATCH 026/189] Added solution to partion list and stack with queue --- .../examples/ds/custom/stack/StackWQueue.java | 54 +++++++++++++++++++ .../examples/ds/custom/stack/Validator.java | 13 +++++ 2 files changed, 67 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWQueue.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWQueue.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWQueue.java new file mode 100644 index 0000000..8958f4f --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWQueue.java @@ -0,0 +1,54 @@ +package com.eprogrammerz.examples.ds.custom.stack; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Implement the following operations of a stack using queues. + * + * push(x) -- Push element x onto stack. + * pop() -- Removes the element on top of the stack. + * top() -- Get the top element. + * empty() -- Return whether the stack is empty. + * Example: + * + * MyStack stack = new MyStack(); + * + * stack.push(1); + * stack.push(2); + * stack.top(); // returns 2 + * stack.pop(); // returns 2 + * stack.empty(); // returns false + */ +public class StackWQueue { + private Queue q1; + /** Initialize your data structure here. */ + public StackWQueue() { + this.q1 = new LinkedList<>(); + } + + /** Push element x onto stack. */ + // O(1) + public void push(int x) { + this.q1.add(x); + int size = q1.size(); + for (int i = 0; i < size - 1; i++) { + q1.add(q1.poll()); + } + } + + /** Removes the element on top of the stack and returns that element. */ + public int pop() { + return this.q1.poll(); + } + + /** Get the top element. */ + public int top() { + return this.q1.peek(); + } + + /** Returns whether the stack is empty. */ + public boolean empty() { + return q1.isEmpty(); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java index 271b60a..b0c869f 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java @@ -70,4 +70,17 @@ public void testSortedStack() { assertEquals(4, sortedStack.pop()); assertEquals(5, sortedStack.pop()); } + + @Test + public void testStackWQueue() { + StackWQueue stack = new StackWQueue(); + stack.push(1); + stack.push(2); + stack.push(3); + assertEquals(3, stack.pop()); + assertEquals(2, stack.pop()); + stack.push(4); + assertEquals(4, stack.pop()); + assertEquals(1, stack.pop()); + } } From 713e71b425eb8b6ac9c34dc008f775478d14b7a1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 08:30:13 -0500 Subject: [PATCH 027/189] Added solution for most water contained in container --- .../leetcode/MostWaterContainer.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MostWaterContainer.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MostWaterContainer.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MostWaterContainer.java new file mode 100644 index 0000000..a0f8cc3 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MostWaterContainer.java @@ -0,0 +1,63 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). + * n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). + * Find two lines, which together with x-axis forms a container, such that the container contains the most water. + * + * Note: You may not slant the container and n is at least 2. + * + * + * + * + * + * The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. + * + * + * + * Example: + * + * Input: [1,8,6,2,5,4,8,3,7] + * Output: 49 + */ +public class MostWaterContainer { + public int maxArea(int[] height) { + // int max = 0; + // for (int i = 0; i < height.length - 1; i++) { + // for (int j = i + 1; j < height.length; j++) { + // int area = (j - i) * Math.min(height[i], height[j]); + // if (max < area) { + // max = area; + // } + // } + // } + // return max; + + int max = 0; + int start = 0; + int end = height.length - 1; + while(start < end) { + int area = (end - start) * Math.min(height[start], height[end]); + if (area > max) { + max = area; + } + + if (height[start] < height[end]) { + start++; + } else { + end--; + } + } + return max; + } + + @Test + public void test() { + assertEquals(100, maxArea(new int[] {1,8,6,100,100,4,8,3,7})); + assertEquals(49, maxArea(new int[] {1,8,6,2,5,4,8,3,7})); + } +} From f2889352816c6a5791d21c23a340e4f65267099a Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 08:30:52 -0500 Subject: [PATCH 028/189] Added solution to find interval intersections --- .../leetcode/IntervalIntersection.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntervalIntersection.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntervalIntersection.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntervalIntersection.java new file mode 100644 index 0000000..46c0485 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntervalIntersection.java @@ -0,0 +1,81 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertArrayEquals; + +/** + * Given two lists of closed intervals, each list of intervals is pairwise disjoint and in sorted order. + *

+ * Return the intersection of these two interval lists. + *

+ * (Formally, a closed interval [a, b] (with a <= b) denotes the set of real numbers x with a <= x <= b. + * The intersection of two closed intervals is a set of real numbers that is either empty, or can be represented as a closed interval. + * For example, the intersection of [1, 3] and [2, 4] is [2, 3].) + *

+ *

+ *

+ * Example 1: + *

+ *

+ *

+ * Input: A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]] + * Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]] + * Reminder: The inputs and the desired output are lists of Interval objects, and not arrays or lists. + */ +public class IntervalIntersection { + public int[][] intervalIntersection(int[][] A, int[][] B) { + int i = 0; + int j = 0; + + List l = new ArrayList<>(); + while (i < A.length && j < B.length) { + int[] a = A[i]; + int[] b = B[j]; + + // if either of start or end falls within the range of either interval, + // then add intersection + if (((b[0] <= a[0] && a[0] <= b[1]) || (b[0] <= a[1] && a[1] <= b[1])) || + (a[0] <= b[0] && b[0] <= a[1]) || (a[0] <= b[1] && b[1] <= a[1])) { + l.add(new int[]{Math.max(a[0], b[0]), Math.min(a[1], b[1])}); + } + + if (a[1] < b[1]) { + i++; + } else { + j++; + } + } + int[][] res = new int[l.size()][2]; + int idx = 0; + for (int[] m : l) { + res[idx++] = m; + } + return res; + } + + @Test + public void test() { + int[][] a = new int[][]{ + {3, 5}, + {9, 20} + }; + int[][] b = new int[][]{ + {4, 5}, + {7, 10}, + {11, 12}, + {14, 15}, + {16, 20} + }; + int[][] merged = intervalIntersection(a, b); + + assertArrayEquals(new int[]{4, 5}, merged[0]); + assertArrayEquals(new int[]{9, 10}, merged[1]); + assertArrayEquals(new int[]{11, 12}, merged[2]); + assertArrayEquals(new int[]{14, 15}, merged[3]); + assertArrayEquals(new int[]{16, 20}, merged[4]); + } +} From 7535852ccbda8f98f430bbd9486686d2e048b959 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 08:31:25 -0500 Subject: [PATCH 029/189] Added solution to partion list by k --- .../ds/custom/linkedList/PartitionList.java | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PartitionList.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PartitionList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PartitionList.java new file mode 100644 index 0000000..ebee85d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/PartitionList.java @@ -0,0 +1,123 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. + * + * You should preserve the original relative order of the nodes in each of the two partitions. + * + * Example: + * + * Input: head = 1->4->3->2->5->2, x = 3 + * Output: 1->2->2->4->3->5 + */ +public class PartitionList { + /** + * O(n) - time + * O(1) - space + * @param head + * @param x + * @return + */ + public ListNode partition(ListNode head, int x) { + if (head == null) return null; + ListNode less = head; + ListNode lessPrev = null; + ListNode ge = head; + ListNode gePrev = null; + + while (less != null && ge != null) { + if(ge.val >= x) { + if (less != ge && less.val < x) { + // change pointers + ListNode newLess = less.next; + lessPrev.next = less.next; + less.next = ge; + + if (gePrev != null) { + gePrev.next = less; + gePrev = gePrev.next; + } else { + head = less; + gePrev = less; + } + less = newLess; + } else { + lessPrev = less; + less = less.next; + } + } else { + lessPrev = less; + less = less.next; + gePrev = ge; + ge = ge.next; + } + } + return head; + } + + @Test + public void test1() { + // 1 -> 4 -> 3 -> 2 -> 5 -> 2 + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(4); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(2); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(2); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + + ListNode res = partition(n1, 3); + assertEquals("1 -> 2 -> 2 -> 4 -> 3 -> 5", printList(res)); + } + + @Test + public void test2() { + // 1 -> 4 -> 3 -> 2 -> 5 -> 2 -> 7 -> 8 -> 9 + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(4); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(2); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(2); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + + ListNode res = partition(n1, 4); + assertEquals("1 -> 3 -> 2 -> 2 -> 4 -> 5 -> 7 -> 8 -> 9", printList(res)); + } + + @Test + public void test3() { + // 2 -> 1 + ListNode n1 = new ListNode(4); + ListNode n2 = new ListNode(3); + ListNode n3 = new ListNode(2); + ListNode n4 = new ListNode(1); + ListNode n5 = new ListNode(1); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + + ListNode res = partition(n1, 2); + assertEquals("1 -> 1 -> 4 -> 3 -> 2", printList(res)); + } +} From ea051d1e2ed0e89d3ef8546b8b7da5636414b653 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 08:34:32 -0500 Subject: [PATCH 030/189] Added solution to break words with Trie --- .../algorithm/leetcode/WordBreak.java | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordBreak.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordBreak.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordBreak.java new file mode 100644 index 0000000..0279840 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordBreak.java @@ -0,0 +1,116 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +/** + * Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine + * if s can be segmented into a space-separated sequence of one or more dictionary words. + *

+ * Note: + *

+ * The same word in the dictionary may be reused multiple times in the segmentation. + * You may assume the dictionary does not contain duplicate words. + * Example 1: + *

+ * Input: s = "leetcode", wordDict = ["leet", "code"] + * Output: true + * Explanation: Return true because "leetcode" can be segmented as "leet code". + */ +public class WordBreak { + + Trie trie = new Trie(); + + public boolean wordBreak(String s, List wordDict) { + for (String word : wordDict) { + trie.insert(word); + } + Node root = trie.root; + + return wordBreak(s, root); + } + + private boolean wordBreak(String s, Node node) { + if ((s == null || s.isEmpty()) && node.terminates()) return true; + else if (s == null || s.isEmpty()) return false; + + Node child = node.getChild(s.charAt(0)); + if (child != null && child.terminates()) { + return wordBreak(s.substring(1), trie.root) || wordBreak(s.substring(1), child); + } else if (child != null) { + return wordBreak(s.substring(1), child); + } else { + return node.terminates() && wordBreak(s, trie.root); + } + } + + @Test + public void test1() { + assertTrue(wordBreak("leetcode", Arrays.asList("leet", "code"))); + } + + @Test + public void test2() { + assertTrue(wordBreak("leetscode", Arrays.asList("leet", "leets", "code"))); + } + + @Test + public void test3() { + assertFalse(wordBreak("leetcode", Arrays.asList("leets", "code"))); + } + + @Test + public void test4() { + assertTrue(wordBreak("bb", Arrays.asList("a", "b", "bbb", "bbbbb"))); + } +} + +class Trie { + Node root = new Node('#'); + + void insert(String word) { + root.insert(word); + } +} + +class Node { + private char data; + Map children; + + Node(char data) { + this.data = data; + this.children = new HashMap<>(); + } + + void insert(String word) { + if (word != null && !word.isEmpty()) { + this.data = word.charAt(0); + Node child = children.get(this.data); + if (child == null) { + + child = new Node(this.data); + children.put(this.data, child); + + } + child.insert(word.substring(1)); + } else { + children.put('\0', null); + } + } + + + boolean terminates() { + return children.containsKey('\0'); + } + + Node getChild(char ch) { + return children.get(ch); + } +} From e9f31d4c061610f8d205a4f87bf140ed2453ba4e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 08:35:15 -0500 Subject: [PATCH 031/189] Added solution to remove elements in-place --- .../algorithm/leetcode/RemoveElement.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveElement.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveElement.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveElement.java new file mode 100644 index 0000000..a14632c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveElement.java @@ -0,0 +1,60 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Given an array nums and a value val, remove all instances of that value in-place and return the new length. + * + * Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. + * + * The order of elements can be changed. It doesn't matter what you leave beyond the new length. + * + * Example 1: + * + * Given nums = [3,2,2,3], val = 3, + * + * Your function should return length = 2, with the first two elements of nums being 2. + * + * It doesn't matter what you leave beyond the returned length. + * + */ +public class RemoveElement { + public int removeElement(int[] nums, int val) { + int i = 0; // index to track target + int j = 0; // index to track non-target + int count = 0; + while (i < nums.length && j < nums.length) { + if (nums[i] == val) { + if (i < j && nums[j] != val) { + swap(nums, i, j); + i++; + } else { + j++; + } + } else { + i++; + j++; + } + } + + for (int n: nums) { + if (n == val) break; + count++; + } + return count; + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + @Test + public void test() { + int[] arr = new int[] {0,1,2,2,3,0,4,2}; + assertEquals(5, removeElement(arr, 2)); + } +} From 2afd10ebe71eb89dbf543edbc84ad44086daedaa Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 15:50:27 -0500 Subject: [PATCH 032/189] Added solution to the basic calculator using stack --- .../algorithm/leetcode/BasicCalculatorII.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorII.java new file mode 100644 index 0000000..53dccb4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorII.java @@ -0,0 +1,79 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * Implement a basic calculator to evaluate a simple expression string. + * + * The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero. + * + * Example 1: + * + * Input: "3+2*2" + * Output: 7 + */ +public class BasicCalculatorII { + private List symbols = Arrays.asList('/', '*', '+', '-'); + + public int calculate(String str) { + str = str.replaceAll(" ", ""); + if (str.length() == 0) return 0; + if (str.length() == 1) return Integer.valueOf(str); + + int start = 0; + int end = 0; + + Stack s = new Stack<>(); + char lastOp = '#'; + while (end < str.length()) { + + while (end < str.length()) { + if (symbols.contains(str.charAt(end))) { + break; + } + end++; + } + // if the expression starts with '-', then it has to be taken care + if (end != 0) { + int n = Integer.valueOf(str.substring(start, end)); + if (lastOp == '*') { + int mul = s.isEmpty() ? 1 : s.pop(); + s.push(mul * n); + } else if (lastOp == '/') { + int mul = s.isEmpty() ? 0 : s.pop(); + s.push(mul / n); + } else if (lastOp == '-') { + s.push((-1) * n); + } else { + s.push(n); + } + } + if (end < str.length()) { + lastOp = str.charAt(end); + end = end + 1; + start = end; + } + + } + + int res = 0; + while (!s.isEmpty()) { + res += s.pop(); + } + return res; + } + + @Test + public void test() { + assertEquals(7, calculate("3+2*2")); + assertEquals(1, calculate("-3+2*2")); + assertEquals(1, calculate("1-1+1")); + assertEquals(27, calculate("3+2*2+4*5")); + assertEquals(5, calculate(" 3+5 / 2 ")); + assertEquals(-2147483647, calculate("0-2147483647")); + } +} From bb8b65d413373ce9531cf5a690847d7a8d1fcadc Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 12 Oct 2019 16:58:47 -0500 Subject: [PATCH 033/189] Added solution for combination sum --- .../algorithm/leetcode/CombinationSum.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java new file mode 100644 index 0000000..2e588b7 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java @@ -0,0 +1,90 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), + * find all unique combinations in candidates where the candidate numbers sums to target. + *

+ * The same repeated number may be chosen from candidates unlimited number of times. + *

+ * Note: + *

+ * All numbers (including target) will be positive integers. + * The solution set must not contain duplicate combinations. + * Example 1: + *

+ * Input: candidates = [2,3,6,7], target = 7, + * A solution set is: + * [ + * [7], + * [2,2,3] + * ] + */ +public class CombinationSum { + + /** + * Time - O(n) + * Space - O(n) + * + * @param candidates + * @param target + * @return + */ + public List> combinationSum(int[] candidates, int target) { + List> l = new ArrayList<>(); + if (candidates.length == 0) return l; + + // this is important as we are pruning the search with index + Arrays.sort(candidates); + backTrack(candidates, 0, new ArrayList<>(), l, target); + + return l; + } + + private void backTrack(int[] candidates, int start, List temp, List> r, int target) { + if (target == 0) { // found the set of element + r.add(new ArrayList<>(temp)); + temp.remove(temp.size() - 1); + } else { + for (int i = start; i < candidates.length; i++) { + int n = candidates[i]; + + if (target - n < 0) break; + + temp.add(n); + backTrack(candidates, i, temp, r, target - n); + } + if (temp.size() > 0) + temp.remove(temp.size() - 1); + } + } + + @Test + public void test1() { + List> actual = combinationSum(new int[]{2, 3, 6, 7}, 7); + + List> expected = new ArrayList<>(); + expected.add(Arrays.asList(2, 2, 3)); + expected.add(Arrays.asList(7)); + assertThat(actual, is(expected)); + } + + @Test + public void test2() { + List> actual = combinationSum(new int[]{2, 3, 5}, 8); + List> expected = new ArrayList<>(); + expected.add(Arrays.asList(2, 2, 2, 2)); + expected.add(Arrays.asList(2, 3, 3)); + expected.add(Arrays.asList(3, 5)); + + assertThat(actual, is(expected)); + } +} From c4deed245199a61d6147276d3223565ab2f4107d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 13 Oct 2019 10:27:59 -0500 Subject: [PATCH 034/189] Added solution to find combinations of digits --- .../algorithm/leetcode/Combinations.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java new file mode 100644 index 0000000..684a4ce --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java @@ -0,0 +1,64 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. + * + * Example: + * + * Input: n = 4, k = 2 + * Output: + * [ + * [2,4], + * [3,4], + * [2,3], + * [1,2], + * [1,3], + * [1,4], + * ] + */ +public class Combinations { + public List> combine(int n, int k) { + List> l = new ArrayList<>(); + + if (n == 0) return l; + + backTrack(n, 1, k, l, new ArrayList<>()); + return l; + } + + private void backTrack(int n, int start, int k, List> l, List temp) { + if (temp.size() == k) { + l.add(new ArrayList<>(temp)); + temp.remove(temp.size() - 1); + } else { + for (int i = start; i <= n; i++) { + temp.add(i); + backTrack(n, i + 1, k, l, temp); + } + if (!temp.isEmpty()) temp.remove(temp.size() - 1); + } + } + + @Test + public void test1() { + List> actual = combine(4, 2); + List> expected = new ArrayList<>(); + expected.add(Arrays.asList(1,2)); + expected.add(Arrays.asList(1,3)); + expected.add(Arrays.asList(1,4)); + expected.add(Arrays.asList(2,3)); + expected.add(Arrays.asList(2,4)); + expected.add(Arrays.asList(3,4)); + + assertThat(actual, is(expected)); + } +} From e1bebb556be2df7617dd7c7bcf15c5b3d7b75684 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 13 Oct 2019 22:03:45 -0500 Subject: [PATCH 035/189] Added dep for hamcrest --- pom.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4ab34fe..10f4609 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,15 @@ opencsv 4.0 + + + + org.hamcrest + hamcrest-library + 2.1 + test + + @@ -134,4 +143,4 @@ http://clojars.org/repo/ - \ No newline at end of file + From caac99bf01efba2f652a65ce72cc7f9126f237f5 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 14 Oct 2019 17:57:11 -0500 Subject: [PATCH 036/189] Added solution for basic calculator --- .../algorithm/leetcode/BasicCalculator.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculator.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculator.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculator.java new file mode 100644 index 0000000..466b7bc --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculator.java @@ -0,0 +1,75 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; + +/** + * Implement a basic calculator to evaluate a simple expression string. + * + * The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces . + * + * Example 1: + * + * Input: "1 + 1" + * Output: 2 + * Example 2: + * + * Input: " 2-1 + 2 " + * Output: 3 + * Example 3: + * + * Input: "(1+(4+5+2)-3)+(6+8)" + * Output: 23 + */ +public class BasicCalculator { + public int calculate(String s) { + s = s.replaceAll(" ", ""); + + Stack stack = new Stack<>(); + + int start = 0; + int mul = 1; + int end = 0; + for (end = 0; end < s.length(); end++) { + if (s.charAt(end) == '+' || s.charAt(end) == '-') { + if (start < end) { + int n = mul * Integer.valueOf(s.substring(start, end)); + stack.push(n); + } + + mul = s.charAt(end) == '-' ? -1: 1; + start = end + 1; + } else if (s.charAt(end) == '(') { + // find closing + int close = end + 1; + int openBrace = 0; + while (++end < s.length()) { + if (s.charAt(end) == '(') openBrace++; + if (s.charAt(end) == ')' && openBrace == 0) break; + else if (s.charAt(end) == ')') openBrace--; + } + stack.push(mul * calculate(s.substring(close, end))); + start = end + 1; + } + } + if (start < end) stack.push(mul * Integer.valueOf(s.substring(start))); + + int sum = 0; + while(!stack.isEmpty()) { + sum += stack.pop(); + } + return sum; + } + + @Test + public void test1() { + assertEquals(2, calculate("1 + 1")); + assertEquals(3, calculate("2 - 1 +2")); + assertEquals(-11, calculate("-12 - 1 +2")); + assertEquals(-9, calculate("-(12 - 1) +2")); + assertEquals(23, calculate("(1+(4+5+2)-3)+(6+8)")); + } +} From 1b6769023ffe0e0b17ea2dd6c6d477e194e60cbc Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 14 Oct 2019 17:57:41 -0500 Subject: [PATCH 037/189] Added solution for binary watch --- .../algorithm/leetcode/BinaryWatch.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryWatch.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryWatch.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryWatch.java new file mode 100644 index 0000000..d925ef7 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryWatch.java @@ -0,0 +1,57 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom represent the minutes (0-59). + *

+ * Each LED represents a zero or one, with the least significant bit on the right. + *

+ *

+ * For example, the above binary watch reads "3:25". + *

+ * Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent. + *

+ * Example: + *

+ * Input: n = 1 + * Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"] + *

+ * https://leetcode.com/problems/binary-watch/ + */ +public class BinaryWatch { + private int[] vals = new int[]{1, 2, 4, 8, 1, 2, 4, 8, 16, 32}; + + public List readBinaryWatch(int num) { + List res = new ArrayList<>(); + backTrack(num, res, 0, 0, 0); + return res; + } + + private void backTrack(int n, List res, int hour, int min, int start) { + if (n == 0) { + res.add(hour + ":" + (min < 10 ? "0" + min : min)); + } else { + for (int i = start; i < vals.length; i++) { + if (hour > 11 || min > 59) continue; + if (i <= 3) + backTrack(n - 1, res, hour + vals[i], min, i + 1); + else + backTrack(n - 1, res, hour, min + vals[i], i + 1); + } + } + } + + + @Test + public void test() { + List actual = readBinaryWatch(1); + List expected = Arrays.asList("1:00, 2:00, 4:00, 8:00, 0:01, 0:02, 0:04, 0:08, 0:16, 0:32".split(", ")); + assertThat(actual, is(expected)); + } +} From 4c193ff7af908b398e2477b8f43fd9a879d05057 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 15 Oct 2019 08:01:44 -0500 Subject: [PATCH 038/189] Added solution for binary tree tilt --- .../algorithm/trees/BinaryTreeTilt.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/BinaryTreeTilt.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/BinaryTreeTilt.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/BinaryTreeTilt.java new file mode 100644 index 0000000..3cf1502 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/BinaryTreeTilt.java @@ -0,0 +1,78 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * Given a binary tree, return the tilt of the whole tree. + * + * The tilt of a tree node is defined as the absolute difference between the sum of all left subtree node values and the sum of all right subtree node values. Null node has tilt 0. + * + * The tilt of the whole tree is defined as the sum of all nodes' tilt. + * + * Example: + * Input: + * 1 + * / \ + * 2 3 + * Output: 1 + * Explanation: + * Tilt of node 2 : 0 + * Tilt of node 3 : 0 + * Tilt of node 1 : |2-3| = 1 + * Tilt of binary tree : 0 + 0 + 1 = 1 + */ +public class BinaryTreeTilt { + private Map nodeSum = new HashMap<>(); + public int findTilt(TreeNode root) { + if (root == null) return 0; + int leftSum = findSum(root.left); + int rightSum = findSum(root.right); + + int rootTilt = Math.abs(leftSum - rightSum); + return rootTilt + findTilt(root.left) + findTilt(root.right); + } + + private int findSum(TreeNode root) { + if (root == null) return 0; + int sum = 0; + if (nodeSum.containsKey(root)) { + sum = nodeSum.get(root); + } else { + sum = root.val + findSum(root.left) + findSum(root.right); + nodeSum.put(root, sum); + } + + return sum; + } + + /** + * 6 + * / \ + * 3 7 + * / \ \ + * 2 5 1 + * \ + * 10 + *

+ * 6 -> 3 -> 2 -> 5 -> 7 -> 1 -> 10 + */ + @Test + public void test1() { + TreeNode root = new TreeNode(6); + root.left = new TreeNode(3); + root.right = new TreeNode(7); + + root.right.right = new TreeNode(1); + + root.left.left = new TreeNode(2); + root.left.right = new TreeNode(5); + root.right.right.right = new TreeNode(10); + + assertEquals(32, findTilt(root)); + } +} From 8e86b04701ee6e76ca9a92dd45de87596bb9201d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 15 Oct 2019 08:04:38 -0500 Subject: [PATCH 039/189] Added solution for pathSumIII --- .../examples/algorithm/trees/PathSumIII.java | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/PathSumIII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathSumIII.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathSumIII.java new file mode 100644 index 0000000..05a540d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathSumIII.java @@ -0,0 +1,115 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import static org.junit.Assert.assertEquals; + +/** + * You are given a binary tree in which each node contains an integer value. + * + * Find the number of paths that sum to a given value. + * + * The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). + * + * The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000. + * + * Example: + * + * root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 + * + * 10 + * / \ + * 5 -3 + * / \ \ + * 3 2 11 + * / \ \ + * 3 -2 1 + * + * Return 3. The paths that sum to 8 are: + * + * 1. 5 -> 3 + * 2. 5 -> 2 -> 1 + * 3. -3 -> 11 + * + * + * + * https://leetcode.com/problems/path-sum-iii/ + */ +public class PathSumIII { + public int pathSum(TreeNode root, int sum) { + int count = 0; + if (root == null) return count; + + Queue q = new LinkedList<>(); + q.add(root); + while (!q.isEmpty()) { + TreeNode node = q.poll(); + List> paths = new ArrayList<>(); + dfs(node, paths, new ArrayList<>(), sum); + count += paths.size(); + + if (node.left != null) q.add(node.left); + if (node.right != null) q.add(node.right); + } + return count; + } + + private void dfs(TreeNode node, List> paths, List temp, int sum) { + if (node == null) return; + + temp.add(node.val); + if (sum - node.val == 0) { + paths.add(new ArrayList<>(temp)); + } + dfs(node.left, paths, temp, sum - node.val); + dfs(node.right, paths, temp, sum - node.val); + + temp.remove(temp.size() - 1); + } + + /** + * 6 + * / \ + * 3 7 + * / \ \ + * 2 5 1 + * \ + * 10 + *

+ * 6 -> 3 -> 2 -> 5 -> 7 -> 1 -> 10 + */ + @Test + public void test1() { + TreeNode root = new TreeNode(6); + root.left = new TreeNode(3); + root.right = new TreeNode(7); + + root.right.right = new TreeNode(1); + + root.left.left = new TreeNode(2); + root.left.right = new TreeNode(5); + root.right.right.right = new TreeNode(10); + + assertEquals(2, pathSum(root, 11)); + } + + @Test + public void test2() { + TreeNode root = new TreeNode(1); + root.left = new TreeNode(-2); + root.right = new TreeNode(-3); + + root.left.left = new TreeNode(1); + root.left.right = new TreeNode(3); + root.right.left = new TreeNode(-2); + + root.left.left.left = new TreeNode(-1); + + assertEquals(4, pathSum(root, -1)); + } +} From d63c2844353850697a48428b500bad7438ce7b07 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 15 Oct 2019 08:05:37 -0500 Subject: [PATCH 040/189] upadating hamcrest matcher --- .../com/eprogrammerz/examples/algorithm/trees/PathToSum.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java index 9e6dcef..ef0a7a6 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PathToSum.java @@ -6,7 +6,7 @@ import java.util.Arrays; import java.util.List; -import static org.hamcrest.Matchers.contains; +import static org.hamcrest.CoreMatchers.hasItems; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -84,7 +84,7 @@ public void testPathSum() { // add right node to rightest node on last level root.right.right.right = new TreeNode(10); List> actual2 = pathSum(root, 24); - assertThat(actual2, contains(Arrays.asList(6, 7, 1, 10))); + assertThat(actual2, hasItems(Arrays.asList(6, 7, 1, 10))); } } From 61b5048c68d712bd6ab49167b41f48632b8e00a6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 15 Oct 2019 18:08:25 -0500 Subject: [PATCH 041/189] Added solution for trie ds --- .../examples/ds/custom/trie/TrieExample.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/trie/TrieExample.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/TrieExample.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/TrieExample.java new file mode 100644 index 0000000..f2fddeb --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/TrieExample.java @@ -0,0 +1,98 @@ +package com.eprogrammerz.examples.ds.custom.trie; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +public class TrieExample { + @Test + public void test() { + Trie trie = new Trie(); + trie.insert("apple"); + assertTrue(trie.search("apple")); + assertFalse(trie.search("app")); + assertTrue(trie.startsWith("app")); + + trie.insert("app"); + assertTrue(trie.search("app")); + + trie.insert("example"); + trie.insert("elephant"); + trie.insert("ex"); + + assertTrue(trie.search("example")); + assertTrue(trie.startsWith("ele")); + assertFalse(trie.startsWith("le")); + } +} + +class Trie { + private TrieNode root; + /** Initialize your data structure here. */ + public Trie() { + root = new TrieNode('#'); + } + + /** Inserts a word into the trie. */ + public void insert(String word) { + this.root.insert(word); + } + + /** Returns if the word is in the trie. */ + public boolean search(String word) { + return this.root.search(word); + } + + /** Returns if there is any word in the trie that starts with the given prefix. */ + public boolean startsWith(String prefix) { + return this.root.startsWith(prefix); + } +} + +class TrieNode { + private char data; + private Map children; + TrieNode(char data) { + this.data = data; + this.children = new HashMap<>(); + } + + public boolean startsWith(String word) { + if (word.isEmpty()) return true; + char ch = word.charAt(0); + TrieNode child = children.get(ch); + if (child == null) return false; + return child.startsWith(word.substring(1)); + } + + public boolean search(String word) { + if (word == null) return false; + if (word.isEmpty() && children.containsKey('\0')) return true; + if (word.isEmpty()) return false; + + char ch = word.charAt(0); + TrieNode child = children.get(ch); + if (child == null) return false; + return child.search(word.substring(1)); + } + + public void insert(String word) { + if (word != null && word.length() > 0) { + char ch = word.charAt(0); + TrieNode child = children.get(ch); + if (child == null) { + child = new TrieNode(ch); + children.put(ch, child); + } + + child.insert(word.substring(1)); + + } else { + children.put('\0', null); + } + } +} From 8832accbd3491e1464f90808e69acae4ff4b944e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 15 Oct 2019 18:12:12 -0500 Subject: [PATCH 042/189] Added example of bayer-moore text search --- .../leetcode/BayerMooreTextSearch.java | 74 +++++++++++++++++ .../algorithm/leetcode/FindAllAnagrams.java | 81 +++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BayerMooreTextSearch.java create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FindAllAnagrams.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BayerMooreTextSearch.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BayerMooreTextSearch.java new file mode 100644 index 0000000..b019a16 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BayerMooreTextSearch.java @@ -0,0 +1,74 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Given string text t of length m and pattern p of length n, find all the indices + * of the starting of p in t + * + * example: + * Text: abcabcdefabc + * P: abc + * + * output: [0,3,9] + */ +public class BayerMooreTextSearch { + public List searchPatterns(String t, String p) { + List l = new ArrayList<>(); + + if (t.length() < p.length()) return l; + + Set set = new HashSet<>(); + for (char ch: p.toCharArray()) { + set.add(ch); + } + + int end = p.length() - 1; + + while (end < t.length()) { + if (t.charAt(end) == p.charAt(p.length() - 1)) { + // do back search + boolean found = true; + int tIdx = 0; + for (int i = p.length() - 1; i >= 0; i--) { + if (t.charAt(end - tIdx++) != p.charAt(i)) { + found = false; + break; + } + } + if (found) { + l.add(end - p.length() + 1); + } + end++; + } else { + // if t.charAt(end) is one of char in p, then end++ + // else jump by p.length() + if (set.contains(t.charAt(end))) { + end++; + } else { + end += p.length(); + } + } + } + return l; + } + + @Test + public void test1() { + List expected = Arrays.asList(0, 3, 9); + List actual = searchPatterns("abcabcdefabc", "abc"); + assertThat(actual, is(expected)); + } + + @Test + public void test2() { + List expected = Arrays.asList(0, 2, 4, 6, 8); + List actual = searchPatterns("abababababa", "aba"); + assertThat(actual, is(expected)); + } +} diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FindAllAnagrams.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FindAllAnagrams.java new file mode 100644 index 0000000..171e23d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FindAllAnagrams.java @@ -0,0 +1,81 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.is; + +/** + * Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. + * + * Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100. + * + * The order of output does not matter. + * + * Example 1: + * + * Input: + * s: "cbaebabacd" p: "abc" + * + * Output: + * [0, 6] + * + * Explanation: + * The substring with start index = 0 is "cba", which is an anagram of "abc". + * The substring with start index = 6 is "bac", which is an anagram of "abc". + */ +public class FindAllAnagrams { + public List findAnagrams(String s, String p) { + List l = new ArrayList<>(); + if (s.length() < p.length()) return l; + Map map = new HashMap<>(); + for (char ch: p.toCharArray()) { + map.put(ch, map.getOrDefault(ch, 0) + 1); + } + + int end = p.length() - 1; + + while (end < s.length()) { + if (map.containsKey(s.charAt(end))) { + // match + Map temp = new HashMap<>(map); + + int j = 0; + for (int i = p.length() - 1; i >= 0; i--) { + char ch = s.charAt(end - j++); + if (!temp.containsKey(ch)) { + break; + } + + int count = temp.get(ch) - 1; + if (count == 0) temp.remove(ch); + else temp.put(ch, count); + } + + if (temp.isEmpty()) { + l.add(end - p.length() + 1); + } + end++; + } else { + end += p.length(); + } + } + return l; + } + + @Test + public void test1() { + List expected = Arrays.asList(0, 6); + List actual = findAnagrams("cbaebabacd", "abc"); + assertThat(actual, is(expected)); + } + + @Test + public void test2() { + List expected = Arrays.asList(0, 1, 2); + List actual = findAnagrams("abab", "ab"); + assertThat(actual, is(expected)); + } +} From fd321af5e1e342d72a678dd9e7f458ef82366d94 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 15 Oct 2019 19:24:47 -0500 Subject: [PATCH 043/189] Added solution to word dictionary --- .../ds/custom/trie/WordDictionaryTest.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/trie/WordDictionaryTest.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/WordDictionaryTest.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/WordDictionaryTest.java new file mode 100644 index 0000000..9498723 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/WordDictionaryTest.java @@ -0,0 +1,121 @@ +package com.eprogrammerz.examples.ds.custom.trie; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +/** + * Design a data structure that supports the following two operations: + * + * void addWord(word) + * bool search(word) + * search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter. + * + * Example: + * + * addWord("bad") + * addWord("dad") + * addWord("mad") + * search("pad") -> false + * search("bad") -> true + * search(".ad") -> true + * search("b..") -> true + */ +public class WordDictionaryTest { + @Test + public void test1() { + WordDictionary dictionary = new WordDictionary(); + dictionary.addWord("a"); + dictionary.addWord("a"); + + assertTrue(dictionary.search(".")); + assertTrue(dictionary.search("a")); + assertFalse(dictionary.search("aa")); + assertTrue(dictionary.search("a")); + assertFalse(dictionary.search("a.")); + assertFalse(dictionary.search(".a")); + + dictionary.addWord("add"); + assertTrue(dictionary.search("a.d")); + } + + @Test + public void test2() { + WordDictionary dictionary = new WordDictionary(); + dictionary.addWord("at"); + dictionary.addWord("and"); + dictionary.addWord("an"); + dictionary.addWord("add"); + assertFalse(dictionary.search(".at")); + dictionary.addWord("bat"); + assertTrue(dictionary.search(".at")); + } +} + +class WordDictionary { + + private Node root; + /** Initialize your data structure here. */ + public WordDictionary() { + this.root = new Node('#'); + } + + /** Adds a word into the data structure. */ + public void addWord(String word) { + root.addWord(word); + } + + /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ + public boolean search(String word) { + return root.search(word); + } +} + +class Node { + char data; + Map children; + Node(char data) { + this.data = data; + this.children = new HashMap<>(); + } + + void addWord(String word) { + if (word == null) return; + + if (word.isEmpty()) { + children.put('\0', null); + return; + } + + char ch = word.charAt(0); + Node child = children.get(ch); + if (child == null) { + child = new Node(ch); + children.put(ch, child); + } + child.addWord(word.substring(1)); + } + + boolean search(String word) { + if (word == null) return false; + if (word.isEmpty() && children.containsKey('\0')) return true; + if (word.isEmpty()) return false; + char ch = word.charAt(0); + if (ch == '.') { + boolean has = false; + for (Node node: children.values()) { + if (node != null) { + has = has || node.search(word.substring(1)); + } + } + return has; + } + Node child = children.get(ch); + if (child == null) return false; + return child.search(word.substring(1)); + } +} \ No newline at end of file From 6b95f6c9a425dcea5116ec6d6ca38efdc510c70c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 16 Oct 2019 18:58:51 -0500 Subject: [PATCH 044/189] Added solution for freq stack --- .../examples/ds/custom/stack/FreqStack.java | 70 +++++++++++++++++++ .../examples/ds/custom/stack/Validator.java | 40 +++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java new file mode 100644 index 0000000..31b01b5 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java @@ -0,0 +1,70 @@ +package com.eprogrammerz.examples.ds.custom.stack; + +import java.util.HashMap; +import java.util.Map; + +public class FreqStack { + private Node head; + private Map map; + + public FreqStack() { + this.map = new HashMap<>(); + } + + public void push(int x) { + Node node = new Node(x); + if (head == null) { + head = node; + } else { + node.next = head; + head = node; + } + + map.put(x, map.getOrDefault(x, 0) + 1); + + } + + public int pop() { + int freq = findFreq(); + if (map.get(head.val) == freq) { + int x = head.val; + head = head.next; + map.put(x, freq - 1); + return x; + } else { + Node prev = head; + Node node = head.next; + // search for requent element and update + while (node != null) { + if (map.get(node.val) == freq) { + prev.next = node.next; + map.put(node.val, freq - 1); + return node.val; + } + prev = node; + node = node.next; + } + } + return Integer.MIN_VALUE; + } + + private int findFreq() { + int top = Integer.MIN_VALUE; + for (int k: map.keySet()) { + int v = map.get(k); + if (v > top) { + top = v; + } + } + return top; + } + + static class Node { + int val; + Node next; + Node(int val) { + this.val = val; + this.next = null; + } + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java index b0c869f..db5ce2c 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java @@ -83,4 +83,44 @@ public void testStackWQueue() { assertEquals(4, stack.pop()); assertEquals(1, stack.pop()); } + + @Test + public void testFreqStack1() { + FreqStack stack = new FreqStack(); + stack.push(5); + stack.push(7); + stack.push(5); + stack.push(7); + stack.push(4); + stack.push(5); + assertEquals(5, stack.pop()); + assertEquals(7, stack.pop()); + assertEquals(5, stack.pop()); + assertEquals(4, stack.pop()); + } + + @Test + public void testFreqStack2() { + FreqStack stack = new FreqStack(); + stack.push(5); + stack.push(1); + stack.push(2); + stack.push(5); + stack.push(5); + stack.push(5); + stack.push(1); + stack.push(6); + stack.push(1); + stack.push(5); + assertEquals(5, stack.pop()); // 5 -> 5, 1 -> 3 + assertEquals(5, stack.pop()); // 5 -> 4, 1 -> 3 + assertEquals(1, stack.pop()); // 5 -> 3, 1 -> 3 + assertEquals(5, stack.pop()); // 5 -> 3, 1 -> 2 + assertEquals(1, stack.pop()); // 5 -> 2, 1 -> 2 + assertEquals(5, stack.pop()); // 5 -> 2, 1 -> 1 + assertEquals(6, stack.pop()); // 5 -> 1, 1 -> 1 + assertEquals(2, stack.pop()); // 5 -> 1, 1 -> 1 + assertEquals(1, stack.pop()); // 5 -> 1, 1 -> 1 + assertEquals(5, stack.pop()); // 5 -> 1, 1 -> 1 + } } From 2a42c8e00f6a7daef4d440bbbbbf73c202e4220f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 18 Oct 2019 20:26:02 -0500 Subject: [PATCH 045/189] Added solution for coloring garden --- .../algorithm/graphs/FloweringPlants.java | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/FloweringPlants.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/FloweringPlants.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/FloweringPlants.java new file mode 100644 index 0000000..07718a3 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/FloweringPlants.java @@ -0,0 +1,116 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertArrayEquals; + + +/** + * You have N gardens, labelled 1 to N. In each garden, you want to plant one of 4 types of flowers. + * + * paths[i] = [x, y] describes the existence of a bidirectional path from garden x to garden y. + * + * Also, there is no garden that has more than 3 paths coming into or leaving it. + * + * Your task is to choose a flower type for each garden such that, for any two gardens connected by a path, they have different types of flowers. + * + * Return any such a choice as an array answer, where answer[i] is the type of flower planted in the (i+1)-th garden. + * The flower types are denoted 1, 2, 3, or 4. It is guaranteed an answer exists. + * + * + * + * Example 1: + * + * Input: N = 3, paths = [[1,2],[2,3],[3,1]] + * Output: [1,2,3] + */ +public class FloweringPlants { + public int[] gardenNoAdj(int N, int[][] paths) { + // 1 --- 2 + // | | + // --3-- + + // adjacency matrix + // 1 - [2,3] + // 2 - [1,3] + // 3 - [1,2] + + // 1 - 1 + // 2 - 2 + int[] colors = new int[N]; + + Arrays.fill(colors, 1); + + Map> gardens = new HashMap<>(); + + for (int[] path : paths) { + List neighbors = gardens.get(path[0]); + if (neighbors == null) { + neighbors = new ArrayList<>(); + } + neighbors.add(path[1]); + gardens.put(path[0], neighbors); + + neighbors = gardens.get(path[1]); + if (neighbors == null) { + neighbors = new ArrayList<>(); + } + neighbors.add(path[0]); + gardens.put(path[1], neighbors); + } + + for (int garden : gardens.keySet()) { + List neighbors = gardens.get(garden); + + int[] gone = new int[5]; + for (int n : neighbors) { + if (colors[n - 1] != -1) { + gone[colors[n - 1]] = colors[n - 1]; + } + } + + int color = 1; + + for (int i = 1; i <= 5; i++) { + if (gone[i] != i) { + color = i; + break; + } + } + colors[garden - 1] = color; + } + return colors; + } + + @Test + public void test1() { + int[] expected = new int[]{2, 3, 1}; + int[][] paths = new int[][]{ + {1, 2}, + {2, 3}, + {3, 1} + }; + assertArrayEquals(expected, gardenNoAdj(3, paths)); + } + + @Test + public void test2() { + int[] expected = new int[]{2, 1, 2, 1}; + int[][] paths = new int[][]{ + {1, 2}, + {3, 4} + }; + assertArrayEquals(expected, gardenNoAdj(4, paths)); + } + + @Test + public void test3() { + int[] expected = new int[]{2, 3, 4, 1}; + int[][] paths = new int[][]{ + {1, 2}, {2, 3}, {3, 4}, {4, 1}, {1, 3}, {2, 4} + }; + assertArrayEquals(expected, gardenNoAdj(4, paths)); + } +} From 52f4103dfa6d610b445f221adba84c0b2656311d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 18 Oct 2019 20:26:51 -0500 Subject: [PATCH 046/189] Added solution to serialize and deserialize tree --- .../trees/SerializeDeserializeTree.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/SerializeDeserializeTree.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/SerializeDeserializeTree.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/SerializeDeserializeTree.java new file mode 100644 index 0000000..b951ffb --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/SerializeDeserializeTree.java @@ -0,0 +1,92 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * serialize given tree to string (bits representation so that it can be written in some form of memory or transmitted over the network + * + * and deserialize the string to the tree + */ +public class SerializeDeserializeTree { + // Encodes a tree to a single string. + // Time - O(n) + // Space - O(n) + public String serialize(TreeNode root) { + if (root == null) return ""; + if (root.left == null && root.right == null) return "" + root.val; + + if (root.right == null) return root.val + "(" + serialize(root.left) + ")"; + + return root.val + "(" + serialize(root.left) + ")(" + serialize(root.right) + ")"; + } + + // Decodes your encoded data to tree. + // Time - O(n) + // Space - O(n) + public TreeNode deserialize(String data) { + if ("".equals(data) || "()".equals(data)) return null; + int idx = data.indexOf("("); + + if (idx < 0) { + return new TreeNode(Integer.valueOf(data)); + } else { + String num = data.substring(0, idx); + if ("".equals(num)) return null; + TreeNode node = new TreeNode(Integer.valueOf(num)); + String remaining = data.substring(idx); + int close = closeIdx(remaining); + node.left = deserialize(remaining.substring(1, close)); + if (close + 2 < remaining.length()) + node.right = deserialize(remaining.substring(close + 2, remaining.length() - 1)); + else + node.right = null; + return node; + } + } + + private int closeIdx(String str) { + int open = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == '(') { + open++; + } else if (str.charAt(i) == ')') { + open--; + if (open == 0) return i; + } + } + return -1; + } + + @Test + public void test() { + /** + * 2 + * / \ + * 1 3 + * / \ + * 4 5 + */ + TreeNode root = new TreeNode(2); + root.left = new TreeNode(1); + root.right = new TreeNode(3); + + root.left.left = new TreeNode(4); + root.right.right = new TreeNode(5); + + String serialize = serialize(root); + assertEquals("2(1(4))(3()(5))", serialize); + + TreeNode deserialize = deserialize(serialize); + assertTrue(sameTree(root, deserialize)); + } + + private boolean sameTree(TreeNode t1, TreeNode t2) { + if (t1 == null && t2 == null) return true; + if (t1 == null || t2 == null || (t1.val != t2.val)) return false; + + return sameTree(t1.left, t2.left) && sameTree(t1.right, t2.right); + } +} From 0a8108334a8f0d101255020e16dd41b4e8aa509c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 19 Oct 2019 13:47:33 -0500 Subject: [PATCH 047/189] Added solution for closest points --- .../leetcode/ClosestPoint2Origin.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java new file mode 100644 index 0000000..3cd185e --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java @@ -0,0 +1,75 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.PriorityQueue; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * We have a list of points on the plane. Find the K closest points to the origin (0, 0). + * + * (Here, the distance between two points on a plane is the Euclidean distance.) + * + * You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.) + * + * + * + * Example 1: + * + * Input: points = [[1,3],[-2,2]], K = 1 + * Output: [[-2,2]] + * Explanation: + * The distance between (1, 3) and the origin is sqrt(10). + * The distance between (-2, 2) and the origin is sqrt(8). + * Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin. + * We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]]. + */ +public class ClosestPoint2Origin { + public int[][] kClosest(int[][] points, int K) { + PriorityQueue pq = new PriorityQueue<>((e1, e2) -> { + return Double.compare(e2.dis, e1.dis); + }); + + for (int[] point : points) { + int x = point[0]; + int y = point[1]; + double dis = Math.sqrt(x * x + y * y); + pq.add(new Pair(dis, point)); + + if (pq.size() > K) { + pq.poll(); + } + } + + int[][] res = new int[K][2]; + int i = 0; + while (!pq.isEmpty()) { + Pair p = pq.poll(); + res[i++] = p.point; + } + return res; + } + + @Test + public void test1() { + int[][] points = new int[][]{ + {1, 3}, + {-2, 2} + }; + int[][] kClosest = kClosest(points, 1); + int[][] expected = new int[][] {{-2, 2}}; + assertThat(kClosest, is(expected)); + } +} + +class Pair { + double dis; + int[] point; + + Pair(double dis, int[] point) { + this.dis = dis; + this.point = point; + } +} \ No newline at end of file From cfab66a85c98d5c2779da70b7cf67d9d17cab98e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 31 Oct 2019 04:02:07 -0500 Subject: [PATCH 048/189] Solution to add to linkedList with recursion --- .../ds/custom/linkedList/AddTwoNumII.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/AddTwoNumII.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/AddTwoNumII.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/AddTwoNumII.java new file mode 100644 index 0000000..16842d2 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/AddTwoNumII.java @@ -0,0 +1,72 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/add-two-numbers-ii/ + *

+ * Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) + * Output: 7 -> 8 -> 0 -> 7 + */ +public class AddTwoNumII { + + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + int len1 = 0; + int len2 = 0; + ListNode h1 = l1; + while (h1 != null) { + len1++; + h1 = h1.next; + } + + ListNode h2 = l2; + while (h2 != null) { + len2++; + h2 = h2.next; + } + ListNode sum = traverse(l1, l2, len1, len2); + return sum.val == 0 ? sum.next: sum; + } + + private ListNode traverse(ListNode l1, ListNode l2, int len1, int len2) { + if (l1 == null && l2 == null) return new ListNode(0); + ListNode next; + int sum; + if (len1 == len2) { + next = traverse(l1.next, l2.next, len1 - 1, len2 - 1); + sum = l1.val + l2.val + next.val; + } else if (len1 > len2) { + next = traverse(l1.next, l2, len1 - 1, len2); + sum = l1.val + next.val; + } else { + next = traverse(l1, l2.next, len1, len2 - 1); + sum = l2.val + next.val; + } + + ListNode node = new ListNode(sum / 10); + next.val = sum % 10; + + node.next = next; + + return node; + } + + @Test + public void test() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(3); + ListNode n3 = new ListNode(8); + n1.next = n2; + n2.next = n3; + + ListNode m1 = new ListNode(2); + ListNode m2 = new ListNode(4); + m1.next = m2; + + ListNode sum = addTwoNumbers(n1, m1); + assertEquals("1 -> 6 -> 2", printList(sum)); + } +} From 236a74fdbe3eb63f39b506fa222ac098390dde6f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 31 Oct 2019 04:44:08 -0500 Subject: [PATCH 049/189] Added recursive solution to swap node pair in linkedlist --- .../ds/custom/linkedList/SwapPair.java | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java index 2926af6..b93bf92 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SwapPair.java @@ -2,6 +2,14 @@ import org.junit.Test; +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * Given a linked list, swap every two adjacent nodes and return its head. + * + * e.g. for a list 1-> 2 -> 3 -> 4, one should return the head of list as 2 -> 1 -> 4 -> 3. + */ public class SwapPair { public ListNode swapPairs(ListNode A) { // temp = current.next @@ -46,6 +54,42 @@ public void testSwapPair() { n7.next = n8; n8.next = n9; ListNode node = swapPairs(n1); - System.out.println(node); + assertEquals("2 -> 1 -> 4 -> 3 -> 6 -> 5 -> 8 -> 7 -> 9", printList(node)); + } + + public ListNode swapPairsRec(ListNode A) { + // first swap two + // call swap with A.next.next + if (A == null || A.next == null) return A; + + ListNode temp = A.next.next; + + A.next.next = A; + ListNode head = A.next; + A.next = swapPairsRec(temp); + return head; + } + + @Test + public void testSwapPairRec() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + ListNode node = swapPairsRec(n1); + assertEquals("2 -> 1 -> 4 -> 3 -> 6 -> 5 -> 8 -> 7 -> 9", printList(node)); } } From 862d47215322f4b4b2b611fe12d1ccf800d023f5 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 31 Oct 2019 16:41:17 -0500 Subject: [PATCH 050/189] Added solution for reverse linkedlist rec --- .../ds/custom/linkedList/ReverseList.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseList.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseList.java new file mode 100644 index 0000000..16f9e36 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseList.java @@ -0,0 +1,48 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import org.junit.Test; + +import static com.eprogrammerz.examples.ds.custom.linkedList.ListUtil.printList; +import static org.junit.Assert.assertEquals; + +/** + * Reverse a singly linked list. + * + * Example: + * + * Input: 1->2->3->4->5->NULL + * Output: 5->4->3->2->1->NULL + */ +public class ReverseList { + public ListNode reverseList(ListNode head) { + if (head == null || head.next == null) return head; + ListNode revHead = reverseList(head.next); + head.next.next = head; + head.next = null; + return revHead; + } + + @Test + public void testReverse() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(3); + ListNode n4 = new ListNode(4); + ListNode n5 = new ListNode(5); + ListNode n6 = new ListNode(6); + ListNode n7 = new ListNode(7); + ListNode n8 = new ListNode(8); + ListNode n9 = new ListNode(9); + n1.next = n2; + n2.next = n3; + n3.next = n4; + n4.next = n5; + n5.next = n6; + n6.next = n7; + n7.next = n8; + n8.next = n9; + + ListNode res = reverseList(n1); + assertEquals("9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1", printList(res)); + } +} From e2a636c5df57c2e8a34db4974d345072edd81eec Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 1 Nov 2019 05:25:15 -0500 Subject: [PATCH 051/189] Added solution for search in rotated sorted array --- .../leetcode/SearchRotatedArray.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SearchRotatedArray.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SearchRotatedArray.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SearchRotatedArray.java new file mode 100644 index 0000000..9db46f8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SearchRotatedArray.java @@ -0,0 +1,67 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. + *

+ * (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).s + *

+ * Input: nums = [4,5,6,7,0,1,2], target = 0 + * Output: 4 + *

+ *

+ * https://leetcode.com/problems/search-in-rotated-sorted-array/ + */ +public class SearchRotatedArray { + public int search(int[] nums, int target) { + int start = 0; + int end = nums.length - 1; + + while (start <= end) { + int mid = start + (end - start) / 2; + if (nums[mid] == target) return mid; + + // if left part is sorted + if (nums[start] <= nums[mid]) { + // make sure target falls in sorted part + if (nums[start] <= target && target < nums[mid]) { + end = mid - 1; + } else { + start = mid + 1; + } + } else { + + if (nums[mid] < target && target <= nums[end]) { + start = mid + 1; + } else { + end = mid - 1; + } + } + } + return -1; + } + + @Test + public void test1() { + assertEquals(0, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 4)); + assertEquals(1, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 5)); + assertEquals(2, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 6)); + assertEquals(3, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 7)); + assertEquals(4, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 0)); + assertEquals(5, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 1)); + assertEquals(6, search(new int[]{4, 5, 6, 7, 0, 1, 2}, 2)); + } + + @Test + public void test2() { + assertEquals(4, search(new int[]{4, 5, 6, 7, 8, 1, 2, 3}, 8)); + } + + @Test + public void test3() { + assertEquals(1, search(new int[]{3, 1}, 1)); + } +} From 7cdd737e1d886a882551447216475f124414ef07 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 2 Nov 2019 09:32:42 -0500 Subject: [PATCH 052/189] Added solution for valid palindrome II --- .../algorithm/leetcode/ValidPalindromeII.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidPalindromeII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidPalindromeII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidPalindromeII.java new file mode 100644 index 0000000..53e3226 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidPalindromeII.java @@ -0,0 +1,47 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +/** + * Find if you can make a string palindrome by removing atmost one character + * + * https://leetcode.com/problems/valid-palindrome-ii/ + */ +public class ValidPalindromeII { + + public boolean validPalindrome(String s) { + if (s == null || s.isEmpty() || s.length() == 1) return true; + int start = 0; + int end = s.length() - 1; + while (start <= end) { + if (s.charAt(start) != s.charAt(end)) { + + return validPalindrome(s, start + 1, end) + || validPalindrome(s, start, end - 1); + } + start++; + end--; + } + return true; + } + + private boolean validPalindrome(String s, int start, int end) { + if (s.isEmpty()) return true; + while (start <= end) { + if (s.charAt(start) != s.charAt(end)) return false; + start++; + end--; + } + return true; + } + + @Test + public void test1() { + assertTrue(validPalindrome("abda")); + assertFalse(validPalindrome("abbcda")); + assertTrue(validPalindrome("aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga")); + } +} From e81d3da5675fb3d04466b5875a9284aac9521e41 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 3 Nov 2019 19:22:55 -0600 Subject: [PATCH 053/189] Added solution for open lock --- .../examples/algorithm/leetcode/OpenLock.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OpenLock.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OpenLock.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OpenLock.java new file mode 100644 index 0000000..cdd43ec --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OpenLock.java @@ -0,0 +1,68 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/open-the-lock/ + */ +public class OpenLock { + public int openLock(String[] deadends, String target) { + Set s = new HashSet<>(); + Collections.addAll(s, deadends); + + Queue q = new LinkedList<>(); + q.add("0000"); + + Set checked = new HashSet<>(); + + int step = 0; + while (!q.isEmpty()) { + int size = q.size(); + for (int i = 0; i < size; i++) { + String str = q.poll(); + if (target.equals(str)) return step; + + if (s.contains(str) || checked.contains(str)) continue; + + checked.add(str); + + for (int j = 0; j < 4; j++) { + char curr = str.charAt(j); + char left = (char) (curr - 1); + if (curr - '0' - 1 == -1) { + // set 9 + left = '9'; + } + // rotate left + + q.add(str.substring(0, j) + left + str.substring(j + 1)); + // rotate right + char right = (char) (curr + 1); + if (curr - '0' + 1 == 10) { + right = '0'; + } + q.add(str.substring(0, j) + right + str.substring(j + 1)); + } + } + + step++; + } + return -1; + } + + @Test + public void test() { + String[] deadends = new String[]{"0201", "0101", "0102", "1212", "2002"}; + assertEquals(6, openLock(deadends, "0202")); + } + + @Test + public void test1() { + String[] deadends = new String[] {"8888"}; + assertEquals(1, openLock(deadends, "0009")); + } +} From b2ad871794cf0f5b6705af471c2a5de7ffa36a5c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 3 Nov 2019 19:24:47 -0600 Subject: [PATCH 054/189] Updated solution for checking palindrome --- .../algorithm/leetcode/Palindrome.java | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Palindrome.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Palindrome.java index 5ae0ad9..7407d88 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Palindrome.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Palindrome.java @@ -18,7 +18,7 @@ public void testIsPalindrome() { assertFalse(isPalindrome(122321)); } - public static boolean isPalindrome(int x) { + public boolean isPalindrome(int x) { int originalVal = x; int reversedX = 0; while(x != 0) { @@ -27,4 +27,46 @@ public static boolean isPalindrome(int x) { } return originalVal == reversedX; } + + public boolean isPalindrome(String s) { + if (s.isEmpty()) return true; + int start = 0; + int end = s.length() - 1; + + while (start <= end) { + char startChar = s.charAt(start); + char endChar = s.charAt(end); + + // startChar is lowercase + if (startChar >= 'a' && startChar <= 'z') { + startChar = (char)('A' + (startChar - 'a')); + } + + if (endChar >= 'a' && endChar <= 'z') { + endChar = (char)('A' + (endChar - 'a')); + } + + if ((startChar < 'A' || startChar > 'Z') && (startChar < '0' || startChar > '9')) { + start++; + continue; + } + + if ((endChar < 'A' || endChar > 'Z') && (endChar < '0' || endChar > '9')) { + end--; + continue; + } + + if (startChar != endChar) { + return false; + } + start++; + end--; + } + return true; + } + + @Test + public void test() { + assertTrue(isPalindrome("A man, a plan, a canal: Panama")); + } } From bdf1d99101d9feb50b9a52a6deb02b464dd60e79 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 3 Nov 2019 19:26:31 -0600 Subject: [PATCH 055/189] Added solution for array right rotation inplace --- .../leetcode/ArrayRightRotation.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ArrayRightRotation.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ArrayRightRotation.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ArrayRightRotation.java new file mode 100644 index 0000000..ab1a703 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ArrayRightRotation.java @@ -0,0 +1,62 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +/** + * Given an array, rotate the array to the right by k steps, where k is non-negative. + * + * Example 1: + * + * Input: [1,2,3,4,5,6,7] and k = 3 + * Output: [5,6,7,1,2,3,4] + * Explanation: + * rotate 1 steps to the right: [7,1,2,3,4,5,6] + * rotate 2 steps to the right: [6,7,1,2,3,4,5] + * rotate 3 steps to the right: [5,6,7,1,2,3,4] + */ +public class ArrayRightRotation { + public void rotate(int[] nums, int k) { + // [5,6,7,1,2,3,4] + if (nums.length <= 1) return; + k = k % nums.length; + + int count = 0; + int i = 0; + while (count < nums.length) { + int start = i; + int temp = nums[i]; + + int end = (k + i) % nums.length; + while (start != end) { + int val = nums[end]; + nums[end] = temp; + temp = val; + end = (end + k) % nums.length; + count++; + } + nums[start] = temp; + count++; + i++; + } + + } + + @Test + public void test1() { + int[] expected = new int[] {5,6,7,1,2,3,4}; + int[] input = new int[] {1,2,3,4,5,6,7}; + rotate(input, 3); + assertArrayEquals(expected, input); + } + + + @Test + public void test2() { + int[] expected = new int[] {5,6,1,2,3,4}; + int[] input = new int[] {1,2,3,4,5,6}; + rotate(input, 2); + assertArrayEquals(expected, input); + } +} From 8791a50956cff89ca36746134fe9b93ecd3a9a6f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 5 Nov 2019 14:41:20 -0600 Subject: [PATCH 056/189] Added solution for NQueen --- .../algorithm/leetcode/NQueensII.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueensII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueensII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueensII.java new file mode 100644 index 0000000..931ce92 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueensII.java @@ -0,0 +1,85 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. + * + * + * + * Given an integer n, return the number of distinct solutions to the n-queens puzzle. + * + * Example: + * + * Input: 4 + * Output: 2 + * Explanation: There are two distinct solutions to the 4-queens puzzle as shown below. + * [ + * [".Q..", // Solution 1 + * "...Q", + * "Q...", + * "..Q."], + * + * ["..Q.", // Solution 2 + * "Q...", + * "...Q", + * ".Q.."] + * ] + */ +public class NQueensII { + private int[][] mem; + private int count; + public int totalNQueens(int n) { + mem = new int[n][n]; + + totalNQueens(n, 0); + return count; + } + + private void totalNQueens(int n, int r) { + for (int c = 0; c < n; c++) { + if (mem[r][c] == 0 && goodSpot(r, c)) { + mem[r][c] = 2; + if (r == n - 1) { + count++; + } else { + totalNQueens(n, r + 1); + } + mem[r][c] = 0; + } + } + } + + private boolean goodSpot(int r, int c) { + for (int col = 0; col < mem[0].length; col++) { + if (mem[r][col] != 0) return false; + } + + for (int row = 0; row < mem.length; row++) { + if (mem[row][c] != 0) return false; + } + + // main diagoal + for (int row = r - 1, col = c - 1; row >= 0 && col >= 0; row--, col--) { + if (mem[row][col] != 0) return false; + } + for (int row = r + 1, col = c + 1; row < mem.length && col < mem.length; row++, col++) { + if (mem[row][col] != 0) return false; + } + // opposite diagonal + for (int row = r - 1, col = c + 1; row >= 0 && col < mem.length; row--, col++) { + if (mem[row][col] != 0) return false; + } + for (int row = r + 1, col = c - 1; row < mem.length && col >= 0; row++, col--) { + if (mem[row][col] != 0) return false; + } + return true; + } + + @Test + public void test1() { + assertEquals(2, totalNQueens(4)); + } +} From 0dde1c5518a77ca9f71703625dffbbed7dd6d746 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 5 Nov 2019 21:25:03 -0600 Subject: [PATCH 057/189] Updated solution to find combinations --- .../eprogrammerz/examples/algorithm/leetcode/Combinations.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java index 684a4ce..14c4d42 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Combinations.java @@ -38,13 +38,12 @@ public List> combine(int n, int k) { private void backTrack(int n, int start, int k, List> l, List temp) { if (temp.size() == k) { l.add(new ArrayList<>(temp)); - temp.remove(temp.size() - 1); } else { for (int i = start; i <= n; i++) { temp.add(i); backTrack(n, i + 1, k, l, temp); + temp.remove(temp.size() - 1); } - if (!temp.isEmpty()) temp.remove(temp.size() - 1); } } From f66b97ec7628e3ae2a65466e6cd156809869f691 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 5 Nov 2019 21:25:45 -0600 Subject: [PATCH 058/189] Added solution to move zeros to the end inplace --- .../examples/algorithm/general/ZeroMover.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/ZeroMover.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/ZeroMover.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/ZeroMover.java new file mode 100644 index 0000000..a7b896b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/ZeroMover.java @@ -0,0 +1,42 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +/** + * move all the zeros to the end of the array + * [1,0,2,0,9] -> [1,2,9,0,0] + */ +public class ZeroMover { + public void moveZerosToEnd(int[] input) { + int zeroIdx = 0; + int nonZeroIdx = 0; + + while (zeroIdx < input.length && nonZeroIdx < input.length) { + if (input[zeroIdx] == 0) { + if (zeroIdx < nonZeroIdx && input[nonZeroIdx] != 0) { + swap(input, zeroIdx, nonZeroIdx); + } else { + nonZeroIdx++; + } + } else { + zeroIdx++; + nonZeroIdx++; + } + } + } + + public void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + @Test + public void test() { + int[] input = new int[] {1,0,2,0,9}; + moveZerosToEnd(input); + assertArrayEquals(new int[] {1,2,9,0,0}, input); + } +} From a79151e1a11c7b02b56fd9497b5c384269b385ad Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 8 Nov 2019 12:02:45 -0600 Subject: [PATCH 059/189] Added solution for strstr implementation --- .../examples/algorithm/leetcode/StrStr.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/StrStr.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/StrStr.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/StrStr.java new file mode 100644 index 0000000..f7cb76c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/StrStr.java @@ -0,0 +1,46 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/implement-strstr/ + */ +public class StrStr { + public int strStr(String haystack, String needle) { + if (haystack == null + || needle == null || needle.length() == 0) return 0; + + // pre-processing of needle + char[] s = new char[256]; + for (char ch : needle.toCharArray()) { + s[ch]++; + } + + int h = haystack.length(); + int n = needle.length(); + for (int i = 0; i + n < h; ) { + if (s[haystack.charAt(n - 1 + i)] > 0) { // haystack matches character, so look within + boolean matches = true; + int iEnd = n - 1 + i; + for (int j = n - 1; j >= 0; j--, iEnd--) { + if (needle.charAt(j) != haystack.charAt(iEnd)) { + matches = false; + break; + } + } + if (matches) return i; + i++; + } else { + i += n; + } + } + return -1; + } + + @Test + public void test1() { + assertEquals(2, strStr("hello", "ll")); + } +} From ffabb59fb54e2ff254f2c039d46968b874cb779e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 8 Nov 2019 12:04:17 -0600 Subject: [PATCH 060/189] Added solution for validating sudoku --- .../algorithm/leetcode/ValidSudoku.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidSudoku.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidSudoku.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidSudoku.java new file mode 100644 index 0000000..0d479d4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ValidSudoku.java @@ -0,0 +1,84 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static junit.framework.TestCase.*; + +/** + * https://leetcode.com/explore/featured/card/top-interview-questions-easy/92/array/769/ + * + * Determine if the filled suduko is valid + */ +public class ValidSudoku { + public boolean isValidSudoku(char[][] board) { + // valid row and col + // row++, col++ + for (int r = 0; r < board.length; r++) { + for (int c = 0; c < board[0].length; c++) { + if (board[r][c] != '.' && !valid(board, r, c)) { + return false; + } + } + } + return true; + } + + private boolean valid(char[][] board, int r, int c) { + // valid row + for (int col = 0; col < 9; col++) { + if (c != col && board[r][col] == board[r][c]) return false; + } + + // valid col + for (int row = 0; row < 9; row++) { + if (r != row && board[row][c] == board[r][c]) return false; + } + + int rStart = r / 3 * 3; + int cStart = c / 3 * 3; + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if ((i + rStart) != r && (j + cStart) != c + && board[i + rStart][j + cStart] == board[r][c]) { + return false; + } + } + } + + return true; + } + + @Test + public void test1() { + char[][] board = new char[][]{ + {'8', '3', '.', '.', '7', '.', '.', '.', '.'}, + {'6', '.', '.', '1', '9', '5', '.', '.', '.'}, + {'.', '9', '8', '.', '.', '.', '.', '6', '.'}, + {'8', '.', '.', '.', '6', '.', '.', '.', '3'}, + {'4', '.', '.', '8', '.', '3', '.', '.', '1'}, + {'7', '.', '.', '.', '2', '.', '.', '.', '6'}, + {'.', '6', '.', '.', '.', '.', '2', '8', '.'}, + {'.', '.', '.', '4', '1', '9', '.', '.', '5'}, + {'.', '.', '.', '.', '8', '.', '.', '7', '9'} + + }; + assertFalse(isValidSudoku(board)); + } + + @Test + public void test2() { + char[][] board = new char[][]{ + {'5', '3', '.', '.', '7', '.', '.', '.', '.'}, + {'6', '.', '.', '1', '9', '5', '.', '.', '.'}, + {'.', '9', '8', '.', '.', '.', '.', '6', '.'}, + {'8', '.', '.', '.', '6', '.', '.', '.', '3'}, + {'4', '.', '.', '8', '.', '3', '.', '.', '1'}, + {'7', '.', '.', '.', '2', '.', '.', '.', '6'}, + {'.', '6', '.', '.', '.', '.', '2', '8', '.'}, + {'.', '.', '.', '4', '1', '9', '.', '.', '5'}, + {'.', '.', '.', '.', '8', '.', '.', '7', '9'} + }; + assertTrue(isValidSudoku(board)); + } +} From ed97a85d8904eff4105c4577886d5b16a0013ed4 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 9 Nov 2019 12:32:55 -0600 Subject: [PATCH 061/189] Added solution to print numbers lexicographically ordered with dfs --- .../trees/LexicographicalNumbers.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/LexicographicalNumbers.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/LexicographicalNumbers.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/LexicographicalNumbers.java new file mode 100644 index 0000000..6184206 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/LexicographicalNumbers.java @@ -0,0 +1,51 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.hasItems; + +/** + * Given an integer n, return 1 - n in lexicographical order. + * + * For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9]. + * + * Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000. + * + * https://leetcode.com/problems/lexicographical-numbers/ + */ +public class LexicographicalNumbers { + public List lexicalOrder(int n) { + List l = new LinkedList<>(); + for (int i = 1; i <= 9; i++) { + dfs(n, l, i); + } + return l; + } + + private void dfs(int n, List l, int start) { + if (start > n) return; + l.add(start); + for (int i = 0; i <= 9; i++) { + dfs(n, l, start * 10 + i); + } + } + + @Test + public void test1() { + List numbers = lexicalOrder(20); + assertEquals(20, numbers.size()); + } + + @Test + public void test2() { + List numbers = lexicalOrder(10); + assertEquals(10, numbers.size()); + assertThat(numbers, hasItems(1,10,2,3,4,5,6,7,8,9)); + } +} + + From d25e746e639b2dc08570e0e9fae07caf46c21208 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 12 Nov 2019 11:57:46 -0600 Subject: [PATCH 062/189] Added solution for longest arithmetic subseq --- .../leetcode/LongestArithmeticSubseq.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestArithmeticSubseq.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestArithmeticSubseq.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestArithmeticSubseq.java new file mode 100644 index 0000000..62534c9 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestArithmeticSubseq.java @@ -0,0 +1,62 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/longest-arithmetic-subsequence-of-given-difference/ + */ +public class LongestArithmeticSubseq { + public int longestSubsequence(int[] arr, int difference) { + //1,5,7,8,5,3,4,2,1, d = -2 [arr[i] - arr[j] = d, arr[i] + d = arr[j]] + + /* + // Time O(n^2) + // Space O(n) + + int[] mem = new int[arr.length]; + Arrays.fill(mem, 1); + for (int i = 1; i < arr.length; i++) { + for (int j = 0; j < i; j++) { + if (arr[i] - arr[j] == difference) { + mem[i] = Math.max(mem[i], mem[j] + 1); + } + } + } + int len = mem[0]; + for (int i = 1; i < mem.length; i++) { + if (len < mem[i]) len = mem[i]; + } + return len; + + */ + + // Time O(n) + // Space O(n) + // d[i] = d[i-k] + 1 + Map map = new HashMap<>(); + + for (int i = 0; i < arr.length; i++) { + int count = map.getOrDefault(arr[i] - difference, 0) + 1; + map.put(arr[i], count); + } + + int len = Integer.MIN_VALUE; + for (int l: map.values()) { + if (l > len) len = l; + } + return len; + } + + @Test + public void test() { + assertEquals(4, longestSubsequence(new int[] {1,2,3,4}, 1)); + assertEquals(1, longestSubsequence(new int[] {1,3,5,7}, 1)); + assertEquals(4, longestSubsequence(new int[] {1,5,7,8,5,3,4,2,1}, -2)); + } +} From e768ae1e441560abb461c7d37cd6fb833d887f52 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 12 Nov 2019 12:01:32 -0600 Subject: [PATCH 063/189] Added solution for decoding string --- .../algorithm/leetcode/DecodeString.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecodeString.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecodeString.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecodeString.java new file mode 100644 index 0000000..db07b67 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecodeString.java @@ -0,0 +1,74 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/decode-string/ + */ +public class DecodeString { + /** + * Do recursive call if there is nested string to form input format + * + * @param s + * @return + */ + public String decodeString(String s) { + Stack stack = new Stack<>(); // + StringBuilder num = new StringBuilder(); + StringBuilder str = new StringBuilder(); + StringBuilder res = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) >= '0' && s.charAt(i) <= '9') { + num.append(s.charAt(i)); // nums = '2' + if (str.length() > 0) { + res.append(str.toString()); + str = new StringBuilder(); + } + } else if (s.charAt(i) == '[') { + stack.push(num.toString()); // stack = ['3'] + // find close and call + int start = ++i; // 1 + int open = 0; + for (; i < s.length(); i++) { + if (s.charAt(i) == '[') { + open++; + } else if (s.charAt(i) == ']') { + if (open == 0) { + + break; + } + open--; + } + } + str.append(decodeString(s.substring(start, i))); + num = new StringBuilder(); // nums = '' + i--; + } else if (s.charAt(i) == ']') { + String curr = stack.pop(); + try { + Integer times = Integer.valueOf(curr); + for (int j = 0 ; j < times; j++) { + res.append(str.toString()); + } + + } catch (NumberFormatException nfe) { + + } + str = new StringBuilder(); + } else { + str.append(s.charAt(i)); + } + } + res.append(str.toString()); + return res.toString(); + } + + @Test + public void test1() { + assertEquals("accaccacc", decodeString("3[a2[c]]")); + } +} From 5482e60f4864153fe7e0c133b8ff750eab8d7fd6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 12 Nov 2019 12:03:46 -0600 Subject: [PATCH 064/189] added solution for brick wall --- .../algorithm/leetcode/BrickWall.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BrickWall.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BrickWall.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BrickWall.java new file mode 100644 index 0000000..7dd4c30 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BrickWall.java @@ -0,0 +1,55 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * https://leetcode.com/problems/brick-wall/ + */ +public class BrickWall { + public int leastBricks(List> wall) { + int m = wall.size(); + int n = 0; + for (int w: wall.get(0)) { + n += w; + } + + Map map = new HashMap<>(); + for (List row: wall) { + int brickSum = 0; + for (int w: row) { + brickSum += w; + map.put(brickSum, map.getOrDefault(brickSum, 0) + 1); + } + } + + int res = Integer.MAX_VALUE; + for (int w: map.keySet()) { + int count = map.get(w); + if (w < n) { + count = m - count; + } + res = Math.min (count, res); + } + + return res; + } + + @Test + public void test1() { + List> wall = asList(asList(1,2,2,1), + asList(3,1,2), + asList(1,3,2), + asList(2,4), + asList(3,1,2), + asList(1,3,1,1)); + int count = leastBricks(wall); + assertEquals(2, count); + } +} From dd9e5843ba36a4b7b501181f6342c486a48f1b61 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 12 Nov 2019 15:28:27 -0600 Subject: [PATCH 065/189] Added solution for remove k digits --- .../algorithm/leetcode/RemoveKDigits.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveKDigits.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveKDigits.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveKDigits.java new file mode 100644 index 0000000..350fce8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RemoveKDigits.java @@ -0,0 +1,60 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/remove-k-digits/ + */ +public class RemoveKDigits { + /** + * if encounter digits less than previous, then remove all of them until it becomes non-decreasing + * + * @param num + * @param k + * @return + */ + public String removeKdigits(String num, int k) { + Stack s = new Stack<>(); + for (char n: num.toCharArray()) { + + while (k > 0 && !s.isEmpty() && s.peek() > n) { + s.pop(); + k--; + } + if (s.isEmpty()) { + if (n != '0') + s.push(n); + } else { + s.push(n); + } + } + + while (k > 0 && !s.isEmpty()) { + s.pop(); + k--; + } + + StringBuilder sb = new StringBuilder(); + while (!s.isEmpty()) { + sb.append(s.pop()); + } + + return sb.length() > 0 ? sb.reverse().toString(): "0"; + } + + @Test + public void test() { + assertEquals("0", removeKdigits("10", 2)); + assertEquals("1219", removeKdigits("1432219", 3)); + assertEquals("200", removeKdigits("10200", 1)); + assertEquals("0", removeKdigits("10", 2)); + assertEquals("123450", removeKdigits("1234567890", 4)); + assertEquals("0", removeKdigits("1234", 4)); + assertEquals("0", removeKdigits("9", 1)); + assertEquals("1111", removeKdigits("1111111", 3)); + } +} From 98e4cdb07ad38cde856b8645dec64b09f2eaec12 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 13 Nov 2019 15:37:36 -0600 Subject: [PATCH 066/189] Added solution for cheapest flight with max k stops --- .../graphs/CheapestFlightWKStops.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/CheapestFlightWKStops.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/CheapestFlightWKStops.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/CheapestFlightWKStops.java new file mode 100644 index 0000000..3ebf891 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/CheapestFlightWKStops.java @@ -0,0 +1,54 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/cheapest-flights-within-k-stops/ + */ +public class CheapestFlightWKStops { + // Dijkstra's algorithm + public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) { + // create adj list to represent graph + List[] graph = new ArrayList[n]; + for (int i = 0; i < n; i++) { + graph[i] = new ArrayList<>(); + } + + for (int[] flight: flights) { + int u = flight[0]; + int v = flight[1]; + int cost = flight[2]; + graph[u].add(new int[] {v, cost}); + } + + // to track which cities has been visited + PriorityQueue q = new PriorityQueue<>((e1, e2) -> e1[1] - e2[1]); + q.add(new int[] {src, 0, K}); + + while (!q.isEmpty()) { + int[] city = q.poll(); + + if (city[0] == dst) { + return city[1]; + } + + if (city[2] >= 0) { + for (int[] neigbhor: graph[city[0]]) { + q.add(new int[] {neigbhor[0], city[1] + neigbhor[1], city[2] - 1}); + } + } + } + return -1; + } + + @Test + public void test() { + assertEquals(200, findCheapestPrice(3, new int[][] {{0,1,100}, {1,2,100}, {0,2,500}}, 0, 2, 1)); + assertEquals(500, findCheapestPrice(3, new int[][] {{0,1,100}, {1,2,100}, {0,2,500}}, 0, 2, 0)); + assertEquals(6, findCheapestPrice(4, new int[][] {{0,1,1},{0,2,5},{1,2,1},{2,3,1}}, 0, 3, 1)); + } +} From e646f4751497ec8a92c742864d70e0769da1f554 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 13 Nov 2019 16:35:27 -0600 Subject: [PATCH 067/189] Added solution for network delay with dijkstra's algorithm --- .../algorithm/graphs/NetworkDelayTime.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/NetworkDelayTime.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/NetworkDelayTime.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/NetworkDelayTime.java new file mode 100644 index 0000000..7898795 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/NetworkDelayTime.java @@ -0,0 +1,68 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/network-delay-time/ + */ +public class NetworkDelayTime { + public int networkDelayTime(int[][] times, int N, int K) { + List[] graph = new ArrayList[N + 1]; + for (int i = 0; i <= N; i++) { + graph[i] = new ArrayList<>(); + } + + for(int[] time: times) { + int u = time[0]; + int v = time[1]; + int w = time[2]; + + graph[u].add(new int[] {v, w}); + } + + PriorityQueue pq = new PriorityQueue<>((e1, e2) -> e1[1] - e2[1]); + pq.offer(new int[] {K, 0}); + + int[] dist = new int[N + 1]; + Arrays.fill(dist, Integer.MAX_VALUE); + dist[K] = 0; + dist[0] = 0; + while (!pq.isEmpty()) { + int[] curr = pq.poll(); + dist[curr[0]] = Math.min(curr[1], dist[curr[0]]); + + for (int[] neighbor: graph[curr[0]]) { + if (dist[neighbor[0]] == Integer.MAX_VALUE) { + pq.add(new int[] {neighbor[0], neighbor[1] + curr[1]}); + } else if (neighbor[1] + curr[1] < dist[neighbor[0]]) { + pq.add(new int[] {neighbor[0], neighbor[1] + curr[1]}); + } + + } + } + + int max = Integer.MIN_VALUE; + + for (int d: dist) { + if (d > max) { + max = d; + } + + if (d == Integer.MAX_VALUE) return -1; // this node never reached + } + + return max; + } + + @Test + public void test() { + assertEquals(2, networkDelayTime(new int[][] {{2,1,1},{2,3,1},{3,4,1}}, 4, 2)); + } +} From 1ee026d48bd6c64b3ea889a39f358e96aa04c719 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 13 Nov 2019 21:48:17 -0600 Subject: [PATCH 068/189] Added solution for redundant connections with kruskal's algorithm --- .../algorithm/graphs/RedundantConnection.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/RedundantConnection.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/RedundantConnection.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/RedundantConnection.java new file mode 100644 index 0000000..41919c0 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/RedundantConnection.java @@ -0,0 +1,62 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +/** + * https://leetcode.com/problems/redundant-connection/ + */ +public class RedundantConnection { + /** + * Kruskal's algorithm implementation + * + * + * @param edges + * @return + */ + public int[] findRedundantConnection(int[][] edges) { + // spanning tree + int[] A = new int[edges.length + 1]; + // initialize + for (int i = 0; i < A.length; i++) { + A[i] = i; + } + int[] res = new int[2]; + for (int[] edge : edges) { + int start = edge[0]; + int end = edge[1]; + if (root(A, start) != root(A, end)) { // if two vertices have different root, then connect them with edge + union(A, start, end); + } else { // else, it is redundant + res[0] = start; + res[1] = end; + } + } + return res; + } + + private int root(int[] A, int v) { + while (v != A[v]) { + v = A[v]; + } + return v; + } + + private void union(int[] A, int u, int v) { + A[root(A, v)] = A[root(A, u)]; + } + + @Test + public void test() { + /** + * Input: [[1,2], [2,3], [3,4], [1,4], [1,5]] + * Output: [1,4] + * Explanation: The given undirected graph will be like this: + * 5 - 1 - 2 + * | | + * 4 - 3 + */ + assertArrayEquals(new int[]{1, 4}, findRedundantConnection(new int[][]{{1, 2}, {2, 3}, {3, 4}, {1, 4}, {1, 5}})); + } +} From c673318588e0a5638fb4261093a9c442b2fbac5b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 14 Nov 2019 11:07:42 -0600 Subject: [PATCH 069/189] Added solution for edit distance with dp --- .../algorithm/leetcode/EditDistance.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EditDistance.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EditDistance.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EditDistance.java new file mode 100644 index 0000000..444917a --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EditDistance.java @@ -0,0 +1,79 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/edit-distance/ + * + * 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 + * Example 1: + * + * Input: word1 = "horse", word2 = "ros" + * Output: 3 + * Explanation: + * horse -> rorse (replace 'h' with 'r') + * rorse -> rose (remove 'r') + * rose -> ros (remove 'e') + */ +public class EditDistance { + public int minDistance(String word1, String word2) { + + + int m = word1.length(); + int n = word2.length(); + + int[][] mem = new int[m + 1][n + 1]; + + for (int i = 0; i <= m; i++) { + for (int j = 0; j <= n; j++) { + if (i == 0) { + mem[i][j] = j; + } else if (j == 0) { + mem[i][j] = i; + } else if (word1.charAt(i - 1) == word2.charAt(j - 1)) { + mem[i][j] = mem[i - 1][j - 1]; + } else { + mem[i][j] = 1 + Math.min(mem[i - 1][j - 1], Math.min( + mem[i - 1][j], mem[i][j - 1])); + } + } + } + return mem[m][n]; + + + /* + + // recursive + // if charAt(0) are same for both, then keep going + // else, min(change, delete on s1, delete on s2) + + if (word1.length() == 0 && word2.length() == 0) return 0; + if (word1.length() == 0) return word2.length(); + if (word2.length() == 0) return word1.length(); + + int count = 0; + if (word1.charAt(0) == word2.charAt(0)) { + count += minDistance(word1.substring(1), word2.substring(1)); + } else { + count += 1 + Math.min(minDistance(word1.substring(1), word2.substring(1)), Math.min(minDistance(word1.substring(1), word2), + minDistance(word1, word2.substring(1)))); + } + return count; + */ + } + + @Test + public void test() { + assertEquals(3, minDistance("horse", "ros")); + assertEquals(5, minDistance("intention", "execution")); + assertEquals(6, minDistance("dinitrophenylhydrazine","acetylphenylhydrazine")); + } +} From 648a7394ae4c4d182e900767a62e8bb5ee64f9cc Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 14 Nov 2019 14:45:48 -0600 Subject: [PATCH 070/189] Added solution to find longest common subseq --- .../leetcode/LongestCommonSubseq.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestCommonSubseq.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestCommonSubseq.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestCommonSubseq.java new file mode 100644 index 0000000..b51b347 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestCommonSubseq.java @@ -0,0 +1,60 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +/** + * Given two sequences of integers, A[i] and B[j], find the longest common subsequence and print it as a line of space-separated integers. + * If there are multiple common subsequences with the same maximum length, print any one of them. + *

+ * Sample Input + *

+ * 5 6 + * 1 2 3 4 1 + * 3 4 1 2 1 3 + * Sample Output + *

+ * 1 2 3 + *

+ *

+ * https://www.hackerrank.com/challenges/dynamic-programming-classics-the-longest-common-subsequence/problem + */ +public class LongestCommonSubseq { + public int[] longestCommonSubsequence(int[] a, int[] b) { + int[][] mem = new int[a.length + 1][b.length + 1]; + for (int i = 1; i <= a.length; i++) { + for (int j = 1; j <= b.length; j++) { + if (a[i - 1] == b[j - 1]) { + mem[i][j] = 1 + mem[i - 1][j - 1]; + } else { + mem[i][j] = Math.max(mem[i - 1][j], mem[i][j - 1]); + } + } + } + + int len = mem[a.length][b.length]; + int[] res = new int[len]; + int i = len - 1; + for (int r = mem.length - 1; r > 0; r--) { + for (int c = mem[0].length - 1; c > 0; c--) { + // if it is coming from diagonal, then add res[i--] = a[c] + while (c > 0 && mem[r][c] == mem[r][c - 1]) { + c--; + } + if (mem[r][c] == mem[r - 1][c - 1] + 1) { + res[i--] = a[c - 1]; + if (i < 0) return res; + } else { + r--; + } + } + } + return res; + } + + @Test + public void test() { + assertArrayEquals(new int[]{3, 4, 1}, longestCommonSubsequence(new int[]{3, 4, 1, 2, 1, 3}, new int[]{1, 2, 3, 4, 1})); + } +} From 9e1be75afe3c421cf10446b31c459086c934c947 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 15 Nov 2019 18:34:02 -0600 Subject: [PATCH 071/189] Added solution for evaluate division with graph dfs --- .../algorithm/leetcode/EvaluateDivision.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EvaluateDivision.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EvaluateDivision.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EvaluateDivision.java new file mode 100644 index 0000000..640ed30 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/EvaluateDivision.java @@ -0,0 +1,120 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertArrayEquals; + +/** + * https://leetcode.com/problems/evaluate-division/submissions/ + * + * Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). + * Given some queries, return the answers. If the answer does not exist, return -1.0. + * + * Example: + * Given a / b = 2.0, b / c = 3.0. + * queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? . + * return [6.0, 0.5, -1.0, 1.0, -1.0 ]. + * + * The input is: vector> equations, vector& values, vector> queries , + * where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector. + * + * According to the example above: + * + * equations = [ ["a", "b"], ["b", "c"] ], + * values = [2.0, 3.0], + * queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. + */ +public class EvaluateDivision { + public double[] calcEquation(List> equations, double[] values, List> queries) { + int n = values.length; + + // construct graph with adj list + Map> graph = new HashMap<>(); + + for (int i = 0; i < n; i++) { + List eq = equations.get(i); + String u = eq.get(0); + String v = eq.get(1); + + double w = values[i]; + + // this is for edge u -> v + if (!graph.containsKey(u)) { + graph.put(u, new ArrayList<>()); + } + List uNeighbors = graph.get(u); + uNeighbors.add(new Pair(v, w)); + + // there is also an edge v -> u with weight 1/w + if (!graph.containsKey(v)) { + graph.put(v, new ArrayList<>()); + } + List vNeighbors = graph.get(v); + vNeighbors.add(new Pair(u, (1.0) / w)); + } + + double[] res = new double[queries.size()]; + + for (int i = 0; i < queries.size(); i++) { + List q = queries.get(i); + String u = q.get(0); + String v = q.get(1); + + // if there is no node with either of u or v, then division not possible + if (!graph.containsKey(u) || !graph.containsKey(v)) { + res[i] = -1.0; + } else { // else do bfs + res[i] = bfs(graph, u, v); + } + } + + return res; + } + + private double bfs(Map> graph, String src, String dst) { + + Pair srcPair = new Pair(src, 1.0); + Queue q = new LinkedList<>(); + q.add(srcPair); + + Set visited = new HashSet<>(); + + while (!q.isEmpty()) { + Pair p = q.poll(); + visited.add(p.name); + + if (p.name.equals(dst)) { + return p.val; + } + + for (Pair n : graph.get(p.name)) { + if (!visited.contains(n.name)) { + double newVal = n.val * p.val; + q.add(new Pair(n.name, newVal)); + } + } + } + return -1.0; + } + + class Pair { + String name; + double val; + + Pair(String name, double val) { + this.name = name; + this.val = val; + } + } + + @Test + public void test() { + assertArrayEquals( + new double[] {6.00000,0.50000,-1.00000,1.00000,-1.00000}, + calcEquation(asList(asList("a","b"),asList("b","c")), new double[] { 2.0,3.0}, asList(asList("a","c"),asList("b","a"),asList("a","e"),asList("a","a"),asList("x","x"))), + 0.0); + } +} From 5c14114ed7824c9b44a2eb70be3c1236b58a315b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 15 Nov 2019 22:13:27 -0600 Subject: [PATCH 072/189] Added solution for rotate string with kmp --- .../algorithm/leetcode/RotateString.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RotateString.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RotateString.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RotateString.java new file mode 100644 index 0000000..e0a8e3d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RotateString.java @@ -0,0 +1,63 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +public class RotateString { + public boolean rotateString(String A, String B) { + if (A.length() != B.length()) return false; + int[] lps = findLps(A); + + int i = 0; + int j = 0; + while (j < A.length() && i < B.length()) { + // A - pattern + // B - text + if (A.charAt(j) == B.charAt(i)) { + i++; + j++; + } else { + if (j == 0) { + i++; + } else { + j = lps[j - 1]; + } + } + } + + return A.substring(j).equals(B.substring(0, B.length() - j)); + + } + + private int[] findLps(String str) { + int[] lps = new int[str.length()]; + + int j = 0; + int i = 1; + while (i < str.length()) { + if (str.charAt(i) == str.charAt(j)) { + j++; + lps[i] = j; + i++; + } else if (str.charAt(i) != str.charAt(j) && j != 0) { + j = lps[j - 1]; + } else { + lps[i] = 0; + i++; + } + } + + return lps; + } + + @Test + public void test() { + assertTrue(rotateString("abcde", "cdeab")); + assertTrue(rotateString("abcde", "bcdea")); + assertTrue(rotateString("abcde", "abcde")); + assertFalse(rotateString("abcde", "abcdf")); + assertTrue(rotateString("bbbacddceeb", "ceebbbbacdd")); + } +} From d6e636bd332b9c86acce56a9fd9a7cbde4448885 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 16 Nov 2019 21:23:22 -0600 Subject: [PATCH 073/189] Updated backtrack implementation --- .../examples/algorithm/leetcode/CombinationSum.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java index 2e588b7..4e49132 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CombinationSum.java @@ -31,7 +31,7 @@ public class CombinationSum { /** - * Time - O(n) + * Time - O(n!) * Space - O(n) * * @param candidates @@ -52,18 +52,16 @@ public List> combinationSum(int[] candidates, int target) { private void backTrack(int[] candidates, int start, List temp, List> r, int target) { if (target == 0) { // found the set of element r.add(new ArrayList<>(temp)); - temp.remove(temp.size() - 1); } else { for (int i = start; i < candidates.length; i++) { int n = candidates[i]; - if (target - n < 0) break; + if (target - n < 0) return; temp.add(n); backTrack(candidates, i, temp, r, target - n); - } - if (temp.size() > 0) temp.remove(temp.size() - 1); + } } } From 66c2049daacf02587a49f3433098145a6dacd8f0 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 17 Nov 2019 09:43:13 -0600 Subject: [PATCH 074/189] Added solution for coin-change-II --- .../algorithm/leetcode/CoinChangeII.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java new file mode 100644 index 0000000..dfbd975 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java @@ -0,0 +1,65 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * You are given coins of different denominations and a total amount of money. + * Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin. + * + * + * + * Example 1: + * + * Input: amount = 5, coins = [1, 2, 5] + * Output: 4 + * Explanation: there are four ways to make up the amount: + * 5=5 + * 5=2+2+1 + * 5=2+1+1+1 + * 5=1+1+1+1+1 + * + * + * https://leetcode.com/problems/coin-change-2/ + */ +public class CoinChangeII { + + public int change(int amount, int[] coins) { + // memoization with amount and coin index + // so that no need to recalculate for that amount and given coins + int[][] mem = new int[amount + 1][coins.length]; + for (int r = 0; r <= amount; r++) { + for (int c = 0; c < coins.length; c++) { + mem[r][c] = -1; + } + } + return change(amount, coins, 0, mem); + } + + private int change(int amt, int[] coins, int start, int[][] mem) { + if (amt == 0) { + return 1; + } + + if (amt < 0 || start == coins.length) return 0; + if (mem[amt][start] != -1) return mem[amt][start]; + int cnt = 0; + + for (int i = start; i < coins.length; i++) { + cnt += change(amt - coins[i], coins, i, mem); + } + mem[amt][start] = cnt; + return mem[amt][start]; + } + + @Test + public void test1() { + assertEquals(4, change(5, new int[]{1, 2, 5})); + assertEquals(0, change(3, new int[]{2})); + assertEquals(1, change(10, new int[]{10})); + assertEquals(35502874, change(500, new int[]{3, 5, 7, 8, 9, 10, 11})); + assertEquals(0, change(500, new int[]{})); + assertEquals(1, change(0, new int[]{})); + } +} From 9fab407c0a1c16a3e6d32fef7e338278e1675ae8 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 17 Nov 2019 09:49:41 -0600 Subject: [PATCH 075/189] Updated solution for coin-change-II with dp --- .../algorithm/leetcode/CoinChangeII.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java index dfbd975..03ff441 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CoinChangeII.java @@ -62,4 +62,26 @@ public void test1() { assertEquals(0, change(500, new int[]{})); assertEquals(1, change(0, new int[]{})); } + + public int changeDp(int amount, int[] coins) { + int[] dp = new int[amount + 1]; + dp[0] = 1; + + for (int i = 0; i < coins.length; i++) { + for (int j = coins[i]; j < dp.length; j++) { + dp[j] += dp[j - coins[i]]; + } + } + return dp[amount]; + } + + @Test + public void testDp() { + assertEquals(4, changeDp(5, new int[]{1, 2, 5})); + assertEquals(0, changeDp(3, new int[]{2})); + assertEquals(1, changeDp(10, new int[]{10})); + assertEquals(35502874, changeDp(500, new int[]{3, 5, 7, 8, 9, 10, 11})); + assertEquals(0, changeDp(500, new int[]{})); + assertEquals(1, changeDp(0, new int[]{})); + } } From 1faa07f467f47774a632cd4076aa9114988d8b9d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 17 Nov 2019 10:26:29 -0600 Subject: [PATCH 076/189] Refactoring product categroy example --- .../general}/ProductCategoryTest.java | 48 ++++++------------- 1 file changed, 14 insertions(+), 34 deletions(-) rename src/main/java/com/eprogrammerz/examples/{ds/custom/trie => algorithm/general}/ProductCategoryTest.java (79%) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/ProductCategoryTest.java similarity index 79% rename from src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java rename to src/main/java/com/eprogrammerz/examples/algorithm/general/ProductCategoryTest.java index 0d6ceeb..f653320 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/ProductCategoryTest.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/ProductCategoryTest.java @@ -1,4 +1,4 @@ -package com.eprogrammerz.examples.ds.custom.trie; +package com.eprogrammerz.examples.algorithm.general; import lombok.AllArgsConstructor; import lombok.Data; @@ -17,12 +17,12 @@ List findByCategory(List products, String categoryName) { List result = new ArrayList<>(); - if (cProducts != null && cProducts.size() > 0) { - result.addAll(cProducts); - } - Category category = categoryMap.get(categoryName); - if (category != null) { - List subCategories = category.getSubCategories(); + if (cProducts == null || cProducts.isEmpty()) return result; + + result.addAll(cProducts); + + for (Product product: cProducts) { + List subCategories = product.getCategory().getSubCategories(); if (subCategories != null) { for (Category c : subCategories) { List subProducts = findByCategory(products, c.getName()); @@ -30,47 +30,27 @@ List findByCategory(List products, String categoryName) { } } } + return result; } private void createCategoryProductsMap(List products) { this.categoryProducts = new HashMap<>(); - this.categoryMap = new HashMap<>(); for (Product product: products) { Category category = product.getCategory(); + if (!this.categoryProducts.containsKey(category.getName())) { + this.categoryProducts.put(category.getName(), new ArrayList<>()); + } List existing = this.categoryProducts.get(category.getName()); - if (existing == null) { - List newList = new ArrayList<>(); - newList.add(product); - - this.categoryProducts.put(category.getName(), newList); - } else { - existing.add(product); - } - populateCategoryMap(category); + existing.add(product); } } - private void populateCategoryMap(Category category) { - if (!categoryMap.containsKey(category.getName())) { - categoryMap.put(category.getName(), category); - - List subCategories = category.getSubCategories(); - - if (subCategories != null) { - for (Category subCategory: subCategories) { - populateCategoryMap(subCategory); - } - } - } - } - private Map> categoryProducts = null; - private Map categoryMap = null; } public class ProductCategoryTest { @@ -125,7 +105,7 @@ public void testProductsByCategory() { List apparels = pc.findByCategory(products, apparel.getName()); System.out.println(apparels); - assertEquals(2, apparels.size()); + assertEquals(1, apparels.size()); List sportsProducts = pc.findByCategory(products, sports.getName()); System.out.println(sportsProducts); @@ -150,4 +130,4 @@ class Category { private String name; List subCategories; -} \ No newline at end of file +} From 34b44da03edc0eb2f121e1d83f371d87caa62c2e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 17 Nov 2019 15:58:38 -0600 Subject: [PATCH 077/189] Added solution for integer break --- .../algorithm/leetcode/IntegerBreak.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntegerBreak.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntegerBreak.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntegerBreak.java new file mode 100644 index 0000000..ac7b698 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/IntegerBreak.java @@ -0,0 +1,51 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. + * Return the maximum product you can get. + * + * Example 1: + * + * Input: 2 + * Output: 1 + * Explanation: 2 = 1 + 1, 1 × 1 = 1. + */ +public class IntegerBreak { + + @Test + public void test1() { + assertEquals(6, integerBreak(5)); + assertEquals(36, integerBreak(10)); + assertEquals(2, integerBreak(3)); + assertEquals(4, integerBreak(4)); + assertEquals(59049, integerBreak(30)); + assertEquals(1549681956, integerBreak(58)); + } + + // memoized version for breaking an integer + public int integerBreak(int n) { + if (n == 3) return 2; + int[] mem = new int[n + 1]; + Arrays.fill(mem, -1); + return intBreak(n, mem); + } + + private int intBreak(int n, int[] mem) { + if (n <= 2) return 1; + + if (mem[n] != -1) return mem[n]; + + int mul = 1; + for (int i = 1; i <= n; i++) { + mul = Math.max(mul, i * intBreak(n - i, mem)); + } + mem[n] = mul; + return mul; + } +} From 1755e3aa8ee9efb90f45ad796574585c651a1151 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 19 Nov 2019 18:35:54 -0600 Subject: [PATCH 078/189] Added solution for first unique in stream --- .../linkedList/FirstUniqueNumberInStream.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/FirstUniqueNumberInStream.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/FirstUniqueNumberInStream.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/FirstUniqueNumberInStream.java new file mode 100644 index 0000000..a8fda20 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/FirstUniqueNumberInStream.java @@ -0,0 +1,147 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import lombok.val; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.*; + +/** + * Design a data structure that support the following methods: + * + * public class Stream { + * + * public Stream() { + * // do intialization if necessary + * } + * + * + * // Adds integer num to a stream of integers. + * + * public void add(int num) { + * // write your code here + * } + * + * * Returns the first unique integer in the stream if found else return null. + * + public Integer getFirstUnique() { + // write your code here + } + +head tail + | | + v V + 3 -> 4 + * Exaple: + Stream s = new Stream(); + s.add(2); + s.getFirstUnique(); // 2 + s.add(2); + s.getFirstUnique(); // null + s.add(3); + s.getFirstUnique(); // 3 + s.add(4); + s.getFirstUnique(); // 3 + s.add(3); + s.getFirstUnique(); // 4 + */ +public class FirstUniqueNumberInStream { + @Test + public void test1() { + Stream s = new Stream(); + s.add(2); + assertThat(s.getFirstUnique(), equalTo(2)); // 2 + s.add(2); + assertNull(s.getFirstUnique()); // null + s.add(3); + assertThat(s.getFirstUnique(), equalTo(3)); // 3 + s.add(4); + assertThat(s.getFirstUnique(), equalTo(3)); // 3 + s.add(3); + assertThat(s.getFirstUnique(), equalTo(4)); // 4 + } +} + +class Stream { + private Map map; + private Node uniqueHead; + private Node uniqueTail; + + public Stream() { + // do intialization if necessary + this.map = new HashMap<>(); + this.uniqueHead = null; + } + + /** + * Adds integer num to a stream of integers. + */ + public void add(int num) { + Node existing = this.map.get(num); + + // there has not been added any entry with num + if (existing == null) { + Node node = new Node(num); + if (uniqueHead == null) { + this.uniqueHead = node; + this.uniqueTail = node; + } else { + node.prev = uniqueTail; + this.uniqueTail.next = node; + this.uniqueTail = node; + } + map.put(num, node); + } else if (existing.unique) { + //remove from list + if (uniqueHead == existing) { + if (uniqueHead == uniqueTail) { + uniqueHead = null; + uniqueTail = null; + } else { + Node nextHead = uniqueHead.next; + uniqueHead.next = null; + uniqueHead = nextHead; + uniqueHead.prev = null; + } + } else if (uniqueTail == existing) { + Node nextTail = uniqueTail.prev; + uniqueTail.prev = null; + uniqueTail = nextTail; + uniqueTail.next = null; + } else { + existing.prev.next = existing.next; + existing.next.prev = existing.prev; + existing.prev = null; + existing.next = null; + } + // update on map + existing.unique = false; + } else { + // do nothing as entry will be there in map, but not in list + } + + } + + /** + * Returns the first unique integer in the stream if found else return null. + */ + public Integer getFirstUnique() { + if (this.uniqueHead == null) return null; + return uniqueHead.val; + } + + class Node { + int val; + Node next; + Node prev; + boolean unique; + + Node(int val) { + this.val = val; + this.unique = true; + } + } +} From 361369ff6e9c1a2080e95da99f2d6dcde946c668 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 20 Nov 2019 20:49:13 -0600 Subject: [PATCH 079/189] Added solution for complex num multiply --- .../algorithm/leetcode/ComplexNumberMul.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ComplexNumberMul.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ComplexNumberMul.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ComplexNumberMul.java new file mode 100644 index 0000000..d082b61 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ComplexNumberMul.java @@ -0,0 +1,40 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Given two strings representing two complex numbers. + * + * You need to return a string representing their multiplication. Note i2 = -1 according to the definition. + * + * Example 1: + * Input: "1+1i", "1+1i" + * Output: "0+2i" + * Explanation: (1 + i) * (1 + i) = 1 + i2 + 2 * i = 2i, and you need convert it to the form of 0+2i. + * + * + * https://leetcode.com/problems/complex-number-multiplication/ + */ +public class ComplexNumberMul { + public String complexNumberMultiply(String a, String b) { + String[] arr = a.split("\\+"); + int x1 = Integer.valueOf(arr[0]); + int y1 = Integer.valueOf(arr[1].substring(0, arr[1].length() - 1)); + + String[] brr = b.split("\\+"); + int x2 = Integer.valueOf(brr[0]); + int y2 = Integer.valueOf(brr[1].substring(0, brr[1].length() - 1)); + + int x = x1 * x2 - y1 * y2; + int y = x1 * y2 + x2 * y1; + + return x + "+" + y + "i"; + } + + @Test + public void test() { + assertEquals("0+2i", complexNumberMultiply("1+1i", "1+1i")); + } +} From f16a538456bf519e77ff9a393c8bb51a9ac6c553 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 20 Nov 2019 22:06:45 -0600 Subject: [PATCH 080/189] Added solution for ambiguous coordinates --- .../leetcode/AmbiguousCoordinates.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AmbiguousCoordinates.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AmbiguousCoordinates.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AmbiguousCoordinates.java new file mode 100644 index 0000000..2c163d6 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AmbiguousCoordinates.java @@ -0,0 +1,98 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * https://leetcode.com/problems/ambiguous-coordinates/ + */ +public class AmbiguousCoordinates { + public List ambiguousCoordinates(String S) { + List l = new ArrayList<>(); + String num = S.substring(1, S.length() - 1); + + for (int i = 1; i < num.length(); i++) { + // we try to put comma at each index + // and see if x and y are valid + String x = num.substring(0, i); + String y = num.substring(i); + + boolean validX = valid(x); + boolean validY = valid(y); + if (validX && validY) { + l.add("(" + x + ", " + y + ")"); + } + + for (int j = 1; j < x.length(); j++) { + String decimal = x.substring(0, j); + String fraction = x.substring(j); + String newX = decimal + "." + fraction; + + boolean validNewX = valid(newX); + if (validNewX && validY) { + l.add("(" + newX + ", " + y + ")"); + } + + if (validNewX) { + for (int k = 1; k < y.length(); k++) { + decimal = y.substring(0, k); + fraction = y.substring(k); + String newY = decimal + "." + fraction; + if (valid(newY)) { + l.add("(" + newX + ", " + newY + ")"); + } + } + } + + } + + for (int j = 1; j < y.length(); j++) { + String decimal = y.substring(0, j); + String fraction = y.substring(j); + String newY = decimal + "." + fraction; + if (validX && valid(newY)) { + l.add("(" + x + ", " + newY + ")"); + } + } + } + + return l; + } + + private boolean valid(String s) { + if (s.length() == 0) return false; + if (s.length() == 1) return true; + + if (s.charAt(0) == '0' && s.charAt(1) != '.') return false; + + int nonZero = 0; + boolean hasPoint = false; + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (ch > '0' && ch <= '9') { + nonZero++; + } else if (ch == '.') { + nonZero = 0; + hasPoint = true; + } + } + + if (hasPoint && s.charAt(s.length() -1) == '0') return false; + return nonZero > 0; + } + + @Test + public void test() { + assertThat(ambiguousCoordinates("(123)"), hasItems("(1, 23)", "(12, 3)", "(1.2, 3)", "(1, 2.3)")); + assertThat(ambiguousCoordinates("(00011)"), hasItems("(0.001, 1)", "(0, 0.011)")); + assertThat(ambiguousCoordinates("(0123)"), hasItems("(0, 123)", "(0, 12.3)", "(0, 1.23)", "(0.1, 23)", "(0.1, 2.3)", "(0.12, 3)")); + assertThat(ambiguousCoordinates("(100)"), hasItems("(10, 0)")); + assertThat(ambiguousCoordinates("(0010)"), hasItems("(0.01, 0)")); + System.out.println(ambiguousCoordinates("(0101)")); + } +} From e569b2680db5ec15893c542b27a74eb9ca886864 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 21 Nov 2019 20:41:06 -0600 Subject: [PATCH 081/189] Added solution for max consecutives 1s --- .../leetcode/MaxConsecutivesIII.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxConsecutivesIII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxConsecutivesIII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxConsecutivesIII.java new file mode 100644 index 0000000..cfb66cf --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxConsecutivesIII.java @@ -0,0 +1,73 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Given an array A of 0s and 1s, we may change up to K values from 0 to 1. + * + * Return the length of the longest (contiguous) subarray that contains only 1s. + * + * + * + * Example 1: + * + * Input: A = [1,1,1,0,0,0,1,1,1,1,0], K = 2 + * Output: 6 + * Explanation: + * [1,1,1,0,0,1,1,1,1,1,1] + * Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. + * + * https://leetcode.com/problems/max-consecutive-ones-iii/ + */ +public class MaxConsecutivesIII { + /** + * Slide start based upon + * 1) if there is 1, then look for freeing atleast one 0, find start + * 2) if there is 0, then free 0, and increase start by 1 + * @param A + * @param K + * @return + */ + public int longestOnes(int[] A, int K) { + int count = 0; + int start = 0; // to track the start of looking potential range + int end = 0; // to track the end of A + + int remK = K; + while (end < A.length) { + if (A[end] == 1) end++; // we are still good to move ahead + else { + if (remK > 0) { + remK--; + end++; + } else { + count = Math.max(count, end - start); + if (A[start] == 1) { + // move start till remK > 0 + while (remK == 0) { + if (A[start] == 0) { + remK++; + } + start++; + } + } else { + remK++; + start++; + } + } + } + } + count = Math.max(count, end - start); + + return count; + } + + @Test + public void test() { + assertEquals(6, longestOnes(new int[] {1,1,1,0,0,0,1,1,1,1,0}, 2)); + assertEquals(10, longestOnes(new int[] {1,1,1,0,0,0,1,1,1,1,0}, 3)); + assertEquals(10, longestOnes(new int[] {0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1}, 3)); + } +} From 79c6f9d9adf47b7639193be4b640a2ec95df2b3f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 23 Nov 2019 15:20:56 -0600 Subject: [PATCH 082/189] Added solution for random index --- .../algorithm/leetcode/RandomPickIndex.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomPickIndex.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomPickIndex.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomPickIndex.java new file mode 100644 index 0000000..ec57fc7 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomPickIndex.java @@ -0,0 +1,52 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.anyOf; + +/** + * https://leetcode.com/problems/random-pick-index/ + */ +class Solution { + + private Random rand; + + /** + * nums[i] -> [i, j, k] + */ + private Map> map; + public Solution(int[] nums) { + this.map = new HashMap<>(); + + for (int i = 0; i < nums.length; i++) { + if (!map.containsKey(nums[i])) { + map.put(nums[i], new ArrayList<>()); + } + List l = map.get(nums[i]); + l.add(i); + } + this.rand = new Random(); + } + + public int pick(int target) { + List l = map.get(target); + + int idx = rand.nextInt(l.size()); + + return l.get(idx); + + } + +} + +public class RandomPickIndex { + @Test + public void test1() { + Solution random = new Solution(new int[]{1, 2, 3, 3, 3}); + assertThat(random.pick(3), anyOf(is(2), is(3), is(4))); + } +} From ebdbec12fb1888f0c4e7d343eaef51b70ffd057f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 23 Nov 2019 18:54:38 -0600 Subject: [PATCH 083/189] Added solution for randomized set --- .../algorithm/leetcode/RandomizedSetTest.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomizedSetTest.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomizedSetTest.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomizedSetTest.java new file mode 100644 index 0000000..1e62c10 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RandomizedSetTest.java @@ -0,0 +1,99 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Random; + +import static org.junit.Assert.*; + +/** + * Design a data structure that supports all following operations in average O(1) time. + * + * insert(val): Inserts an item val to the set if not already present. + * remove(val): Removes an item val from the set if present. + * getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned. + * + * + * https://leetcode.com/problems/insert-delete-getrandom-o1/ + */ +public class RandomizedSetTest { + @Test + public void test1() { + RandomizedSet set = new RandomizedSet(); + assertTrue(set.insert(0)); + assertTrue(set.insert(1)); + assertTrue(set.remove(0)); + assertTrue(set.insert(2)); + assertTrue(set.remove(1)); + } + + @Test + public void test2() { + RandomizedSet set = new RandomizedSet(); + assertTrue(set.insert(0)); + assertTrue(set.remove(0)); + assertTrue(set.insert(-1)); + assertFalse(set.remove(0)); + + assertEquals(-1, set.getRandom()); + } + + @Test + public void test3() { + RandomizedSet set = new RandomizedSet(); + assertTrue(set.insert(3)); + assertFalse(set.insert(3)); + assertTrue(set.insert(1)); + assertTrue(set.remove(3)); + assertTrue(set.insert(0)); + assertTrue(set.remove(0)); + } +} + +class RandomizedSet { + + private Map map; + private LinkedList list; + private Random rand; + /** Initialize your data structure here. */ + public RandomizedSet() { + this.list = new LinkedList<>(); + this.map = new HashMap<>(); + this.rand = new Random(); + } + + /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ + public boolean insert(int val) { + if (map.containsKey(val)) { + return false; + } + int size = list.size(); + map.put(val, size); + list.addLast(val); + return true; + } + + /** Removes a value from the set. Returns true if the set contained the specified element. */ + public boolean remove(int val) { + if (map.containsKey(val)) { + int idx = map.get(val); + int last = list.removeLast(); + if (last != val) { + list.set(idx, last); + map.put(last, idx); + } + map.remove(val); + return true; + } + return false; + } + + /** Get a random element from the set. */ + public int getRandom() { + int idx= rand.nextInt(list.size()); + return list.get(idx); + } +} From 0dda37d16011ddc5a147c38b3bdb75251ab28f9d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 28 Nov 2019 13:46:03 -0600 Subject: [PATCH 084/189] Added solution for two city schedule --- .../algorithm/leetcode/TwoCitySchedule.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TwoCitySchedule.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TwoCitySchedule.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TwoCitySchedule.java new file mode 100644 index 0000000..ec18fde --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TwoCitySchedule.java @@ -0,0 +1,67 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/two-city-scheduling/submissions/ + */ +public class TwoCitySchedule { + public int twoCitySchedCost(int[][] costs) { + int costA = 0; + int costB = 0; + + // sort entries so that we can look greedily the mini first for both city A and B + Arrays.sort(costs, (c1, c2) -> (Math.abs(c2[0] - c2[1]) - Math.abs(c1[0] - c1[1]))); + + int countA = 0; + int countB = 0; + for (int[] cost : costs) { + if (countB == costs.length / 2) { + costA += cost[0]; + countA++; + } else if (countA == costs.length / 2) { + costB += cost[1]; + countB++; + } else { + + if (cost[0] <= cost[1]) { + costA += cost[0]; + countA++; + } else { + costB += cost[1]; + countB++; + } + + } + } + return costA + costB; + } + + @Test + public void test1() { + int[][] costs = new int[][]{ + {100, 20}, {30, 20}, {400, 50}, {30, 30} + }; + assertEquals(130, twoCitySchedCost(costs)); + } + + @Test + public void test2() { + int[][] costs = new int[][]{ + {259, 770}, {448, 54}, {926, 667}, {184, 139}, {840, 118}, {577, 469} + }; + assertEquals(1859, twoCitySchedCost(costs)); + } + + @Test + public void test3() { + int[][] costs = new int[][]{ + {515, 563}, {451, 713}, {537, 709}, {343, 819}, {855, 779}, {457, 60}, {650, 359}, {631, 42} + }; + assertEquals(3086, twoCitySchedCost(costs)); + } +} From 70ecd72459da23b66a412969f7085e81c4e74fa7 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 29 Nov 2019 14:03:34 -0600 Subject: [PATCH 085/189] Added solution for double pair array --- .../algorithm/leetcode/DoublePairArray.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DoublePairArray.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DoublePairArray.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DoublePairArray.java new file mode 100644 index 0000000..ae2be8b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DoublePairArray.java @@ -0,0 +1,55 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static junit.framework.TestCase.assertTrue; + + +/** + * Given an array of integers A with even length, return true if and only if it is possible to reorder + * it such that A[2 * i + 1] = 2 * A[2 * i] for every 0 <= i < len(A) / 2. + * + * https://leetcode.com/problems/array-of-doubled-pairs/ + */ +public class DoublePairArray { + public boolean canReorderDoubled(int[] A) { + Arrays.sort(A); + Map m = new HashMap<>(); + + for (int n: A) { + m.put(n, m.getOrDefault(n, 0) + 1); + } + + for (int n: A) { + if (!m.containsKey(n)) continue; // n has already been processed + int pair = 2 * n; // n = 0, pair = 0, map [(0,1)] + if (m.containsKey(pair)) { + + int updated = m.get(n) - 1; // 0 + if (updated == 0) m.remove(n); + else { + m.put(n, updated); + } + + if (pair != n) { + int updatedPair = m.get(pair) - 1; // -1 + if (updatedPair == 0) m.remove(pair); + else { + m.put(pair, updatedPair); + } + } + } + } + return m.size() == 0; + } + + @Test + public void test() { + assertTrue(canReorderDoubled(new int[] {0, 0})); + assertTrue(canReorderDoubled(new int[] {1,2,1,-8,8,-4,4,-4,2,-2})); + } +} From 4e5b5b7397c6ec5ab2c9a46e6bec15f66b0e1816 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 29 Nov 2019 21:32:23 -0600 Subject: [PATCH 086/189] Added solution for min travel time --- .../algorithm/leetcode/MiniVisitTime.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniVisitTime.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniVisitTime.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniVisitTime.java new file mode 100644 index 0000000..5255378 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniVisitTime.java @@ -0,0 +1,28 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/minimum-time-visiting-all-points/ + */ +public class MiniVisitTime { + public int minTimeToVisitAllPoints(int[][] points) { + int time = 0; + + int[] start = points[0]; // 1,1 + for (int i = 1; i < points.length; i++) { + int[] curr = points[i]; // 3,4 + + time += Math.max(Math.abs(start[0] - curr[0]), Math.abs(start[1] - curr[1])); + start = curr; + } + return time; + } + + @Test + public void test() { + assertEquals(7, minTimeToVisitAllPoints(new int[][]{{1, 1}, {3, 4}, {-1, 0}})); + } +} From 81683ffb5a9e540449cb1017731343beaf1834f1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 30 Nov 2019 09:19:43 -0600 Subject: [PATCH 087/189] Added solution for max subarr sum max one deletion --- .../leetcode/MaxSubArrWOneDeletion.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubArrWOneDeletion.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubArrWOneDeletion.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubArrWOneDeletion.java new file mode 100644 index 0000000..14afd54 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubArrWOneDeletion.java @@ -0,0 +1,48 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Maximum subarray sum with max one deletion allowed + * + * https://leetcode.com/problems/maximum-subarray-sum-with-one-deletion/ + */ +public class MaxSubArrWOneDeletion { + /** + * We only need to track two variables: the maximum sum we can get (with / without) a deletion. + * + * For the maximum without a deletion, it is purely Kadane's algorithm. + * + * For the maximum with a deletion, we can either discard current number, or, add current number to previous maximum with a deletion. + * + * @param arr + * @return + */ + public int maximumSum(int[] arr) { + if (arr.length == 0) return 0; + if (arr.length == 1) return arr[0]; + + int maxSum = arr[0]; + int currWO = arr[0]; // track sum without deletion i.e. Kadane's algorithm + int currWith = arr[0]; // track sum with deletion + + for (int i = 1; i < arr.length; i++) { + currWith = Math.max(currWith + arr[i], currWO); + + currWO = Math.max(arr[i], arr[i] + currWO); + + maxSum = Math.max(Math.max(currWith, currWO), maxSum); + } + + return maxSum; + } + + @Test + public void test() { + assertEquals(3, maximumSum(new int[] {1,-2,-2,3})); + assertEquals(4, maximumSum(new int[] {1,-2,0,3})); + assertEquals(-1, maximumSum(new int[] {-1,-1,-1,-1})); + } +} From 46a6c45844cb0e9f717dea8f03c5bfce9f717ec5 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 1 Dec 2019 09:18:58 -0600 Subject: [PATCH 088/189] Added solution for verify preorder traversal tree --- .../algorithm/leetcode/VerifyPreorder.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/VerifyPreorder.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/VerifyPreorder.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/VerifyPreorder.java new file mode 100644 index 0000000..ea89b32 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/VerifyPreorder.java @@ -0,0 +1,51 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * with given pre-order traversal, verify if the tree is valid or not + */ +public class VerifyPreorder { + public boolean isValidSerialization(String preorder) { + // stack 9 2 3 1 4 + // replace node having two # with # + Stack stack = new Stack<>(); + String[] parts = preorder.split(","); + for (int i = 0; i < parts.length; i++) { + stack.push(parts[i]); + if ("#".equals(stack.peek())) { + int popCount = 0; + while (stack.peek().equals("#")) { + stack.pop(); + if (stack.isEmpty()) break; + popCount++; + + if (popCount == 2) { + stack.pop(); // pop parent node + stack.push("#"); + popCount = 0; + } + + + } + if (i < parts.length - 1 && stack.isEmpty()) return false; + + stack.push("#"); + } + } + + return stack.size() == 1 && "#".equals(stack.peek()); + } + + @Test + public void test() { + assertTrue(isValidSerialization("9,3,4,#,#,1,#,#,2,#,6,#,#")); + assertFalse(isValidSerialization("1,#")); + assertFalse(isValidSerialization("9,#,#,1")); + } +} From 178d080f5bc47879fd3f148c4571385a66ed4bfc Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 1 Dec 2019 10:28:38 -0600 Subject: [PATCH 089/189] Added solution for longest substring with unique chars --- .../leetcode/LongestSubstrWORep.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestSubstrWORep.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestSubstrWORep.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestSubstrWORep.java new file mode 100644 index 0000000..8fde5eb --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestSubstrWORep.java @@ -0,0 +1,77 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/longest-substring-without-repeating-characters/ + */ +public class LongestSubstrWORep { + public int lengthOfLongestSubstring(String s) { + // use map to track index of that character, and if it there in map, + // then start looking into element next to it + + int[] indices = new int[256]; + Arrays.fill(indices, -1); + + int len = 0; + int start = 0; + + int i = 0; + while (i < s.length()) { + + char ch = s.charAt(i); + + int index = indices[ch]; + + if (i > start && index >= start) { + if (i - start > len) len = i - start; + + start = index + 1; + } + indices[ch] = i; + i++; + } + return Math.max(i - start, len); + + /* + Map map = new HashMap<>(); + int len = 0; + for (int i = 0; i < s.length(); i++) { + + char ch = s.charAt(i); + + if (map.containsKey(ch)) { + if (map.size() > len) len = map.size(); + i = map.get(ch); + map.clear(); + } else { + map.put(ch, i); + } + } + return Math.max(map.size(), len); + + */ + } + + @Test + public void test() { + + assertEquals(5, lengthOfLongestSubstring("anviaj")); + assertEquals(3, lengthOfLongestSubstring("dvdf")); + assertEquals(3, lengthOfLongestSubstring("pwwkew")); + assertEquals(3, lengthOfLongestSubstring("abcabcbb")); + assertEquals(1, lengthOfLongestSubstring("bbbbb")); + assertEquals(1, lengthOfLongestSubstring(" ")); + assertEquals(1, lengthOfLongestSubstring(" ")); + assertEquals(2, lengthOfLongestSubstring("abba")); + assertEquals(5, lengthOfLongestSubstring("qrsvbspk")); + assertEquals(2, lengthOfLongestSubstring("aab")); + assertEquals(2, lengthOfLongestSubstring("au")); + } +} From 1b61fc0a7f6c42c9a3707006f49bff149a0f59c9 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 1 Dec 2019 14:14:59 -0600 Subject: [PATCH 090/189] Updated hash ds design with hashing --- .../examples/ds/custom/map/MyMap.java | 24 ++++++++++++++++--- .../examples/ds/custom/map/Validator.java | 2 +- .../examples/ds/custom/set/MyHashSet.java | 16 +++++++++++-- .../examples/ds/custom/set/Validator.java | 2 +- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/map/MyMap.java b/src/main/java/com/eprogrammerz/examples/ds/custom/map/MyMap.java index 414e128..edd2f2a 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/map/MyMap.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/map/MyMap.java @@ -2,19 +2,37 @@ public class MyMap { private Entry[] buckets; - private static final int INITIAL_CAPACITY = 1 << 4; // 16 + private int capacity; // 16 private int size = 0; + private double lf = 0.75; + public MyMap() { - this(INITIAL_CAPACITY); + this(16); } public MyMap(int capacity) { - this.buckets = new Entry[capacity]; + this.capacity = capacity; + this.buckets = new Entry[this.capacity]; } public void put(K key, V value) { + if (size == lf * capacity) { + // rehash + Entry[] old = buckets; + + capacity *= 2; + size = 0; + buckets = new Entry[capacity]; + + for (Entry e: old) { + while (e != null) { + put(e.key, e.value); + e = e.next; + } + } + } Entry entry = new Entry<>(key, value, null); int bucket = getHash(key) % getBucketSize(); diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/map/Validator.java b/src/main/java/com/eprogrammerz/examples/ds/custom/map/Validator.java index 5776bdf..c56bae5 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/map/Validator.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/map/Validator.java @@ -9,7 +9,7 @@ public class Validator { @Test public void testMyMap() { - MyMap myMap = new MyMap<>(); + MyMap myMap = new MyMap<>(3); myMap.put("USA", "Washington DC"); myMap.put("Nepal", "Kathmandu"); myMap.put("India", "New Delhi"); diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/set/MyHashSet.java b/src/main/java/com/eprogrammerz/examples/ds/custom/set/MyHashSet.java index 1b432e2..df1a717 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/set/MyHashSet.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/set/MyHashSet.java @@ -30,7 +30,7 @@ */ public class MyHashSet { - private static final Integer INITIAL_CAPACITY = 1 << 4; // 16 + private int capacity = 0; private Node[] buckets; @@ -42,10 +42,22 @@ public MyHashSet(final int capacity) { } public MyHashSet() { - this(INITIAL_CAPACITY); + this(16); } public void add(T t) { + if (size == 0.75 * capacity) { + // rehash + capacity *= 2; + size = 0; + + for (Node bucket: buckets) { + while (bucket != null) { + add(bucket.data); + bucket = bucket.next; + } + } + } int index = hashCode(t) % buckets.length; Node bucket = buckets[index]; diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/set/Validator.java b/src/main/java/com/eprogrammerz/examples/ds/custom/set/Validator.java index cf6373a..7a59177 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/set/Validator.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/set/Validator.java @@ -10,7 +10,7 @@ public class Validator { @Test public void testMyHashSet() { - MyHashSet set = new MyHashSet<>(); + MyHashSet set = new MyHashSet<>(3); set.add("USA"); set.add("Nepal"); From f4483249d8acb95a705e3a857592586ea780ee38 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 1 Dec 2019 20:53:09 -0600 Subject: [PATCH 091/189] Added solution for shortest palindrome substring --- .../leetcode/ShortestPalindromeSubstring.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestPalindromeSubstring.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestPalindromeSubstring.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestPalindromeSubstring.java new file mode 100644 index 0000000..647edb7 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ShortestPalindromeSubstring.java @@ -0,0 +1,110 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/shortest-palindrome/ + * + * Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. + * Find and return the shortest palindrome you can find by performing this transformation. + * + * Example 1: + * + * Input: "aacecaaa" + * Output: "aaacecaaa" + * Example 2: + * + * Input: "abcd" + * Output: "dcbabcd" + */ +public class ShortestPalindromeSubstring { + public String shortestPalindrome(String s) { + if (s.length() <= 1) return s; + // find longest palindrome p substring in s + // if indexof(p) == 0 + // app chars from p.length() .. s.length() + // else add chars from 1 .. s.length() + + int longest = longestPalindromeSubstringKmp(s); + if (longest == s.length()) return s; + + StringBuilder sb = new StringBuilder(); + sb.append(s.substring(longest)); + + return sb.reverse().toString() + s; + } + + private int longestPalindromeSubstringKmp(String s) { + int[] lps = findLps(s + "#" + new StringBuilder(s).reverse().toString()); + return lps[lps.length - 1]; + } + + private int[] findLps(String s) { + int[] lps = new int[s.length()]; + + lps[0] = 0; + int j = 0; + int i = 1; + + while (i < s.length()) { + if (s.charAt(i) == s.charAt(j)) { + j++; + lps[i] = j; + i++; + } else { + if (j != 0) { + j = lps[j - 1]; + } else { + lps[i] = 0; + i++; + } + } + } + return lps; + } + + + /** + * Time O(n^2) + * Space O(1) + * + * @param s + * @return + */ + private String longestPalindromeSubstring(String s) { + int n = s.length(); + + int start = 0; + int end = n - 1; + + int palindrome = end; + + while (start < end) { + if (s.charAt(start) == s.charAt(end)) { + start++; + end--; + } else { + start = 0; + end = palindrome - 1; + palindrome = end; + } + + } + + return s.substring(0, palindrome + 1); + } + + @Test + public void test() { + assertEquals("ababbabbbababbbabbaba", shortestPalindrome("ababbbabbaba")); + assertEquals("aba", shortestPalindrome("aba")); + assertEquals("dcbabcd", shortestPalindrome("abcd")); + assertEquals("aaacecaaa", shortestPalindrome("aacecaaa")); + assertEquals("bbabb", shortestPalindrome("abb")); + assertEquals("abbaabba", shortestPalindrome("aabba")); + assertEquals("abbbaaaabbba", shortestPalindrome("aaaabbba")); + assertEquals("abbbaaaaabbba", shortestPalindrome("aaaaabbba")); + } +} From f723a688f259da59cbca3d9dd479dc48cd01fc1c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 1 Dec 2019 22:41:09 -0600 Subject: [PATCH 092/189] Added solution for next greater node --- .../ds/custom/linkedList/NextGreaterNode.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/NextGreaterNode.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/NextGreaterNode.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/NextGreaterNode.java new file mode 100644 index 0000000..17b05fe --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/NextGreaterNode.java @@ -0,0 +1,40 @@ +package com.eprogrammerz.examples.ds.custom.linkedList; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * https://leetcode.com/problems/next-greater-node-in-linked-list/ + */ +public class NextGreaterNode { + public int[] nextLargerNodes(ListNode head) { + List l = new ArrayList<>(); + while (head != null) { + l.add(head.val); + head = head.next; + } + + int[] res = new int[l.size()]; + + // to track monotone integer val of nodes + Stack stack = new Stack<>(); + + for (int i = l.size() - 1; i >= 0; i--) { + int curr = l.get(i); + + while (!stack.isEmpty() && curr >= stack.peek()) { + stack.pop(); + } + if (stack.isEmpty()) { + res[i] = 0; + } else { + res[i] = stack.peek(); + } + + stack.push(curr); + } + + return res; + } +} From e25bec9e744716796a3fb64d6826c5b892794689 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 2 Dec 2019 21:15:48 -0600 Subject: [PATCH 093/189] Added solution for map-sum-pairs with trie --- .../examples/ds/custom/trie/MapSumPairs.java | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/trie/MapSumPairs.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MapSumPairs.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MapSumPairs.java new file mode 100644 index 0000000..9c69c15 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MapSumPairs.java @@ -0,0 +1,156 @@ +package com.eprogrammerz.examples.ds.custom.trie; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + + +/** + * https://leetcode.com/problems/map-sum-pairs/ + * + * + * Implement a MapSum class with insert, and sum methods. + * + * For the method insert, you'll be given a pair of (string, integer). + * The string represents the key and the integer represents the value. If the key already existed, then the original key-value pair + * will be overridden to the new one. + * + * For the method sum, you'll be given a string representing the prefix, + * and you need to return the sum of all the pairs' value whose key starts with the prefix. + * + * Example 1: + * Input: insert("apple", 3), Output: Null + * Input: sum("ap"), Output: 3 + * Input: insert("app", 2), Output: Null + * Input: sum("ap"), Output: 5 + */ +public class MapSumPairs { + @Test + public void test() { + MapSum mapSum = new MapSum(); + mapSum.insert("apple", 3); + assertEquals(3, mapSum.sum("ap")); + + mapSum.insert("app", 5); + assertEquals(8, mapSum.sum("ap")); + } +} + +class MapSum { + private Trie trie; + private Map m; + + /** + * Initialize your data structure here. + */ + public MapSum() { + this.m = new HashMap<>(); + this.trie = new Trie(); + } + + public void insert(String key, int val) { + if (!m.containsKey(key)) { + // put into trie + this.trie.insert(key); + } + m.put(key, val); + } + + public int sum(String prefix) { + List words = this.trie.search(prefix); + + int sum = 0; + + for (String word : words) { + sum += m.get(word); + } + + return sum; + } + + + class Trie { + TrieNode root; + + Trie() { + this.root = new TrieNode('#'); + } + + public void insert(String word) { + this.root.insert(word); + } + + public List search(String prefix) { + TrieNode node = this.root.search(prefix); + + List l = new ArrayList<>(); + if (node == null) return l; + + dfs(node, l, prefix.substring(0, prefix.length() - 1)); + return l; + } + + private void dfs(TrieNode node, List l, String word) { + if (node == null) return; + Map children = node.children; + if (children.containsKey('\0')) { + l.add(word + node.data); + } + + for (TrieNode child : children.values()) { + if (child != null && child.data != '\0') { + dfs(child, l, word + node.data); + } + } + } + } + + class TrieNode { + char data; + Map children; + + TrieNode(char data) { + this.data = data; + this.children = new HashMap<>(); + } + + public void insert(String word) { + if (word == null) return; + if (word.length() == 0) { + children.put('\0', null); + return; + } + char start = word.charAt(0); + TrieNode child = null; + if (children.containsKey(start)) { + child = children.get(start); + } else { + child = new TrieNode(start); + children.put(start, child); + } + child.insert(word.substring(1)); + } + + public TrieNode search(String prefix) { + + if (prefix.length() == 0) return null; + + char start = prefix.charAt(0); + TrieNode node = null; + if (children.containsKey(start)) { + + TrieNode child = children.get(start); + + if (prefix.length() == 1) return child; + node = child.search(prefix.substring(1)); + } + return node; + } + } +} + From 4e14811e1eca83c24fc553cc61baf29e438bd4e5 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 3 Dec 2019 12:53:44 -0600 Subject: [PATCH 094/189] Updated solution for sorting linkedList --- .../ds/custom/linkedList/SortLinkedList.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java index a2d841d..f4111bf 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/SortLinkedList.java @@ -22,7 +22,6 @@ public ListNode sortList(ListNode head) { ListNode right = left.next; left.next = null; - left = head; left = sortList(head); right = sortList(right); @@ -34,13 +33,12 @@ public ListNode sortList(ListNode head) { while (left != null && right != null) { if (left.val <= right.val) { runner.next = left; - runner = runner.next; left = left.next; } else { runner.next = right; - runner = runner.next; right = right.next; } + runner = runner.next; } if (left != null) { @@ -101,4 +99,14 @@ public void test2() { ListNode res = sortList(n1); assertEquals("1 -> 2 -> 3", printList(res)); } + + @Test + public void test3() { + ListNode n1 = new ListNode(1); + ListNode n2 = new ListNode(-1); + n1.next = n2; + + ListNode res = sortList(n1); + assertEquals("-1 -> 1", printList(res)); + } } From eabfe984426f6e72d215afe2a0f5aff275652531 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 5 Dec 2019 11:58:28 -0600 Subject: [PATCH 095/189] Added solution for possible-bipartition with dfs --- .../leetcode/PossibleBipartition.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PossibleBipartition.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PossibleBipartition.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PossibleBipartition.java new file mode 100644 index 0000000..a913f27 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PossibleBipartition.java @@ -0,0 +1,72 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Stack; + +import static org.junit.Assert.assertFalse; + + +/** + * https://leetcode.com/problems/possible-bipartition/submissions/ + */ +public class PossibleBipartition { + public boolean possibleBipartition(int N, int[][] dislikes) { + + // create graph with people disliking each other + List[] graph = new ArrayList[N + 1]; + for (int i = 0; i <= N; i++) { + graph[i] = new ArrayList<>(); + } + + for (int[] dislike: dislikes) { + int u = dislike[0]; + int v = dislike[1]; + graph[u].add(v); + graph[v].add(u); + } + + + // to track if particular person node has been visited + int[] visited = new int[N + 1]; + Arrays.fill(visited, -1); + + // this is to make sure all graphs in forests has been visited + for (int i = 1; i <= N; i++) { + if (visited[i] == -1) { + Stack stack = new Stack<>(); + stack.push(new int[] {i, 0}); // stack [vertex,odd or even] + + while (!stack.isEmpty()) { + int[] pair = stack.pop(); + int curr = pair[0]; + int status = pair[1]; + + List neb = graph[curr]; + for (int n: neb) { + // if not visited, add into stack with opposite status + if (visited[n] == -1) { + visited[n] = status == 0 ? 1 : 0; + stack.push(new int[] {n, visited[n]}); + } else { + if (visited[n] == status) return false; + } + } + } + } + } + + return true; + } + + @Test + public void test() { + int[][] dislikes = new int[][] { + {1,2},{3,4},{4,5},{3,5} + }; + assertFalse(possibleBipartition(5, dislikes)); + } +} From bc68b16d9deea35897758ec36e387e07f4576bb6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 6 Dec 2019 09:42:04 -0600 Subject: [PATCH 096/189] Added solution for binary num with alternating bits --- .../leetcode/BinaryNumWAlternatingBits.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryNumWAlternatingBits.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryNumWAlternatingBits.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryNumWAlternatingBits.java new file mode 100644 index 0000000..679655c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BinaryNumWAlternatingBits.java @@ -0,0 +1,37 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +/** + * https://leetcode.com/problems/binary-number-with-alternating-bits/ + * + */ +public class BinaryNumWAlternatingBits { + public boolean hasAlternatingBits(int n) { + boolean one = (n & 1) == 1; + while (n > 0) { + n = n >> 1; + int curr = n & 1; + if ((curr == 1 && one) || (curr == 0 && !one)) { + return false; + } + one = !one; + } + return true; + } + + @Test + public void test() { + assertTrue(hasAlternatingBits(1)); + assertTrue(hasAlternatingBits(2)); + assertFalse(hasAlternatingBits(4)); + assertTrue(hasAlternatingBits(5)); + assertFalse(hasAlternatingBits(7)); + assertFalse(hasAlternatingBits(8)); + assertTrue(hasAlternatingBits(10)); + assertFalse(hasAlternatingBits(11)); + } +} From 16979f230d45bae6245a2a8d4aa4431e1f7ed80b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 8 Dec 2019 19:47:13 -0600 Subject: [PATCH 097/189] Added test for RLEIterator --- .../algorithm/leetcode/RLEIteratorTest.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RLEIteratorTest.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RLEIteratorTest.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RLEIteratorTest.java new file mode 100644 index 0000000..6035b6d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/RLEIteratorTest.java @@ -0,0 +1,78 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/rle-iterator/submissions/ + */ +public class RLEIteratorTest { + + @Test + public void test1() { + RLEIterator iterator = new RLEIterator(new int[] {3, 8, 0, 9 , 2, 5}); + assertEquals(8, iterator.next(2)); + assertEquals(8, iterator.next(1)); + assertEquals(5, iterator.next(1)); + assertEquals(-1, iterator.next(2)); + } + + @Test + public void test2() { + //[[[811,903,310,730,899,684,472,100,434,611]],[358],[345],[154],[265],[73],[220],[138],[4],[170],[88]] + RLEIterator iterator = new RLEIterator(new int[] {811,903,310,730,899,684,472,100,434,611}); + assertEquals(903, iterator.next(358)); + assertEquals(903, iterator.next(345)); + assertEquals(730, iterator.next(154)); + assertEquals(684, iterator.next(265)); + assertEquals(684, iterator.next(73)); + assertEquals(684, iterator.next(220)); + assertEquals(684, iterator.next(138)); + assertEquals(684, iterator.next(4)); + assertEquals(684, iterator.next(170)); + assertEquals(684, iterator.next(88)); + //[null,903,903,730,684,684,684,684,684,684,684] + } + +} + +class RLEIterator { + private int[] A; // 3, 8, 0, 9 , 2, 5 + private int p; + public RLEIterator(int[] A) { + this.A = A; + } + + public int next(int n) { + if (p >= A.length) return -1; // p = 0 + + while (p < A.length && A[p] == 0) { + if (A[p] == 0) { + p = p + 2; + } + } + + if (p >= A.length) return -1; + + // 1 + int rem = A[p] - n; + while (p < A.length) { + + if (rem < 0) { + A[p] = 0; + p = p + 2; + if (p < A.length) { + rem += A[p]; + } + } else { + A[p] = rem; // A[0] = 1 + break; + } + } + + if (p >= A.length) return -1; + + return A[p + 1]; + } +} From 22d8a743be12898d82dce8623e1a3077d9fd5456 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 10 Dec 2019 12:49:11 -0600 Subject: [PATCH 098/189] Added solution for stack with heap --- .../examples/ds/custom/stack/StackWHeap.java | 32 +++++++++++++++++++ .../examples/ds/custom/stack/Validator.java | 14 ++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWHeap.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWHeap.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWHeap.java new file mode 100644 index 0000000..78a5382 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/StackWHeap.java @@ -0,0 +1,32 @@ +package com.eprogrammerz.examples.ds.custom.stack; + +import java.util.Comparator; +import java.util.EmptyStackException; +import java.util.PriorityQueue; + +public class StackWHeap { + private PriorityQueue pq; + public StackWHeap() { + this.pq = new PriorityQueue<>(Comparator.comparingInt(e -> e[1])); + } + + public void push(int n) { + // update all entry in pq with their count + PriorityQueue temp = new PriorityQueue<>(Comparator.comparingInt(e -> e[1])); + while (!pq.isEmpty()) { + int[] e = pq.poll(); + e[1]++; + temp.add(e); + } + pq.addAll(temp); + pq.add(new int[] {n, 1}); + } + + public int pop() { + if (pq.isEmpty()) { + throw new EmptyStackException(); + } + int[] e = pq.poll(); + return e[0]; + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java index db5ce2c..42abd01 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java @@ -123,4 +123,18 @@ public void testFreqStack2() { assertEquals(1, stack.pop()); // 5 -> 1, 1 -> 1 assertEquals(5, stack.pop()); // 5 -> 1, 1 -> 1 } + + @Test + public void testStackWHeap() { + StackWHeap stack = new StackWHeap(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(1); + + assertEquals(1, stack.pop()); + assertEquals(3, stack.pop()); + assertEquals(2, stack.pop()); + assertEquals(1, stack.pop()); + } } From 7bf111ad553aa4f4d3e0ea3bb0453a9c81424f31 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 14 Dec 2019 13:59:05 -0600 Subject: [PATCH 099/189] Added solution for palindrome partitionIII with memoization --- .../leetcode/PalindromePartitionIII.java | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PalindromePartitionIII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PalindromePartitionIII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PalindromePartitionIII.java new file mode 100644 index 0000000..4fd1bd9 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/PalindromePartitionIII.java @@ -0,0 +1,126 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/palindrome-partitioning-iii/ + */ +public class PalindromePartitionIII { + private Map map = new HashMap<>(); + + public int palindromePartition(String s, int k) { + + for (int start = 0; start < s.length(); start++) { + for (int end = start; end < s.length(); end++) { + String sub = s.substring(start, end + 1); + if (!map.containsKey(sub)) { + map.put(sub, makePalindrome(sub)); + } + } + } + + Map mem = new HashMap<>(); + split(s, k, mem); + + return mem.get(new MemKey(s, k)); + } + + private int split(String s, int k, Map mem) { + + if (s.length() <= 1) { + return 0; + } + + MemKey key = new MemKey(s, k); + + if (mem.containsKey(key)) { + return mem.get(key); + } + + if (k == 1) { + int count = map.get(s); + mem.put(key, count); + return count; + } + + int count = Integer.MAX_VALUE; + for (int i = 1; i < s.length(); i++) { + String first = s.substring(0, i); + String second = s.substring(i); + + count = Math.min(count, map.get(first) + split(second, k - 1, mem)); + } + mem.put(key, count); + return count; + } + + private int makePalindrome(String s) { + int start = 0; + int end = s.length() - 1; + + int count = 0; + while (start < end) { + if (s.charAt(start) != s.charAt(end)) { + count++; + } + start++; + end--; + } + return count; + } + + class MemKey { + String str; + int k; + MemKey(String str, int k) { + this.str = str; + this.k = k; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof MemKey)) return false; + MemKey that = (MemKey) obj; + + return this.str.equals(that.str) && this.k == that.k; + } + + @Override + public int hashCode() { + int code = 17; + code = code * 17 + this.str.hashCode(); + code = code * 17 + this.k; + return code; + } + } + + @Test + public void test1() { + assertEquals(0, palindromePartition("aabbcc", 3)); + } + + @Test + public void test2() { + assertEquals(0, palindromePartition("aabbaa", 1)); + } + + @Test + public void test3() { + assertEquals(1, palindromePartition("abc", 2)); + } + + @Test + public void test4() { + assertEquals(0, palindromePartition("faaglagedtwnejzpuarkgwgoefwra", 27)); + } + + @Test + public void test5() { + assertEquals(6, palindromePartition("spsvmwkvwyfnrrfklevvyxsayc", 6)); + } +} From 2f8ac8a5cf2536eba21394e659c7274698387d8f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 16 Dec 2019 22:11:19 -0600 Subject: [PATCH 100/189] Added solution for longest word in dictionary with deletion --- .../algorithm/leetcode/LongestWordInDict.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestWordInDict.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestWordInDict.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestWordInDict.java new file mode 100644 index 0000000..ea3686c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestWordInDict.java @@ -0,0 +1,47 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/ + */ +public class LongestWordInDict { + public String findLongestWord(String s, List d) { + String res = ""; + for (String word: d) { + if (canForm(word, s)) { + if (word.length() > res.length()) + res = word; + else if (word.length() == res.length() && word.compareTo(res) < 0) { + res = word; + } + } + } + return res; + } + + private boolean canForm(String word, String str) { + int i = 0; + int j = 0; + + while (i < word.length() && j < str.length()) { + if (word.charAt(i) == str.charAt(j)) { + i++; + j++; + } else { + j++; + } + } + return i == word.length(); + } + + @Test + public void test() { + assertEquals("apple", findLongestWord("abpcplea", Arrays.asList("ale","apple","monkey","plea"))); + } +} From cc2bc6cec7fbbb563420b295b9206f53c6403182 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 17 Dec 2019 17:09:07 -0600 Subject: [PATCH 101/189] Added solution for missing number II in lintcode --- .../algorithm/leetcode/MissingNumber2.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MissingNumber2.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MissingNumber2.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MissingNumber2.java new file mode 100644 index 0000000..38d7cda --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MissingNumber2.java @@ -0,0 +1,77 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * 570. Find the Missing Number II + + * Giving a string with number from 1-n in random order, but miss 1 number.Find that number. + * + * Example + * Example1 + * + * Input: n = 20 and str = 19201234567891011121314151618 + * Output: 17 + * Explanation: + * 19'20'1'2'3'4'5'6'7'8'9'10'11'12'13'14'15'16'18 + * Example2 + * + * Input: n = 6 and str = 56412 + * Output: 3 + * Explanation: + * 5'6'4'1'2 + * Notice + * n <= 30 + * Data guarantees have only one solution + * + * + * https://www.lintcode.com/problem/find-the-missing-number-ii/description + */ +public class MissingNumber2 { + public int findMissing2(int n, String str) { + // 1 920123 1 9 20123 1 9 2 + // 19 20123 + // write your code here + List l = new ArrayList<>(); + dfs(n, str, l, 0, new ArrayList<>()); + + int res = n; + for (int i = 0; i < l.size(); i++) { + res ^= (i + 1) ^ l.get(i); + } + return res; + } + + private void dfs(int n, String str, List l, int start, List temp) { + if (str.length() == start) { + if (temp.size() == n - 1) { + l.clear(); + l.addAll(temp); + } + + return; + } + int val = 0; + for (int i = start; i < str.length(); i++) { + val = val * 10 + (str.charAt(i) - '0'); + if (temp.contains(val)) continue; + + if (val > 0 && val <= n) { + temp.add(val); + dfs(n, str, l, i + 1, temp); + temp.remove(temp.size() - 1); + } + } + } + + @Test + public void test() { + assertEquals(17, findMissing2(20, "19201234567891011121314151618")); + assertEquals(3, findMissing2(6, "56412")); + } +} From 191bc394ac21d5d869a20ad039738665abd3f8b1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 17 Dec 2019 21:20:22 -0600 Subject: [PATCH 102/189] Added solution for TrappingRainWater --- .../algorithm/leetcode/TrappingRainWater.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TrappingRainWater.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TrappingRainWater.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TrappingRainWater.java new file mode 100644 index 0000000..d47b3f4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TrappingRainWater.java @@ -0,0 +1,39 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/trapping-rain-water/ + */ +public class TrappingRainWater { + public int trap(int[] height) { + if (height.length == 0) return 0; + + int n = height.length; + int[] lMax = new int[n]; + lMax[0] = height[0]; + + for (int i = 1; i < n; i++) { + lMax[i] = Math.max(height[i], lMax[i - 1]); + } + + int[] rMax = new int[n]; + rMax[n - 1] = height[n - 1]; + for (int i = n - 2; i >= 0; i--) { + rMax[i] = Math.max(rMax[i + 1], height[i]); + } + + int vol = 0; + for (int i = 0; i < n; i++) { + vol += Math.min(lMax[i], rMax[i]) - height[i]; + } + return vol; + } + + @Test + public void test() { + assertEquals(6, trap(new int[] {0,1,0,2,1,0,1,3,2,1,2,1})); + } +} From 428ae4ea9b1f8e54ed5bc37027a4466adfe75d2b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 18 Dec 2019 11:50:39 -0600 Subject: [PATCH 103/189] Added solution for Fruits Into Baskets with two pointers --- .../algorithm/leetcode/FruitsIntoBaskets.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FruitsIntoBaskets.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FruitsIntoBaskets.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FruitsIntoBaskets.java new file mode 100644 index 0000000..4bab684 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FruitsIntoBaskets.java @@ -0,0 +1,63 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/fruit-into-baskets/ + */ +public class FruitsIntoBaskets { + public int totalFruit(int[] tree) { + if (tree.length <= 2) return tree.length; + + int n = tree.length; + + int start = 0; + + int b1 = tree[start]; + int b2 = tree[start]; + + int end = 1; + while (end < n) { + b2 = tree[end]; + if (b1 != b2) break; + end++; + } + + int max = end - start; + + int nextStart = end; + + while (end < tree.length) { + if (tree[end] == b1 || tree[end] == b2) { + end++; + } else { + max = Math.max(end - start, max); + // update b1, b2 + // update start and end + start = nextStart; + b1 = tree[start]; + b2 = tree[start]; + + end = start + 1; + while (end < n) { + b2 = tree[end]; + if (b1 != b2) break; + + end++; + } + + nextStart = end; + } + } + return Math.max(max, end - start); + } + + @Test + public void test() { + assertEquals(3, totalFruit(new int[] {0,1,2,2})); + assertEquals(4, totalFruit(new int[] {1,2,3,2,2})); + assertEquals(5, totalFruit(new int[] {3,3,3,1,2,1,1,2,3,3,4})); + } +} From 17c92f8b03ea4619e53e21b13dac44b9604502d1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 18 Dec 2019 15:04:41 -0600 Subject: [PATCH 104/189] Added solution for maximal rectangle area in matrix --- .../algorithm/leetcode/MaxRectangleArea.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxRectangleArea.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxRectangleArea.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxRectangleArea.java new file mode 100644 index 0000000..549035f --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxRectangleArea.java @@ -0,0 +1,75 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +/** + * https://leetcode.com/problems/maximal-rectangle/ + */ +public class MaxRectangleArea { + /** + * Time O((mn)^2) + * Space O(1) + * + * @param matrix + * @return + */ + public int maximalRectangle(char[][] matrix) { + int m = matrix.length; + if (m == 0) return 0; + int n = matrix[0].length; + + int max = 0; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (matrix[i][j] == '1') { + // search for largest rectangle possible + // if at any point encountered 0, then discontinue + int len = 0; + int wid = n - j; + for (int r = 0; r < m - i; r++) { + if (matrix[r + i][j] == '0') break; + + for (int c = 0; c < wid; c++) { + if (matrix[r + i][c + j] == '0') { + max = Math.max(len * wid, max); + wid = Math.min(wid, c); + break; + } + } + len++; + } + max = Math.max(len * wid, max); + + } + } + } + return max; + } + + @Test + public void test() { + char[][] matrix = new char[][]{ + {'1', '0', '1', '0', '0'}, + {'1', '0', '1', '1', '1'}, + {'1', '1', '1', '1', '1'}, + {'1', '0', '0', '1', '0'} + }; + + assertEquals(6, maximalRectangle(matrix)); + } + + @Test + public void test2() { + char[][] matrix = new char[][]{ + {'1', '1', '1', '1', '1', '1', '1', '1'}, + {'1', '1', '1', '1', '1', '1', '1', '0'}, + {'1', '1', '1', '1', '1', '1', '1', '0'}, + {'1', '1', '1', '1', '1', '0', '0', '0'}, + {'0', '1', '1', '1', '1', '0', '0', '0'} + }; + assertEquals(21, maximalRectangle(matrix)); + } +} From f296b4e97f7aa51919e59d63d89d246e3b65335b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 19 Dec 2019 16:32:21 -0600 Subject: [PATCH 105/189] Added solution for max submatrix sum --- .../algorithm/leetcode/MaxSubmatrixSum.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubmatrixSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubmatrixSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubmatrixSum.java new file mode 100644 index 0000000..d2d804f --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxSubmatrixSum.java @@ -0,0 +1,58 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/ + */ +public class MaxSubmatrixSum { + public int maxSumSubmatrix(int[][] matrix, int k) { + int m = matrix.length; + if (m == 0) return 0; + int n = matrix[0].length; + + int[][] height = new int[m][n]; + height[0] = matrix[0]; + + for (int i = 1; i < m; i++) { + for (int j = 0; j < n; j++) { + height[i][j] = height[i - 1][j] + matrix[i][j]; + } + } + + int max = 0; + + for (int i = 0; i < m; i++) { + for (int j = i; j < m; j++) { + int[] curr = new int[n]; + if (i > 0) curr = height[i - 1]; + int currMax = maxSum(height[j], curr, k); + if (currMax <= k) { + max = Math.max(currMax, max); + } + + } + } + return max; + } + + private int maxSum(int[] height, int[] minus, int k) { + int max = 0; + int curr = 0; + + for (int i = 0; i < height.length; i++) { + int h = height[i] - minus[i]; + curr = Math.max(0, curr) + h; + if (curr <= k) max = Math.max(curr, max); + } + return max; + } + + @Test + public void test() { + int[][] matrix = new int[][] {{2,2,-1}}; + assertEquals(3, maxSumSubmatrix(matrix, 3)); + } +} From 59dddde9953402cb0b8025783e777d770310432c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 19 Dec 2019 18:42:58 -0600 Subject: [PATCH 106/189] Added solution for largest plus sign --- .../algorithm/leetcode/LargestPlusSign.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestPlusSign.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestPlusSign.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestPlusSign.java new file mode 100644 index 0000000..cd48e5b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestPlusSign.java @@ -0,0 +1,72 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/largest-plus-sign/ + */ +public class LargestPlusSign { + public int orderOfLargestPlusSign(int N, int[][] mines) { + int[][] matrix = new int[N][N]; + for (int[] mine : mines) { + int r = mine[0]; + int c = mine[1]; + matrix[r][c] = 1; + } + + int[][] left = new int[N][N]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (matrix[i][j] == 0) { + left[i][j] = (j > 0 ? left[i][j - 1] : 0) + 1; + } + } + } + + int[][] right = new int[N][N]; + for (int i = 0; i < N; i++) { + for (int j = N - 1; j >= 0; j--) { + if (matrix[i][j] == 0) { + right[i][j] = (j < N - 1 ? right[i][j + 1] : 0) + 1; + } + } + } + + int[][] top = new int[N][N]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (matrix[i][j] == 0) + top[i][j] = (i > 0 ? top[i - 1][j] : 0) + 1; + } + + } + + int[][] bottom = new int[N][N]; + for (int i = N - 1; i >= 0; i--) { + for (int j = 0; j < N; j++) { + if (matrix[i][j] == 0) { + bottom[i][j] = (i < N - 1 ? bottom[i + 1][j] : 0) + 1; + } + } + } + + int order = 0; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + if (matrix[i][j] == 0) { + int curr = Math.min(Math.min(left[i][j], right[i][j]), + Math.min(top[i][j], bottom[i][j])); + order = Math.max(order, curr); + } + } + } + return order; + } + + @Test + public void test() { + assertEquals(2, orderOfLargestPlusSign(5, new int[][]{{4, 2}})); + } +} From 3c5a9629ff9aca01cac1145e690bc62744231a5d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 19 Dec 2019 18:53:23 -0600 Subject: [PATCH 107/189] Added solution for count-square-submatrices-with-all-ones --- .../leetcode/Count1sSquareSubmatrices.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Count1sSquareSubmatrices.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Count1sSquareSubmatrices.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Count1sSquareSubmatrices.java new file mode 100644 index 0000000..4baa857 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Count1sSquareSubmatrices.java @@ -0,0 +1,42 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/count-square-submatrices-with-all-ones/ + */ +public class Count1sSquareSubmatrices { + public int countSquares(int[][] matrix) { + int m = matrix.length; + if (m == 0) return 0; + int n = matrix[0].length; + int count = 0; + + int[][] mem = new int[m + 1][n + 1]; + + for (int row = 1; row <= m; row++) { + for (int col = 1; col <= n; col++) { + if (matrix[row - 1][col - 1] == 1) { + mem[row][col] = 1 + Math.min(mem[row - 1][col - 1], + Math.min(mem[row - 1][col], mem[row][col - 1])); + count += mem[row][col]; + } + } + } + + return count; + } + + @Test + public void test() { + int[][] matrix = new int[][]{ + {0, 1, 1, 1}, + {1, 1, 1, 1}, + {0, 1, 1, 1} + }; + + assertEquals(15, countSquares(matrix)); + } +} From 5371336e8b8435dafc58c548f9997b0fa39ad4f6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 21 Dec 2019 17:21:47 -0600 Subject: [PATCH 108/189] Added solution for twitter design --- .../examples/design/TwitterTester.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/design/TwitterTester.java diff --git a/src/main/java/com/eprogrammerz/examples/design/TwitterTester.java b/src/main/java/com/eprogrammerz/examples/design/TwitterTester.java new file mode 100644 index 0000000..f5d4ce1 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/design/TwitterTester.java @@ -0,0 +1,114 @@ +package com.eprogrammerz.examples.design; + +import org.junit.Test; + +import java.time.LocalDateTime; +import java.util.*; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.MatcherAssert.assertThat; + +public class TwitterTester { + + @Test + public void test() { + Twitter twitter = new Twitter(); + twitter.postTweet(1,5); + twitter.postTweet(1,3); + twitter.postTweet(1,101); + twitter.postTweet(1,13); + twitter.postTweet(1,10); + twitter.postTweet(1,2); + twitter.postTweet(1,94); + twitter.postTweet(1,505); + twitter.postTweet(1,333); + + System.out.println(twitter.getNewsFeed(1)); + assertThat(twitter.getNewsFeed(1), hasItems(333, 505, 94, 2, 10, 13, 101, 3, 5)); + } +} + + +class Twitter { + + private Map> m1; + private Map> m2; + + private long timestamp; + /** Initialize your data structure here. */ + public Twitter() { + this.m1 = new HashMap<>(); + this.m2 = new HashMap<>(); + } + + /** Compose a new tweet. */ + public void postTweet(int userId, int tweetId) { + if (!m1.containsKey(userId)) { + m1.put(userId, new ArrayList<>()); + } + if (!m2.containsKey(userId)) { + m2.put(userId, new HashSet<>()); + } + this.m1.get(userId).add(new Tweet(tweetId, ++timestamp)); + } + + /** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */ + public List getNewsFeed(int userId) { + PriorityQueue pq = new PriorityQueue<>( + (t1, t2) -> (int) (t1.dateCreated - t2.dateCreated)); + List self = m1.get(userId); + if (self != null && !self.isEmpty()) { + for (Tweet tweet: self) { + pq.offer(tweet); + if (pq.size() > 10) pq.poll(); + } + + } + + Set followees = m2.get(userId); + if (followees != null) { + for (int followee: followees) { + List tweets = m1.get(followee); + if (tweets == null) continue; + + for (Tweet tweet: tweets) { + pq.add(tweet); + if (pq.size() > 10) pq.poll(); + } + } + } + + LinkedList posts = new LinkedList<>(); + while (!pq.isEmpty()) { + posts.addFirst(pq.poll().tweetId); + } + return posts; + } + + /** Follower follows a followee. If the operation is invalid, it should be a no-op. */ + public void follow(int followerId, int followeeId) { + if (followerId == followeeId) return; + + if (!m2.containsKey(followerId)) { + m2.put(followerId, new HashSet<>()); + } + this.m2.get(followerId).add(followeeId); + } + + /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */ + public void unfollow(int followerId, int followeeId) { + if (!m2.containsKey(followerId)) return; + m2.get(followerId).remove(followeeId); + } + + + class Tweet { + int tweetId; + long dateCreated; + + Tweet(int tweetId, long dateCreated) { + this.tweetId = tweetId; + this.dateCreated = dateCreated; + } + } +} From 7e70916d0559c317ab62cab154bc9fca5978540f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 21 Dec 2019 22:05:08 -0600 Subject: [PATCH 109/189] Added solution for Dividing array of into sub arr with size k --- .../leetcode/DivideArrayKSubArr.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DivideArrayKSubArr.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DivideArrayKSubArr.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DivideArrayKSubArr.java new file mode 100644 index 0000000..8a81290 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DivideArrayKSubArr.java @@ -0,0 +1,48 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; +import org.springframework.stereotype.Repository; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +/** + * https://leetcode.com/problems/divide-array-in-sets-of-k-consecutive-numbers/ + */ +public class DivideArrayKSubArr { + public boolean isPossibleDivide(int[] nums, int k) { + + int n = nums.length; + if (n % k != 0) return false; + + int r = n / k; + int[][] partitions = new int[r][k]; + + int[] pos = new int[r]; + + for (int num: nums) { + // n has to go any of parititions + for (int i = 0; i < partitions.length; i++) { + if (pos[i] >= k) continue; + + if (pos[i] == 0 || num == partitions[i][pos[i] - 1] + 1) { + partitions[i][pos[i]] = num; + pos[i]++; + break; + } + } + } + + for (int p: pos) { + if (p != k) return false; + } + return true; + } + + @Test + public void test() { + assertFalse(isPossibleDivide(new int[] {15,16,17,18,19,16,17,18,19,20,6,7,8,9,10,3,4,5,6,20}, 5)); + assertTrue(isPossibleDivide(new int[] {1,2,3,3,4,4,5,6}, 4)); + } +} From 0b3bbc9993de2f67bdbc62fcf0b934a31cc530a2 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 24 Dec 2019 09:18:50 -0600 Subject: [PATCH 110/189] Added example implementation of Fenwick tree --- .../examples/algorithm/trees/FenwickTree.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/FenwickTree.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/FenwickTree.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/FenwickTree.java new file mode 100644 index 0000000..de99563 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/FenwickTree.java @@ -0,0 +1,74 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Representation to calculate prefix sum in O(logn) time + */ +public class FenwickTree { + /** + * Create binary indexed tree is basically updating it + * + * @param arr + * @return + */ + public int[] createBit(int[] arr) { + int n = arr.length; + int[] bit = new int[n + 1]; + + for (int i = 0; i < n; i++) { + updateBit(bit, i + 1, arr[i]); + } + + return bit; + } + + public void updateBit(int[] bit, int idx, int val) { + while (idx < bit.length) { + bit[idx] += val; + idx = nextIndex(idx); + } + } + + private int nextIndex(int idx) { + return idx + (idx & (-idx)); + } + + /** + * idx is index in input array + * We need to look until we reach end of parents of nodes + * + * @param idx + * @return + */ + public int prefixSum(int[] bit, int idx) { + // bit index is arr_index + 1 + idx = idx + 1; + int sum = 0; + while (idx > 0) { + sum += bit[idx]; + idx = parentIdx(idx); + } + return sum; + } + + private int parentIdx(int idx) { + return idx - (idx & (-idx)); + } + + @Test + public void test() { + int[] arr = new int[]{3, 2, -1, 6, 5, 4, -3}; + int[] bit = createBit(arr); + + assertEquals(3, prefixSum(bit, 0)); + assertEquals(5, prefixSum(bit, 1)); + assertEquals(4, prefixSum(bit, 2)); + assertEquals(10, prefixSum(bit, 3)); + assertEquals(15, prefixSum(bit, 4)); + assertEquals(19, prefixSum(bit, 5)); + assertEquals(16, prefixSum(bit, 6)); + } +} From 60c75b72185fdc3a39eaf69509453ff2ab2625b3 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 24 Dec 2019 17:32:36 -0600 Subject: [PATCH 111/189] Added solution for similar strings groups --- .../algorithm/graphs/SimilarStringGroups.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/SimilarStringGroups.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/SimilarStringGroups.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/SimilarStringGroups.java new file mode 100644 index 0000000..ebbf157 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/SimilarStringGroups.java @@ -0,0 +1,74 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/similar-string-groups/ + */ +public class SimilarStringGroups { + public int numSimilarGroups(String[] A) { + Map> graph = new HashMap<>(); + + for (String v: A) { + graph.put(v, new ArrayList<>()); + } + + for (int i = 0; i < A.length; i++) { + String u = A[i]; + + List uNeighbors = graph.get(u); + + for (int j = i + 1; j < A.length; j++) { + String v = A[j]; + List vNeighbors = graph.get(v); + + if (edge(u, v)) { + uNeighbors.add(v); + vNeighbors.add(u); + } + } + } + + Set visited = new HashSet<>(); + + int count = 0; + + for (String v: A) { + if (!visited.contains(v)) { + count++; + dfs(visited, graph, v); + } + } + + return count; + } + + private boolean edge(String u, String v) { + int diff = 0; + + for (int i = 0; i < u.length(); i++) { + if (u.charAt(i) != v.charAt(i)) diff++; + } + return diff == 2; + } + + private void dfs(Set visited, Map> graph, String v) { + if (visited.contains(v)) return; + visited.add(v); + + List neighbors = graph.get(v); + + for (String n: neighbors) { + dfs(visited, graph, n); + } + } + + @Test + public void test() { + assertEquals(2, numSimilarGroups(new String[] {"tars", "star", "arts", "rats"})); + } +} From 0f3559c71ac18dd9d5f40003e9cb936d6a84a4a6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 24 Dec 2019 22:07:49 -0600 Subject: [PATCH 112/189] Added solution for largest component --- .../algorithm/graphs/LargestComponent.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/LargestComponent.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/LargestComponent.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/LargestComponent.java new file mode 100644 index 0000000..5bbd4b4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/LargestComponent.java @@ -0,0 +1,58 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/largest-component-size-by-common-factor/ + */ +public class LargestComponent { + public int largestComponentSize(int[] A) { + int[] parents = new int[100001]; + + for (int i = 0; i < parents.length; i++) { + parents[i] = i; + } + + + for (int a: A) { + for (int j = (int) Math.sqrt(a); j >= 2; j--) { + union(parents, a, j); + union(parents, a, a / j); + } + } + + Map countMap = new HashMap<>(); + + int max = 0; + + for (int a: A) { + int k = root(parents, a); + int curr = countMap.getOrDefault(k, 0) + 1; + if (curr > max) max = curr; + countMap.put(k, curr); + } + + return max; + } + + private int root(int[] parents, int u) { + while (u != parents[u]) { + u = parents[u]; + } + return u; + } + + private void union(int[] parents, int u, int v) { + + parents[root(parents, v)] = parents[root(parents, u)]; + } + + @Test + public void test() { + assertEquals(8, largestComponentSize(new int[] {2,3,6,7,4,12,21,39})); + } +} From 51c56f1547148bc72b4de9d1dac244c7b32b278b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 26 Dec 2019 08:21:06 -0600 Subject: [PATCH 113/189] Added solution for Skyline problem --- .../algorithm/leetcode/SkylineProblem.java | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SkylineProblem.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SkylineProblem.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SkylineProblem.java new file mode 100644 index 0000000..7e5973b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SkylineProblem.java @@ -0,0 +1,111 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.TreeMap; + +import static com.google.common.collect.Lists.newArrayList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/the-skyline-problem/ + */ +public class SkylineProblem { + public List> getSkyline(int[][] buildings) { + List> l = new ArrayList<>(); + + int n = buildings.length; + + if (n == 0) return l; + + // we'll create points with x-value and height and mark if it is start + // or end for that particular building + int[][] points = new int[2 * n][3]; + + for (int i = 0, j = 0; i < n; i++, j += 2) { + int start = buildings[i][0]; + int end = buildings[i][1]; + int height = buildings[i][2]; + + points[j] = new int[]{start, height, 0}; // points[2] == 0 -> start + points[j + 1] = new int[]{end, height, 1}; // points[2] == 1 -> end + } + + // now sort points with start + // if start are equals, then sort them with height or start/end to cover corner cases + Arrays.sort(points, (p1, p2) -> { + int diff = p1[0] - p2[0]; + + if (diff == 0) { + // if both are start point, then we process taller building + if (p1[2] == 0 && p2[2] == 0) { + return p2[1] - p1[1]; + } else if (p1[2] == 1 && p2[2] == 1) { // if both are end point, then we process shorter building first + return p1[1] - p2[1]; + } else { + return p1[2] - p2[0]; // if start of one is end of other, then start has to be processed first + } + } + return diff; + }); + + /** + * 1. have priority queue starting with element 0 + * and max = 0 + * 2. for each point, if it is + * a) start, then put height h into pq, if it changes max, then add (start, h) into result list + * b) end, then remove height h from pq, if it changes max, then add (end, max) int result list + * + * + * Since PriorityQueue has remove with time O(n), overall Time O(n^2) + * But, TreeMap has O(logn) for remove as well. So, we'll use TreeMap + */ + + TreeMap pq = new TreeMap<>((i1, i2) -> i2 - i1); + pq.put(0, 1); + int max = 0; + + for (int[] point : points) { + if (point[2] == 0) { // start + int height = point[1]; + pq.put(height, pq.getOrDefault(height, 0) + 1); + + if (max == pq.firstKey()) continue; + + max = pq.firstKey(); + l.add(newArrayList(point[0], height)); + } else { // end + int rem = pq.get(point[1]) - 1; + if (rem == 0) { + pq.remove(point[1]); + } else { + pq.put(point[1], rem); + } + + if (max == pq.firstKey()) continue; + + max = pq.firstKey(); + + l.add(newArrayList(point[0], max)); + } + } + + return l; + } + + @Test + public void test() { + int[][] buildings = {{2, 9, 10}, {3, 7, 15}, {5, 12, 12}, {15, 20, 10}, {19, 24, 8}}; + List> points = getSkyline(buildings); + + List> expected = newArrayList(newArrayList(2, 10), newArrayList(3, 15), + newArrayList(7, 12), newArrayList(12, 0), newArrayList(15, 10), + newArrayList(20, 8), newArrayList(24, 0)); + + assertThat(points, is(expected)); + } +} From 550801e8a79320de842a4075300176e8baee2aaa Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 26 Dec 2019 11:39:25 -0600 Subject: [PATCH 114/189] Added solution for Count of Range Sum --- .../algorithm/leetcode/CountOfRangeSum.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java new file mode 100644 index 0000000..6b78e0a --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java @@ -0,0 +1,39 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.TreeMap; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/count-of-range-sum/ + */ +public class CountOfRangeSum { + public int countRangeSum(int[] nums, int lower, int upper) { + + TreeMap map = new TreeMap<>(); + map.put(0L, 1); + + long sum = 0; + + int count = 0; + + for (int n : nums) { + sum += n; + + for (int cnt : map.subMap(sum - upper, true, sum - lower, true).values()) { + count += cnt; + } + + map.put(sum, map.getOrDefault(sum, 0) + 1); + } + + return count; + } + + @Test + public void test() { + assertEquals(3, countRangeSum(new int[]{-2, 5, -1}, -2, 2)); + } +} From f37867de5a47b8f2fd4b7c332f262888b0ed3312 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 27 Dec 2019 18:16:39 -0600 Subject: [PATCH 115/189] Added solution minimum falling path sum --- .../leetcode/MiniFallingPathSum.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniFallingPathSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniFallingPathSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniFallingPathSum.java new file mode 100644 index 0000000..800a465 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MiniFallingPathSum.java @@ -0,0 +1,64 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +/** + * https://leetcode.com/problems/minimum-falling-path-sum/ + */ +public class MiniFallingPathSum { + public int minFallingPathSum(int[][] A) { + int min = Integer.MAX_VALUE; + + int m = A.length; + int n = A[0].length; + + int[][] mem = new int[m][n]; + + mem[0] = A[0]; + + for (int r = 1; r < A.length; r++) { + + for (int i = 0; i < n; i++) { + int curr; + if (i == 0) { + curr = Math.min(mem[r - 1][i], mem[r - 1][i + 1]); + } else if (i == n - 1) { + curr = Math.min(mem[r - 1][i - 1], mem[r - 1][i]); + } else { + curr = Math.min(mem[r - 1][i - 1], Math.min(mem[r - 1][i], mem[r - 1][i + 1])); + } + mem[r][i] = curr + A[r][i]; + } + } + + int currMin = findMin(mem[m - 1]); + if (min > currMin) min = currMin; + + return min; + } + + private int findMin(int[] arr) { + int min = arr[0]; + + for (int i = 1; i < arr.length; i++) { + if (arr[i] < min) min = arr[i]; + } + + return min; + } + + @Test + public void test1() { + int[][] mat = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + assertEquals(12, minFallingPathSum(mat)); + } + + @Test + public void test2() { + int[][] mat = {{-51, -35, 74}, {-62, 14, -53}, {94, 61, -10}}; + assertEquals(-98, minFallingPathSum(mat)); + } +} From 4c3173c4f1a69c07375ed826920920c9e3e4157d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 27 Dec 2019 19:04:19 -0600 Subject: [PATCH 116/189] Updated count range sum with merge sort --- .../algorithm/leetcode/CountOfRangeSum.java | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java index 6b78e0a..8098417 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CountOfRangeSum.java @@ -2,8 +2,6 @@ import org.junit.Test; -import java.util.TreeMap; - import static org.junit.Assert.assertEquals; /** @@ -12,26 +10,57 @@ public class CountOfRangeSum { public int countRangeSum(int[] nums, int lower, int upper) { - TreeMap map = new TreeMap<>(); - map.put(0L, 1); + long[] sum = new long[nums.length + 1]; + for (int i = 1; i <= nums.length; i++) { + sum[i] = sum[i - 1] + nums[i - 1]; + } - long sum = 0; + return mergeSort(sum, 0, sum.length - 1, lower, upper); + } - int count = 0; + private int mergeSort(long[] arr, int lo, int hi, int lower, int upper) { + if (lo >= hi) return 0; + int mid = lo + (hi - lo) / 2; - for (int n : nums) { - sum += n; + int count = mergeSort(arr, lo, mid, lower, upper) + mergeSort(arr, mid + 1, hi, lower, upper); - for (int cnt : map.subMap(sum - upper, true, sum - lower, true).values()) { - count += cnt; - } + for (int i = lo, j = mid + 1, k = mid + 1; i <= mid; i++) { + while (j <= hi && arr[j] - arr[i] < lower) j++; + while (k <= hi && arr[k] - arr[i] <= upper) k++; - map.put(sum, map.getOrDefault(sum, 0) + 1); + count += (k - j); } + merge(arr, lo, mid, hi); + return count; } + private void merge(long[] arr, int lo, int mid, int hi) { + long[] copy = new long[hi - lo + 1]; + + int p = lo; + int q = mid + 1; + int i = 0; + while (p <= mid && q <= hi) { + if (arr[p] < arr[q]) { + copy[i++] = arr[p++]; + } else { + copy[i++] = arr[q++]; + } + } + + while (p <= mid) { + copy[i++] = arr[p++]; + } + + while (q <= hi) { + copy[i++] = arr[q++]; + } + + System.arraycopy(copy, 0, arr, lo, hi - lo + 1); + } + @Test public void test() { assertEquals(3, countRangeSum(new int[]{-2, 5, -1}, -2, 2)); From 782f3aaa918dd4bdb35841c567768d5eed2f61fb Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 27 Dec 2019 21:31:31 -0600 Subject: [PATCH 117/189] Added solution for minimum costs for tickets with memoization --- .../algorithm/leetcode/MinCostForTickets.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinCostForTickets.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinCostForTickets.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinCostForTickets.java new file mode 100644 index 0000000..ff256e2 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinCostForTickets.java @@ -0,0 +1,60 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/minimum-cost-for-tickets/ + */ +public class MinCostForTickets { + public int mincostTickets(int[] days, int[] costs) { + int[] mem = new int[days.length]; + + dfs(days, 0, costs, mem); + return mem[0]; + } + + private int dfs(int[] days, int idx, int[] costs, int[] mem) { + if (idx >= days.length) { + return 0; + } + + if (mem[idx] > 0) return mem[idx]; + + int single = costs[0] + dfs(days, idx + 1, costs, mem); // just moves to next index + + int i = idx + 1; + for (; i < days.length; i++) { + + if (days[i] >= days[idx] + 7) { + i--; + break; + } + } + + int week = costs[1] + dfs(days, i + 1, costs, mem); + + i = idx + 1; + for (; i < days.length; i++) { + if (days[i] >= days[idx] + 30) { + i--; + break; + } + } + int months = costs[2] + dfs(days, i + 1, costs, mem); + + mem[idx] = Math.min(single, Math.min(week, months)); + return mem[idx]; + } + + @Test + public void test1() { + assertEquals(11, mincostTickets(new int[] {1,4,6,7,8,20}, new int[] {2, 7, 15})); + } + + @Test + public void test2() { + assertEquals(17, mincostTickets(new int[] {1,2,3,4,5,6,7,8,9,10,30,31}, new int[] {2, 7, 15})); + } +} From 2273896b80709c0998b8b8c9efd78233c542c858 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 28 Dec 2019 09:19:06 -0600 Subject: [PATCH 118/189] Added solution for dice roll with target --- .../leetcode/DiceRollWithTarget.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DiceRollWithTarget.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DiceRollWithTarget.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DiceRollWithTarget.java new file mode 100644 index 0000000..9b7b9a4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DiceRollWithTarget.java @@ -0,0 +1,37 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/number-of-dice-rolls-with-target-sum/ + */ +public class DiceRollWithTarget { + public int numRollsToTarget(int d, int f, int target) { + int mod = 1000000007; + int[] ways = new int[target + 1]; + ways[0] = 1; + for (int i = 1; i <= d; i++) { + int[] newWays = new int[target + 1]; + + for (int j = 0; j <= target; j++) { + for (int k = 1; k <= f; k++) { + if (j >= k) { + newWays[j] += ways[j - k]; + newWays[j] %= mod; + } + + } + } + ways = newWays; + } + + return ways[target]; + } + + @Test + public void test() { + assertEquals(1, numRollsToTarget(1, 6, 3)); + } +} From f195a7acc374b2b4514aed1bffd4bb7156911a8e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 28 Dec 2019 10:49:27 -0600 Subject: [PATCH 119/189] Added solution for buy sell stock with single transaction --- .../algorithm/leetcode/BuySellStock.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BuySellStock.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BuySellStock.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BuySellStock.java new file mode 100644 index 0000000..bb59f38 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BuySellStock.java @@ -0,0 +1,28 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ + */ +public class BuySellStock { + public int maxProfit(int[] prices) { + int minPrice = Integer.MAX_VALUE; + int profit = 0; + + for (int i = 0; i < prices.length; i++) { + if (minPrice > prices[i]) minPrice = prices[i]; + + if (prices[i] - minPrice > profit) profit = prices[i] - minPrice; + } + return profit; + } + + @Test + public void test() { + assertEquals(5, maxProfit(new int[]{7, 1, 5, 3, 6, 4})); + assertEquals(1, maxProfit(new int[]{1, 2})); + } +} From 1f547141a0419320e01aef170bbd26a8b6b7d0f6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 29 Dec 2019 11:01:45 -0600 Subject: [PATCH 120/189] Added solution for ones and zeros --- .../algorithm/leetcode/OnesAndZeros.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OnesAndZeros.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OnesAndZeros.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OnesAndZeros.java new file mode 100644 index 0000000..c00139c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OnesAndZeros.java @@ -0,0 +1,89 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/ones-and-zeroes/ + */ +public class OnesAndZeros { + public int findMaxForm(String[] strs, int m, int n) { + int[][] mem = new int[m + 1][n + 1]; + + for (String str : strs) { + int ones = 0; + int zeros = 0; + + for (char ch : str.toCharArray()) { + if (ch == '0') zeros++; + else ones++; + } + + for (int i = m; i >= zeros; i--) { + for (int j = n; j >= ones; j--) { + + mem[i][j] = Math.max(mem[i][j], mem[i - zeros][j - ones] + 1); + + } + } + } + + return mem[m][n]; + } + /* + private int ans = 0; + public int findMaxForm(String[] strs, int m, int n) { + dfs(strs, m, n, 0); + return ans; + } + + private void dfs(String[] strs, int m, int n, int count) { + if (m < 0 || n < 0) return; + if (count > ans) ans = count; + + for (int i = 0; i < strs.length; i++) { + String[] rem = new String[strs.length - 1]; + for (int j = 0, k = 0; j < strs.length;j++) { + if (i == j) continue; + rem[k++] = strs[j]; + } + + int ones = 0; + int zeros = 0; + + for (char ch: strs[i].toCharArray()) { + if (ch == '0') zeros++; + else ones++; + } + + dfs(rem, m - zeros, n - ones, count + 1); + } + } + */ + + + @Test + public void test1() { + assertEquals(4, findMaxForm(new String[]{"10", "0001", "111001", "1", "0"}, 5, 3)); + } + + @Test + public void test2() { + assertEquals(2, findMaxForm(new String[]{"10", "0", "1"}, 1, 1)); + } + + @Test + public void test3() { + assertEquals(4, findMaxForm(new String[]{"0", "0", "1", "1"}, 2, 2)); + } + + @Test + public void test4() { + assertEquals(3, findMaxForm(new String[]{"10", "0001", "111001", "1", "0"}, 3, 4)); + } +} From f89cbcab81faba1669a88f901f10a7a99af404db Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 29 Dec 2019 13:00:53 -0600 Subject: [PATCH 121/189] Added solution for reverse pairs --- .../algorithm/leetcode/ReversePairs.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReversePairs.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReversePairs.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReversePairs.java new file mode 100644 index 0000000..6d92f3b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReversePairs.java @@ -0,0 +1,78 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * pair of indices (i, j) are important pairs such that i < j & nums[i] > 2 * num[j] + * + * Return count of all those pairs + * + * https://leetcode.com/problems/reverse-pairs/ + */ +public class ReversePairs { + + public int reversePairs(int[] nums) { + int n = nums.length; + return mergeSort(nums, 0, n - 1); + } + + private int mergeSort(int[] nums, int lo, int hi) { + if (lo >= hi) return 0; + int mid = lo + (hi - lo) / 2; + int count = mergeSort(nums, lo, mid) + mergeSort(nums, mid + 1, hi); + + int p = lo; + int q = mid + 1; + + while (p <= mid && q <= hi) { + if (nums[p] > 2L * nums[q]) { + count += (mid - p + 1); + q++; + } else { + p++; + } + } + + merge(nums, lo, mid, hi); + + return count; + } + + private void merge(int[] nums, int lo, int mid, int hi) { + int len = hi - lo + 1; + int[] copy = new int[len]; + + int p = lo; + int q = mid + 1; + + int i = 0; + + while (p <= mid && q <= hi) { + if (nums[p] < nums[q]) { + copy[i++] = nums[p++]; + } else { + copy[i++] = nums[q++]; + } + } + + while (p <= mid) { + copy[i++] = nums[p++]; + } + + while (q <= hi) { + copy[i++] = nums[q++]; + } + + System.arraycopy(copy, 0, nums, lo, len); + } + + + @Test + public void test() { + assertEquals(4, reversePairs(new int[] {5,4,3,2,1})); + assertEquals(2, reversePairs(new int[] {1,3,2,3,1})); + assertEquals(3, reversePairs(new int[] {2,4,3,5,1})); + } +} From b6c9d4c99586a219a8d3a48a26877c40c9309a35 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 29 Dec 2019 13:58:20 -0600 Subject: [PATCH 122/189] Added solution for target sum --- .../algorithm/leetcode/TargetSum.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TargetSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TargetSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TargetSum.java new file mode 100644 index 0000000..5d05cc5 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TargetSum.java @@ -0,0 +1,67 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/target-sum/ + */ +public class TargetSum { + /*public int findTargetSumWays(int[] nums, int S) { + int[] dp = new int[S + 1]; + for (int n: nums) { + if (n < S) { + dp[n] = 1; + } + } + for (int i = 1; i <= S; i++) { + for (int n: nums) { + if (i >= n) + dp[i] += dp[i - n]; + +// if (i + n <= S) +// dp[i] += dp[i + n]; + } + } + + return dp[S - 1]; + }*/ + + public int findTargetSumWays(int[] nums, int S) { + Map mem = new HashMap<>(); + + return dfs(nums, S, 0, mem); + } + + private int dfs(int[] nums, int target, int idx, Map mem) { // 3, 0, 0 + + if (idx > nums.length) return 0; + + if (nums.length == idx) { + if (target == 0) + return 1; // target = 3, sum = -4, idx = 4 + return 0; + } + + String key = target + "#" + idx; + + if (mem.containsKey(key)) return mem.get(key); + + int curr = dfs(nums, target - nums[idx], idx + 1, mem) + + dfs(nums, target + nums[idx], idx + 1, mem); + + mem.put(key, curr); + + return mem.get(key); + } + + + @Test + public void test1() { // 9725438598 + assertEquals(5, findTargetSumWays(new int[] {1, 1, 1, 1, 1}, 3)); + } +} From 7e0f2aa87c407369e0245a29598d98841699c60e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 29 Dec 2019 16:51:40 -0600 Subject: [PATCH 123/189] Added solution for dinner plates stack --- .../ds/custom/stack/DinnerPlates.java | 77 +++++++++++++++++++ .../examples/ds/custom/stack/Validator.java | 52 +++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/stack/DinnerPlates.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/DinnerPlates.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/DinnerPlates.java new file mode 100644 index 0000000..994e0bc --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/DinnerPlates.java @@ -0,0 +1,77 @@ +package com.eprogrammerz.examples.ds.custom.stack; + +import java.util.*; + +/** + * https://leetcode.com/problems/dinner-plate-stacks/ + */ +public class DinnerPlates { + + private List> l; + private PriorityQueue pq; + private int capacity; + private Set candidates; + + public DinnerPlates(int capacity) { + this.capacity = capacity; + this.l = new ArrayList<>(); + this.l.add(new Stack<>()); // add stack at 0 + this.pq = new PriorityQueue<>(); + this.pq.offer(0); // let pq know that stack at 0 is candidate stack + this.candidates = new HashSet<>(); + this.candidates.add(0); + } + + public void push(int val) { + int idx = pq.peek(); + Stack stack = l.get(idx); + stack.push(val); + + if (stack.size() == capacity) { + candidates.remove(idx); + pq.poll(); + + if (l.size() == idx + 1) { + l.add(new Stack<>()); + candidates.add(idx + 1); + pq.offer(idx + 1); + } + + } + } + + public int pop() { + int idx = l.size() - 1; + Stack stack = l.get(idx); + if (stack == null) return -1; + + if (stack.isEmpty()) { + if (idx == 0) return -1; + + l.remove(idx); + return pop(); + } + + int val = stack.pop(); + + if (candidates.add(idx)) { + pq.offer(idx); + } + return val; + } + + public int popAtStack(int index) { + if (index >= l.size()) return -1; // no stack at this index + Stack stack = l.get(index); + + if (stack == null || stack.isEmpty()) return -1; + + int val = stack.pop(); + + if (candidates.add(index)) { + pq.add(index); + } + + return val; + } +} diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java index 42abd01..a3515c2 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/Validator.java @@ -137,4 +137,56 @@ public void testStackWHeap() { assertEquals(2, stack.pop()); assertEquals(1, stack.pop()); } + + @Test + public void testDinnerPlate1() { + DinnerPlates dinnerPlates = new DinnerPlates(2); + dinnerPlates.push(1); + dinnerPlates.push(2); + dinnerPlates.push(3); + dinnerPlates.push(4); + dinnerPlates.push(5); + + assertEquals(2, dinnerPlates.popAtStack(0)); + + dinnerPlates.push(20); + dinnerPlates.push(21); + + assertEquals(20, dinnerPlates.popAtStack(0)); + assertEquals(21, dinnerPlates.popAtStack(2)); + assertEquals(5, dinnerPlates.pop()); + assertEquals(4, dinnerPlates.pop()); + assertEquals(3, dinnerPlates.pop()); + assertEquals(1, dinnerPlates.pop()); + assertEquals(-1, dinnerPlates.pop()); + } + + @Test + public void testDinnerPlate2() { + DinnerPlates dinnerPlates = new DinnerPlates(2); + dinnerPlates.push(1); + dinnerPlates.push(2); + dinnerPlates.push(3); + dinnerPlates.push(4); + dinnerPlates.push(5); + dinnerPlates.push(6); + dinnerPlates.push(7); + + assertEquals(4, dinnerPlates.popAtStack(1)); + assertEquals(3, dinnerPlates.popAtStack(1)); + + + assertEquals(6, dinnerPlates.popAtStack(2)); + assertEquals(5, dinnerPlates.popAtStack(2)); + + + assertEquals(7, dinnerPlates.popAtStack(3)); + + dinnerPlates.push(12); + assertEquals(12, dinnerPlates.popAtStack(1)); + + assertEquals(2, dinnerPlates.pop()); + assertEquals(1, dinnerPlates.pop()); + assertEquals(-1, dinnerPlates.pop()); + } } From af0a30e14b535dfb8771e5bc1d725f4e7bb76523 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 29 Dec 2019 20:22:15 -0600 Subject: [PATCH 124/189] Added solution for expression add operators --- .../leetcode/ExpressionsAddOperators.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressionsAddOperators.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressionsAddOperators.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressionsAddOperators.java new file mode 100644 index 0000000..f914c0e --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressionsAddOperators.java @@ -0,0 +1,99 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Stack; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/expression-add-operators/ + * + * + * Given a string that contains only digits 0-9 and a target value, return all possibilities to + * add binary operators (not unary) +, -, or * between the digits so they evaluate to the target value. + * + * Example 1: + * + * Input: num = "123", target = 6 + * Output: ["1+2+3", "1*2*3"] + */ +public class ExpressionsAddOperators { + public List addOperators(String num, int target) { + List l = new ArrayList<>(); + if (num.length() == 0) return l; + + bt(num, target, l, 1, "" + num.charAt(0)); + return l; + } + + private void bt(String num, int target, List l, int i, String exp) { + if (i == num.length()) { + if (evaluate(exp) == target) { + l.add(exp); + } + return; + } + + bt(num, target, l, i + 1, exp + num.charAt(i)); // no op + bt(num, target, l, i + 1, exp + "+" + num.charAt(i)); + bt(num, target, l, i + 1, exp + "-" + num.charAt(i)); + bt(num, target, l, i + 1, exp + "*" + num.charAt(i)); + } + + private long evaluate(String exp) { + + Stack stack = new Stack<>(); + + char lastExp = '#'; + + long curr = 0; + for (int i = 0; i < exp.length(); i++) { + if ('0' <= exp.charAt(i) && exp.charAt(i) <= '9') { + if (curr == 0 && exp.charAt(i) == '0' + && (i + 1) < exp.length() + && '0' <= exp.charAt(i + 1) && exp.charAt(i + 1) <= '9') + return Integer.MAX_VALUE; + + curr = curr * 10 + (exp.charAt(i) - '0'); + continue; + } + + if (lastExp == '*') { + stack.push(stack.pop() * curr); + } else if (lastExp == '-') { + stack.push(-curr); + } else { + stack.push(curr); + } + lastExp = exp.charAt(i); + curr = 0; + } + + if (lastExp == '*') { + stack.push(stack.pop() * curr); + } else if (lastExp == '-') { + stack.push(-curr); + } else { + stack.push(curr); + } + + + long val = 0; + + while (!stack.isEmpty()) { + val += stack.pop(); + } + return val; + } + + @Test + public void test() { + assertThat(addOperators("123", 6), is(Arrays.asList("1+2+3", "1*2*3"))); + assertThat(addOperators("105", 5), is(Arrays.asList("10-5", "1*0+5"))); + } +} From b5645f67a063327a7795acfbd3ed5e9038c0407b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 1 Jan 2020 16:17:56 -0600 Subject: [PATCH 125/189] Added solution for kth largest element O(n) --- .../algorithm/leetcode/KthLargestElement.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/KthLargestElement.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/KthLargestElement.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/KthLargestElement.java new file mode 100644 index 0000000..77bae08 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/KthLargestElement.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/kth-largest-element-in-an-array/ + */ +public class KthLargestElement { + private Random rnd = new Random(); + + public int findKthLargest(int[] nums, int k) { + // we do with ranking + int n = nums.length; + int left = 0; + int right = n - 1; + + while (left <= right) { + int pivotIdx = left + rnd.nextInt(right - left + 1); + + int pIdx = partition(nums, left, right, pivotIdx); + + if (pIdx == n - k) return nums[pIdx]; + + if (pIdx < n - k) { + left = pIdx + 1; + } else { + right = pIdx - 1; + } + } + return -1; + } + + private int partition(int[] nums, int l, int r, int p) { + + int i = l; + + + int pivot = nums[p]; + // put pivot to the end + swap(nums, p, r); + + for (int j = l; j < r; j++) { + if (nums[j] < pivot) { + swap(nums, i, j); + i++; + } + } + + swap(nums, r, i); + + return i; + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + @Test + public void test() { +// assertEquals(4, findKthLargest(new int[] {3,2,3,1,2,4,5,5,6}, 4)); + assertEquals(5, findKthLargest(new int[] {3,2,3,1,2,4,5,5,6}, 2)); + } +} From e6344737b8296401cd068c3163ea0563d4fe0c5b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 1 Jan 2020 17:03:37 -0600 Subject: [PATCH 126/189] Updated k closest point solution to use quick sort --- .../leetcode/ClosestPoint2Origin.java | 109 ++++++++++++------ 1 file changed, 74 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java index 3cd185e..2ad0a01 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ClosestPoint2Origin.java @@ -2,22 +2,24 @@ import org.junit.Test; +import java.util.Arrays; import java.util.PriorityQueue; +import java.util.Random; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; /** * We have a list of points on the plane. Find the K closest points to the origin (0, 0). - * + *

* (Here, the distance between two points on a plane is the Euclidean distance.) - * + *

* You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.) - * - * - * + *

+ *

+ *

* Example 1: - * + *

* Input: points = [[1,3],[-2,2]], K = 1 * Output: [[-2,2]] * Explanation: @@ -25,31 +27,71 @@ * The distance between (-2, 2) and the origin is sqrt(8). * Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin. * We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]]. + *

+ * https://leetcode.com/problems/k-closest-points-to-origin/ */ public class ClosestPoint2Origin { - public int[][] kClosest(int[][] points, int K) { - PriorityQueue pq = new PriorityQueue<>((e1, e2) -> { - return Double.compare(e2.dis, e1.dis); - }); - - for (int[] point : points) { - int x = point[0]; - int y = point[1]; - double dis = Math.sqrt(x * x + y * y); - pq.add(new Pair(dis, point)); - - if (pq.size() > K) { - pq.poll(); + private Random rnd = new Random(); + + /** + * With Sort - Time O(nlogn) + * With heap - Time O(nlogk) + * With Quick Sort - Time O(n) + * + * @param points + * @param k + * @return + */ + public int[][] kClosest(int[][] points, int k) { + int n = points.length; + + if (n == k) return points; + + int l = 0; + int r = n - 1; + + while (l <= r) { + int pivotIdx = l + rnd.nextInt(r - l + 1); + int pIdx = partition(points, l, r, pivotIdx); + + if (k == pIdx) return Arrays.copyOfRange(points, 0, k); + + if (pIdx > k) { + r = pIdx - 1; + } else { + l = pIdx + 1; } } + return null; + } + + private int partition(int[][] points, int l, int r, int p) { + int i = l; + + int pivot = dist(points[p]); - int[][] res = new int[K][2]; - int i = 0; - while (!pq.isEmpty()) { - Pair p = pq.poll(); - res[i++] = p.point; + swap(points, p, r); + + for (int j = l; j < r; j++) { + if (dist(points[j]) < pivot) { + swap(points, i, j); + i++; + } } - return res; + + swap(points, i, r); + + return i; + } + + private int dist(int[] p) { + return p[0] * p[0] + p[1] * p[1]; + } + + private void swap(int[][] points, int i, int j) { + int[] temp = points[i]; + points[i] = points[j]; + points[j] = temp; } @Test @@ -59,17 +101,14 @@ public void test1() { {-2, 2} }; int[][] kClosest = kClosest(points, 1); - int[][] expected = new int[][] {{-2, 2}}; + int[][] expected = new int[][]{{-2, 2}}; assertThat(kClosest, is(expected)); } -} - -class Pair { - double dis; - int[] point; - Pair(double dis, int[] point) { - this.dis = dis; - this.point = point; + @Test + public void test2() { + int[][] points = {{0, 1}, {1, 0}}; + int[][] expected = {{0, 1}, {1, 0}}; + assertThat(kClosest(points, 2), is(expected)); } -} \ No newline at end of file +} From f6fda50b84c9679d1c069557cd4b58b993e82b7b Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 1 Jan 2020 20:36:18 -0600 Subject: [PATCH 127/189] Added solution for brace expansion --- .../algorithm/leetcode/BraceExpansion.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansion.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansion.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansion.java new file mode 100644 index 0000000..269a5d8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansion.java @@ -0,0 +1,65 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/brace-expansion/ + */ +public class BraceExpansion { + public String[] expand(String S) { + if (S.length() == 0) return new String[0]; + if (S.length() == 1) return new String[] {S}; + // if start {, then + List l = new ArrayList<>(); + + if (S.charAt(0) == '{') { + int i = 1; + while (S.charAt(i) != '}') { + i++; + } + String[] parts = S.substring(1, i).split(","); + Arrays.sort(parts); // to make words in lexicographical order + + String rem = S.substring(i + 1); + + String[] more = expand(rem); + + for (i = 0; i < parts.length; i++) { + if (more.length > 0) { + for (int j = 0; j < more.length; j++) { + l.add(parts[i] + more[j]); + } + } else { + l.add(parts[i]); + } + + } + } else { + String[] more = expand(S.substring(1)); + for (String str: more) { + l.add(S.charAt(0) + str); + } + + } + return l.toArray(new String[l.size()]); + } + + @Test + public void test1() { + String[] expected = {"acdf","acef","bcdf","bcef"}; + assertThat(expand("{a,b}c{d,e}f"), is(expected)); + } + + @Test + public void test2() { + String[] expected = {"abcd"}; + assertThat(expand("abcd"), is(expected)); + } +} From 4506f22d60f2131081e4273d702afb51d296a4d6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 1 Jan 2020 22:03:02 -0600 Subject: [PATCH 128/189] Added solution for brance expansion ii --- .../algorithm/leetcode/BraceExpansionII.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansionII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansionII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansionII.java new file mode 100644 index 0000000..848535e --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BraceExpansionII.java @@ -0,0 +1,101 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/brace-expansion-ii/ + */ +public class BraceExpansionII { + public List braceExpansionII(String expression) { + if (expression.length() == 0) return Collections.emptyList(); + if (expression.length() == 1) return Collections.singletonList(expression); + + Set l = new HashSet<>(); + + if (expression.charAt(0) == '{') { + int i = 1; + int open = 1; + while (i < expression.length()) { + if (expression.charAt(i) == '{') { + open++; + } else if (expression.charAt(i) == '}') { + open--; + if (open == 0) break; + } + i++; + } + + String curr = expression.substring(1, i); + + List parts = new ArrayList<>(); + + int start = 0; + open = 0; + + int j = 0; + for (; j < curr.length(); j++) { + if (curr.charAt(j) == '{') { + open++; + } else if (curr.charAt(j) == '}') { + open--; + + } else if (curr.charAt(j) == ',' && open == 0) { + parts.addAll(braceExpansionII(curr.substring(start, j))); + start = j + 1; + open = 0; + } + } + parts.addAll(braceExpansionII(curr.substring(start, j))); + + List rem = braceExpansionII(expression.substring(i + 1)); + + for (String part: parts) { + if (rem.size() > 0) { + for (String sPart: rem) { + l.add(part + sPart); + } + } else { + l.add(part); + } + } + } else { + String prefix = ""; + + + int i = 0; + for (; i < expression.length(); i++) { + if (expression.charAt(i) == '{') { + break; + } else { + prefix += expression.charAt(i); + } + } + + List parts = braceExpansionII(expression.substring(i)); + + if (parts.size() > 0) { + for (String part: parts) { + l.add(prefix + part); + } + } else { + l.add(prefix); + } + + } + + List formed = new ArrayList<>(l); + formed.sort(Comparator.naturalOrder()); + return formed; + } + + @Test + public void test() { + List expected = Arrays.asList("a","ab","ac","z"); + assertThat(braceExpansionII("{{a,z},a{b,c},{ab,z}}"), is(expected)); + } +} From ce352514c324ab4ef4dc3cac05c3d0cad8d05c8a Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 2 Jan 2020 08:08:34 -0600 Subject: [PATCH 129/189] Added solution for wiggle sort ii --- .../algorithm/leetcode/WiggleSortII.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WiggleSortII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WiggleSortII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WiggleSortII.java new file mode 100644 index 0000000..a3277d8 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WiggleSortII.java @@ -0,0 +1,97 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +/** + * https://leetcode.com/problems/wiggle-sort-ii/ + * + * nums[0] < nums[1] > nums[2] < nums[3] ... + */ +public class WiggleSortII { + + public void wiggleSort(int[] nums) { + int n = nums.length; + + sort(nums, 0, n - 1); + + int l = 0; + int r = n - 1; + + int mid = l + (r - l) / 2; + + int[] temp = new int[n]; + + int p1 = mid, p2 = n - 1; + + int i = 0; + + while (p1 >= 0 || p2 > mid) { + if (i % 2 == 0) { + temp[i++] = nums[p1--]; + } else { + temp[i++] = nums[p2--]; + } + } + + for (i = 0; i < n; i++) { + nums[i] = temp[i]; + } + } + + private void sort(int[] nums, int l, int r) { + if (l < r) { + int mid = l + (r - l) / 2; + int p = partition(nums, l, r, mid); + sort(nums, l, p - 1); + sort(nums, p + 1, r); + } + } + + private int partition(int[] nums, int l, int r, int p) { + int pivot = nums[p]; + int i = l; + + swap(nums, p, r); + + for (int j = l; j < r; j++) { + if (nums[j] < pivot) { + swap(nums, i, j); + i++; + } + } + + swap(nums, i, r); + return i; + } + + private void swap(int[] nums, int i, int j) { + int temp = nums[j]; + nums[j] = nums[i]; + nums[i] = temp; + } + + @Test + public void test1() { + int[] expected = {2, 3, 1, 3, 1, 2}; + int[] actual = {1, 3, 2, 2, 3, 1}; + wiggleSort(actual); + assertArrayEquals(expected, actual); + } + + @Test + public void test2() { + int[] expected = {1, 6, 1, 5, 1, 4}; // 1 1 1 6 5 4 + int[] actual = {1, 1, 1, 5, 6, 4}; + wiggleSort(actual); + assertArrayEquals(expected, actual); + } + + @Test + public void test3() { + int[] actual = {5,3,1,2,6,7,8,5,5}; + wiggleSort(actual); + System.out.println(actual); + } +} From b3d1715c0bdb68dcc1bbe7b88248006f23c2f621 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 2 Jan 2020 16:12:26 -0600 Subject: [PATCH 130/189] Added solution for min swap to make increasing seq --- .../leetcode/MinSwapToMakeIncreasing.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinSwapToMakeIncreasing.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinSwapToMakeIncreasing.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinSwapToMakeIncreasing.java new file mode 100644 index 0000000..f887d66 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinSwapToMakeIncreasing.java @@ -0,0 +1,58 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * We have two integer sequences A and B of the same non-zero length. + * + * We are allowed to swap elements A[i] and B[i]. Note that both elements are in the same index position in their respective sequences. + * + * At the end of some number of swaps, A and B are both strictly increasing. (A sequence is strictly increasing if and only if A[0] < A[1] < A[2] < ... < A[A.length - 1].) + * + * Given A and B, return the minimum number of swaps to make both sequences strictly increasing. It is guaranteed that the given input always makes it possible. + * + * Example: + * Input: A = [1,3,5,4], B = [1,2,3,7] + * Output: 1 + * Explanation: + * Swap A[3] and B[3]. Then the sequences are: + * A = [1, 3, 5, 7] and B = [1, 2, 3, 4] + * which are both strictly increasing. + * + * https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/ + */ +public class MinSwapToMakeIncreasing { + public int minSwap(int[] A, int[] B) { + int n = A.length; + + int[] fix = new int[n]; + int[] swap = new int[n]; + + fix[0] = 0; + swap[1] = 1; + + for (int i = 1; i < n; i++) { + if (A[i - 1] >= B[i] || B[i - 1] >= A[i]) { + fix[i] = fix[i - 1]; + swap[i] = swap[i - 1] + 1; + } else if (A[i - 1] >= A[i] || B[i - 1] >= B[i]) { + fix[i] = swap[i - 1]; + swap[i] = fix[i - 1] + 1; + } else { + int min = Math.min(fix[ i -1], swap[i - 1]); + fix[i] = min; + swap[i] = min + 1; + } + } + + return Math.min(swap[n - 1], fix[n - 1]); + } + + @Test + public void test() { + assertEquals(1, minSwap(new int[]{0, 4, 4, 5, 9}, new int[]{0, 1, 6, 8, 10})); + assertEquals(1, minSwap(new int[]{3, 3, 8, 9, 109}, new int[]{1, 7, 4, 6, 8})); + } +} From 86c067c48c420b9ed1a493a6a47b14627c603a22 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 2 Jan 2020 21:12:57 -0600 Subject: [PATCH 131/189] Added solution for hands of straight --- .../algorithm/leetcode/HandOfStraight.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/HandOfStraight.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/HandOfStraight.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/HandOfStraight.java new file mode 100644 index 0000000..94b26d1 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/HandOfStraight.java @@ -0,0 +1,67 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + + +/** + * https://leetcode.com/problems/hand-of-straights/ + */ +public class HandOfStraight { + public boolean isNStraightHand(int[] hand, int W) { + + int n = hand.length; + + if (n % W != 0) return false; + + int k = n / W; + + int[] arr = new int[k]; + Arrays.fill(arr, W); + + Arrays.sort(hand); + + Map> vmap = new HashMap<>(); + + int curr = -1; + + for (int i = 0; i < n; i++) { + int num = hand[i]; + if (vmap.containsKey(num) && vmap.get(num).size() > 0) { + LinkedList indices = vmap.get(num); + int idx = indices.removeFirst(); + + arr[idx]--; + + if (arr[idx] > 0) + vmap.computeIfAbsent(num + 1, s -> new LinkedList<>()).add(idx); + } else { + curr++; + if (curr >= k) return false; + + arr[curr]--; + if (arr[curr] > 0) + vmap.computeIfAbsent(num + 1, s -> new LinkedList<>()).add(curr); + } + } + + for (int count : arr) { + if (count > 0) return false; + } + return true; + } + + @Test + public void test() { + assertTrue(isNStraightHand(new int[]{1, 2, 3, 6, 2, 3, 4, 7, 8}, 3)); + assertFalse(isNStraightHand(new int[]{1, 2, 3, 4, 5}, 3)); + assertTrue(isNStraightHand(new int[]{2, 1}, 2)); + } +} From 6ea8720d48f308b070999d1e4cf1e95a372a1933 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 2 Jan 2020 22:15:42 -0600 Subject: [PATCH 132/189] Added solution for expressive words --- .../algorithm/leetcode/ExpressiveWords.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressiveWords.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressiveWords.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressiveWords.java new file mode 100644 index 0000000..6605604 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ExpressiveWords.java @@ -0,0 +1,55 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/expressive-words/ + */ +public class ExpressiveWords { + public int expressiveWords(String S, String[] words) { + int count = 0; + for (String word : words) { + if (sketchy(word, S)) count++; + } + return count; + } + + private boolean sketchy(String word, String sketch) { + + int i = 0, j = 0; + while (i < word.length() && j < sketch.length()) { + char p = word.charAt(i); + char q = sketch.charAt(j); + + if (p != q) return false; + + int pc = 0; + int qc = 0; + while (i < word.length() && p == word.charAt(i)) { + pc++; + i++; + } + + while (j < sketch.length() && q == sketch.charAt(j)) { + qc++; + j++; + } + + if (pc > qc) return false; + + int diff = qc - pc; + + if (diff != 0 && diff + pc < 3) return false; + } + + return i == word.length() && j == sketch.length(); + } + + @Test + public void test() { + assertEquals(3, expressiveWords("dddiiiinnssssssoooo", new String[] {"dinnssoo","ddinso","ddiinnso","ddiinnssoo","ddiinso","dinsoo","ddiinsso","dinssoo","dinso"})); + assertEquals(1, expressiveWords("heeellooo", new String[]{"hello", "hi", "helo"})); + } +} From 039e15a627e902143e9e28be1f04aff30d11b870 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 3 Jan 2020 11:33:55 -0600 Subject: [PATCH 133/189] Added solution for campus bike with pq --- .../algorithm/leetcode/CampusBike.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CampusBike.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CampusBike.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CampusBike.java new file mode 100644 index 0000000..a62a798 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CampusBike.java @@ -0,0 +1,66 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.PriorityQueue; + +import static org.junit.Assert.assertArrayEquals; + +/** + * https://leetcode.com/problems/campus-bikes/ + */ +public class CampusBike { + public int[] assignBikes(int[][] workers, int[][] bikes) { + int m = workers.length; + + int n = bikes.length; + + PriorityQueue pq = new PriorityQueue<>((p, q) -> { + int d = p[2] - q[2]; + if (d == 0) { + int w = p[0] - q[0]; + if (w == 0) return p[1] - q[1]; + return w; + } + return d; + }); + + for (int w = 0; w < m; w++) { + for (int b = 0; b < n; b++) { + int d = Math.abs(workers[w][0] - bikes[b][0]) + + Math.abs(workers[w][1] - bikes[b][1]); + pq.offer(new int[]{w, b, d}); + } + } + + int[] res = new int[m]; + + boolean[] used = new boolean[n]; + + Arrays.fill(res, -1); + + int count = 0; + while (!pq.isEmpty() && count < m) { + int[] curr = pq.poll(); + int w = curr[0]; + int b = curr[1]; + + if (res[w] == -1 && !used[b]) { + res[w] = b; + used[b] = true; + count++; + } + } + + return res; + } + + @Test + public void test() { + int[] expected = {0, 8, 2, 7, 1, 5, 3, 4}; + int[][] workers = {{664, 994}, {3, 425}, {599, 913}, {220, 352}, {145, 348}, {604, 428}, {519, 183}, {732, 148}}; + int[][] bikes = {{611, 698}, {113, 338}, {579, 770}, {276, 588}, {948, 679}, {731, 525}, {925, 877}, {182, 281}, {39, 299}}; + assertArrayEquals(expected, assignBikes(workers, bikes)); + } +} From 02528f5fe92e540d988721a72d8b5b1e2562abaf Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 3 Jan 2020 17:13:59 -0600 Subject: [PATCH 134/189] Added solution for Search Suggestion System --- .../design/SearchSuggestionSystem.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java diff --git a/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java b/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java new file mode 100644 index 0000000..8288797 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java @@ -0,0 +1,95 @@ +package com.eprogrammerz.examples.design; + +import org.junit.Test; + +import java.util.*; + +import static java.util.Arrays.asList; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/search-suggestions-system/ + */ +public class SearchSuggestionSystem { + public List> suggestedProducts(String[] products, String searchWord) { + Trie trie = new Trie(); + + Arrays.sort(products); + + for (String product: products) { + trie.insert(product); + } + + List> l = new ArrayList<>(); + + for (int i = 0; i <= searchWord.length(); i++) { + trie.search(searchWord.substring(0, i), l); + } + + return l; + } + + class Trie { + TrieNode root; + + Trie() { + this.root = new TrieNode('#'); + } + + + public void insert(String word) { + + TrieNode curr = root; + + for (char ch: word.toCharArray()) { + if (curr.child[ch - 'a'] == null) { + curr.child[ch - 'a'] = new TrieNode(ch); + } + curr = curr.child[ch - 'a']; + curr.words.add(word); + } + } + + public void search(String str, List> l) { + if (str.length() == 0) return; + TrieNode curr = root; + for (char ch: str.toCharArray()) { + if (curr.child[ch - 'a'] == null) { + l.add(new ArrayList<>()); + return; + } else { + curr = curr.child[ch - 'a']; + + } + } + + + List suggestions = new ArrayList<>(); + for (int i = 0; i < curr.words.size() && i < 3; i++) { + suggestions.add(curr.words.get(i)); + } + l.add(suggestions); + } + } + class TrieNode { + char val; + TrieNode[] child; + List words; + + TrieNode(char val) { + this.val = val; + this.child = new TrieNode[26]; + this.words = new LinkedList<>(); + } + } + + @Test + public void test() { + List> expected = asList(asList("mobile","moneypot","monitor"), + asList("mobile","moneypot","monitor"), asList("mouse","mousepad"), + asList("mouse","mousepad"), asList("mouse","mousepad")); + assertThat(suggestedProducts(new String[] {"mobile","mouse","moneypot","monitor","mousepad"} , "mouse"), is(expected)); + } +} From 4da587420afca38e49729a089196c8394220b881 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 3 Jan 2020 17:14:24 -0600 Subject: [PATCH 135/189] Added solution for critical connection --- .../algorithm/graphs/CriticalConnection.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/CriticalConnection.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/CriticalConnection.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/CriticalConnection.java new file mode 100644 index 0000000..0453740 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/CriticalConnection.java @@ -0,0 +1,87 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static java.util.Arrays.asList; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/critical-connections-in-a-network/ + * + * Tarjen's algorithm + * + * https://www.youtube.com/watch?v=CsGP_s_3GWg&list=PLdo5W4Nhv31bK5n8-RIGhvYs8bJbgJFDR&index=13&t=543s + */ +public class CriticalConnection { + private int d = 0; + public List> criticalConnections(int n, List> connections) { + List> res = new ArrayList<>(); + + List[] graph = new ArrayList[n]; + + for (int i = 0; i < n; i++) { + graph[i] = new ArrayList<>(); + } + + for (List edge: connections) { + int u = edge.get(0); + int v = edge.get(1); + + graph[u].add(v); + graph[v].add(u); + } + + int[] visitTime = new int[n]; + + boolean[] visited = new boolean[n]; + + dfs(0, graph, visited, visitTime, res); + + return res; + } + + private void dfs(int u, List[] graph, boolean[] visited, int[] visitTime, List> res) { + if (visited[u]) return; + + visited[u] = true; + + visitTime[u] = d; + d++; + + for (int v: graph[u]) { + if (!visited[v]) { + + dfs(v, graph, visited, visitTime, res); + + visitTime[v] = lowestVisitedTime(graph, u, v, visitTime); + + if (visitTime[v] > visitTime[u]) { + res.add(asList(u, v)); + } + } + } + } + + private int lowestVisitedTime(List[] graph, int u, int v, int[] visitTime) { + int min = visitTime[v]; + + for (int n: graph[v]) { + if (n != u) { + min = Math.min(visitTime[n], min); + } + } + + return min; + } + + @Test + public void test() { + assertThat(criticalConnections(4, asList(asList(0,1), asList(1,2), asList(2,0), asList(1,3))), is(asList(asList(1,3)))); + } +} From 069b2e15d651fed333e98ef972185eb90f0b3b6d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 3 Jan 2020 17:15:36 -0600 Subject: [PATCH 136/189] Added solution for compressed string iterator --- .../design/CompressedStringIteratorTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/design/CompressedStringIteratorTest.java diff --git a/src/main/java/com/eprogrammerz/examples/design/CompressedStringIteratorTest.java b/src/main/java/com/eprogrammerz/examples/design/CompressedStringIteratorTest.java new file mode 100644 index 0000000..12fe2d2 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/design/CompressedStringIteratorTest.java @@ -0,0 +1,79 @@ +package com.eprogrammerz.examples.design; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * https://leetcode.com/problems/design-compressed-string-iterator/ + */ +public class CompressedStringIteratorTest { + @Test + public void test() { + StringIterator iterator = new StringIterator("L1e2t1C1o1d1e1"); + + assertEquals('L', iterator.next()); + assertEquals('e', iterator.next()); + assertEquals('e', iterator.next()); + assertEquals('t', iterator.next()); + assertEquals('C', iterator.next()); + assertEquals('o', iterator.next()); + assertEquals('d', iterator.next()); + assertTrue(iterator.hasNext()); + assertEquals('e', iterator.next()); + assertFalse(iterator.hasNext()); + assertEquals(' ', iterator.next()); + iterator.next(); // return 'e' + } +} + +class StringIterator { + + private String compressed; + private char curr; + private int count; + private int i = 0; + + public StringIterator(String compressedString) { + this.compressed = compressedString; + + set(); + } + + private void set() { + if (i == compressed.length()) return; + + curr = compressed.charAt(i); + i++; + for (; i < compressed.length(); i++) { + char digit = compressed.charAt(i); + if ('0' <= digit && digit <= '9') { + count = count * 10 + (digit - '0'); + } else { + break; + } + } + } + + public char next() { + if (!hasNext()) return ' '; + + char ans = curr; + count--; + if (count == 0) { + set(); + } + + return ans; + } + + public boolean hasNext() { + if (i == compressed.length()) return count > 0; + return true; + } +} From a6fa60c5d7d0818f2b1eb7b921dc8be2a8f44d32 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 3 Jan 2020 19:05:24 -0600 Subject: [PATCH 137/189] Added solution for magic dictionary --- .../ds/custom/trie/MagicDictionaryTest.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/trie/MagicDictionaryTest.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MagicDictionaryTest.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MagicDictionaryTest.java new file mode 100644 index 0000000..756ee7b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MagicDictionaryTest.java @@ -0,0 +1,100 @@ +package com.eprogrammerz.examples.ds.custom.trie; + +import org.junit.Test; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; + +public class MagicDictionaryTest { + @Test + public void test1() { + MagicDictionary dictionary = new MagicDictionary(); + dictionary.buildDict(new String[] {"hello", "leetcode"}); + + assertFalse(dictionary.search("hello")); + assertTrue(dictionary.search("hhllo")); + assertFalse(dictionary.search("hell")); + assertFalse(dictionary.search("leetcoded")); + } +} + +class MagicDictionary { + private Trie trie; + + /** Initialize your data structure here. */ + public MagicDictionary() { + this.trie = new Trie(); + } + + /** Build a dictionary through a list of words */ + public void buildDict(String[] dict) { + for (String str: dict) { + trie.insert(str); + } + } + + /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ + public boolean search(String word) { + return trie.search(word); + } + + + class Trie { + TrieNode root; + Trie() { + this.root = new TrieNode(); + } + + void insert(String str) { + TrieNode curr = root; + + for (char ch: str.toCharArray()) { + if (curr.child[ch - 'a'] == null) { + curr.child[ch - 'a'] = new TrieNode(); + } + curr = curr.child[ch - 'a']; + } + curr.isWord = true; + } + + boolean search(String str) { + char[] arr = str.toCharArray(); + + for (int i = 0; i < arr.length; i++) { + for (char ch = 'a'; ch <= 'z'; ch++) { + if (ch == arr[i]) continue; + + char org = arr[i]; + arr[i] = ch; + + if (helper(new String(arr))) { + return true; + } + arr[i] = org; + } + } + return false; + } + + boolean helper(String str) { + TrieNode curr = root; + + for (char ch: str.toCharArray()) { + if (curr.child[ch - 'a'] == null) return false; + curr = curr.child[ch - 'a']; + } + return curr.isWord; + } + + + class TrieNode { + boolean isWord; + TrieNode[] child; + TrieNode() { + this.child = new TrieNode[26]; + } + } + } + + +} From a8f794dc9f59e6fa193b2069a14aa97f92a9070f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 7 Jan 2020 07:18:37 -0600 Subject: [PATCH 138/189] Added solution for alphabet board path --- .../algorithm/leetcode/AlphabetBoardPath.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetBoardPath.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetBoardPath.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetBoardPath.java new file mode 100644 index 0000000..3494b10 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetBoardPath.java @@ -0,0 +1,80 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/alphabet-board-path/ + */ +public class AlphabetBoardPath { + public String alphabetBoardPath(String target) { + String[] board = {"abcde", "fghij", "klmno", "pqrst", "uvwxy", "z"}; + + StringBuilder sb = new StringBuilder(); + + int x = 0, y = 0; + + for (char ch: target.toCharArray()) { + Queue q = new LinkedList<>(); + q.add(new Pair(x, y, "")); + + Set visited = new HashSet<>(); + visited.add(x + "#" + y); + + while (!q.isEmpty()) { + Pair curr = q.poll(); + + x = curr.x; + y = curr.y; + + if (board[x].charAt(y) == ch) { + sb.append(curr.path).append('!'); + break; + } + + for (int i = 0; i < 4; i++) { + int nr = x + dr[i]; + int nc = y + dc[i]; + + String key = nr + "#" + nc; + if (nr >= 0 && nr < board.length && nc >= 0 && nc < board[nr].length() && + !visited.contains(key)) { + q.offer(new Pair(nr, nc, curr.path + dir[i])); + visited.add(key); + } + } + } + } + + return sb.toString(); + } + + private int[] dr = {-1,1,0,0}; + private int[] dc = {0,0,-1,1}; + + private char[] dir = {'U', 'D', 'L', 'R'}; + + class Pair { + int x; + int y; + String path; + + Pair(int x, int y, String path) { + this.x = x; + this.y = y; + this.path = path; + } + } + + @Test + public void test() { + assertEquals("DDR!UURRR!!DDD!", alphabetBoardPath("leet")); + assertEquals("RR!DDRR!UUL!R!", alphabetBoardPath("code")); + } +} From 2ee9b1a8cde6e6569a1c068b8344849a9faa6859 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 7 Jan 2020 20:27:19 -0600 Subject: [PATCH 139/189] Added solution for n-queens --- .../examples/algorithm/leetcode/NQueens.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueens.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueens.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueens.java new file mode 100644 index 0000000..c406a46 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/NQueens.java @@ -0,0 +1,89 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class NQueens { + private int[][] mem; + private List> l ; + + private int n; + + public List> solveNQueens(int n) { + this.l = new ArrayList<>(); + this.mem = new int[n][n]; + this.n = n; + + solve(0, new ArrayList<>()); + + return l; + } + + private void solve(int r, List temp) { + + for (int c = 0; c < n; c++) { + + if (mem[r][c] == 0 && goodSpot(r, c)) { + mem[r][c] = 2; + StringBuilder sb = new StringBuilder(); + + for (int k = 0; k < c; k++) sb.append("."); + + sb.append("Q"); + + for (int k = c + 1; k < n; k++) sb.append("."); + + temp.add(sb.toString()); + + if (r == n - 1) { + l.add(new ArrayList<>(temp)); + } else { + + solve(r + 1, temp); + } + mem[r][c] = 0; + temp.remove(temp.size() - 1); + + } + + } + } + + private boolean goodSpot(int r, int c) { + for (int col = 0; col < n; col++) { + if (mem[r][col] != 0) return false; + } + + for (int row = 0; row < n; row++) { + if (mem[row][c] != 0) return false; + } + + // main diagoal + for (int row = r - 1, col = c - 1; row >= 0 && col >= 0; row--, col--) { + if (mem[row][col] != 0) return false; + } + for (int row = r + 1, col = c + 1; row < n && col < n; row++, col++) { + if (mem[row][col] != 0) return false; + } + // opposite diagonal + for (int row = r - 1, col = c + 1; row >= 0 && col < n; row--, col++) { + if (mem[row][col] != 0) return false; + } + for (int row = r + 1, col = c - 1; row < n && col >= 0; row++, col--) { + if (mem[row][col] != 0) return false; + } + return true; + } + + @Test + public void test1() { + List> expected = asList(asList(".Q..","...Q","Q...","..Q."),asList("..Q.","Q...","...Q",".Q..")); + assertThat(solveNQueens(4), is(expected)); + } +} From ef38844fcdf79522bdd2113726f572245e35d7b8 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 7 Jan 2020 20:29:14 -0600 Subject: [PATCH 140/189] Updated solution for search suggestions system --- .../design/SearchSuggestionSystem.java | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java b/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java index 8288797..e96458b 100644 --- a/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java +++ b/src/main/java/com/eprogrammerz/examples/design/SearchSuggestionSystem.java @@ -5,7 +5,6 @@ import java.util.*; import static java.util.Arrays.asList; - import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -16,16 +15,14 @@ public class SearchSuggestionSystem { public List> suggestedProducts(String[] products, String searchWord) { Trie trie = new Trie(); - Arrays.sort(products); - for (String product: products) { trie.insert(product); } List> l = new ArrayList<>(); - for (int i = 0; i <= searchWord.length(); i++) { - trie.search(searchWord.substring(0, i), l); + for (int i = 1; i <= searchWord.length(); i++) { + l.add(trie.search(searchWord.substring(0, i))); } return l; @@ -35,7 +32,7 @@ class Trie { TrieNode root; Trie() { - this.root = new TrieNode('#'); + this.root = new TrieNode(); } @@ -43,45 +40,56 @@ public void insert(String word) { TrieNode curr = root; + List visited = new ArrayList<>(); + for (char ch: word.toCharArray()) { if (curr.child[ch - 'a'] == null) { - curr.child[ch - 'a'] = new TrieNode(ch); + curr.child[ch - 'a'] = new TrieNode(); } curr = curr.child[ch - 'a']; - curr.words.add(word); + + visited.add(curr); + } + + for (TrieNode node: visited) { + node.updateTop(word); } } - public void search(String str, List> l) { - if (str.length() == 0) return; + public List search(String str) { + if (str.length() == 0) return Collections.emptyList(); TrieNode curr = root; for (char ch: str.toCharArray()) { if (curr.child[ch - 'a'] == null) { - l.add(new ArrayList<>()); - return; + return Collections.emptyList(); } else { curr = curr.child[ch - 'a']; } } - - List suggestions = new ArrayList<>(); - for (int i = 0; i < curr.words.size() && i < 3; i++) { - suggestions.add(curr.words.get(i)); - } - l.add(suggestions); + return new LinkedList<>(curr.top); } } class TrieNode { - char val; TrieNode[] child; - List words; + LinkedList top; - TrieNode(char val) { - this.val = val; + TrieNode() { this.child = new TrieNode[26]; - this.words = new LinkedList<>(); + this.top = new LinkedList<>(); + } + + public void updateTop(String word) { + if (!top.contains(word)) { + top.add(word); + } + + top.sort(Comparator.naturalOrder()); + + if (top.size() > 3) { + top.removeLast(); + } } } From 8be2ac8ed02e86e556b3f3e142638a45cdf0a890 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 7 Jan 2020 20:34:28 -0600 Subject: [PATCH 141/189] Added solutionf for autocomplete system --- .../design/AutoCompleteSystemTest.java | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/design/AutoCompleteSystemTest.java diff --git a/src/main/java/com/eprogrammerz/examples/design/AutoCompleteSystemTest.java b/src/main/java/com/eprogrammerz/examples/design/AutoCompleteSystemTest.java new file mode 100644 index 0000000..359c494 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/design/AutoCompleteSystemTest.java @@ -0,0 +1,145 @@ +package com.eprogrammerz.examples.design; + +import org.junit.Test; + +import java.util.*; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/design-search-autocomplete-system/ + */ + +public class AutoCompleteSystemTest { + @Test + public void test() { + String[] sentences = {"i love you", "island","ironman", "i love leetcode"}; + int[] times = {5,3,2,2}; + + AutocompleteSystem system = new AutocompleteSystem(sentences, times); + + assertThat(system.input('i'), is(asList("i love you", "island", "i love leetcode"))); + assertThat(system.input(' '), is(asList("i love you", "i love leetcode"))); + assertThat(system.input('a'), is(asList())); + assertThat(system.input('#'), is(asList())); + } +} + + +class AutocompleteSystem { + + private Trie trie; + + private StringBuilder curr; + public AutocompleteSystem(String[] sentences, int[] times) { + this.curr = new StringBuilder(); + this.trie = new Trie(); + + int n = sentences.length; + + for (int i = 0; i < n; i++) { + this.trie.insert(sentences[i], times[i]); + } + } + + public List input(char c) { + + if (c == '#') { + trie.insert(curr.toString(), 1); + curr = new StringBuilder(); + + return Collections.emptyList(); + } else { + curr.append(c); + } + + return this.trie.search(curr.toString()); + } +} + +class Trie { + private TrieNode root; + + public Trie() { + this.root = new TrieNode(); + } + + public void insert(String str, int count) { + TrieNode curr = root; + + List visited = new ArrayList<>(); + + for (char ch: str.toCharArray()) { + if (curr.childs[ch] == null) { + curr.childs[ch] = new TrieNode(); + } + curr = curr.childs[ch]; + visited.add(curr); + + } + + curr.times += count; + curr.sentence = str; + + for (TrieNode node: visited) { + node.update(curr); + } + + } + + public List search(String str) { + LinkedList l = new LinkedList<>(); + + TrieNode curr = root; + for (char ch: str.toCharArray()) { + if (curr.childs[ch] == null) return l; + curr = curr.childs[ch]; + } + + if (curr == null) return l; + + LinkedList top = curr.top; + + for (TrieNode hot: top) { + l.add(hot.sentence); + } + + return l; + } +} + +class TrieNode implements Comparable { + TrieNode[] childs; + String sentence; + int times; + + LinkedList top; + + public TrieNode() { + this.childs = new TrieNode[128]; + + this.top = new LinkedList<>(); + } + + @Override + public int compareTo(TrieNode that) { + int diff = that.times - this.times; + if (diff == 0) { + return this.sentence.compareTo(that.sentence); + } + return diff; + } + + public void update(TrieNode node) { + if (!top.contains(node)) { + top.add(node); + } + + Collections.sort(top); + + if (top.size() > 3) top.removeLast(); + } + +} From e3a89967a4bd7b714cd23d600afe21d8c436e8ca Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 8 Jan 2020 21:17:45 -0600 Subject: [PATCH 142/189] Added solution for basic calculator iii --- .../leetcode/BasicCalculatorIII.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorIII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorIII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorIII.java new file mode 100644 index 0000000..9f84f95 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/BasicCalculatorIII.java @@ -0,0 +1,95 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/basic-calculator-iii/ + */ +public class BasicCalculatorIII { + public int calculate(String s) { + s = s.trim(); + + Stack stack = new Stack<>(); + + char sign = '#'; + + int curr = 0; + + for (int i = 0; i < s.length();) { + char ch = s.charAt(i); + + if (ch == ' ') { + i++; + continue; + } + + if ('0' <= ch && ch <= '9') { + curr = curr * 10 + (ch - '0'); + + if (i + 1 < s.length()) { + i++; + continue; + } + } else if (ch == '(') { + int j = i + 1; + + int open = 1; + while (j < s.length()) { + char close = s.charAt(j); + + if (close == '(') open++; + else if (close == ')') { + open--; + if (open == 0) { + break; + } + } + j++; + } + curr = calculate(s.substring(i + 1, j)); + i = j + 1; + + while (i < s.length()) { + ch = s.charAt(i); + if (ch == '-' || ch == '+' || ch == '*' || ch == '/') break; + i++; + } + } + + if (sign == '*') { + int prev = stack.pop(); + stack.push(prev * curr); + } else if (sign == '/') { + int prev = stack.pop(); + stack.push(prev / curr); + } else if (sign == '-') { + stack.push((-1) * curr); + } else { + stack.push(curr); + } + + sign = ch; + curr = 0; + i++; + } + + int res = 0; + + while (!stack.isEmpty()) { + res += stack.pop(); + } + return res; + } + + @Test + public void test() { + assertEquals(2, calculate("1 + 1")); + assertEquals(4, calculate(" 6-4 / 2 ")); + assertEquals(21, calculate("2*(5+5*2)/3+(6/2+8)")); + assertEquals(-12, calculate("(2+6* 3+5- (3*14/7+2)*5)+3")); + } +} From 4c907a8e08f7d701d28bc5e162cd32bffcf13a8c Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 9 Jan 2020 19:59:06 -0600 Subject: [PATCH 143/189] Updated example to check if tree is same --- .../examples/algorithm/trees/IdenticalBinaryTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/IdenticalBinaryTree.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/IdenticalBinaryTree.java index c556505..0d39def 100644 --- a/src/main/java/com/eprogrammerz/examples/algorithm/trees/IdenticalBinaryTree.java +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/IdenticalBinaryTree.java @@ -75,7 +75,7 @@ public void testIsSameTree() { public int isSameTreeRecursive(TreeNode root1, TreeNode root2) { if (root1 == null && root2 == null) return 1; - if ((root1 != null && root2 == null) || (root1 == null && root2 != null)) return 0; + if (root1 == null || root2 == null) return 0; if (root1.val != root2.val) return 0; From bc3478045209bc9c19b27144ee044ca39bff951a Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 9 Jan 2020 20:57:58 -0600 Subject: [PATCH 144/189] Added solution for contructing tree from string --- .../trees/ConstructBinaryTreeFromString.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/ConstructBinaryTreeFromString.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/ConstructBinaryTreeFromString.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/ConstructBinaryTreeFromString.java new file mode 100644 index 0000000..425a894 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/ConstructBinaryTreeFromString.java @@ -0,0 +1,57 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/construct-binary-tree-from-string/ + */ +public class ConstructBinaryTreeFromString { + public TreeNode str2tree(String s) { + if (s.length() == 0) return null; + + int i = 0; + int val = 0; + while (i < s.length()) { + if (s.charAt(i) == '(') break; + val = val * 10 + (s.charAt(i) - '0'); + i++; + } + + TreeNode root = new TreeNode(val); + + if (i == s.length()) return root; + + int open = 1; + + int start = ++i; + + while (i < s.length()) { + char ch = s.charAt(i); + if (ch == '(') open++; + else if (ch == ')') { + open--; + if (open == 0) { + break; + } + } + i++; + } + + root.left = str2tree(s.substring(start, i)); + if (i + 1 < s.length()) { + root.right = str2tree(s.substring(i + 2, s.length() - 1)); + } + + return root; + } + + @Test + public void test() { + TreeNode root = str2tree("4(2(3)(1))(6(5))"); + assertEquals(4, root.val); + assertEquals(2, root.left.val); + assertEquals(6, root.right.val); + } +} From 1bb6ee413582fffaff1e90b21b18145ef37530fd Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 12 Jan 2020 09:46:41 -0600 Subject: [PATCH 145/189] Added solution for making network connected --- .../graphs/MakeNetworkConnected.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/MakeNetworkConnected.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/MakeNetworkConnected.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/MakeNetworkConnected.java new file mode 100644 index 0000000..aa584e6 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/MakeNetworkConnected.java @@ -0,0 +1,65 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/number-of-operations-to-make-network-connected/ + */ +public class MakeNetworkConnected { + public int makeConnected(int n, int[][] connections) { + int extra = 0; + + int[] parents = new int[n]; + for (int i = 0; i < n; i++) parents[i] = i; + + for (int[] con: connections) { + int u = con[0]; + int v = con[1]; + + if (root(parents, u) != root(parents, v)) { + union(parents, u, v); + } else { + extra++; + } + } + + Set set = new HashSet<>(); + for (int p: parents) { + set.add(root(parents, p)); + } + + int comp = set.size(); + + if (comp - extra <= 1) return comp - extra == 1 ? extra: comp - 1; + + return -1; + } + + private void union(int[] parents, int u, int v) { + parents[root(parents, v)] = parents[root(parents, u)]; + } + + private int root(int[] parents, int u) { + while (u != parents[u]) { + u = parents[u]; + } + return u; + } + + @Test + public void test1() { + int[][] connections = new int[][] {{0,1},{0,2},{0,3},{1,2},{1,3}}; + assertEquals(2, makeConnected(6, connections)); + } + + @Test + public void test2() { + int[][] connections = new int[][] {{0,1},{0,2},{3,4},{2,3}}; + assertEquals(0, makeConnected(5, connections)); + } +} From 1e418f83d6c2425090505eeadcd424dc1b8716f3 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 12 Jan 2020 16:14:08 -0600 Subject: [PATCH 146/189] Added solution for reorganize string --- .../algorithm/leetcode/ReorganizeString.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReorganizeString.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReorganizeString.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReorganizeString.java new file mode 100644 index 0000000..d1aad4d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ReorganizeString.java @@ -0,0 +1,53 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/reorganize-string/ + */ +public class ReorganizeString { + public String reorganizeString(String S) { + int n = S.length(); + + int[] count = new int[26]; + + for (char ch: S.toCharArray()) { + count[ch - 'a']++; + } + + PriorityQueue pq = new PriorityQueue<>((e1, e2) -> e1[1] == e2[1] ? e1[0] - e2[0] : e2[1] - e1[1]); + + for (int i = 0; i < 26; i++) { + if (count[i] > 0) { + if (count[i] > (n + 1) / 2) return ""; + pq.offer(new int[]{i, count[i]}); + } + } + + StringBuilder sb = new StringBuilder(); + + while (pq.size() >= 2) { + int[] p = pq.poll(); + int[] q = pq.poll(); + + sb.append((char) ('a' + p[0])); + sb.append((char) ('a' + q[0])); + + if (--p[1] > 0) pq.offer(p); + if (--q[1] > 0) pq.offer(q); + } + if (pq.size() > 0) sb.append((char) ('a' + pq.poll()[0])); + + return sb.toString(); + } + + @Test + public void test() { + assertEquals("aba", reorganizeString("aab")); + assertEquals("", reorganizeString("aaab")); + } +} From 82c49c19badcaf3480e0fbe7942941a6c85c50ac Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 12 Jan 2020 21:52:40 -0600 Subject: [PATCH 147/189] Added solution for finding longest increasing subseq --- .../LongestIncreasingSubsequence.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestIncreasingSubsequence.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestIncreasingSubsequence.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestIncreasingSubsequence.java new file mode 100644 index 0000000..be73795 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestIncreasingSubsequence.java @@ -0,0 +1,41 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; + +import static junit.framework.TestCase.*; + + +/** + * https://leetcode.com/problems/longest-increasing-subsequence/ + */ +public class LongestIncreasingSubsequence { + public int findNumberOfLIS(int[] nums) { + int len = Integer.MIN_VALUE; + int[] m = new int[nums.length]; + + Arrays.fill(m, 1); + + for (int i = 1; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + if (nums[j] < nums[i]) { + m[i] = Math.max(m[i], m[j] + 1); + } + } + len = Math.max(len, m[i]); + } + + int count = 0; + + for (int n: m) { + if (n == len) count++; + } + return count; + } + + @Test + public void test1() { + assertEquals(2, findNumberOfLIS(new int[] {1,3,5,4,7})); + } +} From b5ff99bced8fea21223f8d573fa715302001c035 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 12 Jan 2020 22:18:29 -0600 Subject: [PATCH 148/189] Added solution for Four Sum --- .../examples/algorithm/leetcode/FourSum.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FourSum.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FourSum.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FourSum.java new file mode 100644 index 0000000..8f46f26 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FourSum.java @@ -0,0 +1,92 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + + +import org.junit.Test; + +import java.util.*; + +import static java.util.Arrays.asList; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums + * such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. + *

+ * Note: + *

+ * The solution set must not contain duplicate quadruplets. + *

+ * Example: + *

+ * Given array nums = [1, 0, -1, 0, -2, 2], and target = 0. + *

+ * A solution set is: + * [ + * [-1, 0, 0, 1], + * [-2, -1, 1, 2], + * [-2, 0, 0, 2] + * ] + * + * https://leetcode.com/problems/4sum/ + */ +public class FourSum { + public List> fourSum(int[] nums, int target) { + + List> res = new ArrayList<>(); + + int n = nums.length; + + if (n < 3) return res; + + Arrays.sort(nums); + + Map>> map = new HashMap<>(); + + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + int sum = nums[i] + nums[j]; + + map.computeIfAbsent(sum, s -> new ArrayList<>()).add(Arrays.asList(i, j)); + } + } + + Set seen = new HashSet<>(); + + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + int x = nums[i] + nums[j]; + int y = target - x; + if (map.containsKey(y)) { + List> l = map.get(y); + + for (List p : l) { + int k = p.get(0); + int m = p.get(1); + + if (i == k || i == m || j == k || j == m) continue; // avoid same grouping + + List q = Arrays.asList(nums[i], nums[j], nums[k], nums[m]); + q.sort(Comparator.naturalOrder()); + String key = q.get(0) + "#" + q.get(1) + "#" + q.get(2) + "#" + q.get(3); + + if (seen.add(key)) { + res.add(q); + } + } + } + } + } + + return res; + } + + @Test + public void test() { + List> actual = fourSum(new int[]{1, 0, -1, 0, -2, 2}, 0); + List> expected = asList(asList(-2, -1, 1, 2), asList(-2, 0, 0, 2), asList(-1, 0, 0, 1)); + + assertThat(actual, is(expected)); + } +} From 9e15fca12eb0ef7d8f49e77f384763e5b75cd9a2 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 13 Jan 2020 07:35:16 -0600 Subject: [PATCH 149/189] Added solution for consitent hashing implementation --- .../examples/design/ConsistentHashTest.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/design/ConsistentHashTest.java diff --git a/src/main/java/com/eprogrammerz/examples/design/ConsistentHashTest.java b/src/main/java/com/eprogrammerz/examples/design/ConsistentHashTest.java new file mode 100644 index 0000000..061ae66 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/design/ConsistentHashTest.java @@ -0,0 +1,112 @@ +package com.eprogrammerz.examples.design; + +import org.junit.Test; + +import java.util.*; +import java.util.zip.CRC32; + +public class ConsistentHashTest { + @Test + public void test() { + List servers = Arrays.asList(new Server("10.0.0.1"), new Server("10.0.0.2")); + ConsistentHash consistentHash = new ConsistentHash(5, servers); + + Server newServer = new Server("10.0.0.3"); + consistentHash.add(newServer); + + // mapped to any of 3 servers + System.out.println(consistentHash.getServer("key0")); + System.out.println(consistentHash.getServer("key1")); + System.out.println(consistentHash.getServer("key2")); + System.out.println(consistentHash.getServer("key3")); + System.out.println(consistentHash.getServer("key4")); + + consistentHash.remove(newServer); + + // mapped to only of available 2 servers + System.out.println(consistentHash.getServer("key0")); + System.out.println(consistentHash.getServer("key1")); + System.out.println(consistentHash.getServer("key2")); + System.out.println(consistentHash.getServer("key3")); + System.out.println(consistentHash.getServer("key4")); + } +} + +class ConsistentHash { + private int numberOfVirtualNode; + + private TreeMap hashRing; + + public ConsistentHash(int numberOfVirtualNode, Collection servers) { + this.numberOfVirtualNode = numberOfVirtualNode; + this.hashRing = new TreeMap<>(); + + if (servers != null) { + for (Server server: servers) this.add(server); + } + } + + /** + * Add virtual nodes while adding physical server + * + * @param server + */ + public void add(Server server) { + for (int i = 0; i < numberOfVirtualNode; i++) { + hashRing.put(hash(i + server.getIp()), server); + } + } + + /** + * Remove all virtual nodes while removing physical server + * @param server + */ + public void remove(Server server) { + for (int i = 0; i < numberOfVirtualNode; i++) { + hashRing.remove(hash(i + server.getIp())); + } + } + + /** + * Get physical server the key mapped to + * @param key + * @return Server key belonging to + */ + public Server getServer(String key) { + if (hashRing.isEmpty()) return null; + + Long hashVal = hash(key); + + if (!hashRing.containsKey(hashVal)) { + SortedMap tailMap = hashRing.tailMap(hashVal); + hashVal = tailMap.isEmpty() ? hashRing.firstKey() : tailMap.firstKey(); + } + + return hashRing.get(hashVal); + } + + public Long hash(String key) { + CRC32 crc =new CRC32(); + crc.update(key.getBytes()); + + return crc.getValue(); + } +} + +class Server { + private String ip; + + public Server(String ip) { + this.ip = ip; + } + + public String getIp() { + return ip; + } + + @Override + public String toString() { + return ip; + } +} + From fdba4b154627e83e6c415ef484072598099e574d Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 13 Jan 2020 07:58:36 -0600 Subject: [PATCH 150/189] Added solution for linked list --- .../ds/custom/linkedList/MyLinkedList.java | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MyLinkedList.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MyLinkedList.java index 9c03951..4086fdc 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MyLinkedList.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/MyLinkedList.java @@ -2,12 +2,21 @@ public class MyLinkedList { private Node head; + private Node tail; + private int size; public MyLinkedList() {} public void addFirst(T t) { - this.head = new Node<>(t, this.head); + Node node = new Node<>(t); + if (head == null) { + head = node; + tail = node; + } else { + node.next = head; + head = node; + } size++; } @@ -20,27 +29,19 @@ public void addLast(T t) { Node node = new Node<>(t); if (head == null) { head = node; + tail = node; + } else { + tail.next = node; + tail = node; } - Node current = head; - - while (current.next != null) { - current = current.next; - } - current.next = node; - // increment size size++; } public T getLast() { if (head == null) return null; - Node node = head; - - while (node.next != null) { - node = node.next; - } - return node.data; + return tail.data; } public T getAt(int idx) { @@ -134,11 +135,6 @@ public Node(T data) { this.next = null; } - public Node(T data, Node next) { - this.data = data; - this.next = next; - } - @Override public String toString() { return "(" + data + ")"; From 8dbc683235c35326ca7556c92f18b6146b8030c6 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Mon, 13 Jan 2020 12:50:30 -0600 Subject: [PATCH 151/189] Updated solution for reverse list ii --- .../ds/custom/linkedList/ReverseListII.java | 78 ++++++++++--------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java index 26e1fc8..36b885d 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/linkedList/ReverseListII.java @@ -14,63 +14,65 @@ * Given 1->2->3->4->5->NULL, m = 2 and n = 4, * * return 1->4->3->2->5->NULL. + * + * https://leetcode.com/problems/reverse-linked-list-ii/ */ public class ReverseListII { public ListNode reverseBetween(ListNode head, int m, int n) { - if (head.next == null) return head; + ListNode prev = null; + ListNode next = null; + + // if m == 1, then head needed to be updated - /** - * Get first half f1 (0 -> m - 1) - * Traverse and create reversed list (m -> n) mid - * f1.next = mid - */ + int i = 1; - ListNode tracker = head; - ListNode f1Tail = head; + ListNode runner = head; + while (runner != null) { + if (i == m - 1) { + prev = runner; + } - ListNode resultHead = tracker; - for (int i = 1; i < m; i++) { - f1Tail = tracker; - tracker = tracker.next; + if (i == n) { + next = runner.next; + break; + } + + runner = runner.next; + i++; } - ListNode next = tracker.next; + ListNode part = prev == null ? head: prev.next; + + if (prev != null) + prev.next = null; - ListNode midHead = tracker; - midHead.next = null; + runner.next = null; - ListNode midTail = tracker; - for (int i = m; i < n; i++) { - ListNode temp = midHead; - ListNode nextTemp = next.next; - midHead = next; - midHead.next = temp; - next = nextTemp; + ListNode rhead = reverse(part); + + if (prev != null) + prev.next = rhead; + else head = rhead; + + while (rhead.next != null) { + rhead = rhead.next; } - midTail.next = next; - f1Tail.next = midHead; + rhead.next = next; - return resultHead; + return head; } - public ListNode reverse(ListNode node) { - if (node == null) return null; - - ListNode current = node; + private ListNode reverse(ListNode head) { + if (head.next == null) return head; - ListNode next = current.next; + ListNode node = reverse(head.next); - current.next = null; + head.next.next = head; + head.next = null; - while (next != null) { - ListNode temp = next.next; - next.next = current; - current = next; - next = temp; - } - return current; + return node; } @Test From 73c21a89b1a5f09d1d813552a2067310398594c1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 16 Jan 2020 19:01:57 -0600 Subject: [PATCH 152/189] Added solution for counting decreasing subsequence --- .../leetcode/DecreasingSubsequence.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecreasingSubsequence.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecreasingSubsequence.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecreasingSubsequence.java new file mode 100644 index 0000000..a5817ff --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/DecreasingSubsequence.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Given an int array nums of length n. Split it into strictly decreasing subsequences. Output the min number of subsequences you can get by splitting. + * + * Example 1: + * + * Input: [5, 2, 4, 3, 1, 6] + * Output: 3 + * Explanation: + * You can split this array into: [5, 2, 1], [4, 3], [6]. And there are 3 subsequences you get. + * Or you can split it into [5, 4, 3], [2, 1], [6]. Also 3 subsequences. + * But [5, 4, 3, 2, 1], [6] is not legal because [5, 4, 3, 2, 1] is not a subsuquence of the original array. + * Example 2: + * + * Input: [2, 9, 12, 13, 4, 7, 6, 5, 10] + * Output: 4 + * Explanation: [2], [9, 4], [12, 10], [13, 7, 6, 5] + * Example 3: + * + * Input: [1, 1, 1] + * Output: 3 + * Explanation: Because of the strictly descending order you have to split it into 3 subsequences: [1], [1], [1] + */ +public class DecreasingSubsequence { + public int decreasingSubseqences(int[] arr) { + int len = 0; + int n = arr.length; + + if (n == 0) return 0; + + int[] seq = new int[n]; + + for (int a: arr) { + int idx = search(seq, 0, len, a); + + seq[idx] = a; + + if (idx == len) len++; + } + + return len; + } + + private int search(int[] arr, int lo, int hi, int target) { + while (lo < hi) { + int mid = (lo + hi) / 2; + + if (arr[mid] <= target) { + lo = mid + 1; + } else { + hi = mid; + } + } + + return lo; + } + + @Test + public void test() { + assertEquals(3, decreasingSubseqences(new int[] {5, 2, 4, 3, 1, 6})); + assertEquals(4, decreasingSubseqences(new int[] {2, 9, 12, 13, 4, 7, 6, 5, 10})); + assertEquals(3, decreasingSubseqences(new int[] {1, 1, 1})); + } +} From 45adcca62b66495805c6add1dcd4a6380ddeccfa Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 16 Jan 2020 19:48:35 -0600 Subject: [PATCH 153/189] Added solution for fill matrix --- .../algorithm/leetcode/FillMatrix.java | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FillMatrix.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FillMatrix.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FillMatrix.java new file mode 100644 index 0000000..96af543 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FillMatrix.java @@ -0,0 +1,129 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +/** + * Given a NxN matrix. Fill the integers from 1 to n*n to this matrix that makes the sum of each row, each column and the two diagonals equal. + *

+ * Example 1: + *

+ * Input: n = 2 + * Output: null + * Explanation: We need to fill [1, 2, 3, 4] into a 2x2 matrix, which is not possible so return null. + * Example 2: + *

+ * Input: n = 3 + * Output: + * [[8, 3, 4], + * [1, 5, 9], + * [6, 7, 2]] + * Explanation: We need to fill [1, 2, 3... 9] into a 3x3 matrix. This is one way to do it + * Each row [8, 3, 4] [1, 5, 9] [6, 7, 2] sum is 15. + * Each column [8, 1, 6] [3, 5, 7] [4, 9, 2] sum is 15. + * The two diagonals [8, 5, 2] [4, 5, 6] sum is 15. + */ +public class FillMatrix { + // sum = 9 * 8 / 2 = 9* 4 = 45 + // rowSum = sum / 3 = 15 + public int[][] fillMatrix(int n) { + // if there is no way we can get a row with rowSum, then return null + int target = n * (n * n + 1) / 2; + + int[][] mat = new int[n][n]; + + for (int i = 0; i < n; i++) { + Arrays.fill(mat[i], -1); + } + + boolean[] visited = new boolean[n * n + 1]; + + if (fill(mat, 0, 0, target, visited)) return mat; + return null; + } + + private boolean fill(int[][] matrix, int r, int c, int target, boolean[] visited) { + + + int n = matrix.length; + if (c == n) { + c = 0; + r++; + } + + if (r == n) { + return valid(matrix, target); + } + + for (int i = 1; i <= n * n; i++) { + if (!visited[i]) { + visited[i] = true; + matrix[r][c] = i; + + if (fill(matrix, r, c + 1, target, visited)) { + return true; + } + + matrix[r][c] = -1; + visited[i] = false; + } + } + + return false; + } + + private boolean valid(int[][] matrix, int target) { + // row sums + int n = matrix.length; + for (int i = 0; i < n; i++) { + int sum = 0; + for (int j = 0; j < n; j++) { + sum += matrix[i][j]; + } + + if (sum != target) return false; + } + + // col sum + for (int j = 0; j < n; j++) { + int sum = 0; + for (int i = 0; i < n; i++) { + sum += matrix[i][j]; + } + + if (sum != target) return false; + } + + // main diagonal + int sum = 0; + for (int i = 0, j = 0; i < n && j < n; j++, i++) { + sum += matrix[i][j]; + } + + if (sum != target) return false; + + sum = 0; + + // anti diagonal + for (int i = 0, j = n - 1; i < n; i++, j--) { + sum += matrix[i][j]; + } + + if (sum != target) return false; + + return true; + } + + @Test + public void test() { + int[][] expected = {{2, 7, 6}, {9, 5, 1}, {4, 3, 8}}; + assertThat(fillMatrix(3), is(expected)); + + assertNull(fillMatrix(2)); + } +} From 970c62de08f8012a83e4778730cacd04d083bee8 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 16 Jan 2020 21:02:18 -0600 Subject: [PATCH 154/189] Added solution for min days to bloom --- .../algorithm/leetcode/MinDaysToBloom.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDaysToBloom.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDaysToBloom.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDaysToBloom.java new file mode 100644 index 0000000..c975f57 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDaysToBloom.java @@ -0,0 +1,88 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Given an array of roses. roses[i] means rose i will bloom on day roses[i]. Also given an int k, + * which is the minimum number of adjacent bloom roses required for a bouquet, and an int n, which is the number of bouquets we need. + * Return the earliest day that we can get n bouquets of roses. + *

+ * Example: + * Input: roses = [1, 2, 4, 9, 3, 4, 1], k = 2, n = 2 + * Output: 4 + * Explanation: + * day 1: [b, n, n, n, n, n, b] + * The first and the last rose bloom. + *

+ * day 2: [b, b, n, n, n, n, b] + * The second rose blooms. Here the first two bloom roses make a bouquet. + *

+ * day 3: [b, b, n, n, b, n, b] + *

+ * day 4: [b, b, b, n, b, b, b] + * Here the last three bloom roses make a bouquet, meeting the required n = 2 bouquets of bloom roses. So return day 4. + */ +public class MinDaysToBloom { + @Test + public void test() { + assertEquals(4, minDaysBloom(new int[]{1, 2, 4, 9, 3, 4, 1}, 2, 2)); + assertEquals(6, minDaysBloom(new int[]{1, 5, 6, 2}, 1, 4)); + assertEquals(1, minDaysBloom(new int[]{1, 1, 1, 1}, 4, 1)); + } + + public int minDaysBloom(int[] roses, int k, int n) { + int len = roses.length; + if (len == 0) return 0; + + int lo = min(roses); + int hi = max(roses); + + while (lo < hi) { + int mid = (lo + hi) / 2; + if (bouquets(roses, mid, k) < n) { + lo = mid + 1; + } else { + hi = mid; + } + } + + return lo; + } + + private int bouquets(int[] roses, int day, int k) { + int running = 0; + int count = 0; + + for (int i = 0; i < roses.length; i++) { + if (roses[i] < day) { + running++; + } + + if (running == k) { + count++; + running = 0; + } + } + + return count; + } + + private int min(int[] arr) { + int min = arr[0]; + + for (int i = 1; i < arr.length; i++) { + if (arr[i] < min) min = arr[i]; + } + return min; + } + + private int max(int[] arr) { + int max = arr[0]; + for (int i = 1; i < arr.length; i++) { + if (max < arr[i]) max = arr[i]; + } + return max; + } +} From e6f95e24ec5c33f706889f762219488f334d1098 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Thu, 16 Jan 2020 21:51:21 -0600 Subject: [PATCH 155/189] Added solution for min num of chairs --- .../algorithm/leetcode/MinNumberOfChairs.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinNumberOfChairs.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinNumberOfChairs.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinNumberOfChairs.java new file mode 100644 index 0000000..5f57a74 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinNumberOfChairs.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +/** + * There are n guests who are invited to a party. The k-th guest will attend the party at time S[k] and leave the party at time E[k]. + * + * Given an integer array S and an integer array E, both of length n, return an integer denoting the minimum number of chairs + * you need such that everyone attending the party can sit down. + * + * Example: + * + * Input: S = [1, 2, 6, 5, 3], E = [5, 5, 7, 6, 8] + * Output: 3 + * Explanation: + * There are five guests attending the party. + * The 1st guest will arrive at time 1. We need one chair at time 1. + * The 2nd guest will arrive at time 2. There are now two guests at the party, so we need two chairs at time 2. + * The 5th guest will arrive at time 3. There are now three guests at the party, so we need three chairs at time 3. + * The 4th guest will arrive at time 5 and, at the same moment, the 1st and 2nd guests will leave the party. + * There are now two (the 4th and 5th) guests at the party, so we need two chairs at time 5. + * The 3rd guest will arrive at time 6, and the 4th guest will leave the party at the same time. + * There are now two (the 3rd and 5th) guests at the party, so we need two chairs at time 6. + * So we need at least 3 chairs. + */ +public class MinNumberOfChairs { + public int minNumberOfChairs(int[] S, int[] E) { + int n = S.length; + if (n == 0) return 0; + + int[][] intervals = new int[n][2]; + for (int i = 0; i < n; i++) { + intervals[i] = new int[]{S[i], E[i]}; + } + + Arrays.sort(intervals, (i1, i2) -> i1[0] - i2[0]); + + PriorityQueue pq = new PriorityQueue<>(); + pq.add(intervals[0][1]); + + int count = 1; + + for (int i = 1; i < n; i++) { + int[] curr = intervals[i]; + + int prevEnd = pq.peek(); + + if (prevEnd <= curr[0]) { // re-use + pq.poll(); + } else { + count++; + } + + pq.offer(curr[1]); + } + + return count; + } + + @Test + public void test() { + assertEquals(3, minNumberOfChairs(new int[] {1, 2, 6, 5, 3}, new int[] {5, 5, 7, 6, 8})); + } +} From 9c60fcfc8acf46578dcf1155a8fba44e74365e7e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 17 Jan 2020 07:38:45 -0600 Subject: [PATCH 156/189] Added solution for load distribution in servers --- .../leetcode/MinDifferenceServerLoads.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDifferenceServerLoads.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDifferenceServerLoads.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDifferenceServerLoads.java new file mode 100644 index 0000000..08c0f80 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MinDifferenceServerLoads.java @@ -0,0 +1,63 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * There are some processes that need to be executed. Amount of a load that process causes on a server that runs it, + * is being represented by a single integer. Total load caused on a server is the sum of the loads of all the processes that run on that server. + * You have at your disposal two servers, on which mentioned processes can be run. + * Your goal is to distribute given processes between those two servers in the way that, absolute difference of their loads will be minimized. + *

+ * Given an array of n integers, of which represents loads caused by successive processes, return the minimum absolute difference of server loads. + *

+ * Example 1: + *

+ * Input: [1, 2, 3, 4, 5] + * Output: 1 + * Explanation: + * We can distribute the processes with loads [1, 2, 4] to the first server and [3, 5] to the second one, + * so that their total loads will be 7 and 8, respectively, and the difference of their loads will be equal to 1. + */ +public class MinDifferenceServerLoads { + + public int distributeLoad(int[] loads) { + // b1 1 3 + // b2 2 4 + + // 1 2 3 4 5 + // 1 (2 3 4 5) [b1 = 1, b2 = 0] + + Map mem = new HashMap<>(); + return dfs(loads, 0, 0, 0, mem); + } + + private int dfs(int[] loads, int idx, int b1, int b2, Map mem) { + int diff = Math.abs(b1 - b2); + if (idx == loads.length) { + return diff; + } + + String key = idx + "#" + diff; + + if (!mem.containsKey(key)) { + + mem.put(key, Math.min(dfs(loads, idx + 1, b1 + loads[idx], b2, mem), + dfs(loads, idx + 1, b1, b2 + loads[idx], mem))); + } + + + return mem.get(key); + } + + @Test + public void test() { + assertEquals(1, distributeLoad(new int[]{1, 2, 3, 4, 5})); + assertEquals(1, distributeLoad(new int[]{1, 1, 1, 1, 1})); + assertEquals(0, distributeLoad(new int[]{10, 10, 9, 9 ,2})); // [10,10], [9,9,2] + } +} From e6285ec9690b3fbfadb42cc08fccbdcfc1bbd468 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 17 Jan 2020 08:11:23 -0600 Subject: [PATCH 157/189] Added solution for flowering water --- .../algorithm/leetcode/FloweringWater.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FloweringWater.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FloweringWater.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FloweringWater.java new file mode 100644 index 0000000..088c968 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/FloweringWater.java @@ -0,0 +1,49 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Count how many times you and your friend, who is watering flower from last, have to refill the water tank + */ +public class FloweringWater { + public int countRefill(int[] plants, int capacity1, int capacity2) { + int n = plants.length; + + int lo = 0; + int hi = n - 1; + + int count = 2; // fill both tanks initially + int w1 = capacity1; + int w2 = capacity2; + + while (lo < hi) { + if (plants[lo] > w1) { // no sufficient water, so needs to refill + w1 = capacity1; + count++; + } + w1 -= plants[lo]; // watering from start and remaining water + + if (plants[hi] > w2) { + w2 = capacity2; + count++; + } + w2 -= plants[hi]; + + lo++; + hi--; + } + + // if there is flower in between which both can water, then we can sum up + if ((n & 1) == 1) { + if (w1 + w2 < plants[lo]) count++; + } + return count; + } + + @Test + public void test() { + assertEquals(3, countRefill(new int[]{2, 4, 5, 1, 2}, 5, 7)); + } +} From eae920e14ef05fa6b639652bcfb0992b66751401 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 17 Jan 2020 11:00:22 -0600 Subject: [PATCH 158/189] Added solution for largest subarray length k --- .../leetcode/LargestSubarrayLengthK.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestSubarrayLengthK.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestSubarrayLengthK.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestSubarrayLengthK.java new file mode 100644 index 0000000..68283f2 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LargestSubarrayLengthK.java @@ -0,0 +1,47 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +/** + * + * largest subarray is contiguous subarray whose first different element is larger than other subarray + * + * return largest subarray of length k from all contiguous subarray of length k from given array + */ +public class LargestSubarrayLengthK { + public int[] largestSubarray(int[] arr, int k) { // arr.length >= k + // find subarray of length k + // see if it is largest compared to temp_result + // keep on going until you have subarray + + int n = arr.length; + + int[] subarr = new int[k]; + + System.arraycopy(arr, 0, subarr, 0, k); + + for (int i = 1; i <= n - k; i++) { + boolean larger = false; + + for (int j = i, m = 0; j < i + k; j++, m++) { + if (arr[j] > subarr[m]) { + larger = true; + break; + } + } + + if (larger) { + System.arraycopy(arr, i, subarr, 0, k); + } + } + + return subarr; + } + + @Test + public void test() { + assertArrayEquals(new int[] {4, 3, 2, 5}, largestSubarray(new int[] {1, 4, 3, 2, 5}, 4)); + } +} From 5513b0bddfab4d46340254e5a629dad660b4d6d1 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 17 Jan 2020 11:18:32 -0600 Subject: [PATCH 159/189] Added solution for max time --- .../algorithm/leetcode/MaximumTime.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaximumTime.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaximumTime.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaximumTime.java new file mode 100644 index 0000000..700a58e --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaximumTime.java @@ -0,0 +1,82 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * You are given a string that represents time in the format hh:mm. Some of the digits are blank (represented by ?). + * Fill in ? such that the time represented by this string is the maximum possible. Maximum time: 23:59, minimum time: 00:00. + * You can assume that input string is always valid. + * + * Example 1: + * + * Input: "?4:5?" + * Output: "14:59" + * Example 2: + * + * Input: "23:5?" + * Output: "23:59" + * Example 3: + * + * Input: "2?:22" + * Output: "23:22" + * Example 4: + * + * Input: "0?:??" + * Output: "09:59" + * Example 5: + * + * Input: "??:??" + * Output: "23:59" + */ +public class MaximumTime { + public String maxTime(String time) { + char[] arr = time.toCharArray(); + + if (arr[0] == '?') { + if (arr[1] == '?') { + arr[0] = '2'; + arr[1] = '3'; + } else { + if (arr[1] < '4') { + arr[0] = '2'; + } else { + arr[0] = '1'; + } + } + } + + if (arr[1] == '?') { + if (arr[0] == '2') { + arr[1] = '3'; + } else { + arr[1] = '9'; + } + } + + if (arr[3] == '?') { + if (arr[4] == '?') { + arr[3] = '5'; + arr[4] = '9'; + } else { + arr[3] = '5'; + } + } + + if (arr[4] == '?') { + arr[4] = '9'; + } + + return new String(arr); + } + + @Test + public void test() { + assertEquals("14:59", maxTime("?4:5?")); + assertEquals("23:59", maxTime("23:5?")); + assertEquals("23:22", maxTime("2?:22")); + assertEquals("09:59", maxTime("0?:??")); + assertEquals("23:59", maxTime("??:??")); + } +} From 1d5dcfe8b0df15bd416e1d84abbcdc00b2b90921 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 17 Jan 2020 18:29:16 -0600 Subject: [PATCH 160/189] Added solution for odd even jump --- .../algorithm/leetcode/OddEvenJump.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OddEvenJump.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OddEvenJump.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OddEvenJump.java new file mode 100644 index 0000000..9ac9dda --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/OddEvenJump.java @@ -0,0 +1,60 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.TreeMap; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/odd-even-jump/ + */ +public class OddEvenJump { + public int oddEvenJumps(int[] A) { + int n = A.length; + + if (n == 0) return 0; + + int count = 0; // last element counts 1 + + boolean[] odd = new boolean[n]; // if even jump can be made from i + boolean[] even = new boolean[n]; // if odd jump can be made from i + + TreeMap map = new TreeMap<>(); + map.put(A[n - 1], n - 1); + + odd[n - 1] = true; + even[n - 1] = true; + + for (int i = n - 2; i >= 0; i--) { + int curr = A[i]; + + Integer lower = map.floorKey(curr); + Integer higher = map.ceilingKey(curr); + + if (lower != null) { // if lower value exists in forward dir, then should be able to make even jump, and odd jump after that + even[i] = odd[map.get(lower)]; + } + + if (higher != null) { + odd[i] = even[map.get(higher)]; + } + + map.put(curr, i); + } + + for (boolean b: odd) { // since jump start from odd i.e. 1 + if (b) count++; + } + + return count; + } + + @Test + public void test() { + assertEquals(2, oddEvenJumps(new int[]{10, 13, 12, 14, 15})); + assertEquals(3, oddEvenJumps(new int[]{2, 3, 1, 1, 4})); + assertEquals(3, oddEvenJumps(new int[]{5, 1, 3, 4, 2})); + assertEquals(6, oddEvenJumps(new int[]{1, 2, 3, 2, 1, 4, 4, 5})); + } +} From 8990c14dc094d8ded186945a046de1185c742cd0 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 17 Jan 2020 21:06:54 -0600 Subject: [PATCH 161/189] Added solution for score of parentheses --- .../leetcode/ScoreOfParentheses.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ScoreOfParentheses.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ScoreOfParentheses.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ScoreOfParentheses.java new file mode 100644 index 0000000..31d5c65 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/ScoreOfParentheses.java @@ -0,0 +1,50 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/score-of-parentheses/ + */ +public class ScoreOfParentheses { + public int scoreOfParentheses(String S) { + // at i, open = 1, go on till open = 0 at j + // sofar = 2 * substring (i + 1, j) + // ans += sofar + + int n = S.length(); + + if (n == 0) return 0; + + if (n == 2) return 1; + + int ans = 0; + + for (int i = 0; i < n;) { + int open = 1; + int j = i + 1; + while(j < n) { + if (S.charAt(j) == '(') open++; + else { + open--; + if (open == 0) break; + } + j++; + } + String rem = S.substring(i + 1, j); + ans += (rem.length() == 0 ? 1 : 2 * scoreOfParentheses(rem)); + i = j + 1; + } + + return ans; + } + + @Test + public void test() { + assertEquals(2, scoreOfParentheses("()()")); + assertEquals(2, scoreOfParentheses("(())")); + assertEquals(3, scoreOfParentheses("()(())")); + assertEquals(6, scoreOfParentheses("(()(()))")); + } +} From 03094a43657b5c68fa473e6a03fa26aed3a9cd48 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 18 Jan 2020 08:04:44 -0600 Subject: [PATCH 162/189] Added solution for word ladder ii --- .../algorithm/leetcode/WordLadderII.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordLadderII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordLadderII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordLadderII.java new file mode 100644 index 0000000..ca726fd --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/WordLadderII.java @@ -0,0 +1,104 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static java.util.Arrays.asList; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + + +/** + * https://leetcode.com/problems/word-ladder-ii/ + */ +public class WordLadderII { + public List> findLadders(String beginWord, String endWord, List wordList) { + List> l = new ArrayList<>(); + if (!wordList.contains(endWord)) return l; + + Map> graph = new HashMap<>(); + + Set startSet = new HashSet<>(); + startSet.add(beginWord); + + Set dict = new HashSet<>(wordList); + + // to build the graph -> directed graph + bfs(startSet, endWord, graph, dict); + + + List temp = new ArrayList<>(); + temp.add(beginWord); + + // backtrack to create the result ladder + dfs(beginWord, endWord, l, graph, temp); + + return l; + } + + private void bfs(Set startSet, String endWord, Map> graph, Set dict) { + if (startSet.isEmpty()) return; // no more graph building + + Set temp = new HashSet<>(); + + boolean finish = false; + + dict.removeAll(startSet); + + for (String word : startSet) { + char[] chars = word.toCharArray(); + + for (int i = 0; i < chars.length; i++) { + char old = chars[i]; + + // change each char and see if we have a word in dict + for (char ch = 'a'; ch <= 'z'; ch++) { + chars[i] = ch; + + String next = new String(chars); + + if (dict.contains(next)) { + if (next.equals(endWord)) { + finish = true; + } else { + temp.add(next); + } + + graph.computeIfAbsent(word, s -> new ArrayList<>()).add(next); + } + + } + chars[i] = old; + } + } + + if (!finish) bfs(temp, endWord, graph, dict); + } + + private void dfs(String beginWord, String endWord, List> l, Map> graph, List temp) { + if (endWord.equals(beginWord)) { + l.add(new ArrayList<>(temp)); + + return; + } + + if (graph.containsKey(beginWord)) { + for (String word : graph.get(beginWord)) { + + temp.add(word); + dfs(word, endWord, l, graph, temp); + temp.remove(temp.size() - 1); + } + } + } + + @Test + public void test() { + assertThat(findLadders("hot", "dog", Arrays.asList("hot", "dog")), is(Collections.emptyList())); + + assertThat(findLadders("hit", "cog", Arrays.asList("hot","dot","dog","lot","log","cog")), + is(asList(asList("hit","hot","dot","dog","cog"), asList("hit","hot","lot","log","cog")))); + } +} From ce419c91969f397bafd5f55117e7263c954f3ccf Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 18 Jan 2020 13:13:04 -0600 Subject: [PATCH 163/189] Added solution for compare strings --- .../algorithm/leetcode/CompareStrings.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CompareStrings.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CompareStrings.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CompareStrings.java new file mode 100644 index 0000000..a75165c --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CompareStrings.java @@ -0,0 +1,75 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertArrayEquals; + +/** + * One string A strictly smaller than other B if the count(firstSamllestChar A) < count(firstSmallestChar B) + * + * for given array of strings with B, return C[j] where C[j] represents count of smaller strings than C[j] in A + */ +public class CompareStrings { + // Time O(m * n) where m -> length of B, n -> length of A + public int[] compareStrings(String A, String B) { + String[] a = A.split(" "); + String[] b = B.split(" "); + + Map map = new HashMap<>(); + + for (String aa: a) { + map.put(aa, count(aa)); + } + + int len = b.length; + + int[] res = new int[len]; + + for (int i = 0; i < len; i++) { // O(m * n) + res[i] = countStrings(a, map, b[i]); + } + + return res; + } + + private int countStrings(String[] arr, Map map, String str) { + int count = 0; + + int[] bCount = count(str); + + for (String a: arr) { + int[] aCount = map.get(a); + + // if b is strictly larger, then count + 1 + int aVal = 0; + int bVal = 0; + for (int i = 0; i < 26; i++) { + if (aCount[i] > 0 && aVal == 0) aVal = aCount[i]; + + if (bCount[i] > 0 && bVal == 0) bVal = bCount[i]; + } + + if (bVal > aVal) count++; + } + + return count; + } + + private int[] count(String str) { + int[] arr = new int[26]; + + for (char ch: str.toCharArray()) { + arr[ch - 'a']++; + } + + return arr; + } + + @Test + public void test() { + assertArrayEquals(new int[] { 3, 2}, compareStrings("abcd aabc bd", "aaa aa")); + } +} From ff759a31ac96cc484b22184b044d18d0ca6ab48f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 19 Jan 2020 08:08:32 -0600 Subject: [PATCH 164/189] Added solution for ternary expression parser --- .../algorithm/leetcode/TernaryExpression.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TernaryExpression.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TernaryExpression.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TernaryExpression.java new file mode 100644 index 0000000..62f43d0 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TernaryExpression.java @@ -0,0 +1,46 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/ternary-expression-parser/ + */ +public class TernaryExpression { + public String parseTernary(String expression) { + int n = expression.length(); + if (n <= 1) return expression; + + char first = expression.charAt(0); + + int i = 1; + int ques = 0; + + while (i < n) { + if (expression.charAt(i) == ':') { + ques--; + if (ques == 0) break; + } else if (expression.charAt(i) == '?') ques++; + + i++; + } + + if (first == 'T') { + // take first part + + return parseTernary(expression.substring(2, i)); + } else { + // take second part + return parseTernary(expression.substring(i + 1)); + } + + } + + @Test + public void test() { + assertEquals("2", parseTernary("T?2:3")); + assertEquals("4", parseTernary("F?1:T?4:5")); + assertEquals("F", parseTernary("T?T?F:5:3")); + } +} From ef06f4b17b354620436caec9a2890499bce0fe72 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 19 Jan 2020 14:16:12 -0600 Subject: [PATCH 165/189] Added solution for remove comments --- .../algorithm/trees/RemoveComments.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/RemoveComments.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/RemoveComments.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/RemoveComments.java new file mode 100644 index 0000000..87daab9 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/RemoveComments.java @@ -0,0 +1,74 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/remove-comments/ + */ +public class RemoveComments { + public List removeComments(String[] source) { + // read each line and look for '/' char + // look for next char + // if '/', then remove all the strings remaing to end of line + // if '*', then keep on moving until you find '*/' + List l = new ArrayList<>(); + if (source == null || source.length == 0) return l; + boolean open = false; + + StringBuilder sb = new StringBuilder(); + + for (String line: source) { + + if (!open) + sb = new StringBuilder(); + + int i = 0; + while (i < line.length()) { + if (!open && line.charAt(i) == '/' && i + 1 < line.length() && line.charAt(i + 1) == '*') { + open = true; + i++; + } else if (open && line.charAt(i) == '*' && i + 1 < line.length() && line.charAt(i + 1) == '/') { + open = false; + i++; + } else if (!open && line.charAt(i) == '/' && i + 1 < line.length() && line.charAt(i + 1) == '/') { // we can skip content after // + break; + } else if (!open) { + sb.append(line.charAt(i)); + } + i++; + } + + if (sb.length() > 0 && !open) + l.add(sb.toString()); + } + return l; + } + + @Test + public void test1() { + List expected = asList("int main()","{ "," ","int a, b, c;","a = b + c;","}"); + String[] input = {"/*Test program */", "int main()", "{ ", " // variable declaration ", "int a, b, c;", "/* This is a test", " multiline ", " comment for ", " testing */", "a = b + c;", "}"}; + assertThat(removeComments(input), is(expected)); + } + + @Test + public void test2() { + List expected = asList("ab"); + String[] input = {"a/*comment", "line", "more_comment*/b"}; + assertThat(removeComments(input), is(expected)); + } + + @Test + public void test3() { + List expected = asList("main() {"," double s = 33;"," cout << s;","}"); + String[] input = {"main() {", "/* here is commments", " // still comments */", " double s = 33;", " cout << s;", "}"}; + assertThat(removeComments(input), is(expected)); + } +} From 2d337a0a14e9e4a73915f75cdc7be6d4e6aaa121 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 19 Jan 2020 21:36:08 -0600 Subject: [PATCH 166/189] Added solution for alphabet mapping --- .../algorithm/leetcode/AlphabetMapping.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetMapping.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetMapping.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetMapping.java new file mode 100644 index 0000000..b50f658 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/AlphabetMapping.java @@ -0,0 +1,53 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/decrypt-string-from-alphabet-to-integer-mapping/ + */ +public class AlphabetMapping { + public String freqAlphabets(String s) { + int start = 0; + + + StringBuilder sb = new StringBuilder(); + + while (start < s.length()) { + + int val = 0; + int end = start; + for (; end < s.length(); end++) { + if (s.charAt(end) == '#' || val > 26) { + if (val <= 26) { + sb.append((char) (val - 1 + 'a')); + start = end + 1; + } else { + sb.append((char)(s.charAt(start) - '0' - 1 + 'a')); + start++; + } + break; + } + val = val * 10 + (s.charAt(end) - '0'); // val = 10 + } + + if (end == s.length() && s.charAt(end - 1) != '#') { + while (start < s.length()) { + sb.append((char)(s.charAt(start) - '0' - 1 + 'a')); + start++; + } + } + } + + return sb.toString(); + } + + @Test + public void test() { + assertEquals("jkab",freqAlphabets("10#11#12")); + assertEquals("jkl",freqAlphabets("10#11#12#")); + assertEquals("acz",freqAlphabets("1326#")); + assertEquals("abcdefghijklmnopqrstuvwxyz",freqAlphabets("12345678910#11#12#13#14#15#16#17#18#19#20#21#22#23#24#25#26#")); + } +} From 06a10ba5970d043c87d8c5b8cdf99c05a806e17e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 19 Jan 2020 21:37:01 -0600 Subject: [PATCH 167/189] Added solution for max distance in binary string --- .../ds/custom/trie/MaxDistanceTest.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/trie/MaxDistanceTest.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MaxDistanceTest.java b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MaxDistanceTest.java new file mode 100644 index 0000000..a81b75d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/trie/MaxDistanceTest.java @@ -0,0 +1,82 @@ +package com.eprogrammerz.examples.ds.custom.trie; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * The distance between 2 binary strings is the sum of their lengths after removing the common prefix. + * For example: the common prefix of 1011000 and 1011110 is 1011 so the distance is len("000") + len("110") = 3 + 3 = 6. + * + * Given a list of binary strings, pick a pair that gives you maximum distance among all possible pair and return that distance. + */ +public class MaxDistanceTest { + @Test + public void test() { + assertEquals(6, maxDistance(new String[]{"1011000", "1011110"})); + assertEquals(9, maxDistance(new String[]{"1011000", "1011110", "1101"})); + assertEquals(9, maxDistance(new String[]{"1011000", "1011110", "1101", "01"})); + assertEquals(10, maxDistance(new String[]{"1011000", "1011110", "1101", "011"})); + } + + public int maxDistance(String[] strs) { + trie = new Trie(); + + for (String str : strs) { + trie.insert(str); + } + + return trie.search(); + } + + private Trie trie; + + private class Trie { + TrieNode root; + + Trie() { + this.root = new TrieNode(); + } + + public void insert(String word) { + TrieNode curr = root; + + for (char ch : word.toCharArray()) { + int val = (ch - '0'); + + if (curr.childs[val] == null) { + curr.childs[val] = new TrieNode(); + } + curr = curr.childs[val]; + } + } + + int max; + + public int search() { + Set visited = new HashSet<>(); + dfs(root, visited); + return max; + } + + private int dfs(TrieNode node, Set visited) { + if (node == null) return 0; + visited.add(node); + + int l = dfs(node.childs[0], visited); + int r = dfs(node.childs[1], visited); + + if (node.childs[0] != null && node.childs[1] != null) { + max = Math.max(max, l + r); + } + return Math.max(l, r) + 1; + } + } + + private class TrieNode { + TrieNode[] childs = new TrieNode[2]; + } +} \ No newline at end of file From e507d8f36c283ce931a6963da173a407b86be809 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 19 Jan 2020 21:37:38 -0600 Subject: [PATCH 168/189] Added solution for snake game --- .../examples/design/SnakeGameTest.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/design/SnakeGameTest.java diff --git a/src/main/java/com/eprogrammerz/examples/design/SnakeGameTest.java b/src/main/java/com/eprogrammerz/examples/design/SnakeGameTest.java new file mode 100644 index 0000000..30705fd --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/design/SnakeGameTest.java @@ -0,0 +1,105 @@ +package com.eprogrammerz.examples.design; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/design-snake-game/ + */ + +public class SnakeGameTest { + @Test + public void test() { + SnakeGame game = new SnakeGame(2,2, new int[][] {{1,1}, {0,0}}); + + assertEquals(0, game.move("R")); + assertEquals(1, game.move("D")); + assertEquals(1, game.move("L")); + assertEquals(2, game.move("U")); + assertEquals(2, game.move("R")); + } +} + +class SnakeGame { + + /** Initialize your data structure here. + @param width - screen width + @param height - screen height + @param food - A list of food positions + E.g food = [[1,1], [1,0]] means the first food is positioned at [1,1], the second is at [1,0]. */ + // q to track co-ordinates + // add when going to new cell, and poll + + private int r; + private int c; + + private int score; + private int[][] food; + private Deque curr; + + public SnakeGame(int width, int height, int[][] food) { + this.r = height; + this.c = width; + this.food = food; + + this.curr = new ArrayDeque<>(); + this.curr.addFirst(new int[] {0, 0}); + + } + + /** Moves the snake. + @param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down + @return The game's score after the move. Return -1 if game over. + Game over when snake crosses the screen boundary or bites its body. */ + public int move(String direction) { + int[] head = curr.getFirst(); + + int row = head[0]; + int col = head[1]; + + switch(direction) { + case "U": + row--; + break; + case "L": + col--; + break; + case "R": + col++; + break; + case "D": + row++; + break; + } + + if (row == r || row < 0 || col == c || col < 0) return -1; + + if (score < food.length && row == food[score][0] && col == food[score][1]) { + score++; + } else { + + // update snake + curr.removeLast(); + } + + if (isPartOfSnake(row, col)) return -1; + + curr.addFirst(new int[] {row, col}); + + return score; + } + + private boolean isPartOfSnake(int row, int col) { + Iterator itr = curr.iterator(); + + while (itr.hasNext()) { + int[] p = itr.next(); + if (row == p[0] && col == p[1]) return true; + } + + return false; + } +} \ No newline at end of file From 7c9bc179f45f4cb9bd55c07af279a3b0b15e9b2e Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Wed, 22 Jan 2020 07:37:56 -0600 Subject: [PATCH 169/189] Added solution for sentence similarity ii --- .../leetcode/SentenceSimilarityII.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SentenceSimilarityII.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SentenceSimilarityII.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SentenceSimilarityII.java new file mode 100644 index 0000000..fdb6e65 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SentenceSimilarityII.java @@ -0,0 +1,68 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; + +/** + * https://leetcode.com/problems/sentence-similarity-ii/ + */ +public class SentenceSimilarityII { + + // Time O(N * logP) + public boolean areSentencesSimilarTwo(String[] words1, String[] words2, List> pairs) { + + if (words1 == null || words2 == null || words1.length != words2.length) return false; + + Map parents = new HashMap<>(); + + int n = words1.length; + + for (List pair : pairs) { + String u = pair.get(0); + String v = pair.get(1); + + if (!parents.containsKey(u)) parents.put(u, u); + if (!parents.containsKey(v)) parents.put(v, v); + + if (!find(parents, u).equals(find(parents, v))) { + union(parents, u, v); + } + } + + for (int i = 0; i < n; i++) { + String u = words1[i]; + String v = words2[i]; + + if (u.equals(v)) continue; + + if (!parents.containsKey(u) || !parents.containsKey(v) || !find(parents, u).equals(find(parents, v))) { + return false; + } + } + + return true; + } + + private String find(Map parents, String u) { + while (!u.equals(parents.get(u))) { + u = parents.get(u); + } + return u; + } + + private void union(Map parents, String u, String v) { + parents.put(find(parents, v), find(parents, u)); + } + + @Test + public void test() { + assertTrue(areSentencesSimilarTwo(new String[]{"great", "acting", "skills"}, new String[]{"fine", "drama", "talent"}, + asList(asList("great", "good"), asList("fine", "good"), asList("drama", "acting"), asList("skills", "talent")))); + } +} From 645ed16a2e17b3c63a19f621946d163c58711dfe Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 24 Jan 2020 17:32:10 -0600 Subject: [PATCH 170/189] Added solution for circular queue --- .../ds/custom/queue/CircularQueue.java | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/queue/CircularQueue.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/queue/CircularQueue.java b/src/main/java/com/eprogrammerz/examples/ds/custom/queue/CircularQueue.java new file mode 100644 index 0000000..5324627 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/queue/CircularQueue.java @@ -0,0 +1,116 @@ +package com.eprogrammerz.examples.ds.custom.queue; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +/** + * https://leetcode.com/problems/design-circular-queue/ + */ +public class CircularQueue { + class MyCircularQueue { + + private int[] arr; + private int head; + private int tail; + /** Initialize your data structure here. Set the size of the queue to be k. */ + public MyCircularQueue(int k) { + this.arr = new int[k]; + Arrays.fill(this.arr, -1); + } + + /** Insert an element into the circular queue. Return true if the operation is successful. */ + public boolean enQueue(int value) { + if (isFull()) return false; + + if (tail == arr.length - 1) { + tail = 0; + } + + if (tail == 0 && arr[tail] == -1) { + arr[0] = value; + return true; + } + + arr[++tail] = value; + + return true; + } + + /** Delete an element from the circular queue. Return true if the operation is successful. */ + public boolean deQueue() { + if (isEmpty()) return false; + arr[head] = -1; + if (head + 1 < arr.length && arr[head + 1] != -1) { + head++; + } + if (head == arr.length) head = 0; + return true; + } + + /** Get the front item from the queue. */ + public int Front() { + return isEmpty() ? -1 : arr[head]; + } + + /** Get the last item from the queue. */ + public int Rear() { + return isEmpty() ? -1 : arr[tail]; + } + + /** Checks whether the circular queue is empty or not. */ + public boolean isEmpty() { + return head == tail && arr[head] == -1; + } + + /** Checks whether the circular queue is full or not. */ + public boolean isFull() { + return (tail == arr.length - 1 && head == 0 && arr[tail] != -1 && arr[head] != -1) + || (tail + 1 == head && arr[tail] != -1 && arr[head] != -1); + } + } + + @Test + public void test1() { + MyCircularQueue queue = new MyCircularQueue(3); + assertTrue(queue.enQueue(1)); + assertTrue(queue.enQueue(2)); + assertTrue(queue.enQueue(3)); + assertFalse(queue.enQueue(4)); + assertEquals(3, queue.Rear()); + assertTrue(queue.isFull()); + assertTrue(queue.deQueue()); + assertTrue(queue.enQueue(5)); + assertEquals(5, queue.Rear()); + assertEquals(2, queue.Front()); + } + + @Test + public void test2() { + MyCircularQueue queue = new MyCircularQueue(6); + assertTrue(queue.enQueue(6)); + assertEquals(6, queue.Rear()); + assertTrue(queue.deQueue()); + assertTrue(queue.enQueue(4)); + assertEquals(4, queue.Rear()); + assertTrue(queue.deQueue()); + assertEquals(-1, queue.Front()); + assertFalse(queue.deQueue()); + assertFalse(queue.deQueue()); + assertFalse(queue.deQueue()); + } + + @Test + public void test3() { + MyCircularQueue queue = new MyCircularQueue(2); + assertTrue(queue.enQueue(4)); + assertTrue(queue.enQueue(9)); + assertTrue(queue.deQueue()); + assertTrue(queue.deQueue()); + + assertTrue(queue.enQueue(4)); + assertTrue(queue.enQueue(6)); + } +} From 398966c0abfc88fe1e636ba1f701e506ef90b7f3 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 24 Jan 2020 17:41:30 -0600 Subject: [PATCH 171/189] Added solution for blocking queue --- .../ds/custom/queue/BlockingQueue.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/ds/custom/queue/BlockingQueue.java diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/queue/BlockingQueue.java b/src/main/java/com/eprogrammerz/examples/ds/custom/queue/BlockingQueue.java new file mode 100644 index 0000000..bd4c0b1 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/queue/BlockingQueue.java @@ -0,0 +1,59 @@ +package com.eprogrammerz.examples.ds.custom.queue; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * https://leetcode.com/problems/design-bounded-blocking-queue/ + */ +public class BlockingQueue { + class BoundedBlockingQueue { + private Queue q; + private int capacity; + private ReentrantLock lock = new ReentrantLock(); + private Condition full = lock.newCondition(); + private Condition empty = lock.newCondition(); + + + public BoundedBlockingQueue(int capacity) { + this.capacity = capacity; + this.q = new LinkedList<>(); + } + + public void enqueue(int element) throws InterruptedException { + lock.lock(); + try { + while (q.size() >= capacity) full.await(); + + q.add(element); + + empty.signalAll(); + } finally { + if (lock.isLocked()) lock.unlock(); + } + } + + public int dequeue() throws InterruptedException { + lock.lock(); + int val; + try { + while (size() == 0) { + empty.await(); + } + + val = q.poll(); + + full.signalAll(); + } finally { + if (lock.isLocked()) lock.unlock(); + } + return val; + } + + public int size() { + return q.size(); + } + } +} From e2b886d9b26cffb89200bd61ad4624eef2437e18 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 26 Jan 2020 09:11:18 -0600 Subject: [PATCH 172/189] Added solution for binary searchable --- .../algorithm/general/BinarySearchable.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/BinarySearchable.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/BinarySearchable.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/BinarySearchable.java new file mode 100644 index 0000000..ece8b14 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/BinarySearchable.java @@ -0,0 +1,74 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.*; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Binary search is a search algorithm usually used on a sorted sequence to quickly find an element with a given value. + * In this problem we will evaluate how binary search performs on data that isn't necessarily sorted. An element is said to be binary searchable if, + * regardless of how the pivot is chosen the algorithm returns true. For example: + * + * [2, 1, 3, 4, 6, 5] and target = 5, we cannot find 5. Because when the pivot is 4, we get element 6, then right pointer will move left, + * so we'll lose the opportunity to find target 5. + * [2, 1, 3, 4, 5, 6] and target = 5, we can find 5. Because wherever we choose the pivots, we'll find target at last. + * Given an unsorted array of n distinct integers, return the number of elements that are binary searchable. + * + * Example 1: + * + * Input: [1, 3, 2] + * Output: 1 + * Explanation: However we choose the pivots, we will always find the number 1 when looking for it. This does not hold for 3 and 2. + * Example 2: + * + * Input: [2, 1, 3, 5, 4, 6] + * Output: 2 + * Explanation: 3 and 6 are the numbers guaranteed to be found. + * + * https://leetcode.com/discuss/interview-question/352743/ + */ +public class BinarySearchable { + public List binarySearchable(int[] arr) { + LinkedList l = new LinkedList<>(); + + int n = arr.length; + + if (n == 0) return l; + + // keep track of maximums while going left to right + // now traverse from right to left and see + // if curr <= right && curr >= leftMax[i] + // then that is searchable + + int[] leftMax = new int[n]; + leftMax[0] = arr[0]; + + for (int i = 1; i < n; i++) { + leftMax[i] = Math.max(arr[i], leftMax[i - 1]); + } + + int rightMin = Integer.MAX_VALUE; + for (int i = n - 1; i >= 0; i--) { + if (arr[i] <= rightMin && arr[i] >= leftMax[i]) { + l.addFirst(arr[i]); + } + rightMin = Math.min(rightMin, arr[i]); + } + + return l; + } + + @Test + public void test() { + assertThat(binarySearchable(new int[] {1,3,2}), is(Collections.singletonList(1))); + assertThat(binarySearchable(new int[] {2, 1, 3, 5, 4, 6}), is(asList(3, 6))); + assertThat(binarySearchable(new int[] {1, 5, 7, 11, 12, 18}), is(asList(1, 5, 7, 11, 12, 18))); + assertThat(binarySearchable(new int[] {3, 2, 1}), is(Collections.emptyList())); + assertThat(binarySearchable(new int[] {5, 4, 6, 2, 8}), is(Collections.singletonList(8))); + assertThat(binarySearchable(new int[] {1, 3, 2, 4, 5, 7, 6, 8}), is(asList(1, 4, 5, 8))); + } +} From 1fb957077a4cfebf28b623e70c05ce1afa7ed3de Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 26 Jan 2020 09:13:53 -0600 Subject: [PATCH 173/189] Added soluton for max network rank --- .../algorithm/general/MaxNetworkRank.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/MaxNetworkRank.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxNetworkRank.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxNetworkRank.java new file mode 100644 index 0000000..3cb4263 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/MaxNetworkRank.java @@ -0,0 +1,42 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Find the max network rank in infrastructure where rank is total num of road connected to either cities + *

+ * Example + * A = [1,2,3,3] + * B = [2,3,1,4] + * N = 4 + *

+ * return 4 (city 2 and 3 with road [2,1], [2,3], [3,1], [3,4] + */ +public class MaxNetworkRank { + public int maxNetworkRank(int[] A, int[] B, int n) { + // map to store city - ranks + int[] ranks = new int[n]; + for (int i = 0; i < A.length; i++) { + int cityA = A[i]; + int cityB = B[i]; + ranks[cityA - 1]++; + ranks[cityB - 1]++; + } + + int max = 0; + + // traverse each city pair and sum their ranks and see it is max + for (int i = 0; i < A.length; i++) { + max = Math.max(ranks[A[i] - 1] + ranks[B[i] - 1] - 1, max); + } + return max; + } + + @Test + public void test() { + assertEquals(4, maxNetworkRank(new int[]{1, 2, 3, 3}, new int[]{2, 3, 1, 4}, 4)); + assertEquals(5, maxNetworkRank(new int[]{1, 2, 3, 3, 3}, new int[]{2, 3, 1, 4, 5}, 5)); + } +} From 58c280a615c95878838b8ba62e33e5bc7e3c4cb8 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 26 Jan 2020 09:15:56 -0600 Subject: [PATCH 174/189] Added solution for print fractions --- .../algorithm/general/PrintFractions.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/PrintFractions.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/PrintFractions.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/PrintFractions.java new file mode 100644 index 0000000..80d328b --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/PrintFractions.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +/** + * Print all the fractions from 0 to 1 with N being the highest denominator. The fractions must be printed in order. + * If duplicate fraction values are found, then print the fraction in the lowest form. For example, If you have 1/2 and 5/10, then only 1/2 would printed. + * + * Example + * + * Input: n = 4 + * Output: ["0/1", "1/4", "1/3", "1/2", "2/3", "3/4", "1/1"] + */ +public class PrintFractions { + /** + * Time O(n^2) + * Space O(1) + * + * @param n + * @return + */ + public List fractions(int n) { + List l = new ArrayList<>(); + + if (n == 0) return l; + + List pairs = new ArrayList<>(); + + for (int den = 1; den <= n; den++) { + for (int num = 1; num <= den; num++) { + if (gcd(den, num) == 1) { + pairs.add(new int[] {num, den}); + } + } + } + + // O(k * logk) + pairs.sort((p1, p2) -> p1[0] * p2[1] - p1[1] * p2[0]); + + l.add("0/1"); + for (int[] pair: pairs) { + l.add(String.format("%d/%d", pair[0], pair[1])); + } + return l; + } + + private int gcd(int a, int b) { +// if (b == 0) return a; +// return gcd(b, a % b); + while (b != 0) { + int temp = b; + b = a % b; + a = temp; + } + + return a; + } + + @Test + public void test() { + assertEquals(asList("0/1", "1/4", "1/3", "1/2", "2/3", "3/4", "1/1"), fractions(4)); + } +} From 316eb3191c1a180eb72549b34de73ec114e10a30 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 26 Jan 2020 09:18:24 -0600 Subject: [PATCH 175/189] Added solution for shopping cart --- .../algorithm/general/ShoppingCartTest.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/ShoppingCartTest.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/ShoppingCartTest.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/ShoppingCartTest.java new file mode 100644 index 0000000..ff467af --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/ShoppingCartTest.java @@ -0,0 +1,149 @@ +package com.eprogrammerz.examples.algorithm.general; + +import com.google.common.collect.Sets; +import lombok.EqualsAndHashCode; +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class ShoppingCartTest { + + @Test + public void test() { + ShoppingCart cart = new ShoppingCart(); + cart.addOffer(1, 100, 300); + cart.addOffer(1, 200, 450); + cart.addOffer(2, 300, 50); + + // offer close to lower bound + Set offers1 = Sets.newHashSet(new Offer(1, 100, 300)); + assertThat(cart.getClosestOffer(1, 200), is(offers1)); + + Set offers2 = Sets.newHashSet(new Offer(1, 200, 450)); + assertThat(cart.getClosestOffer(1, 500), is(offers2)); + + // remove offer + cart.removeOffer(200); + + // the query should return the lower bound + assertThat(cart.getClosestOffer(1, 500), is(offers1)); + } + +} + +/** + * Assume a Google Shopping cart application. There are multiple products being sold, each product is sold by multiple vendors each having their own offer with a price. + * so each product can have multiple offers. + *

+ * There are three entities prodcutID, offerID, and Price. + *

+ * Implement these three methods in the most efficient manner : + *

+ * public class ShoppingCart { + *

+ * public void addOffer(long productID, long offerID, double price) { + * } + *

+ * public void removeOffer(long offerID) { + * } + *

+ * public long getClosestOffer(long productID, double price) { + * } + *

+ * } + * P1 - O1 - $300 + * P1 - O2 - $450 + * P2 - O3 - $50 + *

+ * getClosestOffer(P1, 250) -> O1 + * getClosestOffer(P1, 500) -> O2 + *

+ * return the offer which is closest to a given price. + *

+ * Assume there is no memory restriction. + */ +class ShoppingCart { + private Map>> store = new HashMap<>(); + private Map offers = new HashMap<>(); + + /** + * Creates new entry for given product id and offers associated if not existed before + * else updated offers with new offer for that particular product + *

+ * Time: O(logm) - for one product, m = no. of offers for particular product + * O(n*logm) - for n products + * + * @param productID + * @param offerID + * @param price + */ + public void addOffer(long productID, long offerID, double price) { + Offer offer = new Offer(productID, offerID, price); + + store.computeIfAbsent(productID, s -> new TreeMap<>()); + + store.get(productID).computeIfAbsent(price, s -> new HashSet<>()); + + store.get(productID).get(price).add(offer); + + offers.put(offerID, offer); + } + + // Time O(logm) for one + // O(n * logm) for n + public void removeOffer(long offerID) { + if (offers.containsKey(offerID)) { + Offer offer = offers.remove(offerID); + + TreeMap> map = store.get(offer.productId); + + map.get(offer.price).remove(offer); + + if (map.get(offer.price).isEmpty()) { + map.remove(offer.price); + } + } + } + + // Time O(logm) + public Set getClosestOffer(long productID, double price) { + TreeMap> map = store.get(productID); + + if (offers == null) return null; + + Double smaller = map.floorKey(price); + Double larger = map.ceilingKey(price); + + if (smaller == null && larger == null) return null; + + if (smaller != null && larger != null) { + double d1 = price - smaller; + double d2 = larger - price; + + double close = d1 < d2 ? smaller : larger; + + return map.get(close); + } + + if (smaller == null) return map.get(larger); + else return map.get(smaller); + } + + +} + +@EqualsAndHashCode +class Offer { + long productId; + long offerId; + double price; + + Offer(long productId, long offerId, double price) { + this.productId = productId; + this.offerId = offerId; + this.price = price; + } +} From 428c7e329d2a794c1bb230e4cced79caa6c89120 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Tue, 28 Jan 2020 08:43:33 -0600 Subject: [PATCH 176/189] Added solution for smallest range k list --- .../leetcode/SmallestRangeKList.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SmallestRangeKList.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SmallestRangeKList.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SmallestRangeKList.java new file mode 100644 index 0000000..e308e04 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SmallestRangeKList.java @@ -0,0 +1,55 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.List; +import java.util.PriorityQueue; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/ + */ +public class SmallestRangeKList { + public int[] smallestRange(List> nums) { + int n = nums.size(); + + if (n == 0) return new int[0]; + + int x = 0, y = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + PriorityQueue pq = new PriorityQueue<>((i1, i2) -> i1[2] - i2[2]); + + for (int i = 0; i < n; i++) { + List l = nums.get(i); + max = Math.max(l.get(0), max); + pq.offer(new int[] {i, 0, l.get(0)}); + } + + while (pq.size() == n) { + int[] curr = pq.poll(); + + int r = curr[0]; + int c = curr[1]; + + if (y - x > max - curr[2]) { + x = nums.get(r).get(c); + y = max; + } + + if (c + 1 < nums.get(r).size()) { + pq.offer(new int[] {r, c + 1, nums.get(r).get(c + 1)}); + max = Math.max(max, nums.get(r).get(c + 1)); + } + } + + return new int[] {x, y}; + } + + @Test + public void test() { + assertThat(smallestRange(asList(asList(4,10,15,24,26), asList(0,9,12,20), asList(5,18,22,30))), is(new int[] {20,24})); + } +} From 3ef6ba9e60272e2541a3138ff2943feb1fa52dfa Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Fri, 31 Jan 2020 07:38:08 -0600 Subject: [PATCH 177/189] Added solution for 2d search board --- .../algorithm/graphs/TwoDSearchBoard.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/graphs/TwoDSearchBoard.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/graphs/TwoDSearchBoard.java b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/TwoDSearchBoard.java new file mode 100644 index 0000000..ee7a6d2 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/graphs/TwoDSearchBoard.java @@ -0,0 +1,80 @@ +package com.eprogrammerz.examples.algorithm.graphs; + +import org.junit.Test; + +import java.util.*; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.junit.Assert.assertThat; + +/** + * https://leetcode.com/problems/word-search-ii/ + */ +public class TwoDSearchBoard { + public List findWords(char[][] board, String[] words) { + List[] map = new ArrayList[26]; + + for (String word : words) { + int key = word.charAt(0) - 'a'; + + if (map[key] == null) { + map[key] = new ArrayList<>(); + } + map[key].add(word); + } + + int m = board.length; + int n = board[0].length; + + Set found = new HashSet<>(); + + for (int r = 0; r < m; r++) { + for (int c = 0; c < n; c++) { + char curr = board[r][c]; + if (map[curr - 'a'] != null) { + List candidates = map[curr - 'a']; + + for (String candidate : candidates) { + if (found.contains(candidate)) continue; + + if (dfs(board, candidate, 0, r, c)) { + found.add(candidate); + } + } + } + } + } + return new ArrayList<>(found); + + } + + private boolean dfs(char[][] board, String word, int idx, int r, int c) { + + if (r < 0 || r >= board.length || c < 0 || c >= board[0].length || board[r][c] != word.charAt(idx)) return false; + + if (idx == word.length() - 1) return true; + + board[r][c] = '0'; + + boolean val = dfs(board, word, idx + 1, r - 1, c) || + dfs(board, word, idx + 1, r + 1, c) || + dfs(board, word, idx + 1, r, c + 1) || + dfs(board, word, idx + 1, r, c - 1); + + board[r][c] = word.charAt(idx); + + return val; + } + + @Test + public void test() { + char[][] board = { + {'o', 'a', 'a', 'n'}, + {'e', 't', 'a', 'e'}, + {'i', 'h', 'k', 'r'}, + {'i', 'f', 'l', 'v'} + }; + List actual = findWords(board, new String[]{"oath", "pea", "eat", "rain"}); + assertThat(actual, hasItems("oath", "eat")); + } +} From 5d00bd28a48d352e3c6a9f6fbaf4b4ca343788fc Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 1 Feb 2020 07:24:43 -0600 Subject: [PATCH 178/189] Added solution for merging k sorted stack --- .../algorithm/leetcode/MergeKStack.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MergeKStack.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MergeKStack.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MergeKStack.java new file mode 100644 index 0000000..dd8ef94 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MergeKStack.java @@ -0,0 +1,101 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Comparator; +import java.util.PriorityQueue; +import java.util.Stack; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + + +/** + * Merge three stacks into one. + * + * s1 = -5,1,2,3,5 + * s2 = -3,4,6,7 + * s3 = 1,5 + * + * output (return one stack) + * -5,-3,1,1,2,3,4,5,5,6,7 + */ +public class MergeKStack { + // n = number of elements in stacks + // Time O(n*logk) + // Space O(n) + public Stack mergeKStack(Stack[] stacks) { + int n = stacks.length; + + Stack[] reversed = new Stack[n]; + + for (int i = 0; i < reversed.length; i++) { + reversed[i] = reverse(stacks[i]); + } + + Stack merged = new Stack<>(); + + PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(i -> reversed[i].peek())); // min heap; return index of stack with min val + + for (int i = 0; i < n; i++) { + pq.offer(i); + } + + while (!pq.isEmpty()) { + + int curr = pq.poll(); + merged.push(reversed[curr].pop()); + + if (!reversed[curr].isEmpty()) pq.add(curr); + + } + return merged; + } + + private Stack reverse(Stack stack) { + Stack reversed = new Stack<>(); + while (!stack.isEmpty()) { + reversed.push(stack.pop()); + } + return reversed; + } + + @Test + public void test() { + Stack s1 = new Stack<>(); + s1.push(-5); + s1.push(1); + s1.push(2); + s1.push(3); + s1.push(5); + + Stack s2 = new Stack<>(); + s2.push(-3); + s2.push(4); + s2.push(6); + s2.push(7); + + Stack s3 = new Stack<>(); + s3.push(1); + s3.push(5); + + Stack[] stacks = new Stack[]{s1, s2, s3}; + + Stack actual = mergeKStack(stacks); + + Stack expected = new Stack<>(); + expected.push(-5); + expected.push(-3); + expected.push(1); + expected.push(1); + expected.push(2); + expected.push(3); + expected.push(4); + expected.push(5); + expected.push(5); + expected.push(6); + expected.push(7); + + assertThat(actual, is(expected)); + } +} From b79cfac61865cb31c3bded89bf47bdb55a28d1cb Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sun, 2 Feb 2020 09:22:29 -0600 Subject: [PATCH 179/189] Added solution for single element in sorted array --- .../leetcode/SingleElementInSortedArray.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SingleElementInSortedArray.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SingleElementInSortedArray.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SingleElementInSortedArray.java new file mode 100644 index 0000000..fd7b222 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/SingleElementInSortedArray.java @@ -0,0 +1,66 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/single-element-in-a-sorted-array/ + */ +public class SingleElementInSortedArray { + public int singleNonDuplicate(int[] nums) { + int n = nums.length; + + int lo = 0; + int hi = n - 1; + + while (lo <= hi) { + int mid = lo + (hi - lo) / 2; + + // 1,2,2 + int left = mid - lo + 1; // 2 + + if (mid > 0 && nums[mid - 1] == nums[mid]) { + left = mid - lo + 1; + } else if (mid < n - 1 && nums[mid + 1] == nums[mid]) { + left = mid - lo; + } else { + return nums[mid]; + } + + if (left % 2 == 0) { + // look into right + if (mid > 0 && nums[mid - 1] == nums[mid]) { + lo = mid + 1; + } else { + lo = mid; + } + + } else { + // look into left + if (mid > 0 && nums[mid - 1] == nums[mid]) { + hi = mid + 1; + } else if (mid + 1 < n && nums[mid + 1] == nums[mid]) { + hi = mid - 1; + } else { + hi = mid; + } + } + + // now we need to go the section where length is odd + } + + return -1; + } + + @Test + public void test() { + assertEquals(1, singleNonDuplicate(new int[] {1,2,2})); + assertEquals(2, singleNonDuplicate(new int[] {1,1,2})); + assertEquals(2, singleNonDuplicate(new int[] {1,1,2,3,3,4,4,8,8})); + assertEquals(1, singleNonDuplicate(new int[] {1,2,2,3,3,4,4,8,8})); + assertEquals(3, singleNonDuplicate(new int[] {1,1,2,2,3,4,4,8,8})); + assertEquals(4, singleNonDuplicate(new int[] {1,1,2,2,3,3,4,8,8})); + assertEquals(8, singleNonDuplicate(new int[] {1,1,2,2,3,3,4,4,8})); + } +} From ccb77e524a9bf59eabb1e8f82cda99f887032614 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 8 Feb 2020 08:58:42 -0600 Subject: [PATCH 180/189] Updated code for LRU cache --- .../examples/ds/cache/LRUCache.java | 95 ++++++++++++++++++- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/eprogrammerz/examples/ds/cache/LRUCache.java b/src/main/java/com/eprogrammerz/examples/ds/cache/LRUCache.java index dd8d34e..26358bc 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/cache/LRUCache.java +++ b/src/main/java/com/eprogrammerz/examples/ds/cache/LRUCache.java @@ -24,12 +24,13 @@ */ public class LRUCache { - private class Node { + + private class Node { K key; V value; - Node next; - Node prev; + Node next; + Node prev; Node(K key, V value) { this.key = key; @@ -42,6 +43,91 @@ public String toString() { } } + private Map> map; + private DDList list; + private int capacity; + + private int size; + + public LRUCache(int capacity) { + this.capacity = capacity; + this.map = new HashMap<>(); + this.list = new DDList(); + } + + public V get(K key) { + Node node = map.get(key); + + if (node == null) return null; + + list.removeNode(node); + list.addToHead(node); + + return node.value; + } + + public void put(K key, V value) { + Node node = map.get(key); + + if (node != null) { + node.value = value; + + list.removeNode(node); + list.addToHead(node); + + return; + } + + node = new Node<>(key, value); + + if (size == capacity) { + Node last = list.removeTail(); + map.remove(last.key); + + size--; + } + + list.addToHead(node); + size++; + map.put(key, node); + } + + class DDList { + Node head; + Node tail; + + DDList() { + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = tail; + this.tail.prev = head; + } + + public void addToHead(Node node) { + node.next = head.next; + node.prev = head; + + head.next.prev = node; + head.next = node; + } + + public void removeNode(Node node) { + node.next.prev = node.prev; + node.prev.next = node.next; + + } + + public Node removeTail() { + if (tail.prev == head) return null; + Node node = tail.prev; + removeNode(node); + + return node; + } + } +} + +/* private int size; private Map> map; @@ -107,5 +193,6 @@ private void removeNode(Node node) { if (tail == node) tail = node.prev; if (head == node) head = node.next; } + } +*/ -} From a2514d1659ba121a1fef41f1f285849cdf58ebdb Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 8 Feb 2020 09:00:56 -0600 Subject: [PATCH 181/189] Updated solution for freq stack --- .../examples/ds/custom/stack/FreqStack.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java index 31b01b5..6ff4f3b 100644 --- a/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java +++ b/src/main/java/com/eprogrammerz/examples/ds/custom/stack/FreqStack.java @@ -2,8 +2,53 @@ import java.util.HashMap; import java.util.Map; +import java.util.PriorityQueue; +import java.util.Stack; public class FreqStack { + private Map map; + private Map> timestamp; + private PriorityQueue pq; + private int count; + + public FreqStack() { + this.map = new HashMap<>(); + this.timestamp = new HashMap<>(); + this.pq = new PriorityQueue<>((e1, e2) -> map.get(e1).equals(map.get(e2)) ? + timestamp.get(e2).peek() - timestamp.get(e1).peek() : + map.get(e2) - map.get(e1)); + } + + public void push(int x) { + map.put(x, map.getOrDefault(x, 0) + 1); + timestamp.computeIfAbsent(x, s -> new Stack<>()).push(count++); + + if (map.get(x) == 1) { + pq.offer(x); + } else { + PriorityQueue temp = new PriorityQueue<>(); + while (!pq.isEmpty()) temp.add(pq.poll()); + + pq.addAll(temp); + } + } + + public int pop() { + int curr = pq.poll(); + + int count = map.get(curr) - 1; + + if (count == 0) { + map.remove(curr); + timestamp.remove(curr); + } else { + map.put(curr, count); + timestamp.get(curr).pop(); + pq.offer(curr); + } + return curr; + } + /* private Node head; private Map map; @@ -67,4 +112,6 @@ static class Node { this.next = null; } } + + */ } From f29267dc957a7365077f5e2bcc40c0b7eeb5f424 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 8 Feb 2020 09:04:46 -0600 Subject: [PATCH 182/189] Added solution for longest absolute file path --- .../leetcode/LongestAbsoluteFilePath.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestAbsoluteFilePath.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestAbsoluteFilePath.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestAbsoluteFilePath.java new file mode 100644 index 0000000..e2988a4 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/LongestAbsoluteFilePath.java @@ -0,0 +1,48 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/longest-absolute-file-path/ + */ +public class LongestAbsoluteFilePath { + public int lengthLongestPath(String input) { + if (input == null || input.length() == 0) return 0; + + Stack stack = new Stack<>(); + stack.push(0); + + int len = 0; + + for (String str: input.split("\n")) { + int level = str.lastIndexOf("\t") + 1; + + while (level + 1 < stack.size()) stack.pop(); + + int curr = stack.peek() + str.length() - level + 1; // remove /t, add / + stack.push(curr); + + if (str.contains(".")) len = Math.max(len, curr - 1); + } + + return len; + } + + @Test + public void test() { + assertEquals(0, lengthLongestPath("file")); + assertEquals(12, lengthLongestPath("dir\n file.txt")); + assertEquals(20, lengthLongestPath("dir\n\t file.txt\n\tfile2.txt")); + assertEquals(25, lengthLongestPath("file name with space.txt")); + assertEquals(8, lengthLongestPath("file.txt")); + assertEquals(0, lengthLongestPath("dir\n\tsubdir1\n\tsubdir2\n\t\tsubdir3")); + assertEquals(16, lengthLongestPath("dir\n file.txt")); + assertEquals(20, lengthLongestPath("dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext")); + assertEquals(20, lengthLongestPath("dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext")); + assertEquals(32, lengthLongestPath("dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext")); + } +} From 7a555aad7ae0029f43a86c10fddee92f4c1abfee Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 8 Feb 2020 09:18:51 -0600 Subject: [PATCH 183/189] Added solution for max points in line --- .../algorithm/leetcode/MaxPointsLine.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxPointsLine.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxPointsLine.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxPointsLine.java new file mode 100644 index 0000000..186328d --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/MaxPointsLine.java @@ -0,0 +1,67 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/max-points-on-a-line/ + */ +public class MaxPointsLine { + public int maxPoints(int[][] points) { + if (points.length <= 2) return points.length; + + int count = 0; + + for (int i = 0; i < points.length; i++) { + + Map map = new HashMap<>(); + + int samep = 1; + + for (int j = 0; j < points.length; j++) { + + if (i == j) continue; + + int[] p1 = points[i]; + int[] p2 = points[j]; + + if (p1[0] == p2[0] && p1[1] == p2[1]) { + samep++; + continue; + } + + int dy = p2[1] - p1[1]; + int dx = p2[0] - p1[0]; + + int gcd = gcd(dy, dx); + + String key = dx / gcd + "#" + dy / gcd; + + if (map.containsKey(key)) map.put(key, map.get(key) + 1); + else map.put(key, 2); + + count = Math.max(count, samep + map.get(key) - 1); + } + + count = Math.max(count, samep); + } + + return count; + } + + private int gcd(int a, int b) { + if (b == 0) return a; + return gcd(b, a % b); + } + + @Test + public void test() { + assertEquals(2, maxPoints(new int[][] { {0,0},{1,65536},{65536,0}})); + assertEquals(3, maxPoints(new int[][] { {4,0},{4,-1},{4,5}})); + } +} + From b44968f95d538cd39d2820f798e3d98f62cb2f0a Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 8 Feb 2020 17:06:19 -0600 Subject: [PATCH 184/189] Added solution for task scheduler --- .../algorithm/leetcode/TaskScheduler.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TaskScheduler.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TaskScheduler.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TaskScheduler.java new file mode 100644 index 0000000..499e360 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/TaskScheduler.java @@ -0,0 +1,69 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/task-scheduler/ + */ +public class TaskScheduler { + /** + * 1. count tasks + * 2. put tasks into priority queue + * 3. fill distances arr with -1 (noting -1 is unreachable) + * 4. pull the from pq with highest count (as we want to finish those task first) + * 5. if polled task is not in enough interval n, then keep looking another + * ready task + * 6. update the interval for each task + * + * @param tasks + * @param n + * @return + */ + public int leastInterval(char[] tasks, int n) { + int[] counts = new int[26]; + for (char task: tasks) { + counts[task - 'A']++; + } + + PriorityQueue pq = new PriorityQueue<>((a1, a2) -> a2 - a1); + for (int count: counts) { + if (count > 0) + pq.add(count); + } + + + int count = 0; + + while (!pq.isEmpty()) { + + List temp = new ArrayList<>(); + + for (int i = 0; i <= n; i++) { + if (!pq.isEmpty()) { + int next = pq.poll(); + if (next > 1) { + temp.add(next - 1); + } + } + + count++; + + if (pq.isEmpty() && temp.isEmpty()) break; + } + + for (int rem: temp) pq.offer(rem); + } + + return count; + } + + @Test + public void test() { + assertEquals(8, leastInterval(new char[] {'A','A','A','B','B','B'}, 2)); + assertEquals(16, leastInterval(new char[] {'A','A','A','A','A','A','B','C','D','E','F','G'}, 2)); + } +} From ebcccd1fb06a2a60e10c649d6747e963be1f049f Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 15 Feb 2020 21:57:08 -0600 Subject: [PATCH 185/189] Added solution for custom sorting string --- .../algorithm/leetcode/CustomSortString.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CustomSortString.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CustomSortString.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CustomSortString.java new file mode 100644 index 0000000..69c69b7 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/CustomSortString.java @@ -0,0 +1,47 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * https://leetcode.com/problems/custom-sort-string/ + */ +public class CustomSortString { + public String customSortString(String S, String T) { + // count[char] = the number of occurrences of 'char' in T. + // This is offset so that count[0] = occurrences of 'a', etc. + // 'count' represents the current state of characters + // (with multiplicity) we need to write to our answer. + int[] count = new int[26]; + for (char c: T.toCharArray()) + count[c - 'a']++; + + // ans will be our final answer. We use StringBuilder to join + // the answer so that we more efficiently calculate a + // concatenation of strings. + StringBuilder ans = new StringBuilder(); + + // Write all characters that occur in S, in the order of S. + for (char c: S.toCharArray()) { + for (int i = 0; i < count[c - 'a']; ++i) + ans.append(c); + // Setting count[char] to zero to denote that we do + // not need to write 'char' into our answer anymore. + count[c - 'a'] = 0; + } + + // Write all remaining characters that don't occur in S. + // That information is specified by 'count'. + for (char c = 'a'; c <= 'z'; ++c) + for (int i = 0; i < count[c - 'a']; ++i) + ans.append(c); + + return ans.toString(); + } + + @Test + public void test() { + assertEquals("cbad", customSortString("cba", "abcd")); + } +} From 94f8372dedff12ac73e15d98ab6699bd46eae4fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 22:53:29 +0000 Subject: [PATCH 186/189] Bump junit from 4.12 to 4.13.1 Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 10f4609..57c82d5 100644 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,7 @@ junit junit - 4.12 + 4.13.1 From 516fc7e727ef1d6641961094240facd41b3ddb0a Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 14 Nov 2020 11:02:22 -0600 Subject: [PATCH 187/189] Added O(1) solution for populating next pointer in perfect binary tree --- pom.xml | 3 +- .../algorithm/trees/PopulateNextRight.java | 82 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/trees/PopulateNextRight.java diff --git a/pom.xml b/pom.xml index 10f4609..c828cf0 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,8 @@ org.projectlombok lombok - 1.16.8 + 1.18.12 + provided diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/trees/PopulateNextRight.java b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PopulateNextRight.java new file mode 100644 index 0000000..3718273 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/trees/PopulateNextRight.java @@ -0,0 +1,82 @@ +package com.eprogrammerz.examples.algorithm.trees; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +/** + * You are given a perfect binary tree where all leaves are on the same level, + * and every parent has two children. The binary tree has the following definition: + * struct Node { + * int val; + * Node *left; + * Node *right; + * Node *next; + * } + * + * https://leetcode.com/problems/populating-next-right-pointers-in-each-node/ + */ +public class PopulateNextRight { + public Node connect(Node root) { + Node curr = root; + + while (curr != null && curr.left != null) { + Node runner = curr.left; + Node temp = runner; + Node prev = null; + + while (curr != null) { + runner = curr.left; + if (prev != null) { + prev.next = runner; + } + + runner.next = curr.right; + runner = runner.next; + prev = runner; + curr = curr.next; + } + + curr = temp; + } + + return root; + } + + @Test + public void test() { + Node root = new Node(1); + root.left = new Node(2); + root.right = new Node(3); + root.left.left = new Node(4); + root.left.right = new Node(5); + root.right.left = new Node(6); + root.right.right = new Node(7); + + Node populated = connect(root); + + assertEquals(3, populated.left.next.val); + assertEquals(6, populated.left.right.next.val); + } + + static class Node { + public int val; + public Node left; + public Node right; + public Node next; + + public Node() {} + + public Node(int _val) { + val = _val; + } + + public Node(int _val, Node _left, Node _right, Node _next) { + val = _val; + left = _left; + right = _right; + next = _next; + } + } +} From 86799b2de7a5f2187a95130be12b7b1e7fda1385 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 3 Apr 2021 14:38:24 -0500 Subject: [PATCH 188/189] Add example to determine if array product is negative, positive or zero --- .../algorithm/leetcode/Multiplication.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Multiplication.java diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Multiplication.java b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Multiplication.java new file mode 100644 index 0000000..2d17fbd --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/leetcode/Multiplication.java @@ -0,0 +1,25 @@ +package com.eprogrammerz.examples.algorithm.leetcode; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +// Return 1 if multiplication is +ve, -1 if negative and 0 if 0 +public class Multiplication { + public int solution(int[] A) { + int neg = 0; + for (int a : A) { + if (a < 0) neg++; + if (a == 0) return 0; + } + + return neg % 2 == 0 ? 1 : -1; + } + + @Test + public void test() { + assertEquals(1, solution(new int[]{-1,2,3,-1})); + assertEquals(-1, solution(new int[]{-1,2,3,-1,-2})); + assertEquals(0, solution(new int[]{-1,2,3,-1,-2,0})); + } +} From 9b7c9b6008206d3d094c503ce0a57aba88f99480 Mon Sep 17 00:00:00 2001 From: Yogen Rai Date: Sat, 8 May 2021 09:59:55 -0500 Subject: [PATCH 189/189] Added solution for Anadrome - Anagram of Palindrome --- pom.xml | 14 ++++++-- .../examples/algorithm/general/Anadrome.java | 34 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/eprogrammerz/examples/algorithm/general/Anadrome.java diff --git a/pom.xml b/pom.xml index 5f4acee..30891ae 100644 --- a/pom.xml +++ b/pom.xml @@ -12,8 +12,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.8 - 1.8 + 11 + 11 @@ -134,6 +134,16 @@ 2.1 test + + org.apache.beam + beam-sdks-java-harness + 2.22.0 + + + com.fasterxml.jackson.core + jackson-databind + 2.12.3 + diff --git a/src/main/java/com/eprogrammerz/examples/algorithm/general/Anadrome.java b/src/main/java/com/eprogrammerz/examples/algorithm/general/Anadrome.java new file mode 100644 index 0000000..a153640 --- /dev/null +++ b/src/main/java/com/eprogrammerz/examples/algorithm/general/Anadrome.java @@ -0,0 +1,34 @@ +package com.eprogrammerz.examples.algorithm.general; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Return number of character to be added to make a given string 'word' a anagram of palindrome. + */ +public class Anadrome { + public int changeToAnadrome(String word) { + int[] map = new int[128]; + int n = word.length(); + for (int i = 0; i < n; i++) { + map[word.charAt(i)]++; + } + + int odds = 0; + + for (int count: map) { + if (count % 2 != 0) odds++; + } + + if (odds == 0) return 0; + return odds - 1; + } + + @Test + public void test() { + assertEquals(1, changeToAnadrome("abcb")); + assertEquals(2, changeToAnadrome("abc")); + assertEquals(0, changeToAnadrome("tatoo")); + } +}