diff --git a/Concurrency/Building H2O.java b/Concurrency/Building H2O.java new file mode 100644 index 00000000..04fda0bc --- /dev/null +++ b/Concurrency/Building H2O.java @@ -0,0 +1,24 @@ +class H2O { + + private Semaphore hydrogenSemaphore; + private Semaphore oxygenSemaphore; + + public H2O() { + this.hydrogenSemaphore = new Semaphore(2); + this.oxygenSemaphore = new Semaphore(0); + } + + public void hydrogen(Runnable releaseHydrogen) throws InterruptedException { + hydrogenSemaphore.acquire(); + // releaseHydrogen.run() outputs "H". Do not change or remove this line. + releaseHydrogen.run(); + this.oxygenSemaphore.release(); + } + + public void oxygen(Runnable releaseOxygen) throws InterruptedException { + this.oxygenSemaphore.acquire(2); + // releaseOxygen.run() outputs "O". Do not change or remove this line. + releaseOxygen.run(); + this.hydrogenSemaphore.release(2); + } +} diff --git a/Concurrency/Design Bounded Blocking Queue.java b/Concurrency/Design Bounded Blocking Queue.java new file mode 100644 index 00000000..a8e0a3d2 --- /dev/null +++ b/Concurrency/Design Bounded Blocking Queue.java @@ -0,0 +1,42 @@ +class BoundedBlockingQueue { + + private final Queue queue; + private final Semaphore mutex; + private final Semaphore items; + private final Semaphore capacityTracker; + private int currentCapacity; + + public BoundedBlockingQueue(int capacity) { + this.queue = new LinkedList<>(); + this.mutex = new Semaphore(1); + this.items = new Semaphore(0); + this.capacityTracker = new Semaphore(capacity); + this.currentCapacity = 0; + } + + public void enqueue(int element) throws InterruptedException { + this.capacityTracker.acquire(); + this.mutex.acquire(); + this.queue.add(element); + this.currentCapacity++; + this.mutex.release(); + this.items.release(); + } + + public int dequeue() throws InterruptedException { + this.items.acquire(); + this.mutex.acquire(); + int result = this.queue.remove(); + this.currentCapacity--; + this.mutex.release(); + this.capacityTracker.release(); + return result; + } + + public int size() throws InterruptedException { + this.mutex.acquire(); + int currentSize = this.currentCapacity; + this.mutex.release(); + return currentSize; + } +} diff --git a/Concurrency/Fizz Buzz Multithreaded.java b/Concurrency/Fizz Buzz Multithreaded.java new file mode 100644 index 00000000..b749ba25 --- /dev/null +++ b/Concurrency/Fizz Buzz Multithreaded.java @@ -0,0 +1,71 @@ +class FizzBuzz { + private int n; + private final Semaphore fizzSemaphore; + private final Semaphore buzzSemaphore; + private final Semaphore fizzBuzzSemaphore; + private final Semaphore numSemaphore; + + public FizzBuzz(int n) { + this.n = n; + this.fizzSemaphore = new Semaphore(0); + this.buzzSemaphore = new Semaphore(0); + this.fizzBuzzSemaphore = new Semaphore(0); + this.numSemaphore = new Semaphore(1); + } + + // printFizz.run() outputs "fizz". + public void fizz(Runnable printFizz) throws InterruptedException { + for (int i = 1; i <= n; i++) { + if (i % 3 == 0 && i % 5 != 0) { + fizzSemaphore.acquire(); + printFizz.run(); + releaseLock(i + 1); + } + } + } + + // printBuzz.run() outputs "buzz". + public void buzz(Runnable printBuzz) throws InterruptedException { + for (int i = 1; i <= n; i++) { + if (i % 3 != 0 && i % 5 == 0) { + buzzSemaphore.acquire(); + printBuzz.run(); + releaseLock(i + 1); + } + } + } + + // printFizzBuzz.run() outputs "fizzbuzz". + public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException { + for (int i = 1; i <= n; i++) { + if (i % 3 == 0 && i % 5 == 0) { + fizzBuzzSemaphore.acquire(); + printFizzBuzz.run(); + releaseLock(i + 1); + } + } + } + + // printNumber.accept(x) outputs "x", where x is an integer. + public void number(IntConsumer printNumber) throws InterruptedException { + for (int i = 1; i <= n; i++) { + if (i % 3 != 0 && i % 5 != 0) { + numSemaphore.acquire(); + printNumber.accept(i); + releaseLock(i + 1); + } + } + } + + private void releaseLock(int num) { + if (num % 3 == 0 && num % 5 == 0) { + fizzBuzzSemaphore.release(); + } else if (num % 3 == 0 && num % 5 != 0) { + fizzSemaphore.release(); + } else if (num % 3 != 0 && num % 5 == 0) { + buzzSemaphore.release(); + } else { + numSemaphore.release(); + } + } +} diff --git a/Concurrency/Print FooBar Alternately.java b/Concurrency/Print FooBar Alternately.java new file mode 100644 index 00000000..94fa19cc --- /dev/null +++ b/Concurrency/Print FooBar Alternately.java @@ -0,0 +1,33 @@ +class FooBar { + private int n; + + private final Semaphore fooMutex; + private final Semaphore barMutex; + + public FooBar(int n) { + this.n = n; + this.fooMutex = new Semaphore(1); + this.barMutex = new Semaphore(0); + } + + public void foo(Runnable printFoo) throws InterruptedException { + + for (int i = 0; i < n; i++) { + + // printFoo.run() outputs "foo". Do not change or remove this line. + this.fooMutex.acquire(); + printFoo.run(); + this.barMutex.release(); + } + } + + public void bar(Runnable printBar) throws InterruptedException { + + for (int i = 0; i < n; i++) { + this.barMutex.acquire(); + // printBar.run() outputs "bar". Do not change or remove this line. + printBar.run(); + this.fooMutex.release(); + } + } +} diff --git a/Concurrency/Print Zero Even Odd.java b/Concurrency/Print Zero Even Odd.java new file mode 100644 index 00000000..784b7fd7 --- /dev/null +++ b/Concurrency/Print Zero Even Odd.java @@ -0,0 +1,43 @@ +class ZeroEvenOdd { + private int n; + + private final Semaphore zeroMutex; + private final Semaphore oddMutex; + private final Semaphore evenMutex; + + public ZeroEvenOdd(int n) { + this.n = n; + this.zeroMutex = new Semaphore(1); + this.oddMutex = new Semaphore(0); + this.evenMutex = new Semaphore(0); + } + + // printNumber.accept(x) outputs "x", where x is an integer. + public void zero(IntConsumer printNumber) throws InterruptedException { + for (int i = 0; i < n; i++) { + this.zeroMutex.acquire(); + printNumber.accept(0); + if (i % 2 == 0) { + this.oddMutex.release(); + } else { + this.evenMutex.release(); + } + } + } + + public void even(IntConsumer printNumber) throws InterruptedException { + for (int i = 2; i <= n; i += 2) { + this.evenMutex.acquire(); + printNumber.accept(i); + this.zeroMutex.release(); + } + } + + public void odd(IntConsumer printNumber) throws InterruptedException { + for (int i = 1; i <= n; i += 2) { + this.oddMutex.acquire(); + printNumber.accept(i); + this.zeroMutex.release(); + } + } +} diff --git a/Concurrency/Print in Order.java b/Concurrency/Print in Order.java new file mode 100644 index 00000000..f9de39ff --- /dev/null +++ b/Concurrency/Print in Order.java @@ -0,0 +1,44 @@ +import java.util.concurrent.atomic.AtomicInteger; + +class Foo { + + private Object lock; + private AtomicInteger counter; + + public Foo() { + this.lock = new Object(); + this.counter = new AtomicInteger(0); + } + + public void first(Runnable printFirst) throws InterruptedException { + + // printFirst.run() outputs "first". Do not change or remove this line. + synchronized (lock) { + printFirst.run(); + this.counter.incrementAndGet(); + this.lock.notifyAll(); + } + } + + public void second(Runnable printSecond) throws InterruptedException { + // printSecond.run() outputs "second". Do not change or remove this line. + synchronized (lock) { + while (this.counter.get() != 1) { + this.lock.wait(); + } + printSecond.run(); + this.counter.incrementAndGet(); + this.lock.notifyAll(); + } + } + + public void third(Runnable printThird) throws InterruptedException { + // printThird.run() outputs "third". Do not change or remove this line. + synchronized (lock) { + while (this.counter.get() != 2) { + this.lock.wait(); + } + printThird.run(); + } + } +} diff --git a/Concurrency/README.md b/Concurrency/README.md new file mode 100644 index 00000000..8bc6ef63 --- /dev/null +++ b/Concurrency/README.md @@ -0,0 +1,11 @@ +# Concurrency LeetCode Java Solutions +S.no | Coding Problem +--- | --- +1 | [Building H2O](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Building%20H2O.java) +2 | [Design Bounded Blocking Queue](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Design%20Bounded%20Blocking%20Queue.java) +3 | [Fizz Buzz Multithreaded](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Fizz%20Buzz%20Multithreaded.java) +4 | [Print FooBar Alternately](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Print%20FooBar%20Alternately.java) +5 | [Print Zero Even Odd](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Print%20Zero%20Even%20Odd.java) +6 | [Print in Order](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Print%20in%20Order.java) +7 | [The Dining Philosophers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/The%20Dining%20Philosophers.java) +8 | [Traffic Light Controlled Intersection](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Concurrency/Traffic%20Light%20Controlled%20Intersection.java) diff --git a/Concurrency/The Dining Philosophers.java b/Concurrency/The Dining Philosophers.java new file mode 100644 index 00000000..01409d64 --- /dev/null +++ b/Concurrency/The Dining Philosophers.java @@ -0,0 +1,51 @@ +class DiningPhilosophers { + + private List forks; + private Semaphore dinersOnTable; + private List state; + + public DiningPhilosophers() { + this.forks = new ArrayList<>(); + this.state = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + this.forks.add(new Semaphore(1)); + this.state.add("idle"); + } + this.dinersOnTable = new Semaphore(4); + } + + // call the run() method of any runnable to execute its code + public void wantsToEat(int philosopher, + Runnable pickLeftFork, + Runnable pickRightFork, + Runnable eat, + Runnable putLeftFork, + Runnable putRightFork) throws InterruptedException { + int leftForkIdx = philosopher; + int rightForkIdx = (philosopher + 4) % 5; + + this.dinersOnTable.acquire(); + if (this.state.get(philosopher).equals("eating")) { + this.dinersOnTable.release(); + return; + } + this.state.set(philosopher, "eating"); + pickFork(leftForkIdx, pickLeftFork); + pickFork(rightForkIdx, pickRightFork); + eat.run(); + putFork(rightForkIdx, putRightFork); + putFork(leftForkIdx, putLeftFork); + this.state.set(philosopher, "idle"); + this.dinersOnTable.release(); + } + + private void putFork(int idx, Runnable put) { + put.run(); + this.forks.get(idx).release(); + } + + private void pickFork(int idx, Runnable pick) throws InterruptedException { + this.forks.get(idx).acquire(); + pick.run(); + } +} diff --git a/Concurrency/Traffic Light Controlled Intersection.java b/Concurrency/Traffic Light Controlled Intersection.java new file mode 100644 index 00000000..3328a2e8 --- /dev/null +++ b/Concurrency/Traffic Light Controlled Intersection.java @@ -0,0 +1,26 @@ +class TrafficLight { + + private boolean greenOnRoadA; + private ReentrantLock lock; + + public TrafficLight() { + this.greenOnRoadA = true; + this.lock = new ReentrantLock(); + } + + public void carArrived( + int carId, // ID of the car + int roadId, // ID of the road the car travels on. Can be 1 (road A) or 2 (road B) + int direction, // Direction of the car + Runnable turnGreen, // Use turnGreen.run() to turn light to green on current road + Runnable crossCar // Use crossCar.run() to make car cross the intersection + ) { + this.lock.lock(); + if(greenOnRoadA && roadId==2 || !greenOnRoadA && roadId==1){ + greenOnRoadA = !greenOnRoadA; + turnGreen.run(); + } + crossCar.run(); + this.lock.unlock(); + } +} diff --git a/Concurrency/Web Crawler Multithreaded.java b/Concurrency/Web Crawler Multithreaded.java new file mode 100644 index 00000000..bb48616c --- /dev/null +++ b/Concurrency/Web Crawler Multithreaded.java @@ -0,0 +1,108 @@ +/** + * // This is the HtmlParser's API interface. + * // You should not implement it, or speculate about its implementation + * interface HtmlParser { + * public List getUrls(String url) {} + * } + */ +import java.net.URI; +import java.net.URISyntaxException; + + +class Solution { + public List crawl(String startUrl, HtmlParser htmlParser) { + ResultRecord resultRecord = new ResultRecord(); + CrawlTask task = new CrawlTask( + startUrl, htmlParser, resultRecord, UrlUtil.parseHostname(startUrl)); + try { + task.start(); + task.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return resultRecord.getResultList(); + } +} + +class CrawlTask extends Thread { + + private final String url; + private final HtmlParser htmlParser; + private final ResultRecord resultRecord; + private final String parentHost; + + public CrawlTask(String url, + HtmlParser htmlParser, + ResultRecord resultRecord, + String parentHost) { + this.url = url; + this.htmlParser = htmlParser; + this.resultRecord = resultRecord; + this.parentHost = parentHost; + } + + public void run() { + String hostname = UrlUtil.parseHostname(url); + if (!hostname.equals(parentHost)) { + return; + } + if (resultRecord.addIfNotExists(url)) { + List childUrls = htmlParser.getUrls(url); + List tasks = new ArrayList<>(); + for (String childUrl : childUrls) { + tasks.add(new CrawlTask( + childUrl, htmlParser, resultRecord, parentHost)); + } + try { + for (CrawlTask task : tasks) { + task.start(); + } + for (CrawlTask task : tasks) { + task.join(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} + +class UrlUtil { + + public static String parseHostname(String url) { + try { + URI uri = new URI(url); + return uri.getHost(); + } catch(URISyntaxException e) { + e.printStackTrace(); + } + return null; + } +} + +class ResultRecord { + + private Set urls; + private Semaphore mutex; + + public ResultRecord() { + this.urls = new HashSet<>(); + this.mutex = new Semaphore(1); + } + + public boolean addIfNotExists(String url) { + try { + this.mutex.acquire(); + boolean added = this.urls.add(url); + this.mutex.release(); + return added; + } catch (InterruptedException e) { + e.printStackTrace(); + } + return false; + } + + public List getResultList() { + return new ArrayList<>(urls); + } +} diff --git a/Contests/Weekly Contest 102/Fruits Into Basket.java b/Contests/Weekly Contest 102/Fruits Into Basket.java deleted file mode 100644 index 6d509ca1..00000000 --- a/Contests/Weekly Contest 102/Fruits Into Basket.java +++ /dev/null @@ -1,34 +0,0 @@ -class Solution { - public static int totalFruit(int[] tree) { - int maxFruits = Integer.MIN_VALUE; - int count = 0; - Map map = new HashMap<>(); - int start = 0; - - for (int num : tree) { - if (map.size() < 2 || map.containsKey(num)) { - map.put(num, map.getOrDefault(num, 0) + 1); - count++; - } - else { - map.put(num, map.getOrDefault(num, 0) + 1); - count++; - - while (true) { - int key = tree[start++]; - map.put(key, map.get(key)-1); - count--; - - if (map.get(key) == 0) { - map.remove(key); - break; - } - } - } - - maxFruits = Math.max(maxFruits, count); - } - - return Math.max(count, maxFruits); - } -} diff --git a/Contests/Weekly Contest 102/Sort Array By Parity.java b/Contests/Weekly Contest 102/Sort Array By Parity.java deleted file mode 100644 index 96bf6ca0..00000000 --- a/Contests/Weekly Contest 102/Sort Array By Parity.java +++ /dev/null @@ -1,28 +0,0 @@ -class Solution { - public static int[] sortArrayByParity(int[] A) { - List even = new ArrayList<>(); - List odd = new ArrayList<>(); - - - for (int num : A) { - if (num%2 == 0) { - even.add(num); - } - else { - odd.add(num); - } - } - - int i = 0; - - for (int num : even) { - A[i++] = num; - } - - for (int num : odd) { - A[i++] = num; - } - - return A; - } -} diff --git a/Contests/Weekly Contest 102/Sum of Subarray Minimums.java b/Contests/Weekly Contest 102/Sum of Subarray Minimums.java deleted file mode 100644 index 5126978f..00000000 --- a/Contests/Weekly Contest 102/Sum of Subarray Minimums.java +++ /dev/null @@ -1,32 +0,0 @@ -class Solution { - public static int sumSubarrayMins(int[] A) { - Stack> stack = new Stack<>(); - int n = A.length; - int tempSum = 0; - int mod = 1000000007; - int ans = 0; - - for (int i = 0; i < n; i++) { - if((!stack.empty()) && A[i] >= stack.peek().get(0)) { - tempSum += A[i]; - stack.push(Arrays.asList(A[i], 1)); - } - else { - int count = 1; - - while((!stack.empty()) && stack.peek().get(0) > A[i]) { - count += stack.peek().get(1); - tempSum -= stack.peek().get(1) * stack.peek().get(0); - stack.pop(); - } - - stack.push(Arrays.asList(A[i], count)); - tempSum += count * A[i]; - } - - ans = (ans + tempSum)%mod; - } - - return ans; - } -} diff --git a/Contests/Weekly Contest 103/Online Election.java b/Contests/Weekly Contest 103/Online Election.java deleted file mode 100644 index 86ed54fa..00000000 --- a/Contests/Weekly Contest 103/Online Election.java +++ /dev/null @@ -1,46 +0,0 @@ -class TopVotedCandidate { - int[] times; - int[] persons; - int[] winner; - - public TopVotedCandidate(int[] persons, int[] times) { - this.times = times; - this.persons = persons; - int[] counter = new int[persons.length+1]; - winner = new int[times.length]; - int max = Integer.MIN_VALUE; - int maxPerson = -1; - int i = 0; - - while (i < times.length) { - counter[persons[i]]++; - if (max < counter[persons[i]]) { - max = counter[persons[i]]; - maxPerson = persons[i]; - } - else if (max == counter[persons[i]]) { - maxPerson = persons[i]; - } - - winner[i] = maxPerson; - - i++; - } - } - - public int q(int t) { - int i = 0; - while (i < times.length && times[i] <= t) { - i++; - } - - return winner[i-1]; - } -} - - -/** - * Your TopVotedCandidate object will be instantiated and called as such: - * TopVotedCandidate obj = new TopVotedCandidate(persons, times); - * int param_1 = obj.q(t); - */ diff --git a/Contests/Weekly Contest 103/Smallest Range I.java b/Contests/Weekly Contest 103/Smallest Range I.java deleted file mode 100644 index b93686ed..00000000 --- a/Contests/Weekly Contest 103/Smallest Range I.java +++ /dev/null @@ -1,7 +0,0 @@ -class Solution { - - public static int smallestRangeI(int[] A, int K) { - Arrays.sort(A); - return Math.max((A[A.length-1] - K) - (A[0] + K), 0); - } -} diff --git a/Contests/Weekly Contest 103/Smallest Range II.java b/Contests/Weekly Contest 103/Smallest Range II.java deleted file mode 100644 index 2ad7c801..00000000 --- a/Contests/Weekly Contest 103/Smallest Range II.java +++ /dev/null @@ -1,16 +0,0 @@ -class Solution { - public int smallestRangeII(int[] A, int K) { - int N = A.length; - Arrays.sort(A); - int ans = A[N-1] - A[0]; - - for (int i=0; i=0; i--) { - minVal = Math.min(minVal, A[i]); - min[i] = minVal; - } - - int[] max = new int[A.length]; - int maxVal = Integer.MIN_VALUE; - - for (int i=0; i wordSubsets(String[] A, String[] B) { - Map> map1 = getMap(A); - - Map map2 = new HashMap<>(); - for (String s : B) { - Map temp = new HashMap<>(); - char[] tempChar = s.toCharArray(); - - for (char c : tempChar) { - temp.put(c, temp.getOrDefault(c, 0) + 1); - } - - for (Map.Entry entry : temp.entrySet()) { - int val1 = entry.getValue(); - int val2 = map2.getOrDefault(entry.getKey(), 0); - - map2.put(entry.getKey(), Math.max(val1, val2)); - } - } - - List ans = new ArrayList<>(); - - for (String s : A) { - boolean flag = true; - Map temp2 = map1.get(s); - - for (Map.Entry entry : map2.entrySet()) { - if (!(temp2.containsKey(entry.getKey()) && temp2.get(entry.getKey()) >= entry.getValue())) { - flag = false; - break; - } - } - - if (flag) { - ans.add(s); - } - } - - return ans; - } - - private static Map> getMap(String[] A) { - Map> map = new HashMap<>(); - - for (String a : A) { - char[] arr = a.toCharArray(); - Map charMap = new HashMap<>(); - for (char c : arr) { - charMap.put(c, charMap.getOrDefault(c, 0) + 1); - } - - map.put(a, charMap); - } - - return map; - } -} diff --git a/Contests/Weekly Contest 104/X of a Kind in a Deck of Cards.java b/Contests/Weekly Contest 104/X of a Kind in a Deck of Cards.java deleted file mode 100644 index 327fc563..00000000 --- a/Contests/Weekly Contest 104/X of a Kind in a Deck of Cards.java +++ /dev/null @@ -1,47 +0,0 @@ -class Solution { - public static boolean hasGroupsSizeX(int[] deck) { - Map map = new HashMap<>(); - - for (int card: deck) { - map.put(card, map.getOrDefault(card, 0) + 1); - } - - int X = -1; - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() < 2) { - return false; - } - - if (X == -1) { - X = entry.getValue(); - } - else { - X = findGCD(X, entry.getValue()); - } - } - - if (X == 1) { - return false; - } - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() % X != 0) { - return false; - } - } - - return true; - } - - private static int findGCD(int n1, int n2) { - while(n1 != n2) { - if(n1 > n2) - n1 -= n2; - else - n2 -= n1; - } - - return n1; - } -} diff --git a/Contests/Weekly Contest 105/Maximum Sum Circular Subarray.java b/Contests/Weekly Contest 105/Maximum Sum Circular Subarray.java deleted file mode 100644 index bdc17368..00000000 --- a/Contests/Weekly Contest 105/Maximum Sum Circular Subarray.java +++ /dev/null @@ -1,28 +0,0 @@ -class Solution { - public static int maxSubarraySumCircular(int[] A) { - int max = kadane(A); - int wrap = 0; - - for(int i=0; i < A.length; i++) { - wrap = wrap+A[i]; - A[i] *= -1; - } - - wrap = wrap + kadane(A); - - return Math.abs(wrap) < Math.abs(max) ? max : wrap; - } - - - private static int kadane(int[] a){ - int maxSoFar=a[0]; - int maxGlobal =a[0]; - - for(int i=1; i map = new HashMap<>(); - for (int i=start; i open = new Stack<>(); - int count = 0; - - for (char c : S.toCharArray()) { - if (c == '(') { - open.push(c); - } - else { - if (open.empty()) { - count++; - } - else { - open.pop(); - } - } - } - - count += open.size(); - - return count; - } -} diff --git a/Contests/Weekly Contest 106/Sort Array By Parity II.java b/Contests/Weekly Contest 106/Sort Array By Parity II.java deleted file mode 100644 index 1289a2e4..00000000 --- a/Contests/Weekly Contest 106/Sort Array By Parity II.java +++ /dev/null @@ -1,35 +0,0 @@ -class Solution { - public int[] sortArrayByParityII(int[] A) { - int[] ans = new int[A.length]; - int[] odd = new int[A.length/2]; - int[] even = new int[A.length/2]; - - int i = 0; - int j = 0; - int k = 0; - - while (k < A.length) { - if (A[k]%2 == 0) { - even[j++] = A[k++]; - } - else { - odd[i++] = A[k++]; - } - } - - i = 0; - j = 0; - k = 0; - - while (k < ans.length) { - if (k%2 == 0) { - ans[k++] = even[j++]; - } - else { - ans[k++] = odd[i++]; - } - } - - return ans; - } -} diff --git a/Contests/Weekly Contest 107/Flip String to Monotone Increasing.java b/Contests/Weekly Contest 107/Flip String to Monotone Increasing.java deleted file mode 100644 index 6f98ab13..00000000 --- a/Contests/Weekly Contest 107/Flip String to Monotone Increasing.java +++ /dev/null @@ -1,27 +0,0 @@ -class Solution { - public static int minFlipsMonoIncr(String S) { - int zeroCount = 0; - int flipCount = 0; - int oneCount = 0; - - for (char c : S.toCharArray()) { - if (c == '0') { - if (oneCount == 0) { - continue; - } - else { - flipCount++; - } - } - else { - oneCount++; - } - - if (flipCount > oneCount) { - flipCount = oneCount; - } - } - - return flipCount; - } -} diff --git a/Contests/Weekly Contest 107/Long Pressed Name.java b/Contests/Weekly Contest 107/Long Pressed Name.java deleted file mode 100644 index 5bf9065a..00000000 --- a/Contests/Weekly Contest 107/Long Pressed Name.java +++ /dev/null @@ -1,29 +0,0 @@ -class Solution { - public static boolean isLongPressedName(String name, String typed) { - int slow = 0; - int fast = 0; - - while (slow < name.length() && fast < typed.length()) { - if (name.charAt(slow) == typed.charAt(fast)) { - slow++; - fast++; - } - else if (fast > 0 && typed.charAt(fast) == typed.charAt(fast-1)) { - fast++; - } - else { - return false; - } - } - - while (fast < typed.length()) { - if (typed.charAt(fast) != typed.charAt(fast-1)) { - return false; - } - - fast++; - } - - return slow == name.length(); - } -} diff --git a/Contests/Weekly Contest 108/Binary Subarrays With Sum.java b/Contests/Weekly Contest 108/Binary Subarrays With Sum.java deleted file mode 100644 index 37cc0a30..00000000 --- a/Contests/Weekly Contest 108/Binary Subarrays With Sum.java +++ /dev/null @@ -1,18 +0,0 @@ -class Solution { - public int numSubarraysWithSum(int[] A, int S) { - Map c = new HashMap<>(); - - c.put(0, 1); - - int psum = 0; - int res = 0; - - for (int i : A) { - psum += i; - res += c.getOrDefault(psum - S, 0); - c.put(psum, c.getOrDefault(psum, 0)+1); - } - - return res; - } -} diff --git a/Contests/Weekly Contest 108/Minimum Falling Path Sum.java b/Contests/Weekly Contest 108/Minimum Falling Path Sum.java deleted file mode 100644 index 056d9501..00000000 --- a/Contests/Weekly Contest 108/Minimum Falling Path Sum.java +++ /dev/null @@ -1,37 +0,0 @@ -class Solution { - public int minFallingPathSum(int[][] A) { - int n = A.length; - int[][] dp = new int[n][n]; - - for (int[] arr : dp) { - Arrays.fill(arr, Integer.MAX_VALUE); - } - - for (int i=0; i= 0) { - dp[i][j] = Math.min(dp[i][j], dp[i-1][j-1]); - } - - if (j+1 < A.length) { - dp[i][j] = Math.min(dp[i][j], dp[i-1][j+1]); - } - - dp[i][j] += A[i][j]; - } - } - } - - int minVal = Integer.MAX_VALUE; - for (int num : dp[n-1]) { - minVal = Math.min(minVal, num); - } - - return minVal; - } -} diff --git a/Contests/Weekly Contest 108/Unique Email Addresses.java b/Contests/Weekly Contest 108/Unique Email Addresses.java deleted file mode 100644 index b234df03..00000000 --- a/Contests/Weekly Contest 108/Unique Email Addresses.java +++ /dev/null @@ -1,20 +0,0 @@ -class Solution { - public int numUniqueEmails(String[] emails) { - Set set = new HashSet<>(); - - for (String email : emails) { - String localName = email.split("@")[0]; - String domainName = email.split("@")[1]; - - localName = localName.replace(".", ""); - int idx = localName.indexOf('+'); - if (idx != -1) { - localName = localName.substring(0, idx); - } - - set.add(localName+"@"+domainName); - } - - return set.size(); - } -} diff --git a/Contests/Weekly Contest 109/Knight Dialer.java b/Contests/Weekly Contest 109/Knight Dialer.java deleted file mode 100644 index 3626b968..00000000 --- a/Contests/Weekly Contest 109/Knight Dialer.java +++ /dev/null @@ -1,25 +0,0 @@ -class Solution { - public int knightDialer(int N) { - int MOD = 1000000007; - long[] counts = new long[10]; - Arrays.fill(counts, 1); - long[] temp; - - for (int i=1; i<=N-1; i++) { - temp = counts.clone(); - - counts[0] = (temp[4] + temp[6]) % MOD; - counts[1] = (temp[6] + temp[8]) % MOD; - counts[2] = (temp[7] + temp[9]) % MOD; - counts[3] = (temp[4] + temp[8]) % MOD; - counts[4] = (temp[3] + temp[9] + temp[0]) % MOD; - counts[5] = 0; - counts[6] = (temp[1] + temp[7] + temp[0]) % MOD; - counts[7] = (temp[2] + temp[6]) % MOD; - counts[8] = (temp[1] + temp[3]) % MOD; - counts[9] = (temp[2] + temp[4]) % MOD; - } - - return (int)(Arrays.stream(counts).sum()%MOD); - } -} diff --git a/Contests/Weekly Contest 109/Number of Recent Calls.java b/Contests/Weekly Contest 109/Number of Recent Calls.java deleted file mode 100644 index 097b56c8..00000000 --- a/Contests/Weekly Contest 109/Number of Recent Calls.java +++ /dev/null @@ -1,23 +0,0 @@ -class RecentCounter { - - Queue queue; - public RecentCounter() { - queue = new LinkedList<>(); - } - - public int ping(int t) { - while (!queue.isEmpty() && t - queue.peek() > 3000) { - queue.remove(); - } - - queue.add(t); - - return queue.size(); - } -} - -/** - * Your RecentCounter object will be instantiated and called as such: - * RecentCounter obj = new RecentCounter(); - * int param_1 = obj.ping(t); - */ diff --git a/Contests/Weekly Contest 110/Distinct Subsequence II.java b/Contests/Weekly Contest 110/Distinct Subsequence II.java deleted file mode 100644 index af605fb7..00000000 --- a/Contests/Weekly Contest 110/Distinct Subsequence II.java +++ /dev/null @@ -1,12 +0,0 @@ -class Solution { - public int distinctSubseqII(String s) { - long[] occurenceIndx = new long[26]; - long MOD = 1000000007; - - for (char c : s.toCharArray()) { - occurenceIndx[c - 'a'] = Arrays.stream(occurenceIndx).sum() % MOD + 1; - } - - return (int) (Arrays.stream(occurenceIndx).sum() % MOD); - } -} diff --git a/Contests/Weekly Contest 110/Minimum Area Rectangle.java b/Contests/Weekly Contest 110/Minimum Area Rectangle.java deleted file mode 100644 index be63eb90..00000000 --- a/Contests/Weekly Contest 110/Minimum Area Rectangle.java +++ /dev/null @@ -1,32 +0,0 @@ -class Solution { - public int minAreaRect(int[][] points) { - Map> rows = new TreeMap<>(); - for (int[] point : points) { - int x = point[0]; - int y = point[1]; - rows.computeIfAbsent(x , z -> new ArrayList<>()).add(y); - } - - int ans = Integer.MAX_VALUE; - Map lastIdx = new HashMap<>(); - for (int key : rows.keySet()) { - List row = rows.get(key); - Collections.sort(row); - - for (int i=0; i= low && root.val <= high) { - sum += root.val; - rangeSumBSTHelper(root.right, low, high); - rangeSumBSTHelper(root.left, low, high); - } - else { - if (root.val < low) { - rangeSumBSTHelper(root.right, low, high); - } - - if (root.val > high) { - rangeSumBSTHelper(root.left, low, high); - } - } - } -} diff --git a/Contests/Weekly Contest 110/Reorder Log Files.java b/Contests/Weekly Contest 110/Reorder Log Files.java deleted file mode 100644 index 6e2d505c..00000000 --- a/Contests/Weekly Contest 110/Reorder Log Files.java +++ /dev/null @@ -1,53 +0,0 @@ -class Solution { - public String[] reorderLogFiles(String[] logs) { - List letterLogs = new ArrayList<>(); - List digitLogs = new ArrayList<>(); - - for (String log : logs) { - if(Character.isDigit(log.split("\\s+")[1].charAt(0))) { - digitLogs.add(log); - } - else { - letterLogs.add(log); - } - } - - Collections.sort(letterLogs, new Comparator() { - @Override - public int compare(String o1, String o2) { - String[] s1 = o1.split("\\s+"); - String[] s2 = o2.split("\\s+"); - - StringBuilder sb1 = new StringBuilder(); - StringBuilder sb2 = new StringBuilder(); - - for (int i=1; i 0 && A[j] < A[j-1]) { - j--; - } - - return i > 0 && i == j && j < n; - } -} diff --git a/Contests/Weekly Contest 112/Bag of Tokens.java b/Contests/Weekly Contest 112/Bag of Tokens.java deleted file mode 100644 index 610c54e4..00000000 --- a/Contests/Weekly Contest 112/Bag of Tokens.java +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { - public int bagOfTokensScore(int[] tokens, int P) { - Arrays.sort(tokens); - int start = 0; - int end = tokens.length - 1; - int numOfPoints = 0; - int maxPoint = 0; - - while (start <= end) { - if (P >= tokens[start]) { - P -= tokens[start]; - start++; - numOfPoints++; - } - else { - if (numOfPoints > 0) { - numOfPoints--; - P += tokens[end]; - end--; - } - else { - break; - } - } - - maxPoint = Math.max(numOfPoints, maxPoint); - } - - return maxPoint; - } -} diff --git a/Contests/Weekly Contest 112/Minimum Increment to Make Array Unique.java b/Contests/Weekly Contest 112/Minimum Increment to Make Array Unique.java deleted file mode 100644 index 983f6d29..00000000 --- a/Contests/Weekly Contest 112/Minimum Increment to Make Array Unique.java +++ /dev/null @@ -1,19 +0,0 @@ -class Solution { - public int minIncrementForUnique(int[] arr) { - int count = 0; - - Arrays.sort(arr); - int previous = Integer.MIN_VALUE; - - for (int i=0; i= arr[i]) { - count += previous - arr[i] == 0 ? 1 : previous + 1 - arr[i]; - arr[i] = previous + 1; - } - - previous = arr[i]; - } - - return count; - } -} diff --git a/Contests/Weekly Contest 112/Most Stones Removed with Same Row or Column.java b/Contests/Weekly Contest 112/Most Stones Removed with Same Row or Column.java deleted file mode 100644 index 916ceeb5..00000000 --- a/Contests/Weekly Contest 112/Most Stones Removed with Same Row or Column.java +++ /dev/null @@ -1,44 +0,0 @@ -class Solution { - public int count = 0; - public int removeStones(int[][] stones) { - Map map = new HashMap<>(); - count = stones.length; - - for (int[] stone : stones) { - String key = stone[0] + " " + stone[1]; - map.put(key, key); - } - - for (int[] stone : stones) { - String key = stone[0] + " " + stone[1]; - for (int[] stone2 : stones) { - if (stone2[0] == stone[0] || stone2[1] == stone[1]) { - String key2 = stone2[0] + " " + stone2[1]; - union(map, key, key2); - } - } - } - - return stones.length - count; - } - - private void union(Map map, String s1, String s2) { - String r1 = find(map, s1); - String r2 = find(map, s2); - - if (r1.equals(r2)) { - return; - } - - map.put(r1, r2); - count--; - } - - private String find(Map map, String s) { - if (!map.get(s).equals(s)) { - map.put(s, find(map, map.get(s))); - } - - return map.get(s); - } -} diff --git a/Contests/Weekly Contest 112/Validate Stack Sequences.java b/Contests/Weekly Contest 112/Validate Stack Sequences.java deleted file mode 100644 index c90d9957..00000000 --- a/Contests/Weekly Contest 112/Validate Stack Sequences.java +++ /dev/null @@ -1,30 +0,0 @@ -class Solution { - public boolean validateStackSequences(int[] pushed, int[] popped) { - Stack stack = new Stack<>(); - - int i = 0; - int j = 0; - - while (i < pushed.length || j < popped.length) { - if (stack.isEmpty() || stack.peek() != popped[j]) { - if (i < pushed.length) { - stack.push(pushed[i++]); - } - else { - return false; - } - } - else { - if (j < popped.length && stack.peek() == popped[j]) { - stack.pop(); - j++; - } - else { - return false; - } - } - } - - return true; - } -} diff --git a/Contests/Weekly Contest 113/Flip Equivalent Binary Trees.java b/Contests/Weekly Contest 113/Flip Equivalent Binary Trees.java deleted file mode 100644 index 9b025770..00000000 --- a/Contests/Weekly Contest 113/Flip Equivalent Binary Trees.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public boolean flipEquiv(TreeNode root1, TreeNode root2) { - if (root1 == null) { - return root2 == null; - } - - if (root2 == null) { - return root1 == null; - } - - if (root1.val != root2.val) { - return false; - } - - return (flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right) || - flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left)); - } -} diff --git a/Contests/Weekly Contest 113/Largest Time for Given Digits.java b/Contests/Weekly Contest 113/Largest Time for Given Digits.java deleted file mode 100644 index 7a645e07..00000000 --- a/Contests/Weekly Contest 113/Largest Time for Given Digits.java +++ /dev/null @@ -1,57 +0,0 @@ -class Solution { - public String largestTimeFromDigits(int[] arr) { - List permutations = permuteUnique(arr); - String maxStr = ""; - - for (String str : permutations) { - if (isValid(str)) { - if (maxStr.length() == 0) { - maxStr = str; - } - else if (maxStr.compareTo(str) < 0) { - maxStr = str; - } - } - } - - return maxStr.length() > 0 ? maxStr.substring(0, 2) + ":" + maxStr.substring(2) : maxStr; - } - - private boolean isValid(String str) { - int left = Integer.parseInt(str.substring(0, 2)); - int right = Integer.parseInt(str.substring(2)); - - return left >= 0 && left <= 23 && right >= 0 && right <= 59; - } - - private List permuteUnique(int[] nums) { - List ans = new ArrayList<>(); - Arrays.sort(nums); - permuteHelper(nums, new ArrayList<>(), ans, new boolean[nums.length]); - return new ArrayList<>(ans); - } - - private void permuteHelper(int[] nums, List list, List ans, boolean[] used) { - if (list.size() == nums.length) { - ans.add(list.stream().map(n -> String.valueOf(n)).collect(Collectors.joining(""))); - } - else { - for (int i=0; i 0 && nums[i] == nums[i-1] && !used[i-1])) { - continue; - } - - used[i] = true; - list.add(nums[i]); - - // Explore - permuteHelper(nums, list, ans, used); - - // Un-choose - used[i] = false; - list.remove(list.size()-1); - } - } - } -} diff --git a/Contests/Weekly Contest 113/Reveal Cards In Increasing Order.java b/Contests/Weekly Contest 113/Reveal Cards In Increasing Order.java deleted file mode 100644 index b2aed465..00000000 --- a/Contests/Weekly Contest 113/Reveal Cards In Increasing Order.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public int[] deckRevealedIncreasing(int[] deck) { - int n = deck.length; - int[] ans = new int[n]; - Deque deque = new LinkedList<>(); - Arrays.sort(deck); - deque.addFirst(deck[n-1]); - - for (int i=n-2; i>=0; i--) { - int temp = deque.removeLast(); - deque.addFirst(temp); - deque.addFirst(deck[i]); - } - - int idx = 0; - while (!deque.isEmpty()) { - ans[idx++] = deque.pollFirst(); - } - - return ans; - } -} diff --git a/Contests/Weekly Contest 115/Check Completeness of a Binary Tree.java b/Contests/Weekly Contest 115/Check Completeness of a Binary Tree.java deleted file mode 100644 index 33573b90..00000000 --- a/Contests/Weekly Contest 115/Check Completeness of a Binary Tree.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public boolean isCompleteTree(TreeNode root) { - if (root == null) { - return true; - } - int numOfNodes = getNumOfNodes(root); - return isCompleteTreeHelper(root, 0, numOfNodes); - } - - private boolean isCompleteTreeHelper(TreeNode root, int curr, int numOfNodes) { - if (root == null) { - return true; - } - - if (curr >= numOfNodes) { - return false; - } - - return isCompleteTreeHelper(root.left, 2 * curr + 1, numOfNodes) && isCompleteTreeHelper(root.right, 2 * curr + 2, numOfNodes); - } - - private int getNumOfNodes(TreeNode root) { - if (root == null) { - return 0; - } - - return 1 + getNumOfNodes(root.left) + getNumOfNodes(root.right); - } -} diff --git a/Contests/Weekly Contest 126/Check If Word Is Valid After Substitutions.java b/Contests/Weekly Contest 126/Check If Word Is Valid After Substitutions.java deleted file mode 100644 index dc030951..00000000 --- a/Contests/Weekly Contest 126/Check If Word Is Valid After Substitutions.java +++ /dev/null @@ -1,21 +0,0 @@ -class Solution { - public boolean isValid(String S) { - Stack stack = new Stack<>(); - for (char c : S.toCharArray()) { - if (c == 'a' || c == 'b') { - stack.push(c); - } - else { - if (stack.isEmpty() || stack.pop() != 'b') { - return false; - } - - if (stack.isEmpty() || stack.pop() != 'a') { - return false; - } - } - } - - return stack.size() == 0; - } -} diff --git a/Contests/Weekly Contest 126/Find Common Characters.java b/Contests/Weekly Contest 126/Find Common Characters.java deleted file mode 100644 index b0fea474..00000000 --- a/Contests/Weekly Contest 126/Find Common Characters.java +++ /dev/null @@ -1,30 +0,0 @@ -class Solution { - public List commonChars(String[] A) { - int[] mainCounter = new int[26]; - Arrays.fill(mainCounter, Integer.MAX_VALUE); - - for (String str : A) { - int[] counter = new int[26]; - for (char c : str.toCharArray()) { - counter[c - 'a']++; - } - - for (int i = 0; i < 26; i++) { - mainCounter[i] = Math.min(mainCounter[i], counter[i]); - } - } - - List list = new ArrayList<>(); - - for (int i = 0; i < 26; i++) { - int count = mainCounter[i]; - char c = (char) (97 + i); - - while (count-- > 0) { - list.add(String.valueOf(c)); - } - } - - return list; - } -} diff --git a/Contests/Weekly Contest 126/Max Consecutive Ones III.java b/Contests/Weekly Contest 126/Max Consecutive Ones III.java deleted file mode 100644 index 49349bd8..00000000 --- a/Contests/Weekly Contest 126/Max Consecutive Ones III.java +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { - public int longestOnes(int[] A, int K) { - int slow = 0; - int fast = 0; - int count = 0; - int end = A.length; - int maxLen = 0; - - while (fast < end) { - if (A[fast] != 1) { - count++; - } - - while (count > K && slow < end) { - if (A[slow] == 0) { - count--; - } - - slow++; - } - - fast++; - - if (fast - slow > maxLen) { - maxLen = fast - slow; - } - } - - return maxLen; - } -} diff --git a/Contests/Weekly Contest 127/Clumsy Factorial.java b/Contests/Weekly Contest 127/Clumsy Factorial.java deleted file mode 100644 index 391ede85..00000000 --- a/Contests/Weekly Contest 127/Clumsy Factorial.java +++ /dev/null @@ -1,59 +0,0 @@ -class Solution { - public int clumsy(int N) { - if (N <= 1) { - return N; - } - - char[] oper = {'*', '/', '+', '-'}; - int idx = 0; - - StringBuilder sb = new StringBuilder(); - while (N > 0) { - sb.append(N).append(" ").append(oper[idx++]).append(" "); - if (idx > 3) { - idx = 0; - } - - N--; - } - - return basicCalculator(sb.toString().substring(0, sb.length() - 2)); - } - - private int basicCalculator(String s) { - int num = 0; - char sign = '+'; - Stack stack = new Stack<>(); - - for (int i = 0; i < s.length(); i++) { - if (Character.isDigit(s.charAt(i))) { - num = num * 10 + Character.getNumericValue(s.charAt(i)); - } - - if (!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ' || i == s.length() - 1) { - if (sign == '+') { - stack.push(num); - } - else if (sign == '-') { - stack.push(-num); - } - else if (sign == '*') { - stack.push(stack.pop() * num); - } - else { - stack.push(stack.pop() / num); - } - - sign = s.charAt(i); - num = 0; - } - } - - int res = 0; - while (!stack.isEmpty()) { - res += stack.pop(); - } - - return res; - } -} diff --git a/Contests/Weekly Contest 127/Construct Binary Search Tree from Preorder Traversal.java b/Contests/Weekly Contest 127/Construct Binary Search Tree from Preorder Traversal.java deleted file mode 100644 index 276ff05d..00000000 --- a/Contests/Weekly Contest 127/Construct Binary Search Tree from Preorder Traversal.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - int idx; - public TreeNode bstFromPreorder(int[] preorder) { - idx = 0; - return bstFromPreorderHelper(preorder, preorder[0], Integer.MIN_VALUE, Integer.MAX_VALUE); - } - - private TreeNode bstFromPreorderHelper(int[] preorder, int key, int min, int max) { - if (idx >= preorder.length) { - return null; - } - - TreeNode root = null; - - if (preorder[idx] > min && preorder[idx] < max) { - root = new TreeNode(key); - idx++; - - if (idx < preorder.length) { - root.left = bstFromPreorderHelper(preorder, preorder[idx], min, key); - - if (idx < preorder.length) { - root.right = bstFromPreorderHelper(preorder, preorder[idx], key, max); - } - } - } - - return root; - } -} diff --git a/Contests/Weekly Contest 127/Maximize Sum Of Array After K Negations.java b/Contests/Weekly Contest 127/Maximize Sum Of Array After K Negations.java deleted file mode 100644 index a4db5a84..00000000 --- a/Contests/Weekly Contest 127/Maximize Sum Of Array After K Negations.java +++ /dev/null @@ -1,23 +0,0 @@ -class Solution { - public int largestSumAfterKNegations(int[] A, int K) { - PriorityQueue pq = new PriorityQueue<>(); - - for (int num : A) { - pq.add(num); - } - - while (K-- > 0) { - int popped = pq.poll(); - popped *= -1; - - pq.add(popped); - } - - int sum = 0; - while (!pq.isEmpty()) { - sum += pq.poll(); - } - - return sum; - } -} diff --git a/Contests/Weekly Contest 127/Minimum Domino Rotations For Equal Row.java b/Contests/Weekly Contest 127/Minimum Domino Rotations For Equal Row.java deleted file mode 100644 index c9908513..00000000 --- a/Contests/Weekly Contest 127/Minimum Domino Rotations For Equal Row.java +++ /dev/null @@ -1,25 +0,0 @@ -class Solution { - public int minDominoRotations(int[] A, int[] B) { - int[] aCount = new int[7]; - int[] bCount = new int[7]; - int[] sameCount = new int[7]; - - for (int i = 0; i < A.length; i++) { - if (A[i] == B[i]) { - sameCount[A[i]]++; - } - else { - aCount[A[i]]++; - bCount[B[i]]++; - } - } - - for (int i = 1; i <= 6; i++) { - if (aCount[i] + bCount[i] + sameCount[i] == A.length) { - return sameCount[i] == A.length ? 0 : Math.min(aCount[i], bCount[i]); - } - } - - return -1; - } -} diff --git a/Contests/Weekly Contest 129/Best Sightseeing Pair.java b/Contests/Weekly Contest 129/Best Sightseeing Pair.java deleted file mode 100644 index 173b530d..00000000 --- a/Contests/Weekly Contest 129/Best Sightseeing Pair.java +++ /dev/null @@ -1,13 +0,0 @@ -class Solution { - public int maxScoreSightseeingPair(int[] A) { - int maxVal = 0; - int currMax = 0; - - for (int spot : A) { - maxVal = Math.max(maxVal, currMax + spot); - currMax = Math.max(spot, currMax) - 1; - } - - return maxVal; - } -} diff --git a/Contests/Weekly Contest 129/Binary String With Substrings Representing 1 To N.java b/Contests/Weekly Contest 129/Binary String With Substrings Representing 1 To N.java deleted file mode 100644 index 179b0ec2..00000000 --- a/Contests/Weekly Contest 129/Binary String With Substrings Representing 1 To N.java +++ /dev/null @@ -1,15 +0,0 @@ -class Solution { - public boolean queryString(String S, int N) { - - int num = N; - while (num >= N / 2) { - if (S.indexOf(Integer.toBinaryString(num)) == -1) { - return false; - } - - num--; - } - - return true; - } -} diff --git a/Contests/Weekly Contest 129/Partition Array Into Three Parts With Equal Sum.java b/Contests/Weekly Contest 129/Partition Array Into Three Parts With Equal Sum.java deleted file mode 100644 index b325e556..00000000 --- a/Contests/Weekly Contest 129/Partition Array Into Three Parts With Equal Sum.java +++ /dev/null @@ -1,30 +0,0 @@ -class Solution { - public boolean canThreePartsEqualSum(int[] A) { - int totalSum = 0; - for (int num : A) { - totalSum += num; - } - - if (totalSum % 3 != 0) { - return false; - } - - int singlePartitionSum = totalSum / 3; - int idx = 0; - int len = A.length; - int currPartitionSum = 0; - int count = 0; - - while (idx < len) { - currPartitionSum += A[idx]; - if (currPartitionSum == singlePartitionSum) { - count++; - currPartitionSum = 0; - } - - idx++; - } - - return count == 3; - } -} diff --git a/Contests/Weekly Contest 129/Smallest Integer Divisible by K.java b/Contests/Weekly Contest 129/Smallest Integer Divisible by K.java deleted file mode 100644 index aba8f5e3..00000000 --- a/Contests/Weekly Contest 129/Smallest Integer Divisible by K.java +++ /dev/null @@ -1,17 +0,0 @@ -class Solution { - public int smallestRepunitDivByK(int K) { - if (K % 2 == 0 || K % 5 == 0) { - return -1; - } - - int rem = 0; - for (int i = 1; i <= K; i++) { - rem = (rem * 10 + 1) % K; - if (rem == 0) { - return i; - } - } - - return -1; - } -} diff --git a/Contests/Weekly Contest 131/Camelcase Matching.java b/Contests/Weekly Contest 131/Camelcase Matching.java deleted file mode 100644 index 2313a4ee..00000000 --- a/Contests/Weekly Contest 131/Camelcase Matching.java +++ /dev/null @@ -1,43 +0,0 @@ -class Solution { - public List camelMatch(String[] queries, String pattern) { - List ans = new ArrayList<>(); - - for (String query : queries) { - ans.add(check(query, pattern)); - } - - return ans; - } - - private boolean check(String query, String pattern) { - int qIdx = 0; - int pIdx = 0; - int qLen = query.length(); - int pLen = pattern.length(); - - while (qIdx < qLen && pIdx < pLen) { - if (query.charAt(qIdx) == pattern.charAt(pIdx)) { - qIdx++; - pIdx++; - } - else { - if (Character.isUpperCase(query.charAt(qIdx))) { - return false; - } - else { - qIdx++; - } - } - } - - while (qIdx < qLen) { - if (Character.isUpperCase(query.charAt(qIdx))) { - return false; - } - - qIdx++; - } - - return pIdx == pLen; - } -} diff --git a/Contests/Weekly Contest 131/Remove Outermost Parentheses.java b/Contests/Weekly Contest 131/Remove Outermost Parentheses.java deleted file mode 100644 index dfff44c7..00000000 --- a/Contests/Weekly Contest 131/Remove Outermost Parentheses.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public String removeOuterParentheses(String S) { - StringBuilder sb = new StringBuilder(); - int count = 0; - int prev = 0; - - for (int i = 0; i < S.length(); i++) { - if (S.charAt(i) == '(') { - count++; - } - else { - count--; - if (count == 0) { - sb.append(S.substring(prev + 1, i)); - prev = i + 1; - } - } - } - - return sb.toString(); - } -} diff --git a/Contests/Weekly Contest 131/Sum of Root To Leaf Binary Numbers.java b/Contests/Weekly Contest 131/Sum of Root To Leaf Binary Numbers.java deleted file mode 100644 index 8b630ccd..00000000 --- a/Contests/Weekly Contest 131/Sum of Root To Leaf Binary Numbers.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public int sumRootToLeaf(TreeNode root) { - return dfsHelper(root, 0); - } - - private int MOD = 1000000007; - - private int dfsHelper(TreeNode root, int curr) { - if (root == null) { - return curr % MOD; - } - - curr = (curr * 2 + root.val) % MOD; - - if (root.left == null && root.right == null) { - return curr % MOD; - } - - int sum = 0; - - if (root.left != null) { - sum += dfsHelper(root.left, curr); - } - - if (root.right != null) { - sum += dfsHelper(root.right, curr); - } - - return sum % MOD; - } -} diff --git a/Contests/Weekly Contest 132/Divisor Game.java b/Contests/Weekly Contest 132/Divisor Game.java deleted file mode 100644 index 8a30b499..00000000 --- a/Contests/Weekly Contest 132/Divisor Game.java +++ /dev/null @@ -1,5 +0,0 @@ -class Solution { - public boolean divisorGame(int N) { - return N % 2 == 0; - } -} diff --git a/Contests/Weekly Contest 132/Longest Arithmetic Sequence.java b/Contests/Weekly Contest 132/Longest Arithmetic Sequence.java deleted file mode 100644 index 15ad247d..00000000 --- a/Contests/Weekly Contest 132/Longest Arithmetic Sequence.java +++ /dev/null @@ -1,35 +0,0 @@ -class Solution { - public int longestArithSeqLength(int[] A) { - if (A.length <= 1) { - return A.length; - } - - int res = 0; - HashMap[] dp = new HashMap[A.length]; - - for (int i = 0; i < A.length; i++) { - dp[i] = new HashMap<>(); - } - - for (int i = 1; i < A.length; i++) { - int curr = A[i]; - for (int j = 0; j < i; j++) { - int prev = A[j]; - int diff = curr - prev; - - int len = 2; - - if (dp[j].containsKey(diff)) { - len = dp[j].get(diff) + 1; - } - - int currLen = dp[i].getOrDefault(diff, 0); - dp[i].put(diff, Math.max(currLen, len)); - - res = Math.max(res, dp[i].get(diff)); - } - } - - return res; - } -} diff --git a/Contests/Weekly Contest 132/Maximum Difference Between Node and Ancestor.java b/Contests/Weekly Contest 132/Maximum Difference Between Node and Ancestor.java deleted file mode 100644 index ea63ea0d..00000000 --- a/Contests/Weekly Contest 132/Maximum Difference Between Node and Ancestor.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public int maxAncestorDiff(TreeNode root) { - return dfs(root, root.val, root.val); - } - - public int dfs(TreeNode root, int min, int max) { - if (root == null) { - return 0; - } - - int res = Math.max(max - root.val, root.val - min); - max = Math.max(root.val, max); - min = Math.min(root.val, min); - - res = Math.max(res, dfs(root.left, min, max)); - res = Math.max(res, dfs(root.right, min, max)); - - return res; - } -} diff --git a/Easy/1-bit and 2-bit Characters.java b/Easy/1-bit and 2-bit Characters.java index 90f44fbf..f58ff16a 100644 --- a/Easy/1-bit and 2-bit Characters.java +++ b/Easy/1-bit and 2-bit Characters.java @@ -1,16 +1,12 @@ class Solution { - public boolean isOneBitCharacter(int[] bits) { - int l = bits.length; - int i = 0; - - while(i= 5) { + purchaseAmount += 10 - purchaseAmount % 10; + } else { + purchaseAmount -= purchaseAmount % 10; + } + return 100 - purchaseAmount; + } +} diff --git a/Easy/Add Binary.java b/Easy/Add Binary.java index 3b4aacda..d35b471f 100644 --- a/Easy/Add Binary.java +++ b/Easy/Add Binary.java @@ -1,45 +1,20 @@ class Solution { - public String addBinary(String a, String b) { - StringBuilder sb = new StringBuilder(); - int carry = 0; - int idx1 = a.length() - 1; - int idx2 = b.length() - 1; - - while (idx1 >= 0 && idx2 >= 0) { - if (a.charAt(idx1) == '1' && b.charAt(idx2) == '1') { - sb.append(carry == 1 ? 1 : 0); - carry = 1; - } - else if (a.charAt(idx1) == '1' || b.charAt(idx2) == '1') { - sb.append(carry == 0 ? 1 : 0); - } - else { - sb.append(carry); - carry = 0; - } - - idx1--; - idx2--; - } - - String remainingString = a.length() > b.length() ? a : b; - int idx = Math.max(idx2, idx1); - while (idx >= 0) { - if (remainingString.charAt(idx) == '1') { - sb.append(carry == 1 ? 0 : 1); - } - else { - sb.append(carry); - carry = 0; - } - - idx--; - } - - if (carry > 0) { - sb.append(carry); - } - - return sb.reverse().toString(); + public String addBinary(String a, String b) { + StringBuilder sb = new StringBuilder(); + int endIdxA = a.length() - 1; + int endIdxB = b.length() - 1; + int carry = 0; + while (endIdxA >= 0 || endIdxB >= 0 || carry > 0) { + int value = carry; + if (endIdxA >= 0) { + value += Character.getNumericValue(a.charAt(endIdxA--)); + } + if (endIdxB >= 0) { + value += Character.getNumericValue(b.charAt(endIdxB--)); + } + sb.append(value % 2); + carry = value / 2; } + return sb.reverse().toString(); + } } diff --git a/Easy/Add Digits.java b/Easy/Add Digits.java new file mode 100644 index 00000000..a17de297 --- /dev/null +++ b/Easy/Add Digits.java @@ -0,0 +1,13 @@ +class Solution { + public int addDigits(int num) { + if (num / 10 == 0) { + return num; + } + int digitSum = 0; + while (num > 0) { + digitSum += num % 10; + num /= 10; + } + return addDigits(digitSum); + } +} diff --git a/Easy/Add Strings.java b/Easy/Add Strings.java index 7f91e6e1..16cf5461 100644 --- a/Easy/Add Strings.java +++ b/Easy/Add Strings.java @@ -1,31 +1,20 @@ class Solution { - public String addStrings(String num1, String num2) { - StringBuilder sb = new StringBuilder(); - int idx1 = num1.length() - 1; - int idx2 = num2.length() - 1; - int carry = 0; - - while (idx1 >= 0 || idx2 >= 0) { - int temp = carry; - if (idx1 >= 0 && idx2 >= 0) { - temp += (num1.charAt(idx1) - '0') + (num2.charAt(idx2) - '0'); - } - else if (idx1 >= 0 && idx2 < 0) { - temp += (num1.charAt(idx1) - '0'); - } - else { - temp += (num2.charAt(idx2) - '0'); - } - - carry = temp > 9 ? temp / 10 : 0; - temp = temp > 9 ? temp % 10 : temp; - sb.append(temp); - idx1--; - idx2--; - } - - sb.append(carry > 0 ? carry : ""); - - return sb.reverse().toString(); + public String addStrings(String num1, String num2) { + int carry = 0; + StringBuilder sb = new StringBuilder(); + int idxOne = num1.length() - 1; + int idxTwo = num2.length() - 1; + while (idxOne >= 0 || idxTwo >= 0 || carry > 0) { + if (idxOne >= 0 && idxTwo >= 0) { + carry += Character.getNumericValue(num1.charAt(idxOne--)) + Character.getNumericValue(num2.charAt(idxTwo--)); + } else if (idxOne >= 0 && idxTwo < 0) { + carry += Character.getNumericValue(num1.charAt(idxOne--)); + } else if (idxOne < 0 && idxTwo >= 0) { + carry += Character.getNumericValue(num2.charAt(idxTwo--)); + } + sb.append(carry % 10); + carry = carry > 9 ? carry / 10 : 0; } + return sb.reverse().toString(); + } } diff --git a/Easy/Add to Array-Form of Integer.java b/Easy/Add to Array-Form of Integer.java index be084446..64cbbb31 100644 --- a/Easy/Add to Array-Form of Integer.java +++ b/Easy/Add to Array-Form of Integer.java @@ -1,58 +1,22 @@ class Solution { - public List addToArrayForm(int[] A, int K) { - int[] kArr = getArray(K); - int len1 = A.length - 1; - int len2 = kArr.length - 1; + public List addToArrayForm(int[] num, int k) { + List result = new ArrayList<>(); + int idx = num.length - 1; int carry = 0; - - List list = new ArrayList<>(); - - while (len1 >= 0 || len2 >= 0) { - int temp = 0; - - if (len1 >= 0 && len2 >= 0) { - temp = A[len1] + kArr[len2] + carry; - len1--; - len2--; + while (idx >= 0 || k > 0 || carry > 0) { + if (idx >= 0 && k > 0) { + carry += num[idx--] + k % 10; + k /= 10; + } else if (idx >= 0 && k == 0) { + carry += num[idx--]; + } else if (idx < 0 && k > 0) { + carry += k % 10; + k /= 10; } - else if (len1 >= 0 && len2 < 0) { - temp = A[len1] + carry; - len1--; - } - else { - temp = kArr[len2] + carry; - len2--; - } - - if (temp > 9) { - carry = temp / 10; - temp %= 10; - } - else { - carry = 0; - } - - list.add(temp); - } - - if (carry > 0) { - list.add(carry); - } - - Collections.reverse(list); - - return list; - } - - private int[] getArray(int k) { - int len = String.valueOf(k).length(); - int[] ans = new int[len]; - - for (int i=len-1; i>=0; i--) { - ans[i] = k % 10; - k /= 10; + result.add(carry % 10); + carry /= 10; } - - return ans; + Collections.reverse(result); + return result; } } diff --git a/Easy/Adjacent Increasing Subarrays Detection I.java b/Easy/Adjacent Increasing Subarrays Detection I.java new file mode 100644 index 00000000..5be82de7 --- /dev/null +++ b/Easy/Adjacent Increasing Subarrays Detection I.java @@ -0,0 +1,20 @@ +class Solution { + public boolean hasIncreasingSubarrays(List nums, int k) { + int n = nums.size(); + for (int i = 0; i <= n - 2 * k; i++) { + if (isStrictlyIncreasing(nums, i, k) && isStrictlyIncreasing(nums, i + k, k)) { + return true; + } + } + return false; + } + + private boolean isStrictlyIncreasing(List nums, int idx, int k) { + for (int start = idx; start < idx + k - 1; start++) { + if (nums.get(start) >= nums.get(start + 1)) { + return false; + } + } + return true; + } +} diff --git a/Easy/Alternating Digit Sum.java b/Easy/Alternating Digit Sum.java new file mode 100644 index 00000000..4505e2e3 --- /dev/null +++ b/Easy/Alternating Digit Sum.java @@ -0,0 +1,18 @@ +class Solution { + public int alternateDigitSum(int n) { + int firstHalf = 0; + int secondHalf = 0; + int count = 0; + while (n > 0) { + secondHalf += n % 10; + n /= 10; + count++; + if (n > 0) { + firstHalf += n % 10; + n /= 10; + count++; + } + } + return count % 2 == 0 ? (firstHalf + -1 * secondHalf) : (secondHalf + -1 * firstHalf); + } +} diff --git a/Easy/Alternating Groups I.java b/Easy/Alternating Groups I.java new file mode 100644 index 00000000..9730d5ea --- /dev/null +++ b/Easy/Alternating Groups I.java @@ -0,0 +1,18 @@ +class Solution { + public int numberOfAlternatingGroups(int[] colors) { + int count = 0; + int n = colors.length; + for (int i = 0; i < n - 2; i++) { + if (colors[i + 1] != colors[i] && colors[i + 1] != colors[i + 2]) { + count++; + } + } + if (colors[n - 2] != colors[n - 1] && colors[n - 2] == colors[0]) { + count++; + } + if (colors[n - 1] != colors[0] && colors[n - 1] == colors[1]) { + count++; + } + return count; + } +} diff --git a/Easy/Ant on the Boundary.java b/Easy/Ant on the Boundary.java new file mode 100644 index 00000000..25e95d0a --- /dev/null +++ b/Easy/Ant on the Boundary.java @@ -0,0 +1,13 @@ +class Solution { + public int returnToBoundaryCount(int[] nums) { + int currPosition = 0; + int count = 0; + for (int num : nums) { + currPosition += num; + if (currPosition == 0) { + count++; + } + } + return count; + } +} diff --git a/Easy/Apple Redistribution into Boxes.java b/Easy/Apple Redistribution into Boxes.java new file mode 100644 index 00000000..d84bd8a8 --- /dev/null +++ b/Easy/Apple Redistribution into Boxes.java @@ -0,0 +1,20 @@ +class Solution { + public int minimumBoxes(int[] apple, int[] capacity) { + int totalApples = 0; + for (int count : apple) { + totalApples += count; + } + Arrays.sort(capacity); + int idx = capacity.length - 1; + int currCapacity = capacity[idx--]; + while (totalApples > 0) { + int applesDeleted = Math.min(currCapacity, totalApples); + totalApples -= applesDeleted; + currCapacity -= applesDeleted; + if (currCapacity == 0 && totalApples > 0) { + currCapacity = capacity[idx--]; + } + } + return capacity.length - idx - 1; + } +} diff --git a/Easy/Apply Operations to an Array.java b/Easy/Apply Operations to an Array.java new file mode 100644 index 00000000..3b2bca86 --- /dev/null +++ b/Easy/Apply Operations to an Array.java @@ -0,0 +1,21 @@ +class Solution { + public int[] applyOperations(int[] nums) { + int n = nums.length; + for (int i = 0; i < n - 1; i++) { + if (nums[i] == nums[i + 1]) { + nums[i] *= 2; + nums[i + 1] = 0; + } + } + int start = 0; + for (int i = 0; i < n; i++) { + if (nums[i] != 0) { + nums[start++] = nums[i]; + } + } + while (start < n) { + nums[start++] = 0; + } + return nums; + } +} diff --git a/Easy/Armstrong Number.java b/Easy/Armstrong Number.java new file mode 100644 index 00000000..fa13ed94 --- /dev/null +++ b/Easy/Armstrong Number.java @@ -0,0 +1,27 @@ +class Solution { + public boolean isArmstrong(int N) { + int n = getLength(N); + return getNthPowerSum(N, n) == N; + } + + private int getNthPowerSum(int n, int p) { + int sum = 0; + while (n > 0) { + int temp = n % 10; + n /= 10; + sum += (int) Math.pow(temp, p); + } + + return sum; + } + + private int getLength(int n) { + int count = 0; + while (n > 0) { + n /= 10; + count++; + } + + return count; + } +} diff --git a/Easy/Arranging Coins.java b/Easy/Arranging Coins.java index 6e5767df..0719ca73 100644 --- a/Easy/Arranging Coins.java +++ b/Easy/Arranging Coins.java @@ -1,20 +1,18 @@ class Solution { - public int arrangeCoins(int n) { - long j = 1; - long sum = 0; - - int ans = 0; - while (true) { - sum += j; - if (sum <= n) { - ans++; - } - else { - break; - } - j++; - } - - return ans; + public int arrangeCoins(int n) { + long left = 1; + long right = n; + while (left <= right) { + long mid = (left + right) / 2; + long sum = mid * (mid + 1) / 2; + if (sum == n) { + return (int) mid; + } else if (sum > n) { + right = mid - 1; + } else { + left = mid + 1; + } } + return (int) right; + } } diff --git a/Easy/Array Partition I.java b/Easy/Array Partition I.java index cb082777..9c263d99 100644 --- a/Easy/Array Partition I.java +++ b/Easy/Array Partition I.java @@ -1,11 +1,20 @@ class Solution { - public int arrayPairSum(int[] nums) { - Arrays.sort(nums); - int sum = 0; - for (int i = 0; i < nums.length; i += 2) { - sum += nums[i]; + public int arrayPairSum(int[] nums) { + int[] counter = new int[20001]; + for (int num : nums) { + counter[num + 10000]++; + } + int sum = 0; + boolean pickFirst = true; + for (int i = 0; i < counter.length; i++) { + while (counter[i] > 0) { + if (pickFirst) { + sum += i - 10000; } - - return sum; + pickFirst = !pickFirst; + counter[i]--; + } } + return sum; + } } diff --git a/Easy/Array Transformation.java b/Easy/Array Transformation.java new file mode 100644 index 00000000..76be3292 --- /dev/null +++ b/Easy/Array Transformation.java @@ -0,0 +1,17 @@ +class Solution { + public List transformArray(int[] arr) { + int[] ans = new int[arr.length]; + while (!Arrays.equals(ans, arr)) { + ans = arr.clone(); + for (int i = 1; i < arr.length - 1; i++) { + if (ans[i] > ans[i - 1] && ans[i] > ans[i + 1]) { + arr[i]--; + } + else if (ans[i - 1] > ans[i] && ans[i + 1] > ans[i]) { + arr[i]++; + } + } + } + return Arrays.stream(ans).boxed().collect(Collectors.toList()); + } +} diff --git a/Easy/Assign Cookies.java b/Easy/Assign Cookies.java index 164c2bfe..32b09bf6 100644 --- a/Easy/Assign Cookies.java +++ b/Easy/Assign Cookies.java @@ -1,17 +1,13 @@ class Solution { - public int findContentChildren(int[] g, int[] s) { - Arrays.sort(g); - Arrays.sort(s); - int count = 0; - for (int i=0;i= greed[idx]) { + idx++; } } - return count; + return idx; } } diff --git a/Easy/Available Captures for Rook.java b/Easy/Available Captures for Rook.java index b994dcaa..52cea4ec 100644 --- a/Easy/Available Captures for Rook.java +++ b/Easy/Available Captures for Rook.java @@ -1,86 +1,33 @@ class Solution { - public int numRookCaptures(char[][] board) { - int numOfPawns = 0; - - int[] rookPos = getRookPos(board); - int row = rookPos[0]; - int col = rookPos[1]; - - for (int i = col + 1; i < board[0].length; i++) { - if (board[row][i] == '.') { - continue; - } - - if (board[row][i] == 'B') { - break; - } - - if (board[row][i] == 'p') { - numOfPawns++; - break; - } + int[][] dirs = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; + public int numRookCaptures(char[][] board) { + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[i].length; j++) { + if (board[i][j] == 'R') { + return getPawnCount(board, i, j); } - - for (int i = col - 1; i >= 0; i--) { - if (board[row][i] == '.') { - continue; - } - - if (board[row][i] == 'B') { - break; - } - - if (board[row][i] == 'p') { - numOfPawns++; - break; - } - } - - for (int i = row + 1; i < board.length; i++) { - if (board[i][col] == '.') { - continue; - } - - if (board[i][col] == 'B') { - break; - } - - if (board[i][col] == 'p') { - numOfPawns++; - break; - } - } - - for (int i = row - 1; i >= 0; i--) { - if (board[i][col] == '.') { - continue; - } - - if (board[i][col] == 'B') { - break; - } - - if (board[i][col] == 'p') { - numOfPawns++; - break; - } - } - - return numOfPawns; + } } - - private int[] getRookPos(char[][] board) { - int[] pos = new int[2]; - - for (int i = 0; i < board.length; i++) { - for (int j = 0; j < board[i].length; j++) { - if (board[i][j] == 'R') { - pos[0] = i; - pos[1] = j; - } - } + return 0; + } + + private int getPawnCount(char[][] board, int i, int j) { + int count = 0; + for (int[] dir : dirs) { + int newX = i + dir[0]; + int newY = j + dir[1]; + while (newX >= 0 && newX < board.length && newY >= 0 && newY < board[0].length) { + if (board[newX][newY] == 'p') { + count++; + break; + } + else if (board[newX][newY] == 'B') { + break; } - - return pos; + newX = newX + dir[0]; + newY = newY + dir[1]; + } } + return count; + } } diff --git a/Easy/Average Salary Excluding the Minimum and Maximum Salary.java b/Easy/Average Salary Excluding the Minimum and Maximum Salary.java new file mode 100644 index 00000000..1d4d872c --- /dev/null +++ b/Easy/Average Salary Excluding the Minimum and Maximum Salary.java @@ -0,0 +1,13 @@ +class Solution { + public double average(int[] salary) { + int minSalary = salary[0]; + int maxSalary = salary[0]; + double totalSalary = 0; + for (int s : salary) { + minSalary = Math.min(minSalary, s); + maxSalary = Math.max(maxSalary, s); + totalSalary += s; + } + return (totalSalary - minSalary - maxSalary) / (salary.length - 2); + } +} diff --git a/Easy/Average Value of Even Numbers That Are Divisible by Three.java b/Easy/Average Value of Even Numbers That Are Divisible by Three.java new file mode 100644 index 00000000..c0e3274e --- /dev/null +++ b/Easy/Average Value of Even Numbers That Are Divisible by Three.java @@ -0,0 +1,13 @@ +class Solution { + public int averageValue(int[] nums) { + int total = 0; + int count = 0; + for (int num : nums) { + if (num % 2 == 0 && num % 3 == 0) { + total += num; + count++; + } + } + return count == 0 ? 0 : total / count; + } +} diff --git a/Easy/Average of Levels in Binary Tree.java b/Easy/Average of Levels in Binary Tree.java new file mode 100644 index 00000000..28bd78a2 --- /dev/null +++ b/Easy/Average of Levels in Binary Tree.java @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List averageOfLevels(TreeNode root) { + List result = new ArrayList<>(); + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + double total = 0.0; + for (int i = 0; i < size; i++) { + TreeNode removed = queue.remove(); + total += removed.val; + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + result.add(total / size); + } + return result; + } +} diff --git a/Easy/Average of levels in a binary tree.java b/Easy/Average of levels in a binary tree.java deleted file mode 100644 index 138ec958..00000000 --- a/Easy/Average of levels in a binary tree.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public List averageOfLevels(TreeNode root) { - List result = new ArrayList<>(); - Queue q = new LinkedList<>(); - - if(root == null) return result; - q.add(root); - while(!q.isEmpty()) { - int n = q.size(); - double sum = 0.0; - for(int i = 0; i < n; i++) { - TreeNode node = q.poll(); - sum += node.val; - if(node.left != null) q.add(node.left); - if(node.right != null) q.add(node.right); - } - result.add(sum / n); - } - return result; - } -} diff --git a/Easy/Backspace String Compare.java b/Easy/Backspace String Compare.java index 604ae07d..91ef6593 100644 --- a/Easy/Backspace String Compare.java +++ b/Easy/Backspace String Compare.java @@ -1,20 +1,23 @@ class Solution { - public boolean backspaceCompare(String S, String T) { - return getEncodedString(S).equals(getEncodedString(T)); + public boolean backspaceCompare(String s, String t) { + return buildBackspaceString(s).equals(buildBackspaceString(t)); } - - private String getEncodedString(String s) { - StringBuilder sb = new StringBuilder(); - + + private static String buildBackspaceString(String s) { + Stack stack = new Stack<>(); for (char c : s.toCharArray()) { - if (c != '#') { - sb.append(c); - } - else if (sb.length() > 0) { - sb.deleteCharAt(sb.length() - 1); + if (c == '#') { + if (!stack.isEmpty()) { + stack.pop(); + } + } else { + stack.push(c); } } - + StringBuilder sb = new StringBuilder(); + for (char c : stack) { + sb.append(c); + } return sb.toString(); } } diff --git a/Easy/Balanced Binary Tree.java b/Easy/Balanced Binary Tree.java index 99084872..fb3ea347 100644 --- a/Easy/Balanced Binary Tree.java +++ b/Easy/Balanced Binary Tree.java @@ -4,23 +4,38 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public boolean isBalanced(TreeNode root) { - if (root == null) return true; - - int lh = height(root.left); - int rh = height(root.right); - - return Math.abs(lh-rh) <= 1 && isBalanced(root.left) && isBalanced(root.right); + public boolean isBalanced(TreeNode root) { + if (root == null) { + return true; } - - public int height(TreeNode root) { - if(root == null) return 0; - - return 1 + Math.max(height(root.left), height(root.right)); + Map map = new HashMap<>(); + int leftHeight = getHeight(root.left, map); + int rightHeight = getHeight(root.right, map); + if (Math.abs(leftHeight - rightHeight) > 1) { + return false; } - + return isBalanced(root.left) && isBalanced(root.right); + } + + private int getHeight(TreeNode root, Map map) { + if (root == null) { + return 0; + } + if (map.containsKey(root)) { + return map.get(root); + } + int height = 1 + Math.max(getHeight(root.left, map), getHeight(root.right, map)); + map.put(root, height); + return height; + } } diff --git a/Easy/Base 7.java b/Easy/Base 7.java index 88c05c8a..8da9a029 100644 --- a/Easy/Base 7.java +++ b/Easy/Base 7.java @@ -1,12 +1,15 @@ class Solution { public String convertToBase7(int num) { - if (num == 0) return "0"; - int temp = Math.abs(num); - StringBuilder sb = new StringBuilder(""); - while (temp > 0) { - sb.append(String.valueOf(temp%7)); - temp /= 7; + StringBuilder sb = new StringBuilder(); + boolean isNegative = num < 0; + num = Math.abs(num); + while (num > 0) { + sb.append(num % 7); + num /= 7; } - return num < 0 ? "-" + sb.reverse().toString() : sb.reverse().toString(); + if (isNegative) { + sb.append('-'); + } + return sb.isEmpty() ? "0" : sb.reverse().toString(); } } diff --git a/Easy/Baseball Game.java b/Easy/Baseball Game.java index 48a8cc49..87e2eea4 100644 --- a/Easy/Baseball Game.java +++ b/Easy/Baseball Game.java @@ -1,54 +1,25 @@ class Solution { - public int calPoints(String[] ops) { - int prev = Integer.MIN_VALUE; - int prevprev = Integer.MIN_VALUE; - Stack st = new Stack<>(); - int s = 0; - int j = 0; - - for (int i=0;i stack = new Stack<>(); + int totalScore = 0; + for (String op : ops) { + if (op.equals("D")) { + int newScore = 2 * stack.peek(); + totalScore += newScore; + stack.push(newScore); + } else if (op.equals("C")) { + totalScore -= stack.pop(); + } else if (op.equals("+")) { + int scoreTwo = stack.pop(); + int newScore = scoreTwo + stack.peek(); + stack.push(scoreTwo); + stack.push(newScore); + totalScore += newScore; + } else { + stack.push(Integer.parseInt(op)); + totalScore += Integer.parseInt(op); + } } + return totalScore; + } } diff --git a/Easy/Best Poker Hand.java b/Easy/Best Poker Hand.java new file mode 100644 index 00000000..3a648cc1 --- /dev/null +++ b/Easy/Best Poker Hand.java @@ -0,0 +1,28 @@ +class Solution { + public String bestHand(int[] ranks, char[] suits) { + char suitCard = '-'; + for (int i = 0; i < suits.length; i++) { + if (suitCard != '-' && suitCard != suits[i]) { + break; + } + if (suitCard == '-') { + suitCard = suits[i]; + } + if (i == suits.length - 1) { + return "Flush"; + } + } + Map frequencyMap = new HashMap<>(); + boolean pairFound = false; + for (int rank : ranks) { + frequencyMap.put(rank, frequencyMap.getOrDefault(rank, 0) + 1); + if (frequencyMap.get(rank) == 3) { + return "Three of a Kind"; + } + if (frequencyMap.get(rank) == 2) { + pairFound = true; + } + } + return pairFound ? "Pair" : "High Card"; + } +} diff --git a/Easy/Best Time to Buy and Sell Stock.java b/Easy/Best Time to Buy and Sell Stock.java new file mode 100644 index 00000000..08df1870 --- /dev/null +++ b/Easy/Best Time to Buy and Sell Stock.java @@ -0,0 +1,13 @@ +class Solution { + public int maxProfit(int[] prices) { + int minPrice = prices[0]; + int maxProfit = 0; + for (int price : prices) { + if (price < minPrice) { + minPrice = price; + } + maxProfit = Math.max(maxProfit, price - minPrice); + } + return maxProfit; + } +} diff --git a/Easy/Best time to buy & sell a stock II.java b/Easy/Best time to buy & sell a stock II.java deleted file mode 100644 index a175bce0..00000000 --- a/Easy/Best time to buy & sell a stock II.java +++ /dev/null @@ -1,16 +0,0 @@ -class Solution { - public int maxProfit(int[] prices) { - int currMin = Integer.MAX_VALUE; - int profit = 0; - - for (int price : prices) { - if (price > currMin) { - profit += price - currMin; - } - - currMin = price; - } - - return profit; - } -} diff --git a/Easy/Best time to buy & sell a stock.java b/Easy/Best time to buy & sell a stock.java deleted file mode 100644 index d03f8686..00000000 --- a/Easy/Best time to buy & sell a stock.java +++ /dev/null @@ -1,21 +0,0 @@ -class Solution { - public int maxProfit(int[] prices) { - if (prices.length == 0) return 0; - - int min = prices[0]; - int profit = 0; - - for (int i=1;i profit) { - profit = prices[i] - min; - } - } - } - - return profit; - } -} diff --git a/Easy/Binary Gap.java b/Easy/Binary Gap.java index c86d7908..fcd7178f 100644 --- a/Easy/Binary Gap.java +++ b/Easy/Binary Gap.java @@ -1,21 +1,19 @@ class Solution { - public int binaryGap(int N) { - char[] binValues = Integer.toBinaryString(N).toCharArray(); - int oneIndex = -1; - int maxDistance = 0; - - for (int i=0; i 0) { + int rem = n % 2; + n /= 2; + if (rem == 1) { + if (lastOnePosition != -1) { + maxGap = Math.max(maxGap, currPosition - lastOnePosition); } + lastOnePosition = currPosition; } + currPosition++; } - - return maxDistance; + return maxGap; } } diff --git a/Easy/Binary Number with Alternating Bits.java b/Easy/Binary Number with Alternating Bits.java index 8b0bde44..82288dd5 100644 --- a/Easy/Binary Number with Alternating Bits.java +++ b/Easy/Binary Number with Alternating Bits.java @@ -1,12 +1,15 @@ class Solution { - public boolean hasAlternatingBits(int n) { - int prev = n%2; - n /=2; - while (n>0) { - if (n%2 == prev) return false; - prev = n%2; - n /= 2; - } - return true; + public boolean hasAlternatingBits(int n) { + Integer prev = null; + while (n > 0) { + int rem = n % 2; + n /= 2; + if (prev == null || prev != rem) { + prev = rem; + } else { + return false; + } } + return true; + } } diff --git a/Easy/Binary Search.java b/Easy/Binary Search.java index baaf9570..0acaa8aa 100644 --- a/Easy/Binary Search.java +++ b/Easy/Binary Search.java @@ -1,23 +1,17 @@ class Solution { - public int search(int[] nums, int target) { - return searchImpl(nums, target, 0, nums.length-1); - } - - public int searchImpl(int[] nums, int target, int start, int end) { - if (start > end) { - return -1; - } - - int mid = (start + end)/2; - - if (nums[mid] == target) { - return mid; - } - else if (nums[mid] > target) { - return searchImpl(nums, target, start, mid-1); - } - else { - return searchImpl(nums, target, mid+1, end); - } + public int search(int[] nums, int target) { + int start = 0; + int end = nums.length - 1; + while (start <= end) { + int mid = (start + end) / 2; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] < target) { + start = mid + 1; + } else { + end = mid - 1; + } } + return -1; + } } diff --git a/Easy/Binary Tree Inorder Traversal.java b/Easy/Binary Tree Inorder Traversal.java new file mode 100644 index 00000000..d17cf649 --- /dev/null +++ b/Easy/Binary Tree Inorder Traversal.java @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List inorderTraversal(TreeNode root) { + if (root == null) { + return List.of(); + } + Stack stack = new Stack<>(); + while (root != null) { + stack.push(root); + root = root.left; + } + List result = new ArrayList<>(); + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + result.add(removed.val); + TreeNode rightNode = removed.right; + while (rightNode != null) { + stack.push(rightNode); + rightNode = rightNode.left; + } + } + return result; + } +} diff --git a/Easy/Binary Tree Level Order Traversal II.java b/Easy/Binary Tree Level Order Traversal II.java index 80efe5aa..3abbbb30 100644 --- a/Easy/Binary Tree Level Order Traversal II.java +++ b/Easy/Binary Tree Level Order Traversal II.java @@ -8,24 +8,29 @@ * } */ class Solution { - public List> levelOrderBottom(TreeNode root) { - List> ans = new ArrayList<>(); - if(root == null) return ans; - Queue q = new LinkedList<>(); - q.add(root); - - while(q.size()>0) { - List arr = new ArrayList<>(); - int size = q.size(); - for (int i=0;i> levelOrderBottom(TreeNode root) { + List> list = new ArrayList<>(); + if (root == null) { + return list; + } + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + List temp = new ArrayList<>(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + temp.add(removed.val); + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); } - - return ans; + } + list.add(temp); } + Collections.reverse(list); + return list; + } } diff --git a/Easy/Binary Tree Paths.java b/Easy/Binary Tree Paths.java index af9298bc..72739836 100644 --- a/Easy/Binary Tree Paths.java +++ b/Easy/Binary Tree Paths.java @@ -4,30 +4,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public List binaryTreePaths(TreeNode root) { - List list = new ArrayList<>(); - if (root != null) { - getString(root, "", list); - } - - return list; + public List binaryTreePaths(TreeNode root) { + List result = new ArrayList<>(); + helper(root, result, new StringBuilder()); + return result; + } + + private void helper(TreeNode root, List result, StringBuilder path) { + if (root == null) { + return; } - - public void getString(TreeNode root, String s, List list) { - if (root.left == null && root.right == null) { - list.add(s + root.val); - } - - if (root.left != null) { - getString(root.left, s + root.val + "->", list); - } - - if (root.right != null) { - getString(root.right, s + root.val + "->", list); - } + path.append(root.val); + if (root.left == null && root.right == null) { + result.add(path.toString()); + } else { + path.append("->"); + helper(root.left, result, new StringBuilder(path)); + helper(root.right, result, new StringBuilder(path)); } + } } diff --git a/Easy/Binary Tree Postorder Traversal.java b/Easy/Binary Tree Postorder Traversal.java new file mode 100644 index 00000000..4e839ba8 --- /dev/null +++ b/Easy/Binary Tree Postorder Traversal.java @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List postorderTraversal(TreeNode root) { + List result = new ArrayList<>(); + Stack stack = new Stack<>(); + TreeNode node = root; + while (!stack.isEmpty() || node != null) { + if (node != null) { + stack.push(node); + result.add(node.val); + node = node.right; + } else { + TreeNode removed = stack.pop(); + node = removed.left; + } + } + Collections.reverse(result); + return result; + } +} diff --git a/Easy/Binary Tree Tilt.java b/Easy/Binary Tree Tilt.java index e4f8ad0a..48a6c409 100644 --- a/Easy/Binary Tree Tilt.java +++ b/Easy/Binary Tree Tilt.java @@ -4,22 +4,29 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int findTilt(TreeNode root) { - if (root == null) { - return 0; - } - return Math.abs(sum(root.left) - sum(root.right)) + findTilt(root.right) + findTilt(root.left); - } - - - public int sum(TreeNode root) { - if(root == null) { - return 0; - } - return root.val + sum(root.left) + sum(root.right); + public int findTilt(TreeNode root) { + int[] total = {0}; + helper(root, total); + return total[0]; + } + + private int helper(TreeNode root, int[] total) { + if (root == null) { + return 0; } + int left = helper(root.left, total); + int right = helper(root.right, total); + total[0] += Math.abs(left - right); + return left + right + root.val; + } } diff --git a/Easy/Binary Watch.java b/Easy/Binary Watch.java new file mode 100644 index 00000000..454f9b6c --- /dev/null +++ b/Easy/Binary Watch.java @@ -0,0 +1,13 @@ +class Solution { + public List readBinaryWatch(int turnedOn) { + return IntStream.range(0, 12) + .boxed() + .flatMap( + h -> IntStream.range(0, 60) + .boxed() + .filter(s -> Integer.bitCount(h) + Integer.bitCount(s) == turnedOn) + .map(m -> String.format("%d:%02d", h, m)) + ) + .collect(Collectors.toList()); + } +} diff --git a/Easy/Bold Words in String.java b/Easy/Bold Words in String.java deleted file mode 100644 index d17849db..00000000 --- a/Easy/Bold Words in String.java +++ /dev/null @@ -1,43 +0,0 @@ -class Solution { - public String boldWords(String[] words, String S) { - if (S.length() == 0 || words.length == 0) { - return S; - } - - int l = S.length(); - int[] match = new int[l]; - - for (String word : words) { - int idx = 0; - while (idx < l) { - int startIdx = S.indexOf(word, idx); - if (startIdx != -1) { - for (int i = startIdx; i < startIdx + word.length(); i++) { - match[i] = 1; - } - - idx = startIdx + 1; - } - else { - break; - } - } - } - - String startTag = ""; - String endTag = ""; - - StringBuilder sb = new StringBuilder(); - for (int i=0; i s = new HashSet(); - for (char c : A.toCharArray()) { - s.add(c); - } - - return s.size() < A.length(); + + private static final int SWAP_DONE_IDX = Integer.MIN_VALUE; + + public boolean buddyStrings(String s, String goal) { + if (s.length() != goal.length()) { + return false; } - - List dif = new ArrayList<>(); - for (int i = 0; i < A.length(); ++i) { - if (A.charAt(i) != B.charAt(i)) { - dif.add(i); + int swapIdx = -1; + Set set = new HashSet<>(); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == goal.charAt(i)) { + set.add(s.charAt(i)); + continue; + } + if (s.charAt(i) != goal.charAt(i)) { + if (swapIdx == SWAP_DONE_IDX) { + return false; + } + if (swapIdx == -1) { + swapIdx = i; + continue; + } + if (!(s.charAt(swapIdx) == goal.charAt(i) && s.charAt(i) == goal.charAt(swapIdx))) { + return false; + } + swapIdx = SWAP_DONE_IDX; } } - - return dif.size() == 2 && A.charAt(dif.get(0)) == B.charAt(dif.get(1)) && A.charAt(dif.get(1)) == B.charAt(dif.get(0)); - } + return (swapIdx != -1 && swapIdx == SWAP_DONE_IDX) || (swapIdx == -1 && set.size() < s.length()); + } } diff --git a/Easy/Build Array from Permutation.java b/Easy/Build Array from Permutation.java new file mode 100644 index 00000000..6a2a6dec --- /dev/null +++ b/Easy/Build Array from Permutation.java @@ -0,0 +1,12 @@ +class Solution { + public int[] buildArray(int[] nums) { + int n = nums.length; + for (int i = 0; i < n; i++) { + nums[i] = nums[i] + n * (nums[nums[i]] % n); + } + for (int i = 0; i < n; i++) { + nums[i] = nums[i] / n; + } + return nums; + } +} diff --git a/Easy/Bulls and Cows.java b/Easy/Bulls and Cows.java new file mode 100644 index 00000000..d071ff1d --- /dev/null +++ b/Easy/Bulls and Cows.java @@ -0,0 +1,20 @@ +class Solution { + public String getHint(String secret, String guess) { + int[] counter = new int[10]; + for (Character c : secret.toCharArray()) { + counter[Character.getNumericValue(c)]++; + } + int bulls = 0; + int cows = 0; + for (int i = 0; i < guess.length(); i++) { + if (guess.charAt(i) == secret.charAt(i)) { + bulls++; + } + if (counter[Character.getNumericValue(guess.charAt(i))] > 0) { + counter[Character.getNumericValue(guess.charAt(i))]--; + cows++; + } + } + return bulls + "A" + (cows - bulls) + "B"; + } +} diff --git a/Easy/Button with Longest Push Time.java b/Easy/Button with Longest Push Time.java new file mode 100644 index 00000000..650bb1e4 --- /dev/null +++ b/Easy/Button with Longest Push Time.java @@ -0,0 +1,18 @@ +class Solution { + public int buttonWithLongestTime(int[][] events) { + int maxTime = 0; + int resultIdx = 0; + int prevTime = 0; + for (int i = 0; i < events.length; i++) { + int timePressed = events[i][1] - prevTime; + if (timePressed > maxTime) { + maxTime = timePressed; + resultIdx = events[i][0]; + } else if (timePressed == maxTime && resultIdx > events[i][0]) { + resultIdx = events[i][0]; + } + prevTime = events[i][1]; + } + return resultIdx; + } +} diff --git a/Easy/Buy Two Chocolates.java b/Easy/Buy Two Chocolates.java new file mode 100644 index 00000000..fac6699e --- /dev/null +++ b/Easy/Buy Two Chocolates.java @@ -0,0 +1,16 @@ +class Solution { + public int buyChoco(int[] prices, int money) { + int cheapestChocolate = Math.min(prices[0], prices[1]); + int secondCheapestChocolate = Math.max(prices[0], prices[1]); + for (int i = 2; i < prices.length; i++) { + if (prices[i] < cheapestChocolate) { + secondCheapestChocolate = cheapestChocolate; + cheapestChocolate = prices[i]; + } else if (prices[i] < secondCheapestChocolate) { + secondCheapestChocolate = prices[i]; + } + } + int totalCost = cheapestChocolate + secondCheapestChocolate; + return totalCost <= money ? (money - totalCost) : money; + } +} diff --git a/Easy/Calculate Amount Paid in Taxes.java b/Easy/Calculate Amount Paid in Taxes.java new file mode 100644 index 00000000..77ae27e2 --- /dev/null +++ b/Easy/Calculate Amount Paid in Taxes.java @@ -0,0 +1,20 @@ +class Solution { + public double calculateTax(int[][] brackets, int income) { + if (income == 0) { + return 0.0; + } + double tax = 0.0; + int idx = 0; + while (idx < brackets.length) { + int[] currentBracket = brackets[idx]; + int amount = idx > 0 ? (Math.min(currentBracket[0], income)) - brackets[idx - 1][0] : Math.min(currentBracket[0], income); + double taxPercentage = ((double) currentBracket[1]) / 100; + tax += taxPercentage * amount; + if (income < currentBracket[0]) { + break; + } + idx++; + } + return tax; + } +} diff --git a/Easy/Calculate Delayed Arrival Time.java b/Easy/Calculate Delayed Arrival Time.java new file mode 100644 index 00000000..47367e00 --- /dev/null +++ b/Easy/Calculate Delayed Arrival Time.java @@ -0,0 +1,6 @@ +class Solution { + public int findDelayedArrivalTime(int arrivalTime, int delayedTime) { + int newTime = arrivalTime + delayedTime; + return newTime - (newTime >= 24 ? 24 : 0); + } +} diff --git a/Easy/Calculate Digit Sum of a String.java b/Easy/Calculate Digit Sum of a String.java new file mode 100644 index 00000000..cf5e9bad --- /dev/null +++ b/Easy/Calculate Digit Sum of a String.java @@ -0,0 +1,20 @@ +class Solution { + public String digitSum(String s, int k) { + while (s.length() > k) { + s = formDigitSum(s, k); + } + return s; + } + + private String formDigitSum(String s, int k) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i += k) { + int currSum = 0; + for (int j = i; j < Math.min(i + k, s.length()); j++) { + currSum += Character.getNumericValue(s.charAt(j)); + } + sb.append(currSum); + } + return sb.toString(); + } +} diff --git a/Easy/Calculate Money in Leetcode Bank.java b/Easy/Calculate Money in Leetcode Bank.java new file mode 100644 index 00000000..0b4a35dc --- /dev/null +++ b/Easy/Calculate Money in Leetcode Bank.java @@ -0,0 +1,21 @@ +class Solution { + public int totalMoney(int n) { + int totalAmount = 0; + int mondayMoney = 1; + while (n > 0) { + totalAmount += mondayMoney++; + n--; + int daysInWeek = Math.min(6, n); + totalAmount += getCummulativeSum(mondayMoney, daysInWeek); + n -= daysInWeek; + } + return totalAmount; + } + + private int getCummulativeSum(int firstTerm, int n) { + if (n <= 0) { + return 0; + } + return ((2 * firstTerm + (n - 1)) * n) / 2; + } +} diff --git a/Easy/Can Make Arithmetic Progression From Sequence.java b/Easy/Can Make Arithmetic Progression From Sequence.java new file mode 100644 index 00000000..fbd09e98 --- /dev/null +++ b/Easy/Can Make Arithmetic Progression From Sequence.java @@ -0,0 +1,12 @@ +class Solution { + public boolean canMakeArithmeticProgression(int[] arr) { + Arrays.sort(arr); + int diff = arr[1] - arr[0]; + for (int i = 2; i < arr.length; i++) { + if (arr[i] - arr[i - 1] != diff) { + return false; + } + } + return true; + } +} diff --git a/Easy/Can Place Flowers.java b/Easy/Can Place Flowers.java index c02aa20b..eb2a21fb 100644 --- a/Easy/Can Place Flowers.java +++ b/Easy/Can Place Flowers.java @@ -1,28 +1,19 @@ class Solution { public boolean canPlaceFlowers(int[] flowerbed, int n) { - for (int i=0;i 1) { - if (flowerbed[i] == 0 && flowerbed[i+1] == 0) { - flowerbed[i] = 1; - n--; - } - } - else if (flowerbed[i] == 0 && flowerbed.length > 2 && flowerbed[i-1] == 0 && i+1 < flowerbed.length && flowerbed[i+1] == 0) { + for (int i = 0; i < flowerbed.length && n > 0; i++) { + if (canPlaceCheck(i, flowerbed)) { flowerbed[i] = 1; n--; - } - else if (i == flowerbed.length-1 && flowerbed.length > 1) { - if (flowerbed[i-1] == 0 && flowerbed[i] == 0) { - flowerbed[i] = 1; - n--; - } - } - else if (flowerbed.length == 1 && flowerbed[0] == 0) { - n--; - } - - if (n <= 0) break; + } } - return n<=0; + return n == 0; + } + + private boolean canPlaceCheck(int i, int[] flowerbed) { + return flowerbed[i] == 0 && ( + (i == 0 && (i + 1 == flowerbed.length || flowerbed[i + 1] == 0)) || + (i == flowerbed.length - 1 && (i - 1 == -1 || flowerbed[i - 1] == 0)) || + (i != 0 && i != flowerbed.length - 1 && flowerbed[i - 1] == 0 && flowerbed[i + 1] == 0) + ); } } diff --git a/Easy/Capitalize the Title.java b/Easy/Capitalize the Title.java new file mode 100644 index 00000000..2481e553 --- /dev/null +++ b/Easy/Capitalize the Title.java @@ -0,0 +1,8 @@ +class Solution { + public String capitalizeTitle(String title) { + return Arrays.stream(title.split("\\s+")) + .map(e -> e.length() <= 2 ? e.toLowerCase() : + e.substring(0, 1).toUpperCase() + e.substring(1).toLowerCase()) + .collect(Collectors.joining(" ")); + } +} diff --git a/Easy/Categorize Box According to Criteria.java b/Easy/Categorize Box According to Criteria.java new file mode 100644 index 00000000..0c817a0a --- /dev/null +++ b/Easy/Categorize Box According to Criteria.java @@ -0,0 +1,23 @@ +class Solution { + + private static final int BULKY_DIMENSION_THRESHOLD = 1000_0; + private static final int BULKY_VOLUME_THRESHOLD = 1000_000_000; + private static final int HEAVY_MASS_THRESHOLD = 100; + + public String categorizeBox(int length, int width, int height, int mass) { + long volume = ((long) length) * width * height; + boolean isBulky = length >= BULKY_DIMENSION_THRESHOLD || + width >= BULKY_DIMENSION_THRESHOLD || + height >= BULKY_DIMENSION_THRESHOLD || + mass >= BULKY_DIMENSION_THRESHOLD || + volume >= BULKY_VOLUME_THRESHOLD; + boolean isHeavy = mass >= HEAVY_MASS_THRESHOLD; + if (isBulky && isHeavy) { + return "Both"; + } + if (!(isBulky || isHeavy)) { + return "Neither"; + } + return isBulky ? "Bulky" : "Heavy"; + } +} diff --git a/Easy/Cells in a Range on an Excel Sheet.java b/Easy/Cells in a Range on an Excel Sheet.java new file mode 100644 index 00000000..8307c2b5 --- /dev/null +++ b/Easy/Cells in a Range on an Excel Sheet.java @@ -0,0 +1,16 @@ +class Solution { + public List cellsInRange(String s) { + List cells = new ArrayList<>(); + String[] splits = s.split(":"); + char startCol = splits[0].charAt(0); + int startRow = Character.getNumericValue(splits[0].charAt(1)); + char endCol = splits[1].charAt(0); + int endRow = Character.getNumericValue(splits[1].charAt(1)); + for (char c = startCol; c <= endCol; c = (char) (c + 1)) { + for (int j = startRow; j <= endRow; j++) { + cells.add(c + "" + j); + } + } + return cells; + } +} diff --git a/Easy/Cells with Odd Values in a Matrix.java b/Easy/Cells with Odd Values in a Matrix.java new file mode 100644 index 00000000..fbd4b6cb --- /dev/null +++ b/Easy/Cells with Odd Values in a Matrix.java @@ -0,0 +1,20 @@ +class Solution { + public int oddCells(int n, int m, int[][] indices) { + Map rowMap = new HashMap<>(); + Map colMap = new HashMap<>(); + for (int[] indice : indices) { + rowMap.put(indice[0], rowMap.getOrDefault(indice[0], 0) + 1); + colMap.put(indice[1], colMap.getOrDefault(indice[1], 0) + 1); + } + int count = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + int temp = 0; + temp += rowMap.getOrDefault(i, 0); + temp += colMap.getOrDefault(j, 0); + count += temp % 2; + } + } + return count; + } +} diff --git a/Easy/Check Array Formation Through Concatenation.java b/Easy/Check Array Formation Through Concatenation.java new file mode 100644 index 00000000..c3fb461d --- /dev/null +++ b/Easy/Check Array Formation Through Concatenation.java @@ -0,0 +1,17 @@ +class Solution { + public boolean canFormArray(int[] arr, int[][] pieces) { + Map indexMap = new HashMap<>(); + for (int idx = 0; idx < arr.length; idx++) { + indexMap.put(arr[idx], idx); + } + for (int[] piece : pieces) { + for (int idx = 0; idx < piece.length; idx++) { + if (!indexMap.containsKey(piece[idx]) || + idx > 0 && indexMap.getOrDefault(piece[idx], -1) < indexMap.getOrDefault(piece[idx - 1], -1)) { + return false; + } + } + } + return true; + } +} diff --git a/Easy/Check Distances Between Same Letters.java b/Easy/Check Distances Between Same Letters.java new file mode 100644 index 00000000..ed5367f6 --- /dev/null +++ b/Easy/Check Distances Between Same Letters.java @@ -0,0 +1,16 @@ +class Solution { + public boolean checkDistances(String s, int[] distance) { + Map charToIdx = new HashMap<>(); + for (int i = 0; i < s.length(); i++) { + if (charToIdx.containsKey(s.charAt(i))) { + int diff = i - charToIdx.get(s.charAt(i)) - 1; + if (diff != distance[s.charAt(i) - 'a']) { + return false; + } + } else { + charToIdx.put(s.charAt(i), i); + } + } + return true; + } +} diff --git a/Easy/Check If It Is a Straight Line.java b/Easy/Check If It Is a Straight Line.java new file mode 100644 index 00000000..407ed220 --- /dev/null +++ b/Easy/Check If It Is a Straight Line.java @@ -0,0 +1,21 @@ +class Solution { + public boolean checkStraightLine(int[][] coordinates) { + int deltaY = getYDiff(coordinates[1], coordinates[0]); + int deltaX = getXDiff(coordinates[1], coordinates[0]); + for (int i = 2; i < coordinates.length; i++) { + if (deltaY * getXDiff(coordinates[i], coordinates[0]) != deltaX * getYDiff(coordinates[i], coordinates[0])) { + return false; + } + } + return true; + } + + private int getYDiff(int[] a, int[] b) { + return a[1] - b[1]; + } + + private int getXDiff(int[] a, int[] b) { + return a[0] - b[0]; + } + +} diff --git a/Easy/Check If N and Its Double Exist.java b/Easy/Check If N and Its Double Exist.java new file mode 100644 index 00000000..a7af36ea --- /dev/null +++ b/Easy/Check If N and Its Double Exist.java @@ -0,0 +1,12 @@ +class Solution { + public boolean checkIfExist(int[] arr) { + Set set = new HashSet<>(); + for (Integer num : arr) { + if (set.contains(num * 2) || (num % 2 == 0 && set.contains(num / 2))) { + return true; + } + set.add(num); + } + return false; + } +} diff --git a/Easy/Check If String Is a Prefix of Array.java b/Easy/Check If String Is a Prefix of Array.java new file mode 100644 index 00000000..faf8f894 --- /dev/null +++ b/Easy/Check If String Is a Prefix of Array.java @@ -0,0 +1,17 @@ +class Solution { + public boolean isPrefixString(String s, String[] words) { + int idx = 0; + for (String word : words) { + for (int i = 0; i < word.length(); i++) { + if (word.charAt(i) != s.charAt(idx)) { + return false; + } + idx++; + if (idx == s.length()) { + return i == word.length() - 1; + } + } + } + return idx == s.length(); + } +} diff --git a/Easy/Check If Two String Arrays are Equivalent.java b/Easy/Check If Two String Arrays are Equivalent.java new file mode 100644 index 00000000..880301c2 --- /dev/null +++ b/Easy/Check If Two String Arrays are Equivalent.java @@ -0,0 +1,24 @@ +class Solution { + public boolean arrayStringsAreEqual(String[] word1, String[] word2) { + int idxOne = 0; + int idxTwo = 0; + int wordIdxOne = 0; + int wordIdxTwo = 0; + while (idxOne < word1.length && idxTwo < word2.length) { + if (word1[idxOne].charAt(wordIdxOne) != word2[idxTwo].charAt(wordIdxTwo)) { + return false; + } + wordIdxOne++; + wordIdxTwo++; + if (wordIdxOne == word1[idxOne].length()) { + wordIdxOne = 0; + idxOne++; + } + if (wordIdxTwo == word2[idxTwo].length()) { + wordIdxTwo = 0; + idxTwo++; + } + } + return idxOne == word1.length && idxTwo == word2.length; + } +} diff --git a/Easy/Check If a Number Is Majority Element in a Sorted Array.java b/Easy/Check If a Number Is Majority Element in a Sorted Array.java new file mode 100644 index 00000000..6491d715 --- /dev/null +++ b/Easy/Check If a Number Is Majority Element in a Sorted Array.java @@ -0,0 +1,38 @@ +class Solution { + + private static enum Direction { + LEFT, RIGHT; + } + + public boolean isMajorityElement(int[] nums, int target) { + int firstIndex = findIndex(nums, target, Direction.LEFT); + if (firstIndex == -1) { + return false; + } + int lastIndex = findIndex(nums, target, Direction.RIGHT); + int occurrences = lastIndex - firstIndex + 1; + return occurrences > nums.length / 2; + } + + private int findIndex(int[] nums, int target, Direction direction) { + int idx = -1; + int start = 0; + int end = nums.length - 1; + while (start <= end) { + int mid = (start + end) / 2; + if (nums[mid] == target) { + idx = mid; + if (direction == Direction.LEFT) { + end = mid - 1; + } else { + start = mid + 1; + } + } else if (nums[mid] > target) { + end = mid - 1; + } else { + start = mid + 1; + } + } + return idx; + } +} diff --git a/Easy/Check If a Word Occurs As a Prefix of Any Word in a Sentence.java b/Easy/Check If a Word Occurs As a Prefix of Any Word in a Sentence.java new file mode 100644 index 00000000..5948c716 --- /dev/null +++ b/Easy/Check If a Word Occurs As a Prefix of Any Word in a Sentence.java @@ -0,0 +1,52 @@ +class Solution { + public int isPrefixOfWord(String sentence, String searchWord) { + Node root = new Node('-'); + String[] words = sentence.split("\\s+"); + Map indexMap = new HashMap<>(); + for (int i = 0; i< words.length; i++) { + addWord(words[i], root, 0); + if (!indexMap.containsKey(words[i])) { + indexMap.put(words[i], i + 1); + } + } + for (int i = 0; i < searchWord.length(); i++) { + char c = searchWord.charAt(i); + if (!root.map.containsKey(c)) { + return -1; + } + root = root.map.get(c); + } + PriorityQueue pq = new PriorityQueue<>(new Comparator(){ + public int compare(String s1, String s2) { + return indexMap.get(s1) - indexMap.get(s2); + } + }); + pq.addAll(root.words); + return indexMap.get(pq.poll()); + } + + private void addWord(String s, Node root, int idx) { + if (idx == s.length()) { + return; + } + char c = s.charAt(idx); + if (!root.map.containsKey(c)) { + root.map.put(c, new Node(c)); + } + Node next = root.map.get(c); + next.words.add(s); + addWord(s, next, idx + 1); + } +} + +class Node { + char c; + Map map; + Set words; + + public Node(char c) { + this.c = c; + map = new HashMap<>(); + words = new HashSet<>(); + } +} diff --git a/Easy/Check Whether Two Strings are Almost Equivalent.java b/Easy/Check Whether Two Strings are Almost Equivalent.java new file mode 100644 index 00000000..e80ee212 --- /dev/null +++ b/Easy/Check Whether Two Strings are Almost Equivalent.java @@ -0,0 +1,15 @@ +class Solution { + public boolean checkAlmostEquivalent(String word1, String word2) { + int[] frequency = new int[26]; + for (int i = 0; i < word1.length(); i++) { + frequency[word1.charAt(i) - 'a']++; + frequency[word2.charAt(i) - 'a']--; + } + for (int i = 0; i < 26; i++) { + if (Math.abs(frequency[i]) > 3) { + return false; + } + } + return true; + } +} diff --git a/Easy/Check if All A's Appears Before All B's.java b/Easy/Check if All A's Appears Before All B's.java new file mode 100644 index 00000000..aab35c42 --- /dev/null +++ b/Easy/Check if All A's Appears Before All B's.java @@ -0,0 +1,17 @@ +class Solution { + public boolean checkString(String s) { + boolean aFound = false; + boolean bFound = false; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == 'a') { + if (bFound) { + return false; + } + aFound = true; + } else { + bFound = true; + } + } + return true; + } +} diff --git a/Easy/Check if All Characters Have Equal Number of Occurrences.java b/Easy/Check if All Characters Have Equal Number of Occurrences.java new file mode 100644 index 00000000..1de5d301 --- /dev/null +++ b/Easy/Check if All Characters Have Equal Number of Occurrences.java @@ -0,0 +1,7 @@ +class Solution { + public boolean areOccurrencesEqual(String s) { + return new HashSet<>(s.chars().mapToObj(c -> (char) c) + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())) + .values()).size() == 1; + } +} diff --git a/Easy/Check if All the Integers in a Range Are Covered.java b/Easy/Check if All the Integers in a Range Are Covered.java new file mode 100644 index 00000000..63a5fd2d --- /dev/null +++ b/Easy/Check if All the Integers in a Range Are Covered.java @@ -0,0 +1,14 @@ +class Solution { + public boolean isCovered(int[][] ranges, int left, int right) { + Arrays.sort(ranges, Comparator.comparingInt((int[] o) -> o[0])); + for (int[] range : ranges) { + if (left >= range[0] && left <= range[1]) { + left = range[1] + 1; + } + if (left > right) { + return true; + } + } + return false; + } +} diff --git a/Easy/Check if Array Is Sorted and Rotated.java b/Easy/Check if Array Is Sorted and Rotated.java new file mode 100644 index 00000000..6ecc109d --- /dev/null +++ b/Easy/Check if Array Is Sorted and Rotated.java @@ -0,0 +1,14 @@ +class Solution { + public boolean check(int[] nums) { + boolean rotated = false; + for (int i = 0; i < nums.length - 1; i++) { + if (nums[i] > nums[i + 1]) { + if (rotated) { + return false; + } + rotated = true; + } + } + return !rotated || nums[nums.length - 1] <= nums[0]; + } +} diff --git a/Easy/Check if Array is Good.java b/Easy/Check if Array is Good.java new file mode 100644 index 00000000..f0b86ddc --- /dev/null +++ b/Easy/Check if Array is Good.java @@ -0,0 +1,24 @@ +class Solution { + public boolean isGood(int[] nums) { + if (nums.length <= 1) { + return false; + } + int n = nums.length - 1; + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + for (int i = 1; i <= n; i++) { + if (!map.containsKey(i)) { + return false; + } + if (map.get(i) > 1 && i != n) { + return false; + } + if (i == n && map.get(i) != 2) { + return false; + } + } + return true; + } +} diff --git a/Easy/Check if Binary String Has at Most One Segment of Ones.java b/Easy/Check if Binary String Has at Most One Segment of Ones.java new file mode 100644 index 00000000..5c9f9f51 --- /dev/null +++ b/Easy/Check if Binary String Has at Most One Segment of Ones.java @@ -0,0 +1,23 @@ +class Solution { + public boolean checkOnesSegment(String s) { + boolean foundContiguousSegment = false; + int idx = 0; + int n = s.length(); + while (idx < n) { + int count = 0; + while (idx < n && s.charAt(idx) == '1') { + count++; + idx++; + } + if (count >= 1) { + if (foundContiguousSegment) { + return false; + } + foundContiguousSegment = true; + } else { + idx++; + } + } + return foundContiguousSegment; + } +} diff --git a/Easy/Check if Bitwise OR Has Trailing Zeros.java b/Easy/Check if Bitwise OR Has Trailing Zeros.java new file mode 100644 index 00000000..b1aedc22 --- /dev/null +++ b/Easy/Check if Bitwise OR Has Trailing Zeros.java @@ -0,0 +1,7 @@ +class Solution { + public boolean hasTrailingZeros(int[] nums) { + return Arrays.stream(nums) + .filter(num -> Integer.numberOfTrailingZeros(num) > 0) + .count() >= 2; + } +} diff --git a/Easy/Check if Every Row and Column Contains All Numbers.java b/Easy/Check if Every Row and Column Contains All Numbers.java new file mode 100644 index 00000000..f64e1cfc --- /dev/null +++ b/Easy/Check if Every Row and Column Contains All Numbers.java @@ -0,0 +1,14 @@ +class Solution { + public boolean checkValid(int[][] matrix) { + Map> rowMap = new HashMap<>(); + Map> colMap = new HashMap<>(); + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length; j++) { + rowMap.computeIfAbsent(i, k -> new HashSet<>()).add(matrix[i][j]); + colMap.computeIfAbsent(j, k -> new HashSet<>()).add(matrix[i][j]); + } + } + return rowMap.values().stream().allMatch(e -> e.size() == matrix.length) && + colMap.values().stream().allMatch(e -> e.size() == matrix.length); + } +} diff --git a/Easy/Check if Grid Satisfies Conditions.java b/Easy/Check if Grid Satisfies Conditions.java new file mode 100644 index 00000000..93891460 --- /dev/null +++ b/Easy/Check if Grid Satisfies Conditions.java @@ -0,0 +1,17 @@ +class Solution { + public boolean satisfiesConditions(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (i + 1 < rows && grid[i][j] != grid[i + 1][j]) { + return false; + } + if (j + 1 < cols && grid[i][j] == grid[i][j + 1]) { + return false; + } + } + } + return true; + } +} diff --git a/Easy/Check if Matrix Is X-Matrix.java b/Easy/Check if Matrix Is X-Matrix.java new file mode 100644 index 00000000..34bc31af --- /dev/null +++ b/Easy/Check if Matrix Is X-Matrix.java @@ -0,0 +1,19 @@ +class Solution { + public boolean checkXMatrix(int[][] grid) { + int n = grid.length; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j || i + j == n - 1) { + if (grid[i][j] == 0) { + return false; + } + } else { + if (grid[i][j] != 0) { + return false; + } + } + } + } + return true; + } +} diff --git a/Easy/Check if Number Has Equal Digit Count and Digit Value.java b/Easy/Check if Number Has Equal Digit Count and Digit Value.java new file mode 100644 index 00000000..8ea9bbc7 --- /dev/null +++ b/Easy/Check if Number Has Equal Digit Count and Digit Value.java @@ -0,0 +1,16 @@ +class Solution { + public boolean digitCount(String num) { + int[] frequency = new int[10]; + for (char c : num.toCharArray()) { + frequency[Character.getNumericValue(c)]++; + } + for (int i = 0; i < num.length(); i++) { + int digit = i; + int expectedFrequency = Character.getNumericValue(num.charAt(i)); + if (frequency[digit] != expectedFrequency) { + return false; + } + } + return true; + } +} diff --git a/Easy/Check if Numbers Are Ascending in a Sentence.java b/Easy/Check if Numbers Are Ascending in a Sentence.java new file mode 100644 index 00000000..b7f5ac65 --- /dev/null +++ b/Easy/Check if Numbers Are Ascending in a Sentence.java @@ -0,0 +1,19 @@ +class Solution { + public boolean areNumbersAscending(String s) { + int prevValue = Integer.MIN_VALUE; + for (int i = 0; i < s.length(); ) { + if (Character.isDigit(s.charAt(i))) { + int currNum = 0; + while (i < s.length() && Character.isDigit(s.charAt(i))) { + currNum = currNum * 10 + Character.getNumericValue(s.charAt(i++)); + } + if (currNum <= prevValue) { + return false; + } + prevValue = currNum; + } + i++; + } + return true; + } +} diff --git a/Easy/Check if One String Swap Can Make Strings Equal.java b/Easy/Check if One String Swap Can Make Strings Equal.java new file mode 100644 index 00000000..fca6fc9d --- /dev/null +++ b/Easy/Check if One String Swap Can Make Strings Equal.java @@ -0,0 +1,21 @@ +class Solution { + public boolean areAlmostEqual(String s1, String s2) { + int swapIdx = -1; + boolean swapped = false; + for (int i = 0; i < s1.length(); i++) { + if (s1.charAt(i) != s2.charAt(i)) { + if (swapped) { + return false; + } + if (swapIdx != -1) { + if (!(s1.charAt(swapIdx) == s2.charAt(i) && s1.charAt(i) == s2.charAt(swapIdx))) { + return false; + } + swapped = true; + } + swapIdx = i; + } + } + return swapIdx == -1 || (swapIdx != -1 && swapped); + } +} diff --git a/Easy/Check if String Is Decomposable Into Value-Equal Substrings.java b/Easy/Check if String Is Decomposable Into Value-Equal Substrings.java new file mode 100644 index 00000000..6d6d55c4 --- /dev/null +++ b/Easy/Check if String Is Decomposable Into Value-Equal Substrings.java @@ -0,0 +1,25 @@ +class Solution { + public boolean isDecomposable(String s) { + boolean sizeTwoFound = false; + int idx = 0; + while (idx < s.length()) { + char c = s.charAt(idx); + int tempIdx = idx; + while (tempIdx < s.length() && s.charAt(tempIdx) == c && tempIdx - idx < 3) { + tempIdx++; + } + int occurrences = tempIdx - idx; + if (occurrences < 2) { + return false; + } + if (occurrences == 2) { + if (sizeTwoFound) { + return false; + } + sizeTwoFound = true; + } + idx = tempIdx; + } + return sizeTwoFound; + } +} diff --git a/Easy/Check if Strings Can be Made Equal With Operations I.java b/Easy/Check if Strings Can be Made Equal With Operations I.java new file mode 100644 index 00000000..cc99065a --- /dev/null +++ b/Easy/Check if Strings Can be Made Equal With Operations I.java @@ -0,0 +1,9 @@ +class Solution { + public boolean canBeEqual(String s1, String s2) { + boolean firstSwap = (s1.charAt(0) == s2.charAt(0) && s1.charAt(2) == s2.charAt(2)) || + (s1.charAt(2) == s2.charAt(0) && s1.charAt(0) == s2.charAt(2)); + boolean secondSwap = (s1.charAt(1) == s2.charAt(1) && s1.charAt(3) == s2.charAt(3)) || + (s1.charAt(1) == s2.charAt(3) && s1.charAt(3) == s2.charAt(1)); + return firstSwap && secondSwap; + } +} diff --git a/Easy/Check if The Number is Fascinating.java b/Easy/Check if The Number is Fascinating.java new file mode 100644 index 00000000..d5074568 --- /dev/null +++ b/Easy/Check if The Number is Fascinating.java @@ -0,0 +1,13 @@ +class Solution { + public boolean isFascinating(int n) { + return isFascinatingHelper(n + "" + 2 * n + "" + 3 * n); + } + + private boolean isFascinatingHelper(String s) { + return s.length() == 9 && s.chars() + .mapToObj(c -> (char) c) + .filter(c -> c != '0') + .collect(Collectors.toSet()) + .size() == 9; + } +} diff --git a/Easy/Check if Word Equals Summation of Two Words.java b/Easy/Check if Word Equals Summation of Two Words.java new file mode 100644 index 00000000..d7aa68ce --- /dev/null +++ b/Easy/Check if Word Equals Summation of Two Words.java @@ -0,0 +1,13 @@ +class Solution { + public boolean isSumEqual(String firstWord, String secondWord, String targetWord) { + return getNumericalValue(firstWord) + getNumericalValue(secondWord) == getNumericalValue(targetWord); + } + + private int getNumericalValue(String s) { + int value = 0; + for (char c : s.toCharArray()) { + value = value * 10 + (c - 'a'); + } + return value; + } +} diff --git a/Easy/Check if a String Is an Acronym of Words.java b/Easy/Check if a String Is an Acronym of Words.java new file mode 100644 index 00000000..5608783c --- /dev/null +++ b/Easy/Check if a String Is an Acronym of Words.java @@ -0,0 +1,9 @@ +class Solution { + public boolean isAcronym(List words, String s) { + StringBuilder sb = new StringBuilder(); + for (String word : words) { + sb.append(word.charAt(0)); + } + return sb.toString().equals(s); + } +} diff --git a/Easy/Check if an Array Is Consecutive.java b/Easy/Check if an Array Is Consecutive.java new file mode 100644 index 00000000..618d43e6 --- /dev/null +++ b/Easy/Check if an Array Is Consecutive.java @@ -0,0 +1,15 @@ +class Solution { + public boolean isConsecutive(int[] nums) { + int min = Integer.MAX_VALUE; + for (int num : nums) { + min = Math.min(num, min); + } + Set set = new HashSet<>(); + for (int num : nums) { + if (num - min >= nums.length || !set.add(num - min)) { + return false; + } + } + return true; + } +} diff --git a/Easy/Check if the Sentence Is Pangram.java b/Easy/Check if the Sentence Is Pangram.java new file mode 100644 index 00000000..a7d7b8e8 --- /dev/null +++ b/Easy/Check if the Sentence Is Pangram.java @@ -0,0 +1,5 @@ +class Solution { + public boolean checkIfPangram(String sentence) { + return sentence.chars().mapToObj(c -> (char) c).collect(Collectors.toSet()).size() == 26; + } +} diff --git a/Easy/Circular Sentence.java b/Easy/Circular Sentence.java new file mode 100644 index 00000000..51b21134 --- /dev/null +++ b/Easy/Circular Sentence.java @@ -0,0 +1,16 @@ +class Solution { + public boolean isCircularSentence(String sentence) { + String[] words = sentence.split("\\s+"); + int n = words.length; + for (int i = 0; i < n - 1; i++) { + char lastCharOfCurrentWord = words[i].charAt(words[i].length() - 1); + char firstCharOfNextWord = words[i + 1].charAt(0); + if (lastCharOfCurrentWord != firstCharOfNextWord) { + return false; + } + } + char lastCharOfLastWord = words[n - 1].charAt(words[n - 1].length() - 1); + char firstCharOfFirstWord = words[0].charAt(0); + return lastCharOfLastWord == firstCharOfFirstWord; + } +} diff --git a/Easy/Clear Digits.java b/Easy/Clear Digits.java new file mode 100644 index 00000000..1d308863 --- /dev/null +++ b/Easy/Clear Digits.java @@ -0,0 +1,15 @@ +class Solution { + public String clearDigits(String s) { + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + if (Character.isDigit(c)) { + if (!sb.isEmpty()) { + sb.deleteCharAt(sb.length() - 1); + } + } else { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/Easy/Climbing Stairs.java b/Easy/Climbing Stairs.java index b29021af..ad49acda 100644 --- a/Easy/Climbing Stairs.java +++ b/Easy/Climbing Stairs.java @@ -1,18 +1,19 @@ class Solution { public int climbStairs(int n) { - if (n == 1) return 1; - if (n == 2) return 2; - - int oneStep = 2; - int twoStep = 1; - int all = 0; - - for (int i=2;i target) { + helper(root.left, target, result); + } else { + helper(root.right, target, result); + } + } } diff --git a/Easy/Compare Strings by Frequency of the Smallest Character.java b/Easy/Compare Strings by Frequency of the Smallest Character.java new file mode 100644 index 00000000..a65ff4aa --- /dev/null +++ b/Easy/Compare Strings by Frequency of the Smallest Character.java @@ -0,0 +1,45 @@ +class Solution { + public int[] numSmallerByFrequency(String[] queries, String[] words) { + List list = new ArrayList<>(); + for (String word : words) { + list.add(getMinWordFreq(word)); + } + Collections.sort(list); + int[] ans = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int minCount = getMinWordFreq(queries[i]); + int idx = 0; + ans[i] = binarySearch(minCount, list); + } + return ans; + } + + private int binarySearch(int target, List list) { + int left = 0; + int right = list.size() - 1; + while (left <= right) { + int mid = (left + right) / 2; + if (list.get(mid) <= target) { + left = mid + 1; + } + else { + right = mid - 1; + } + } + + return list.size() - left; + } + + private int getMinWordFreq(String word) { + int[] counter = new int[26]; + for (char c : word.toCharArray()) { + counter[c - 'a']++; + } + for (int i = 0; i < 26; i++) { + if (counter[i] != 0) { + return counter[i]; + } + } + return 0; + } +} diff --git a/Easy/Complement of Base 10 Integer.java b/Easy/Complement of Base 10 Integer.java index f4b73786..5bf5695d 100644 --- a/Easy/Complement of Base 10 Integer.java +++ b/Easy/Complement of Base 10 Integer.java @@ -1,32 +1,15 @@ class Solution { - public int bitwiseComplement(int N) { - String binaryString = getInvertedBinaryString(N); - return getDecimalVal(binaryString); + public int bitwiseComplement(int N) { + if (N == 0) { + return 1; } - - private String getInvertedBinaryString(int n) { - if (n == 0) { - return "1"; - } - - StringBuilder sb = new StringBuilder(); - while (n > 0) { - sb.append(n % 2 == 0 ? 1 : 0); - n /= 2; - } - - return sb.reverse().toString(); - } - - private int getDecimalVal(String s) { - int pow = 0; - int sum = 0; - - for (int i = s.length() - 1; i >= 0; i--) { - sum += Math.pow(2, pow) * Character.getNumericValue(s.charAt(i)); - pow++; - } - - return sum; + int todo = N; + int bit = 1; + while (todo != 0) { + N = N ^ bit; + bit = bit << 1; + todo = todo >> 1; } + return N; + } } diff --git a/Easy/Concatenation of Array.java b/Easy/Concatenation of Array.java new file mode 100644 index 00000000..f4042c0b --- /dev/null +++ b/Easy/Concatenation of Array.java @@ -0,0 +1,9 @@ +class Solution { + public int[] getConcatenation(int[] nums) { + int[] ans = new int[nums.length * 2]; + for (int i = 0; i < nums.length; i++) { + ans[i + nums.length] = ans[i] = nums[i]; + } + return ans; + } +} diff --git a/Easy/Confusing Number.java b/Easy/Confusing Number.java index 288ad306..0f053ecb 100644 --- a/Easy/Confusing Number.java +++ b/Easy/Confusing Number.java @@ -1,25 +1,20 @@ class Solution { - public boolean confusingNumber(int N) { - if (N == 0) { - return false; - } - int copy = N; - StringBuilder sb = new StringBuilder(); - while (N > 0) { - int temp = N % 10; - if (temp == 6 || temp == 9) { - sb.append(temp == 6 ? 9 : 6); - } - else if (temp == 0 || temp == 1 || temp == 8) { - sb.append(temp); - } - else { - return false; - } - - N /= 10; - } - - return Integer.parseInt(sb.toString()) != copy; + public boolean confusingNumber(int N) { + int newNum = 0; + int copy = N; + while (N > 0) { + int rem = N % 10; + N /= 10; + if (rem == 0 || rem == 1 || rem == 8) { + newNum = newNum * 10 + rem; + } + else if (rem == 6 || rem == 9) { + newNum = newNum * 10 + (rem == 6 ? 9 : 6); + } + else { + return false; + } } + return newNum != copy; + } } diff --git a/Easy/Consecutive Characters.java b/Easy/Consecutive Characters.java new file mode 100644 index 00000000..594b38c9 --- /dev/null +++ b/Easy/Consecutive Characters.java @@ -0,0 +1,14 @@ +class Solution { + public int maxPower(String s) { + int maximumRepeatingCount = 0; + for (int idx = 0; idx < s.length();) { + char currentChar = s.charAt(idx); + int currIdx = idx; + while (idx < s.length() && s.charAt(idx) == currentChar) { + idx++; + } + maximumRepeatingCount = Math.max(maximumRepeatingCount, idx - currIdx); + } + return maximumRepeatingCount; + } +} diff --git a/Easy/Construct String from Binary Tree.java b/Easy/Construct String from Binary Tree.java index 64c762a2..a6b1a205 100644 --- a/Easy/Construct String from Binary Tree.java +++ b/Easy/Construct String from Binary Tree.java @@ -4,29 +4,37 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public String tree2str(TreeNode t) { - StringBuilder sb = new StringBuilder(); - helper(sb,t); - return sb.toString(); + public String tree2str(TreeNode root) { + StringBuilder sb = new StringBuilder(); + helper(root, sb); + return sb.toString(); + } + + private void helper(TreeNode root, StringBuilder sb) { + if (root == null) { + return; } - - public void helper(StringBuilder sb,TreeNode t){ - if(t!=null){ - sb.append(t.val); - if(t.left!=null||t.right!=null){ - sb.append("("); - helper(sb,t.left); - sb.append(")"); - if(t.right!=null){ - sb.append("("); - helper(sb,t.right); - sb.append(")"); - } - } - } + sb.append(root.val); + if (root.left == null && root.right == null) { + return; } + sb.append("("); + helper(root.left, sb); + sb.append(")"); + if (root.right != null) { + sb.append("("); + helper(root.right, sb); + sb.append(")"); + } + } } diff --git a/Easy/Contains Duplicate II.java b/Easy/Contains Duplicate II.java index 579e6ae4..1200875f 100644 --- a/Easy/Contains Duplicate II.java +++ b/Easy/Contains Duplicate II.java @@ -1,14 +1,12 @@ class Solution { - public boolean containsNearbyDuplicate(int[] nums, int k) { - Map map = new HashMap<>(); - for (int i=0;i map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + if (map.containsKey(nums[i]) && Math.abs(map.get(nums[i]) - i) <= k) { + return true; + } + map.put(nums[i], i); } + return false; + } } diff --git a/Easy/Contains Duplicate.java b/Easy/Contains Duplicate.java new file mode 100644 index 00000000..156ad8f9 --- /dev/null +++ b/Easy/Contains Duplicate.java @@ -0,0 +1,5 @@ +class Solution { + public boolean containsDuplicate(int[] nums) { + return Arrays.stream(nums).boxed().collect(Collectors.toSet()).size() < nums.length; + } +} diff --git a/Easy/Convert 1D Array Into 2D Array.java b/Easy/Convert 1D Array Into 2D Array.java new file mode 100644 index 00000000..80b7323e --- /dev/null +++ b/Easy/Convert 1D Array Into 2D Array.java @@ -0,0 +1,17 @@ +class Solution { + public int[][] construct2DArray(int[] original, int m, int n) { + if (m * n != original.length) { + return new int[][]{}; + } + int[][] arr = new int[m][n]; + int idx = 0; + int arrIdx = 0; + while (idx < original.length) { + for (int i = 0; i < n; i++) { + arr[arrIdx][i] = original[idx++]; + } + arrIdx++; + } + return arr; + } +} diff --git a/Easy/Convert BST to Greater Tree.java b/Easy/Convert BST to Greater Tree.java new file mode 100644 index 00000000..8a0ff782 --- /dev/null +++ b/Easy/Convert BST to Greater Tree.java @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode convertBST(TreeNode root) { + Stack stack = new Stack<>(); + addToStack(stack, root); + int currSum = 0; + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + currSum += removed.val; + removed.val = currSum; + addToStack(stack, removed.left); + } + return root; + } + + private void addToStack(Stack stack, TreeNode node) { + while (node != null) { + stack.push(node); + node = node.right; + } + } +} diff --git a/Easy/Convert BST to greater tree.java b/Easy/Convert BST to greater tree.java deleted file mode 100644 index 390d5b93..00000000 --- a/Easy/Convert BST to greater tree.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - - int sum = 0; - public TreeNode convertBST(TreeNode root) { - convert(root); - return root; - } - - public void convert(TreeNode cur) { - if (cur == null) return; - convert(cur.right); - cur.val += sum; - sum = cur.val; - convert(cur.left); - } -} diff --git a/Easy/Convert Binary Number in a Linked List to Integer.java b/Easy/Convert Binary Number in a Linked List to Integer.java new file mode 100644 index 00000000..88ac4468 --- /dev/null +++ b/Easy/Convert Binary Number in a Linked List to Integer.java @@ -0,0 +1,27 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public int getDecimalValue(ListNode head) { + int nodeLength = -1; + ListNode curr = head; + while (curr != null) { + nodeLength++; + curr = curr.next; + } + int decimalValue = 0; + curr = head; + while (curr != null) { + decimalValue += curr.val * Math.pow(2, nodeLength--); + curr = curr.next; + } + return decimalValue; + } +} diff --git a/Easy/Convert Sorted Array To Binary Search Tree.java b/Easy/Convert Sorted Array To Binary Search Tree.java index e595edc3..19d14059 100644 --- a/Easy/Convert Sorted Array To Binary Search Tree.java +++ b/Easy/Convert Sorted Array To Binary Search Tree.java @@ -4,30 +4,28 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode sortedArrayToBST(int[] nums) { - if (nums.length == 0) { - return null; - } - - TreeNode root = convertToBST(nums, 0, nums.length-1); - return root; - } - - public TreeNode convertToBST(int[] nums, int low, int high) { - if (low > high) { - return null; - } - - int mid = (low + high)/2; - TreeNode root = new TreeNode(nums[mid]); - - root.left = convertToBST(nums,low,mid-1); - root.right = convertToBST(nums,mid+1,high); - - return root; + public TreeNode sortedArrayToBST(int[] nums) { + return helper(nums, 0, nums.length - 1); + } + + private TreeNode helper(int[] nums, int start, int end) { + if (start > end) { + return null; } + int mid = (start + end) / 2; + TreeNode root = new TreeNode(nums[mid]); + root.left = helper(nums, start, mid - 1); + root.right = helper(nums, mid + 1, end); + return root; + } } diff --git a/Easy/Convert the Temperature.java b/Easy/Convert the Temperature.java new file mode 100644 index 00000000..0b1f250c --- /dev/null +++ b/Easy/Convert the Temperature.java @@ -0,0 +1,5 @@ +class Solution { + public double[] convertTemperature(double celsius) { + return new double[]{/* kelvin= */celsius + 273.15, /* fahrenheit= */celsius * 1.80 + 32.00}; + } +} diff --git a/Easy/Correct a Binary Tree.java b/Easy/Correct a Binary Tree.java new file mode 100644 index 00000000..3ec5f055 --- /dev/null +++ b/Easy/Correct a Binary Tree.java @@ -0,0 +1,48 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode correctBinaryTree(TreeNode root) { + Queue queue = new LinkedList<>(); + queue.add(new Pair(root, null)); + while (!queue.isEmpty()) { + int size = queue.size(); + Set visited = new HashSet<>(); + for (int i = 0; i < size; i++) { + Pair pair = queue.remove(); + TreeNode node = pair.node(); + TreeNode parent = pair.parent(); + if (visited.contains(node.right)) { + if (parent.left == node) { + parent.left = null; + } else { + parent.right = null; + } + return root; + } + visited.add(node); + if (node.right != null) { + queue.add(new Pair(node.right, node)); + } + if (node.left != null) { + queue.add(new Pair(node.left, node)); + } + } + } + return root; + } + + private static record Pair(TreeNode node, TreeNode parent) {} +} diff --git a/Easy/Count Asterisks.java b/Easy/Count Asterisks.java new file mode 100644 index 00000000..14a53656 --- /dev/null +++ b/Easy/Count Asterisks.java @@ -0,0 +1,16 @@ +class Solution { + public int countAsterisks(String s) { + int asteriskCount = 0; + int barCount = 0; + for (char c : s.toCharArray()) { + if (c == '|') { + barCount++; + } else if (c == '*') { + if (barCount % 2 == 0) { + asteriskCount++; + } + } + } + return asteriskCount; + } +} diff --git a/Easy/Count Binary Substrings.java b/Easy/Count Binary Substrings.java index fec040fe..a0818c9f 100644 --- a/Easy/Count Binary Substrings.java +++ b/Easy/Count Binary Substrings.java @@ -1,17 +1,19 @@ class Solution { - public int countBinarySubstrings(String s) { - int prev = 0; - int curr = 1; - int res = 0; - - for (int i=1;i= curr) res++; - } - return res; + public int countBinarySubstrings(String s) { + int totalCount = 0; + int currCount = 0; + int oppositeCount = 0; + char currChar = s.charAt(0); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == currChar) { + currCount++; + } else { + totalCount += Math.min(currCount, oppositeCount); + oppositeCount = currCount; + currCount = 1; + currChar = s.charAt(i); + } } + return totalCount + Math.min(currCount, oppositeCount); + } } diff --git a/Easy/Count Common Words With One Occurrence.java b/Easy/Count Common Words With One Occurrence.java new file mode 100644 index 00000000..514a87bc --- /dev/null +++ b/Easy/Count Common Words With One Occurrence.java @@ -0,0 +1,16 @@ +class Solution { + public int countWords(String[] words1, String[] words2) { + Map map = new HashMap<>(); + buildFrequencyMap(words1, map, 0); + buildFrequencyMap(words2, map, 1); + return (int) map.entrySet().stream() + .filter(entry -> entry.getValue()[0] == 1 && entry.getValue()[1] == 1) + .count(); + } + + private void buildFrequencyMap(String[] words, Map map, int idx) { + for (String word : words) { + map.computeIfAbsent(word, k -> new int[2])[idx]++; + } + } +} diff --git a/Easy/Count Distinct Numbers on Board.java b/Easy/Count Distinct Numbers on Board.java new file mode 100644 index 00000000..42a7ad68 --- /dev/null +++ b/Easy/Count Distinct Numbers on Board.java @@ -0,0 +1,5 @@ +class Solution { + public int distinctIntegers(int n) { + return Math.max(n - 1, 1); + } +} diff --git a/Easy/Count Elements With Maximum Frequency.java b/Easy/Count Elements With Maximum Frequency.java new file mode 100644 index 00000000..0f023200 --- /dev/null +++ b/Easy/Count Elements With Maximum Frequency.java @@ -0,0 +1,17 @@ +class Solution { + public int maxFrequencyElements(int[] nums) { + Map map = new HashMap<>(); + int maxFrequency = 0; + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + maxFrequency = Math.max(maxFrequency, map.get(num)); + } + int count = 0; + for (int num : nums) { + if (map.get(num) == maxFrequency) { + count++; + } + } + return count; + } +} diff --git a/Easy/Count Elements With Strictly Smaller and Greater Elements.java b/Easy/Count Elements With Strictly Smaller and Greater Elements.java new file mode 100644 index 00000000..42b3f09d --- /dev/null +++ b/Easy/Count Elements With Strictly Smaller and Greater Elements.java @@ -0,0 +1,17 @@ +class Solution { + public int countElements(int[] nums) { + int minValue = nums[0]; + int maxValue = nums[0]; + for (int num : nums) { + minValue = Math.min(minValue, num); + maxValue = Math.max(maxValue, num); + } + int count = 0; + for (int num : nums) { + if (num > minValue && num < maxValue) { + count++; + } + } + return count; + } +} diff --git a/Easy/Count Equal and Divisible Pairs in an Array.java b/Easy/Count Equal and Divisible Pairs in an Array.java new file mode 100644 index 00000000..309c090a --- /dev/null +++ b/Easy/Count Equal and Divisible Pairs in an Array.java @@ -0,0 +1,19 @@ +class Solution { + public int countPairs(int[] nums, int k) { + Map> map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.computeIfAbsent(nums[i], j -> new ArrayList<>()).add(i); + } + int numOfPairs = 0; + for (List indices : map.values()) { + for (int i = 0; i < indices.size(); i++) { + for (int j = 0; j < i; j++) { + if (indices.get(i) * indices.get(j) % k == 0) { + numOfPairs++; + } + } + } + } + return numOfPairs; + } +} diff --git a/Easy/Count Good Triplets.java b/Easy/Count Good Triplets.java new file mode 100644 index 00000000..d903c472 --- /dev/null +++ b/Easy/Count Good Triplets.java @@ -0,0 +1,20 @@ +class Solution { + public int countGoodTriplets(int[] arr, int a, int b, int c) { + int count = 0; + int n = arr.length; + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + for (int k = j + 1; k < n; k++) { + if ( + Math.abs(arr[i] - arr[j]) <= a && + Math.abs(arr[j] - arr[k]) <= b && + Math.abs(arr[k] - arr[i]) <= c + ) { + count++; + } + } + } + } + return count; + } +} diff --git a/Easy/Count Hills and Valleys in an Array.java b/Easy/Count Hills and Valleys in an Array.java new file mode 100644 index 00000000..40372dfd --- /dev/null +++ b/Easy/Count Hills and Valleys in an Array.java @@ -0,0 +1,13 @@ +class Solution { + public int countHillValley(int[] nums) { + int count = 0; + int left = nums[0]; + for (int i = 1; i < nums.length - 1; i++) { + if ((left < nums[i] && nums[i] > nums[i + 1]) || (left > nums[i] && nums[i] < nums[i + 1])) { + left = nums[i]; + count++; + } + } + return count; + } +} diff --git a/Easy/Count Integers With Even Digit Sum.java b/Easy/Count Integers With Even Digit Sum.java new file mode 100644 index 00000000..172a17d3 --- /dev/null +++ b/Easy/Count Integers With Even Digit Sum.java @@ -0,0 +1,14 @@ +class Solution { + public int countEven(int num) { + return (int) IntStream.range(1, num + 1).boxed().filter(this::isSumOfDigitsEven).count(); + } + + private boolean isSumOfDigitsEven(int num) { + int sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum % 2 == 0; + } +} diff --git a/Easy/Count Items Matching a Rule.java b/Easy/Count Items Matching a Rule.java new file mode 100644 index 00000000..3ce28691 --- /dev/null +++ b/Easy/Count Items Matching a Rule.java @@ -0,0 +1,6 @@ +class Solution { + public int countMatches(List> items, String ruleKey, String ruleValue) { + int ruleIdx = ruleKey.equals("type") ? 0 : (ruleKey.equals("color") ? 1 : 2); + return (int) items.stream().filter(item -> item.get(ruleIdx).equals(ruleValue)).count(); + } +} diff --git a/Easy/Count Largest Group.java b/Easy/Count Largest Group.java new file mode 100644 index 00000000..d009c400 --- /dev/null +++ b/Easy/Count Largest Group.java @@ -0,0 +1,30 @@ +class Solution { + public int countLargestGroup(int n) { + Map map = new HashMap<>(); + for (int i = 1; i <= n; i++) { + int digitSum = getDigitSum(i); + map.put(digitSum, map.getOrDefault(digitSum, 0) + 1); + } + int maxCount = 0; + int size = 0; + for (Integer key : map.keySet()) { + if (maxCount < map.get(key)) { + maxCount = map.get(key); + size = 1; + } + else if (maxCount == map.get(key)) { + size++; + } + } + return size; + } + + private int getDigitSum(int n) { + int sum = 0; + while (n > 0) { + sum += n % 10; + n /= 10; + } + return sum; + } +} diff --git a/Easy/Count Negative Numbers in a Sorted Matrix.java b/Easy/Count Negative Numbers in a Sorted Matrix.java new file mode 100644 index 00000000..af842b43 --- /dev/null +++ b/Easy/Count Negative Numbers in a Sorted Matrix.java @@ -0,0 +1,26 @@ +class Solution { + public int countNegatives(int[][] grid) { + int count = 0; + for (int[] row : grid) { + int idx = findFirstNonNegativeIndex(row); + count += idx == -1 ? 0 : (row.length - idx); + } + return count; + } + + private int findFirstNonNegativeIndex(int[] row) { + int start = 0; + int end = row.length - 1; + int idx = -1; + while (start <= end) { + int mid = (start + end) / 2; + if (row[mid] < 0) { + idx = mid; + end = mid - 1; + } else { + start = mid + 1; + } + } + return idx; + } +} diff --git a/Easy/Count Number of Pairs With Absolute Difference K.java b/Easy/Count Number of Pairs With Absolute Difference K.java new file mode 100644 index 00000000..8ff77d76 --- /dev/null +++ b/Easy/Count Number of Pairs With Absolute Difference K.java @@ -0,0 +1,12 @@ +class Solution { + public int countKDifference(int[] nums, int k) { + int count = 0; + Map map = new HashMap<>(); + for (int num : nums) { + count += map.getOrDefault(num + k, 0); + count += map.getOrDefault(num - k, 0); + map.put(num, map.getOrDefault(num, 0) + 1); + } + return count; + } +} diff --git a/Easy/Count Odd Numbers in an Interval Range.java b/Easy/Count Odd Numbers in an Interval Range.java new file mode 100644 index 00000000..7155bbc8 --- /dev/null +++ b/Easy/Count Odd Numbers in an Interval Range.java @@ -0,0 +1,5 @@ +class Solution { + public int countOdds(int low, int high) { + return (high - low) / 2 + (low % 2 != 0 || high % 2 != 0 ? 1 : 0); + } +} diff --git a/Easy/Count Operations to Obtain Zero.java b/Easy/Count Operations to Obtain Zero.java new file mode 100644 index 00000000..7f1678c6 --- /dev/null +++ b/Easy/Count Operations to Obtain Zero.java @@ -0,0 +1,14 @@ +class Solution { + public int countOperations(int num1, int num2) { + int numOfOperations = 0; + while (num1 != 0 && num2 != 0) { + if (num1 >= num2) { + num1 -= num2; + } else { + num2 -= num1; + } + numOfOperations++; + } + return numOfOperations; + } +} diff --git a/Easy/Count Pairs Of Similar Strings.java b/Easy/Count Pairs Of Similar Strings.java new file mode 100644 index 00000000..d9b1f7f9 --- /dev/null +++ b/Easy/Count Pairs Of Similar Strings.java @@ -0,0 +1,26 @@ +class Solution { + public int similarPairs(String[] words) { + Map map = new HashMap<>(); + int pairCount = 0; + for (String word : words) { + String key = buildSortedCharString(word); + pairCount += map.getOrDefault(key, 0); + map.put(key, map.getOrDefault(key, 0) + 1); + } + return pairCount; + } + + private static String buildSortedCharString(String s) { + boolean[] exists = new boolean[26]; + for (char c : s.toCharArray()) { + exists[c - 'a'] = true; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 26; i++) { + if (exists[i]) { + sb.append((char) (97 + i)); + } + } + return sb.toString(); + } +} diff --git a/Easy/Count Pairs That Form a Complete Day I.java b/Easy/Count Pairs That Form a Complete Day I.java new file mode 100644 index 00000000..785a5937 --- /dev/null +++ b/Easy/Count Pairs That Form a Complete Day I.java @@ -0,0 +1,11 @@ +class Solution { + public int countCompleteDayPairs(int[] hours) { + int count = 0; + Map map = new HashMap<>(); + for (int hour : hours) { + count += map.getOrDefault((24 - hour % 24) % 24, 0); + map.put(hour % 24, map.getOrDefault(hour % 24, 0) + 1); + } + return count; + } +} diff --git a/Easy/Count Pairs Whose Sum is Less than Target.java b/Easy/Count Pairs Whose Sum is Less than Target.java new file mode 100644 index 00000000..90c31c23 --- /dev/null +++ b/Easy/Count Pairs Whose Sum is Less than Target.java @@ -0,0 +1,18 @@ +class Solution { + public int countPairs(List nums, int target) { + Collections.sort(nums); + int start = 0; + int end = nums.size() - 1; + int count = 0; + while (start < end) { + int sum = nums.get(start) + nums.get(end); + if (sum < target) { + count += end - start; + start++; + } else { + end--; + } + } + return count; + } +} diff --git a/Easy/Count Partitions with Even Sum Difference.java b/Easy/Count Partitions with Even Sum Difference.java new file mode 100644 index 00000000..0390a5a1 --- /dev/null +++ b/Easy/Count Partitions with Even Sum Difference.java @@ -0,0 +1,17 @@ +class Solution { + public int countPartitions(int[] nums) { + int n = nums.length; + int[] prefixSum = new int[n]; + for (int i = 0; i < n; i++) { + prefixSum[i] = nums[i]; + prefixSum[i] += i == 0 ? 0 : prefixSum[i - 1]; + } + int partitions = 0; + for (int i = 0; i < n - 1; i++) { + int leftSum = prefixSum[i]; + int rightSum = prefixSum[n - 1] - prefixSum[i]; + partitions += (rightSum - leftSum) % 2 == 0 ? 1 : 0; + } + return partitions; + } +} diff --git a/Easy/Count Prefix and Suffix Pairs I.java b/Easy/Count Prefix and Suffix Pairs I.java new file mode 100644 index 00000000..919d41d1 --- /dev/null +++ b/Easy/Count Prefix and Suffix Pairs I.java @@ -0,0 +1,14 @@ +class Solution { + public int countPrefixSuffixPairs(String[] words) { + int count = 0; + for (int i = 0; i < words.length; i++) { + String target = words[i]; + for (int j = i + 1; j < words.length; j++) { + if (words[j].startsWith(target) && words[j].endsWith(target)) { + count++; + } + } + } + return count; + } +} diff --git a/Easy/Count Prefixes of a Given String.java b/Easy/Count Prefixes of a Given String.java new file mode 100644 index 00000000..52438307 --- /dev/null +++ b/Easy/Count Prefixes of a Given String.java @@ -0,0 +1,5 @@ +class Solution { + public int countPrefixes(String[] words, String s) { + return (int) Arrays.stream(words).filter(word -> s.startsWith(word)).count(); + } +} diff --git a/Easy/Count Primes.java b/Easy/Count Primes.java index e6cbb56b..4f1f9ec1 100644 --- a/Easy/Count Primes.java +++ b/Easy/Count Primes.java @@ -1,23 +1,21 @@ class Solution { - public int countPrimes(int n) { - int[] arr = new int[n]; - - for (int i=2;i e != -1).count(); + } + + private void populateSieveArray(int[] nums) { + Arrays.fill(nums, 0, 2, -1); + for (int i = 2; i < nums.length; i++) { + if (nums[i] != -1) { + for (int j = i + i; j < nums.length; j += i) { + nums[j] = -1; } - - return count; + } } + } } diff --git a/Easy/Count Special Quadruplets.java b/Easy/Count Special Quadruplets.java new file mode 100644 index 00000000..1c1cdb71 --- /dev/null +++ b/Easy/Count Special Quadruplets.java @@ -0,0 +1,18 @@ +class Solution { + public int countQuadruplets(int[] nums) { + Map map = new HashMap<>(); + int count = 0; + map.put(nums[nums.length - 1], 1); + for (int i = nums.length - 2; i > 1; i--) { + for (int j = i - 1; j > 0; j--) { + for (int k = j - 1; k >= 0; k--) { + if (map.containsKey(nums[i] + nums[j] + nums[k])) { + count += map.get(nums[i] + nums[j] + nums[k]); + } + } + } + map.put(nums[i], map.getOrDefault(nums[i], 0) + 1); + } + return count; + } +} diff --git a/Easy/Count Square Sum Triples.java b/Easy/Count Square Sum Triples.java new file mode 100644 index 00000000..a7c47e94 --- /dev/null +++ b/Easy/Count Square Sum Triples.java @@ -0,0 +1,18 @@ +class Solution { + public int countTriples(int n) { + Map map = new HashMap<>(); + for (int i = 1; i <= n; i++) { + map.put(i*i, i); + } + int count = 0; + for (int i = 1; i <= n; i++) { + for (int j = i + 1; j <= n; j++) { + int key = i * i + j * j; + if (map.containsKey(key) && !map.get(key).equals(i) && !map.get(key).equals(j)) { + count += 2; + } + } + } + return count; + } +} diff --git a/Easy/Count Subarrays of Length Three With a Condition.java b/Easy/Count Subarrays of Length Three With a Condition.java new file mode 100644 index 00000000..4694fb65 --- /dev/null +++ b/Easy/Count Subarrays of Length Three With a Condition.java @@ -0,0 +1,11 @@ +class Solution { + public int countSubarrays(int[] nums) { + int count = 0; + for (int i = 0; i < nums.length - 2; i++) { + if (2 * (nums[i] + nums[i + 2]) == nums[i + 1]) { + count++; + } + } + return count; + } +} diff --git a/Easy/Count Substrings That Satisfy K-Constraint I.java b/Easy/Count Substrings That Satisfy K-Constraint I.java new file mode 100644 index 00000000..9f44425d --- /dev/null +++ b/Easy/Count Substrings That Satisfy K-Constraint I.java @@ -0,0 +1,21 @@ +class Solution { + public int countKConstraintSubstrings(String s, int k) { + Map map = new HashMap<>(); + int start = 0; + int end = 0; + int n = s.length(); + int result = 0; + while (end < n) { + map.put(s.charAt(end), map.getOrDefault(s.charAt(end), 0) + 1); + end++; + while (start < end && map.getOrDefault('0', 0) > k && map.getOrDefault('1', 0) > k) { + map.put(s.charAt(start), map.get(s.charAt(start)) - 1); + start++; + } + if (map.getOrDefault('0', 0) <= k || map.getOrDefault('1', 0) <= k) { + result += end - start; + } + } + return result; + } +} diff --git a/Easy/Count Substrings with Only One Distinct Letter.java b/Easy/Count Substrings with Only One Distinct Letter.java new file mode 100644 index 00000000..acb84e7e --- /dev/null +++ b/Easy/Count Substrings with Only One Distinct Letter.java @@ -0,0 +1,19 @@ +class Solution { + public int countLetters(String S) { + int start = 0; + int end = 0; + Map map = new HashMap<>(); + int count = 0; + int n = S.length(); + while (end < n) { + char c = S.charAt(end); + while (end < n && S.charAt(end) == c) { + end++; + } + int temp = end - start; + start = end; + count += temp * (temp + 1) / 2; + } + return count; + } +} diff --git a/Easy/Count Symmetric Integers.java b/Easy/Count Symmetric Integers.java new file mode 100644 index 00000000..8ae9c320 --- /dev/null +++ b/Easy/Count Symmetric Integers.java @@ -0,0 +1,27 @@ +class Solution { + public int countSymmetricIntegers(int low, int high) { + int count = 0; + for (int i = low; i <= high; i++) { + if (isSymmetric(i)) { + count++; + } + } + return count; + } + + private static boolean isSymmetric(int num) { + String s = String.valueOf(num); + int n = s.length(); + if (n % 2 != 0) { + return false; + } + int sum = 0; + for (int i = 0; i < n / 2; i++) { + sum += Character.getNumericValue(s.charAt(i)); + } + for (int i = n / 2; i < n; i++) { + sum -= Character.getNumericValue(s.charAt(i)); + } + return sum == 0; + } +} diff --git a/Easy/Count Tested Devices After Test Operations.java b/Easy/Count Tested Devices After Test Operations.java new file mode 100644 index 00000000..1f6cdb0f --- /dev/null +++ b/Easy/Count Tested Devices After Test Operations.java @@ -0,0 +1,13 @@ +class Solution { + public int countTestedDevices(int[] batteryPercentages) { + int count = 0; + int diff = 0; + for (int batteryPercentage : batteryPercentages) { + if (Math.max(0, batteryPercentage - diff) > 0) { + count++; + diff++; + } + } + return count; + } +} diff --git a/Easy/Count Vowel Substrings of a String.java b/Easy/Count Vowel Substrings of a String.java new file mode 100644 index 00000000..93ddc212 --- /dev/null +++ b/Easy/Count Vowel Substrings of a String.java @@ -0,0 +1,32 @@ +class Solution { + public int countVowelSubstrings(String word) { + return atMostVowel(word, 5) - atMostVowel(word, 4); + } + + private int atMostVowel(String word, int atMostGoal) { + int start = 0; + int count = 0; + int n = word.length(); + Map map = new HashMap<>(); + for (int end = 0; end < n; end++) { + if (!isVowel(word.charAt(end))) { + map.clear(); + start = end + 1; + } else { + map.put(word.charAt(end), map.getOrDefault(word.charAt(end), 0) + 1); + for (; map.size() > atMostGoal; start++) { + map.put(word.charAt(start), map.get(word.charAt(start)) - 1); + if (map.get(word.charAt(start)) == 0) { + map.remove(word.charAt(start)); + } + } + count += end - start + 1; + } + } + return count; + } + + private boolean isVowel(char c) { + return "aeiou".indexOf(c) != -1; + } +} diff --git a/Easy/Count and Say.java b/Easy/Count and Say.java deleted file mode 100644 index 8fd83c74..00000000 --- a/Easy/Count and Say.java +++ /dev/null @@ -1,32 +0,0 @@ -class Solution { - public String countAndSay(int n) { - String first = "1"; - String str = "11"; - - if (n == 1) return first; - if (n == 2) return str; - - for (int i = 3; i<=n; i++) { - str += "$"; - int len = str.length(); - - int cnt = 1; - String tmp = ""; - - for (int j = 1; j < len; j++) { - if (str.charAt(j) != str.charAt(j-1)) { - tmp += String.valueOf(cnt); - tmp += str.charAt(j-1); - - cnt = 1; - } - - else cnt++; - } - - str = tmp; - } - - return str; - } -} diff --git a/Easy/Count of Matches in Tournament.java b/Easy/Count of Matches in Tournament.java new file mode 100644 index 00000000..1fc5a6e4 --- /dev/null +++ b/Easy/Count of Matches in Tournament.java @@ -0,0 +1,10 @@ +class Solution { + public int numberOfMatches(int n) { + int numOfMatches = 0; + while (n > 1) { + numOfMatches += n / 2; + n = n / 2 + n % 2; + } + return numOfMatches; + } +} diff --git a/Easy/Count the Digits That Divide a Number.java b/Easy/Count the Digits That Divide a Number.java new file mode 100644 index 00000000..085c312b --- /dev/null +++ b/Easy/Count the Digits That Divide a Number.java @@ -0,0 +1,14 @@ +class Solution { + public int countDigits(int num) { + int count = 0; + int copy = num; + while (num > 0) { + int digit = num % 10; + num /= 10; + if (digit != 0 && copy % digit == 0) { + count++; + } + } + return count; + } +} diff --git a/Easy/Count the Number of Consistent Strings.java b/Easy/Count the Number of Consistent Strings.java new file mode 100644 index 00000000..24aad751 --- /dev/null +++ b/Easy/Count the Number of Consistent Strings.java @@ -0,0 +1,10 @@ +class Solution { + public int countConsistentStrings(String allowed, String[] words) { + return (int) + Arrays.stream(words) + .filter( + word -> + word.chars().mapToObj(c -> (char) c).allMatch(c -> allowed.indexOf(c) != -1)) + .count(); + } +} diff --git a/Easy/Count the Number of Special Characters I.java b/Easy/Count the Number of Special Characters I.java new file mode 100644 index 00000000..44c9950f --- /dev/null +++ b/Easy/Count the Number of Special Characters I.java @@ -0,0 +1,20 @@ +class Solution { + public int numberOfSpecialChars(String word) { + boolean[] upperPresent = new boolean[26]; + boolean[] lowerPresent = new boolean[26]; + for (char c : word.toCharArray()) { + if (Character.isUpperCase(c)) { + upperPresent[c - 'A'] = true; + } else { + lowerPresent[c - 'a'] = true; + } + } + int count = 0; + for (int i = 0; i < 26; i++) { + if (upperPresent[i] && lowerPresent[i]) { + count++; + } + } + return count; + } +} diff --git a/Easy/Count the Number of Vowel Strings in Range.java b/Easy/Count the Number of Vowel Strings in Range.java new file mode 100644 index 00000000..38eeb76e --- /dev/null +++ b/Easy/Count the Number of Vowel Strings in Range.java @@ -0,0 +1,10 @@ +class Solution { + public int vowelStrings(String[] words, int left, int right) { + Set vowels = Set.of('a', 'e', 'i', 'o', 'u'); + return (int) Arrays.stream(words) + .skip(left) + .limit(right - left + 1) + .filter(word -> vowels.contains(word.charAt(0)) && vowels.contains(word.charAt(word.length() - 1))) + .count(); + } +} diff --git a/Easy/Counting Bits.java b/Easy/Counting Bits.java new file mode 100644 index 00000000..4b5c69fa --- /dev/null +++ b/Easy/Counting Bits.java @@ -0,0 +1,9 @@ +class Solution { + public int[] countBits(int n) { + int[] result = new int[n + 1]; + for (int i = 1; i <= n; i++) { + result[i] = result[i / 2] + i % 2; + } + return result; + } +} diff --git a/Easy/Counting Elements.java b/Easy/Counting Elements.java new file mode 100644 index 00000000..f24753ae --- /dev/null +++ b/Easy/Counting Elements.java @@ -0,0 +1,15 @@ +class Solution { + public int countElements(int[] arr) { + int[] counter = new int[1001]; + for (int num : arr) { + counter[num]++; + } + int count = 0; + for (int i = 0; i < 1001; i++) { + if (i != 1000 && counter[i + 1] != 0) { + count += counter[i]; + } + } + return count; + } +} diff --git a/Easy/Counting Words With a Given Prefix.java b/Easy/Counting Words With a Given Prefix.java new file mode 100644 index 00000000..b3ed8f47 --- /dev/null +++ b/Easy/Counting Words With a Given Prefix.java @@ -0,0 +1,5 @@ +class Solution { + public int prefixCount(String[] words, String pref) { + return (int) Arrays.stream(words).filter(w -> w.startsWith(pref)).count(); + } +} diff --git a/Easy/Cousins in Binary Tree.java b/Easy/Cousins in Binary Tree.java index fdedb1c5..f2325e25 100644 --- a/Easy/Cousins in Binary Tree.java +++ b/Easy/Cousins in Binary Tree.java @@ -4,53 +4,43 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public boolean isCousins(TreeNode root, int x, int y) { - if (root == null) { - return false; - } - - DetailedNode nodeX = helper(root, null, x, 0); - DetailedNode nodeY = helper(root, null, y, 0); - - if (nodeX == null || nodeY == null) { - return false; - } - - return nodeX.depth == nodeY.depth && nodeX.parent != nodeY.parent; + public boolean isCousins(TreeNode root, int x, int y) { + ParentDepthPair xPair = getParentDepthPair(root, x, 0); + ParentDepthPair yPair = getParentDepthPair(root, y, 0); + return xPair.parent != yPair.parent && xPair.depth == yPair.depth; + } + + private ParentDepthPair getParentDepthPair(TreeNode root, int val, int currDepth) { + if (root == null) { + return null; } - - private DetailedNode helper(TreeNode root, TreeNode parent, int num, int depth) { - if (root == null) { - return null; - } - - if (root.val == num) { - return new DetailedNode(root, parent, depth - 1); - } - - DetailedNode left = helper(root.left, root, num, depth + 1); - DetailedNode right = helper(root.right, root, num, depth + 1); - - if (left == null) { - return right; - } - - return left; + if (root.val == val) { + return new ParentDepthPair(root, currDepth); + } + if ((root.left != null && root.left.val == val) || (root.right != null && root.right.val == val)) { + return new ParentDepthPair(root, currDepth); } + ParentDepthPair leftPair = getParentDepthPair(root.left, val, currDepth + 1); + return leftPair != null ? leftPair : getParentDepthPair(root.right, val, currDepth + 1); + } + + private static class ParentDepthPair { + TreeNode parent; + int depth; - class DetailedNode { - public TreeNode node; - public TreeNode parent; - public int depth; - - public DetailedNode(TreeNode node, TreeNode parent, int depth) { - this.node = node; - this.parent = parent; - this.depth = depth; - } + public ParentDepthPair(TreeNode parent, int depth) { + this.parent = parent; + this.depth = depth; } + } } diff --git a/Easy/Crawler Log Folder.java b/Easy/Crawler Log Folder.java new file mode 100644 index 00000000..935c1b28 --- /dev/null +++ b/Easy/Crawler Log Folder.java @@ -0,0 +1,14 @@ +class Solution { + public int minOperations(String[] logs) { + int currPos = 0; + for (String log : logs) { + if (log.equals("../")) { + currPos -= currPos == 0 ? 0 : 1; + } + else if (!log.equals("./")) { + currPos++; + } + } + return currPos; + } +} diff --git a/Easy/Create Target Array in the Given Order.java b/Easy/Create Target Array in the Given Order.java new file mode 100644 index 00000000..126b0e5c --- /dev/null +++ b/Easy/Create Target Array in the Given Order.java @@ -0,0 +1,13 @@ +class Solution { + public int[] createTargetArray(int[] nums, int[] index) { + List list = new ArrayList<>(); + for (int i = 0; i < nums.length; i++) { + list.add(index[i], nums[i]); + } + int[] ans = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + ans[i] = list.get(i); + } + return ans; + } +} diff --git a/Easy/DI String Match.java b/Easy/DI String Match.java new file mode 100644 index 00000000..f33d420d --- /dev/null +++ b/Easy/DI String Match.java @@ -0,0 +1,13 @@ +class Solution { + public int[] diStringMatch(String S) { + int n = S.length(); + int low = 0; + int high = n; + int[] ans = new int[n + 1]; + for (int i = 0; i < n; i++) { + ans[i] = S.charAt(i) == 'I' ? low++ : high--; + } + ans[n] = low; + return ans; + } +} diff --git a/Easy/Day of the Week.java b/Easy/Day of the Week.java new file mode 100644 index 00000000..026f91cd --- /dev/null +++ b/Easy/Day of the Week.java @@ -0,0 +1,30 @@ +class Solution { + int[] m = {0,31,28,31,30,31,30,31,31,30,31,30,31}; + String[] res = {"Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"}; + public String dayOfTheWeek(int day, int month, int year) { + int days = years(year); + if(isLeap(year)) + m[2] = 29; + for(int i=0; i < month; i++){ + days += m[i]; + } + days += day-1; + return res[days%7]; + } + private int years(int y){ + int count = 0; + for(int i=1971; i < y; i++){ + if(isLeap(i)) + count += 366; + else + count += 365; + } + return count; + } + private boolean isLeap(int y){ + if(y % 4 != 0) return false; + else if(y%100 != 0) return true; + else if(y % 400 != 0) return false; + else return true; + } +} diff --git a/Easy/Day of the Year.java b/Easy/Day of the Year.java new file mode 100644 index 00000000..a71ad72e --- /dev/null +++ b/Easy/Day of the Year.java @@ -0,0 +1,37 @@ +class Solution { + List daysInMonth = Arrays.asList(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); + public int dayOfYear(String date) { + int year = Integer.parseInt(date.split("-")[0]); + int month = Integer.parseInt(date.split("-")[1]); + int day = Integer.parseInt(date.split("-")[2]); + + int numOfDays = getNumOfDays(month, isLeapYear(year)); + + return numOfDays + day; + } + + private boolean isLeapYear(int year) { + if (year % 4 == 0) { + if (year % 100 == 0) { + return year % 400 == 0; + } + else { + return true; + } + } + return false; + } + + private int getNumOfDays(int month, boolean isLeapYear) { + int numOfDays = 0; + for (int i = 1; i < month; i++) { + if (i == 2) { + numOfDays += isLeapYear ? daysInMonth.get(i - 1) + 1 : daysInMonth.get(i - 1); + } + else { + numOfDays += daysInMonth.get(i - 1); + } + } + return numOfDays; + } +} diff --git a/Easy/Decode XORed Array.java b/Easy/Decode XORed Array.java new file mode 100644 index 00000000..fa9442a4 --- /dev/null +++ b/Easy/Decode XORed Array.java @@ -0,0 +1,10 @@ +class Solution { + public int[] decode(int[] encoded, int first) { + int[] ans = new int[encoded.length + 1]; + ans[0] = first; + for (int i = 0; i < encoded.length; i++) { + ans[i + 1] = ans[i] ^ encoded[i]; + } + return ans; + } +} diff --git a/Easy/Decode the Message.java b/Easy/Decode the Message.java new file mode 100644 index 00000000..c7396320 --- /dev/null +++ b/Easy/Decode the Message.java @@ -0,0 +1,16 @@ +class Solution { + public String decodeMessage(String key, String message) { + int counter = 0; + Map map = new HashMap<>(); + for (char c : key.toCharArray()) { + if (!map.containsKey(c) && c != ' ') { + map.put(c, (char) ('a' + counter++)); + } + } + StringBuilder sb = new StringBuilder(); + for (char c : message.toCharArray()) { + sb.append(c == ' ' ? ' ' : map.get(c)); + } + return sb.toString(); + } +} diff --git a/Easy/Decompress Run-Length Encoded List.java b/Easy/Decompress Run-Length Encoded List.java new file mode 100644 index 00000000..caf7b35a --- /dev/null +++ b/Easy/Decompress Run-Length Encoded List.java @@ -0,0 +1,18 @@ +class Solution { + public int[] decompressRLElist(int[] nums) { + int count = 0; + for (int i = 0; i < nums.length; i += 2) { + count += nums[i]; + } + int idx = 0; + int[] ans = new int[count]; + for (int i = 1; i < nums.length; i+= 2) { + int freq = nums[i - 1]; + int val = nums[i]; + while (freq-- > 0) { + ans[idx++] = val; + } + } + return ans; + } +} diff --git a/Easy/Decrypt String from Alphabet to Integer Mapping.java b/Easy/Decrypt String from Alphabet to Integer Mapping.java new file mode 100644 index 00000000..08b2561c --- /dev/null +++ b/Easy/Decrypt String from Alphabet to Integer Mapping.java @@ -0,0 +1,21 @@ +class Solution { + public String freqAlphabets(String s) { + StringBuilder sb = new StringBuilder(); + int idx = 0; + int n = s.length(); + while (idx < n) { + char c = s.charAt(idx); + int asciiAdd = -1; + if (idx + 2 < n && s.charAt(idx + 2) == '#') { + asciiAdd = Integer.parseInt(s.substring(idx, idx + 2)); + idx += 3; + } + else { + asciiAdd = Integer.parseInt(s.substring(idx, idx + 1)); + idx++; + } + sb.append((char) (96 + asciiAdd)); + } + return sb.toString(); + } +} diff --git a/Easy/Defanging an IP Address.java b/Easy/Defanging an IP Address.java new file mode 100644 index 00000000..7f9b1525 --- /dev/null +++ b/Easy/Defanging an IP Address.java @@ -0,0 +1,9 @@ +class Solution { + public String defangIPaddr(String address) { + StringBuilder sb = new StringBuilder(); + for (char c : address.toCharArray()) { + sb.append(c == '.' ? "[.]" : c); + } + return sb.toString(); + } +} diff --git a/Easy/Defuse the Bomb.java b/Easy/Defuse the Bomb.java new file mode 100644 index 00000000..502f887c --- /dev/null +++ b/Easy/Defuse the Bomb.java @@ -0,0 +1,18 @@ +class Solution { + public int[] decrypt(int[] code, int k) { + int n = code.length; + int[] result = new int[n]; + for (int i = 0; i < n; i++) { + if (k > 0) { + for (int j = i + 1; j < i + k + 1; j++) { + result[i] += code[j % n]; + } + } else if (k < 0) { + for (int j = i - 1; j > i + k - 1; j--) { + result[i] += code[(j + n) % n]; + } + } + } + return result; + } +} diff --git a/Easy/Degree of an array.java b/Easy/Degree of an array.java index 70d31543..85c1622e 100644 --- a/Easy/Degree of an array.java +++ b/Easy/Degree of an array.java @@ -1,42 +1,24 @@ class Solution { - public int findShortestSubArray(int[] nums) { - Map map = new HashMap<>(); - - for (int i = 0; i < nums.length; i++) { - if (map.containsKey(nums[i])) { - map.get(nums[i]).degree++; - map.get(nums[i]).endIdx = i; - } - else { - map.put(nums[i], new Entry(1, i, i)); - } - } - - int res = Integer.MAX_VALUE; - int degree = Integer.MIN_VALUE; - - for (Entry entry : map.values()) { - if (degree < entry.degree) { - degree = entry.degree; - res = entry.endIdx - entry.startIdx + 1; - } - else if (degree == entry.degree) { - res = Math.min(entry.endIdx - entry.startIdx + 1, res); - } - } - - return res; + public int findShortestSubArray(int[] nums) { + Map map = new HashMap<>(); + int maxCount = 0; + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + maxCount = Math.max(maxCount, map.get(num)); } - - class Entry { - int degree; - int startIdx; - int endIdx; - - public Entry(int degree, int startIdx, int endIdx) { - this.degree = degree; - this.startIdx = startIdx; - this.endIdx = endIdx; - } + int start = 0; + int end = 0; + map.clear(); + int minLength = Integer.MAX_VALUE; + while (end < nums.length) { + map.put(nums[end], map.getOrDefault(nums[end], 0) + 1); + while (start <= end && map.get(nums[end]) == maxCount) { + minLength = Math.min(minLength, end - start + 1); + map.put(nums[start], map.get(nums[start]) - 1); + start++; + } + end++; } + return minLength; + } } diff --git a/Easy/Delete Characters to Make Fancy String.java b/Easy/Delete Characters to Make Fancy String.java new file mode 100644 index 00000000..ff26a1b4 --- /dev/null +++ b/Easy/Delete Characters to Make Fancy String.java @@ -0,0 +1,18 @@ +class Solution { + public String makeFancyString(String s) { + int idx = 0; + StringBuilder sb = new StringBuilder(); + while (idx < s.length()) { + char c = s.charAt(idx); + int count = 0; + while (idx < s.length() && s.charAt(idx) == c) { + idx++; + count++; + if (count <= 2) { + sb.append(c); + } + } + } + return sb.toString(); + } +} diff --git a/Easy/Delete Columns to Make Sorted.java b/Easy/Delete Columns to Make Sorted.java new file mode 100644 index 00000000..8cece5a2 --- /dev/null +++ b/Easy/Delete Columns to Make Sorted.java @@ -0,0 +1,16 @@ +class Solution { + public int minDeletionSize(String[] A) { + int numRows = A.length; + int numCols = A[0].length(); + int numDeletions = 0; + for (int i = 0; i < numCols; i++) { + for (int j = 1; j < numRows; j++) { + if (A[j].charAt(i) < A[j - 1].charAt(i)) { + numDeletions++; + break; + } + } + } + return numDeletions; + } +} diff --git a/Easy/Delete Greatest Value in Each Row.java b/Easy/Delete Greatest Value in Each Row.java new file mode 100644 index 00000000..ca6794aa --- /dev/null +++ b/Easy/Delete Greatest Value in Each Row.java @@ -0,0 +1,16 @@ +class Solution { + public int deleteGreatestValue(int[][] grid) { + for (int[] g : grid) { + Arrays.sort(g); + } + int result = 0; + for (int i = grid[0].length - 1; i >= 0; i--) { + int maxValue = Integer.MIN_VALUE; + for (int[] g : grid) { + maxValue = Math.max(maxValue, g[i]); + } + result += maxValue; + } + return result; + } +} diff --git a/Easy/Delete N Nodes After M Nodes of a Linked List.java b/Easy/Delete N Nodes After M Nodes of a Linked List.java new file mode 100644 index 00000000..4e3509bd --- /dev/null +++ b/Easy/Delete N Nodes After M Nodes of a Linked List.java @@ -0,0 +1,40 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode deleteNodes(ListNode head, int m, int n) { + ListNode curr = head; + ListNode prev = null; + boolean toDelete = false; + int deleteCount = 0; + int skipCount = 0; + while (curr != null) { + if (toDelete) { + prev.next = curr.next; + deleteCount++; + curr = prev.next; + if (deleteCount == n) { + deleteCount = 0; + toDelete = false; + } + } + else { + prev = curr; + curr = curr.next; + skipCount++; + if (skipCount == m) { + skipCount = 0; + toDelete = true; + } + } + } + return head; + } +} diff --git a/Easy/Delete Node in a Linked List.java b/Easy/Delete Node in a Linked List.java new file mode 100644 index 00000000..0cfa6304 --- /dev/null +++ b/Easy/Delete Node in a Linked List.java @@ -0,0 +1,15 @@ +/** +* Definition for singly-linked list. +* public class ListNode { +* int val; +* ListNode next; +* ListNode(int x) { val = x; } +* } +*/ +class Solution { + public void deleteNode(ListNode node) { + int nextVal = node.next.val; + node.next = node.next.next; + node.val = nextVal; + } +} diff --git a/Easy/Delete node in a linked list.java b/Easy/Delete node in a linked list.java deleted file mode 100644 index 3704d05b..00000000 --- a/Easy/Delete node in a linked list.java +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public void deleteNode(ListNode node) { - node.val = node.next.val; - node.next=node.next.next; - } -} \ No newline at end of file diff --git a/Easy/Design Compressed String Iterator.java b/Easy/Design Compressed String Iterator.java index 8d128e75..a13e5d9e 100644 --- a/Easy/Design Compressed String Iterator.java +++ b/Easy/Design Compressed String Iterator.java @@ -1,61 +1,49 @@ class StringIterator { - int letterPointer = 0; - int numberPointer = letterPointer + 1; - int counter; - char c; - String s; - StringBuilder num; - public StringIterator(String compressedString) { - s = compressedString; - c = s.charAt(letterPointer); - - num = new StringBuilder(); - while (numberPointer s.length()-1) { - return false; - } - } - return true; + public boolean hasNext() { + updateCurrCount(); + return this.currCount > 0; + } + + private void updateCurrCount() { + if (this.currCount != null && this.currCount == 0) { + this.charIdx = this.counterIdx; + this.counterIdx = this.charIdx + 1; } + if (this.currCount == null) { + this.charIdx = 0; + this.counterIdx = this.charIdx + 1; + this.currCount = 0; + } + if (this.currCount == 0) { + while (this.counterIdx < this.s.length() + && Character.isDigit(this.s.charAt(this.counterIdx))) { + this.currCount = + this.currCount * 10 + Character.getNumericValue(this.s.charAt(this.counterIdx++)); + } + } + } } + /** * Your StringIterator object will be instantiated and called as such: * StringIterator obj = new StringIterator(compressedString); diff --git a/Easy/Design HashMap.java b/Easy/Design HashMap.java index 2738efa9..ff29c920 100644 --- a/Easy/Design HashMap.java +++ b/Easy/Design HashMap.java @@ -1,25 +1,39 @@ class MyHashMap { - /** Initialize your data structure here. */ - int[] arr; - public MyHashMap() { - arr = new int[1000001]; - Arrays.fill(arr, -1); - } + private static final int BUCKET_COUNT = 1001; + + private static final int BUCKET_SIZE = 1001; + + private final Integer[][] map; - /** value will always be non-negative. */ + public MyHashMap() { + this.map = new Integer[BUCKET_COUNT][BUCKET_SIZE]; + } + public void put(int key, int value) { - arr[key] = value; + Position position = getPosition(key); + map[position.bucket()][position.index()] = value; } - - /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */ + public int get(int key) { - return arr[key]; + Position position = getPosition(key); + Integer value = map[position.bucket()][position.index()]; + return value == null ? -1 : value; } - - /** Removes the mapping of the specified value key if this map contains a mapping for the key */ + public void remove(int key) { - arr[key] = -1; + Position position = getPosition(key); + map[position.bucket()][position.index()] = null; + } + + private static Position getPosition(int key) { + int bucket = key / BUCKET_COUNT; + int index = key % BUCKET_SIZE; + return new Position(bucket, index); + } + + private static record Position(int bucket, int index) { + } } diff --git a/Easy/Design HashSet.java b/Easy/Design HashSet.java index 7bad79cc..a8cb00ad 100644 --- a/Easy/Design HashSet.java +++ b/Easy/Design HashSet.java @@ -1,32 +1,139 @@ class MyHashSet { - /** Initialize your data structure here. */ - List list; - public MyHashSet() { - list = new ArrayList<>(); + /** Initialize your data structure here. */ + private Bucket[] bucketArray; + private int keyRange; + public MyHashSet() { + this.keyRange = 769; + this.bucketArray = new Bucket[this.keyRange]; + for (int i = 0; i < this.keyRange; i++) { + this.bucketArray[i] = new Bucket(); } - - public void add(int key) { - if (!list.contains(key)) { - list.add(key); - } + } + + protected int _hash(int key) { + return key % this.keyRange; + } + + public void add(int key) { + int bucketIndex = this._hash(key); + this.bucketArray[bucketIndex].insert(key); + } + + public void remove(int key) { + int bucketIndex = this._hash(key); + this.bucketArray[bucketIndex].delete(key); + } + + /** Returns true if this set contains the specified element */ + public boolean contains(int key) { + int bucketIndex = this._hash(key); + return this.bucketArray[bucketIndex].exists(key); + } +} + + +class Bucket { + private BSTree tree; + + public Bucket() { + tree = new BSTree(); + } + + public void insert(Integer key) { + this.tree.root = this.tree.insertToBST(this.tree.root, key); + } + + public void delete(Integer key) { + this.tree.root = this.tree.deleteFromBST(this.tree.root, key); + } + + public boolean exists(Integer key) { + TreeNode node = this.tree.searchBST(this.tree.root, key); + return node != null; + } +} + + +class BSTree { + TreeNode root = null; + + public TreeNode searchBST(TreeNode root, int val) { + if (root == null || val == root.val) { + return root; + } + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); + } + + public TreeNode insertToBST(TreeNode root, int val) { + if (root == null) { + return new TreeNode(val); } - public void remove(int key) { - Iterator it = list.iterator(); - while(it.hasNext()) { - int val = it.next(); - if (val == key) { - it.remove(); - return; - } - } + if (root.val < val) { + root.right = insertToBST(root.right, val); } + else if (root.val > val) { + root.left = insertToBST(root.left, val); + } + else { + return root; + } + return root; + } + + public TreeNode deleteFromBST(TreeNode root, int key) { + if (root == null) { + return null; + } + if (root.val < key) { + root.right = deleteFromBST(root.right, key); + } + else if (root.val > key) { + root.left = deleteFromBST(root.left, key); + } + else { + if (root.left == null && root.right == null) { + root = null; + } + else if (root.right != null) { + root.val = successor(root); + root.right = deleteFromBST(root.right, root.val); + } + else { + root.val = predecessor(root); + root.left = deleteFromBST(root.left, root.val); + } + } + return root; + } + + private int successor(TreeNode root) { + root = root.right; + while (root.left != null) { + root = root.left; + } + return root.val; + } - /** Returns true if this set did not already contain the specified element */ - public boolean contains(int key) { - return list.contains(key); + private int predecessor(TreeNode root) { + root = root.left; + while (root.right != null) { + root = root.right; } + return root.val; + } +} + + +class TreeNode { + int val; + TreeNode left; + TreeNode right; + + public TreeNode(int x) { + val = x; + } } /** diff --git a/Easy/Design Linked List.java b/Easy/Design Linked List.java index 9788cd08..1f59ba54 100644 --- a/Easy/Design Linked List.java +++ b/Easy/Design Linked List.java @@ -1,49 +1,88 @@ class MyLinkedList { + + private Node head; + private Node tail; + private int count; + + public MyLinkedList() { + this.head = new Node(-1); + this.tail = new Node(-1); + head.next = tail; + tail.prev = head; + this.count = 0; + } - /** Initialize your data structure here. */ - List list; - public MyLinkedList() { - list = new ArrayList<>(); - } - - /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ - public int get(int index) { - if (index >= list.size() || index < 0) { - return -1; - } - - return list.get(index); + public int get(int index) { + Node node = getNode(index); + return node == null ? -1 : node.val; + } + + public void addAtHead(int val) { + Node node = new Node(val); + Node nextNode = head.next; + node.next = nextNode; + node.prev = head; + nextNode.prev = node; + head.next = node; + count++; + } + + public void addAtTail(int val) { + Node node = new Node(val); + Node prevNode = tail.prev; + node.next = tail; + tail.prev = node; + prevNode.next = node; + node.prev = prevNode; + count++; + } + + public void addAtIndex(int index, int val) { + if (index == count) { + addAtTail(val); + } else if (index < count) { + Node nodeAtIndex = getNode(index); + Node prevNode = nodeAtIndex.prev; + Node node = new Node(val); + node.prev = prevNode; + prevNode.next = node; + node.next = nodeAtIndex; + nodeAtIndex.prev = node; + count++; } - - /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */ - public void addAtHead(int val) { - list.add(0, val); + } + + public void deleteAtIndex(int index) { + Node node = getNode(index); + if (node != null) { + Node prevNode = node.prev; + Node nextNode = node.next; + prevNode.next = nextNode; + nextNode.prev = prevNode; + count--; } - - /** Append a node of value val to the last element of the linked list. */ - public void addAtTail(int val) { - list.add(val); + } + + private Node getNode(int index) { + if (index >= count) { + return null; } - - /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */ - public void addAtIndex(int index, int val) { - if (index > list.size()) { - return; - } - if (index == list.size()) { - addAtTail(val); - } - else { - list.add(index, val); - } + Node curr = head.next; + for (int i = 0; i < index; i++) { + curr = curr.next; } + return curr; + } + + private static class Node { + int val; + Node next; + Node prev; - /** Delete the index-th node in the linked list, if the index is valid. */ - public void deleteAtIndex(int index) { - if (index >= 0 && index < list.size()) { - list.remove(index); - } + public Node(int val) { + this.val = val; } + } } /** diff --git a/Easy/Design Neighbor Sum Service.java b/Easy/Design Neighbor Sum Service.java new file mode 100644 index 00000000..93446e53 --- /dev/null +++ b/Easy/Design Neighbor Sum Service.java @@ -0,0 +1,50 @@ +class neighborSum { + + private static final int[][] ADJACENT_DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + private static final int[][] DIAGONAL_DIRS = {{1, -1}, {-1, 1}, {1, 1}, {-1, -1}}; + + private final int[][] grid; + private final int numRows; + private final int numCols; + private final Map valueToCoordinateMap; + + public neighborSum(int[][] grid) { + this.numRows = grid.length; + this.numCols = grid[0].length; + this.valueToCoordinateMap = new HashMap<>(); + this.grid = new int[numRows][numCols]; + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + this.grid[i][j] = grid[i][j]; + this.valueToCoordinateMap.put(grid[i][j], new int[]{i, j}); + } + } + } + + public int adjacentSum(int value) { + return calculateSum(valueToCoordinateMap.get(value), ADJACENT_DIRS); + } + + public int diagonalSum(int value) { + return calculateSum(valueToCoordinateMap.get(value), DIAGONAL_DIRS); + } + + private int calculateSum(int[] coordinate, int[][] directions) { + int sum = 0; + for (int[] dir : directions) { + int newX = dir[0] + coordinate[0]; + int newY = dir[1] + coordinate[1]; + if (newX >= 0 && newX < numRows && newY >= 0 && newY < numCols) { + sum += grid[newX][newY]; + } + } + return sum; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum obj = new neighborSum(grid); + * int param_1 = obj.adjacentSum(value); + * int param_2 = obj.diagonalSum(value); + */ diff --git a/Easy/Design Parking System.java b/Easy/Design Parking System.java new file mode 100644 index 00000000..331e14fc --- /dev/null +++ b/Easy/Design Parking System.java @@ -0,0 +1,17 @@ +class ParkingSystem { + + private int[] availableSpaces; + public ParkingSystem(int big, int medium, int small) { + this.availableSpaces = new int[]{big, medium, small}; + } + + public boolean addCar(int carType) { + return this.availableSpaces[carType - 1]-- > 0; + } +} + +/** + * Your ParkingSystem object will be instantiated and called as such: + * ParkingSystem obj = new ParkingSystem(big, medium, small); + * boolean param_1 = obj.addCar(carType); + */ diff --git a/Easy/Design an Ordered Stream.java b/Easy/Design an Ordered Stream.java new file mode 100644 index 00000000..68c1eba7 --- /dev/null +++ b/Easy/Design an Ordered Stream.java @@ -0,0 +1,23 @@ +class OrderedStream { + private String[] stream; + private int currIdx; + public OrderedStream(int n) { + this.stream = new String[n]; + this.currIdx = 0; + } + + public List insert(int idKey, String value) { + this.stream[idKey - 1] = value; + List result = new ArrayList<>(); + while (this.currIdx < stream.length && this.stream[this.currIdx] != null) { + result.add(this.stream[this.currIdx++]); + } + return result; + } +} + +/** + * Your OrderedStream object will be instantiated and called as such: + * OrderedStream obj = new OrderedStream(n); + * List param_1 = obj.insert(idKey,value); + */ diff --git a/Easy/Design an Ordered System.java b/Easy/Design an Ordered System.java new file mode 100644 index 00000000..e6427b9f --- /dev/null +++ b/Easy/Design an Ordered System.java @@ -0,0 +1,23 @@ +class OrderedStream { + int ptr; + String[] map; + public OrderedStream(int n) { + map = new String[n]; + ptr = 0; + } + + public List insert(int id, String value) { + List list = new ArrayList<>(); + map[id - 1] = value; + while (ptr < map.length && map[ptr] != null) { + list.add(map[ptr++]); + } + return list; + } +} + +/** + * Your OrderedStream object will be instantiated and called as such: + * OrderedStream obj = new OrderedStream(n); + * List param_1 = obj.insert(id,value); + */ diff --git a/Easy/Destination City.java b/Easy/Destination City.java new file mode 100644 index 00000000..f6e330ab --- /dev/null +++ b/Easy/Destination City.java @@ -0,0 +1,12 @@ +class Solution { + public String destCity(List> paths) { + Set cities = new HashSet<>(); + Set outgoingCities = new HashSet<>(); + for (List path : paths) { + cities.addAll(path); + outgoingCities.add(path.get(0)); + } + cities.removeAll(outgoingCities); + return cities.iterator().next(); + } +} diff --git a/Easy/Detect Capital.java b/Easy/Detect Capital.java index 60b5cae1..863fe0f5 100644 --- a/Easy/Detect Capital.java +++ b/Easy/Detect Capital.java @@ -1,26 +1,25 @@ -public class Solution { - public boolean detectCapitalUse(String word) { - boolean capitalFirst = Character.isUpperCase(word.charAt(0)); - if (word.length() > 1) { - boolean capitalSec = Character.isUpperCase(word.charAt(1)); - for (int i=1;i queue = new LinkedList<>(); + int count = 0; + int freq = 1; + for (int i = 0; i < arr.length; i++) { + if (i >= m) { + if (arr[i] == queue.poll()) { + count++; + if (count == m) { + freq++; + count = 0; + } + if (freq == k) { + return true; + } + } + else { + count = 0; + freq = 1; + } + } + queue.add(arr[i]); + } + return false; + } +} diff --git a/Easy/Determine Color of a Chessboard Square.java b/Easy/Determine Color of a Chessboard Square.java new file mode 100644 index 00000000..c18cab14 --- /dev/null +++ b/Easy/Determine Color of a Chessboard Square.java @@ -0,0 +1,10 @@ +class Solution { + public boolean squareIsWhite(String coordinates) { + return ( + ("aceg".indexOf(coordinates.charAt(0)) != -1 + && Character.getNumericValue(coordinates.charAt(1)) % 2 == 0) || + ("aceg".indexOf(coordinates.charAt(0)) == -1 + && Character.getNumericValue(coordinates.charAt(1)) % 2 != 0) + ); + } +} diff --git a/Easy/Determine Whether Matrix Can Be Obtained By Rotation.java b/Easy/Determine Whether Matrix Can Be Obtained By Rotation.java new file mode 100644 index 00000000..7d1d6d46 --- /dev/null +++ b/Easy/Determine Whether Matrix Can Be Obtained By Rotation.java @@ -0,0 +1,39 @@ +class Solution { + public boolean findRotation(int[][] mat, int[][] target) { + for (int i = 0; i < 4; i++) { + if (isEqual(mat, target)) { + return true; + } + rotate(mat); + } + return false; + } + + private boolean isEqual(int[][] mat, int[][] target) { + for (int i = 0; i < mat.length; i++) { + for (int j = 0; j < mat[i].length; j++) { + if (mat[i][j] != target[i][j]) { + return false; + } + } + } + return true; + } + + private void rotate(int[][] mat){ + for(int i = 0; i < mat.length; i++){ + for(int j = i; j < mat[0].length; j++){ + int temp = mat[i][j]; + mat[i][j] = mat[j][i]; + mat[j][i] = temp; + } + } + for(int i = 0; i < mat[0].length / 2; i++){ + for(int j = 0; j < mat.length; j++){ + int temp = mat[j][i]; + mat[j][i] = mat[j][mat[0].length - i - 1]; + mat[j][mat[0].length - i - 1] = temp; + } + } + } +} diff --git a/Easy/Determine if String Halves Are Alike.java b/Easy/Determine if String Halves Are Alike.java new file mode 100644 index 00000000..f7c9a995 --- /dev/null +++ b/Easy/Determine if String Halves Are Alike.java @@ -0,0 +1,20 @@ +class Solution { + + private static final Set VOWELS = Set.of( + 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' + ); + + public boolean halvesAreAlike(String s) { + int count = 0; + int n = s.length(); + for (int i = 0; i < n / 2; i++) { + if (VOWELS.contains(s.charAt(i))) { + count++; + } + if (VOWELS.contains(s.charAt(i + n / 2))) { + count--; + } + } + return count == 0; + } +} diff --git a/Easy/Determine if Two Events Have Conflict.java b/Easy/Determine if Two Events Have Conflict.java new file mode 100644 index 00000000..66c19dce --- /dev/null +++ b/Easy/Determine if Two Events Have Conflict.java @@ -0,0 +1,14 @@ +class Solution { + public boolean haveConflict(String[] event1, String[] event2) { + int minutesEvent1Start = getMinutes(event1[0]); + int minutesEvent1End = getMinutes(event1[1]); + int minutesEvent2Start = getMinutes(event2[0]); + int minutesEvent2End = getMinutes(event2[1]); + return !(minutesEvent1End < minutesEvent2Start || minutesEvent2End < minutesEvent1Start); + } + + private static int getMinutes(String time) { + String[] split = time.split(":"); + return Integer.parseInt(split[0]) * 60 + Integer.parseInt(split[1]); + } +} diff --git a/Easy/Determine the Winner of a Bowling Game.java b/Easy/Determine the Winner of a Bowling Game.java new file mode 100644 index 00000000..0b64db30 --- /dev/null +++ b/Easy/Determine the Winner of a Bowling Game.java @@ -0,0 +1,25 @@ +class Solution { + public int isWinner(int[] player1, int[] player2) { + int score1 = 0; + int score2 = 0; + int tenIndex1 = -1; + int tenIndex2 = -1; + for (int i = 0; i < player1.length; i++) { + score1 += player1[i]; + score2 += player2[i]; + if (tenIndex1 != -1 && i - tenIndex1 <= 2) { + score1 += player1[i]; + } + if (tenIndex2 != -1 && i - tenIndex2 <= 2) { + score2 += player2[i]; + } + if (player1[i] == 10) { + tenIndex1 = i; + } + if (player2[i] == 10) { + tenIndex2 = i; + } + } + return score1 > score2 ? 1 : (score1 == score2 ? 0 : 2); + } +} diff --git a/Easy/Diameter of Binary Tree.java b/Easy/Diameter of Binary Tree.java index d7e874c7..e62673f3 100644 --- a/Easy/Diameter of Binary Tree.java +++ b/Easy/Diameter of Binary Tree.java @@ -4,25 +4,29 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int diameterOfBinaryTree(TreeNode root) { - if (root == null) return 0; - - int rootDiam = depth(root.left) + depth(root.right); - int leftDia = diameterOfBinaryTree(root.left); - int rightDia = diameterOfBinaryTree(root.right); - - return Math.max(rootDiam, Math.max(leftDia, rightDia)); - } - - public int depth(TreeNode root) { - if (root == null) { - return 0; - } - - return 1 + Math.max(depth(root.left), depth(root.right)); + public int diameterOfBinaryTree(TreeNode root) { + int[] diameter = {0}; + dfs(root, diameter); + return diameter[0]; + } + + private int dfs(TreeNode root, int[] diameter) { + if (root == null) { + return 0; } + int leftDiameter = dfs(root.left, diameter); + int rightDiameter = dfs(root.right, diameter); + diameter[0] = Math.max(leftDiameter + rightDiameter, diameter[0]); + return Math.max(leftDiameter, rightDiameter) + 1; + } } diff --git a/Easy/Diet Plan Performance.java b/Easy/Diet Plan Performance.java new file mode 100644 index 00000000..f2cc1fab --- /dev/null +++ b/Easy/Diet Plan Performance.java @@ -0,0 +1,16 @@ +class Solution { + public int dietPlanPerformance(int[] calories, int k, int lower, int upper) { + int points = 0; + int totalCalories = 0; + for (int i = 0; i < k - 1; i++) { + totalCalories += calories[i]; + } + for (int i = k - 1; i < calories.length; i++) { + totalCalories += calories[i]; + points += totalCalories < lower ? -1 : 0; + points += totalCalories > upper ? 1 : 0; + totalCalories -= calories[i - k + 1]; + } + return points; + } +} diff --git a/Easy/Difference Between Element Sum and Digit Sum of an Array.java b/Easy/Difference Between Element Sum and Digit Sum of an Array.java new file mode 100644 index 00000000..1aef4cbe --- /dev/null +++ b/Easy/Difference Between Element Sum and Digit Sum of an Array.java @@ -0,0 +1,20 @@ +class Solution { + public int differenceOfSum(int[] nums) { + int elementSum = 0; + int digitSum = 0; + for (int num : nums) { + elementSum += num; + digitSum += getDigitSum(num); + } + return Math.abs(elementSum - digitSum); + } + + private static int getDigitSum(int num) { + int sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum; + } +} diff --git a/Easy/Distance Between Bus Stops.java b/Easy/Distance Between Bus Stops.java new file mode 100644 index 00000000..e387e92b --- /dev/null +++ b/Easy/Distance Between Bus Stops.java @@ -0,0 +1,31 @@ +class Solution { + public int distanceBetweenBusStops(int[] distance, int start, int destination) { + if (start == destination) { + return 0; + } + int n = distance.length; + int actualStart = Math.min(start, destination); + int actualDestination = Math.max(start, destination); + return Math.min( + getStraightDistance(distance, actualStart, actualDestination, n), + getReverseDistance(distance, actualDestination, actualStart, n) + ); + } + + private int getStraightDistance(int[] distance, int start, int end, int n) { + int dist = 0; + while (start != end) { + dist += distance[start++]; + } + return dist; + } + + private int getReverseDistance(int[] distance, int end, int start, int n) { + int dist = 0; + while (end != start) { + dist += distance[end++]; + end = end % n; + } + return dist; + } +} diff --git a/Easy/Distribute Candies to People.java b/Easy/Distribute Candies to People.java index ee8a8fab..a7895dd2 100644 --- a/Easy/Distribute Candies to People.java +++ b/Easy/Distribute Candies to People.java @@ -1,18 +1,9 @@ class Solution { - public int[] distributeCandies(int candies, int num_people) { - int[] count = new int[num_people]; - int idx = 0; - int currCount = 0; - int startCandy = 1; - - while (currCount < candies) { - count[idx++] += currCount + startCandy > candies ? candies - currCount : startCandy; - currCount += startCandy++; - if (idx == num_people) { - idx = 0; - } - } - - return count; + public int[] distributeCandies(int candies, int num_people) { + int[] people = new int[num_people]; + for (int give = 0; candies > 0; candies -= give) { + people[give % num_people] += Math.min(candies, ++give); } + return people; + } } diff --git a/Easy/Distribute Candies.java b/Easy/Distribute Candies.java index 65ff099e..0cad02b6 100644 --- a/Easy/Distribute Candies.java +++ b/Easy/Distribute Candies.java @@ -1,15 +1,8 @@ class Solution { - public int distributeCandies(int[] candies) { - Map count = new HashMap<>(); - int unique = 0; - int n = candies.length; - for (int i=0;i n/2 ? n/2 : unique; - } + public int distributeCandies(int[] candyType) { + return Math.min( + Arrays.stream(candyType).boxed().collect(Collectors.toSet()).size(), + candyType.length / 2 + ); + } } diff --git a/Easy/Distribute Elements Into Two Arrays I.java b/Easy/Distribute Elements Into Two Arrays I.java new file mode 100644 index 00000000..9b4bd7d1 --- /dev/null +++ b/Easy/Distribute Elements Into Two Arrays I.java @@ -0,0 +1,26 @@ +class Solution { + public int[] resultArray(int[] nums) { + int start = 0; + int end = nums.length - 1; + int[] result = new int[nums.length]; + result[start++] = nums[0]; + result[end--] = nums[1]; + for (int i = 2; i < nums.length; i++) { + if (result[start - 1] > result[end + 1]) { + result[start++] = nums[i]; + } else { + result[end--] = nums[i]; + } + } + int left = end + 1; + int right = nums.length - 1; + while (left < right) { + int temp = result[left]; + result[left] = result[right]; + result[right] = temp; + left++; + right--; + } + return result; + } +} diff --git a/Easy/Distribute Money to Maximum Children.java b/Easy/Distribute Money to Maximum Children.java new file mode 100644 index 00000000..06dd063f --- /dev/null +++ b/Easy/Distribute Money to Maximum Children.java @@ -0,0 +1,15 @@ +class Solution { + public int distMoney(int money, int children) { + money -= children; + if (money < 0) { + return -1; + } + if (money / 7 == children && money % 7 == 0) { + return children; + } + if (money / 7 == children - 1 && money % 7 == 3) { + return children - 2; + } + return Math.min(children - 1, money / 7); + } +} diff --git a/Easy/Divide Array Into Equal Pairs.java b/Easy/Divide Array Into Equal Pairs.java new file mode 100644 index 00000000..ce8122d3 --- /dev/null +++ b/Easy/Divide Array Into Equal Pairs.java @@ -0,0 +1,8 @@ +class Solution { + public boolean divideArray(int[] nums) { + return Arrays.stream(nums) + .boxed() + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())) + .values().stream().allMatch(e -> e % 2 == 0); + } +} diff --git a/Easy/Divide a String Into Groups of Size k.java b/Easy/Divide a String Into Groups of Size k.java new file mode 100644 index 00000000..c37d5a6d --- /dev/null +++ b/Easy/Divide a String Into Groups of Size k.java @@ -0,0 +1,20 @@ +class Solution { + public String[] divideString(String s, int k, char fill) { + int n = s.length() % k == 0 ? s.length() / k : s.length() / k + 1; + String[] result = new String[n]; + int idx = 0; + for (int i = 0; i < n; i++) { + String split = s.substring(idx, Math.min(idx + k, s.length())); + result[i] = formString(split, k, fill); + idx += k; + } + return result; + } + + private String formString(String s, int k, char fill) { + if (s.length() != k) { + return s + String.join("", Collections.nCopies(k - s.length(), String.valueOf(fill))); + } + return s; + } +} diff --git a/Easy/Divide an Array Into Subarrays With Minimum Cost I.java b/Easy/Divide an Array Into Subarrays With Minimum Cost I.java new file mode 100644 index 00000000..7b214fa7 --- /dev/null +++ b/Easy/Divide an Array Into Subarrays With Minimum Cost I.java @@ -0,0 +1,15 @@ +class Solution { + public int minimumCost(int[] nums) { + int minOne = Integer.MAX_VALUE; + int minTwo = Integer.MAX_VALUE; + for (int i = 1; i < nums.length; i++) { + if (nums[i] < minOne) { + minTwo = minOne; + minOne = nums[i]; + } else if (nums[i] < minTwo) { + minTwo = nums[i]; + } + } + return nums[0] + minOne + minTwo; + } +} diff --git a/Easy/Divisible and Non-divisible Sums Difference.java b/Easy/Divisible and Non-divisible Sums Difference.java new file mode 100644 index 00000000..a9c53cc8 --- /dev/null +++ b/Easy/Divisible and Non-divisible Sums Difference.java @@ -0,0 +1,8 @@ +class Solution { + public int differenceOfSums(int n, int m) { + int num1 = n * (n + 1) / 2; + int num2 = n / m; + num2 = m * num2 * (num2 + 1) / 2; + return num1 - 2 * num2; + } +} diff --git a/Easy/Divisor Game.java b/Easy/Divisor Game.java new file mode 100644 index 00000000..a9b03a25 --- /dev/null +++ b/Easy/Divisor Game.java @@ -0,0 +1,18 @@ +class Solution { + public boolean divisorGame(int N) { + boolean[] dp = new boolean[N + 1]; + dp[0] = false; + dp[1] = false; + for (int i = 2; i <= N; i++) { + for (int j = 1; j < i; j++) { + if (i % j == 0) { + if (dp[i - j] == false) { + dp[i] = true; + break; + } + } + } + } + return dp[N]; + } +} diff --git a/Easy/Duplicate Zeros.java b/Easy/Duplicate Zeros.java index 62b546f7..9f97be38 100644 --- a/Easy/Duplicate Zeros.java +++ b/Easy/Duplicate Zeros.java @@ -1,22 +1,23 @@ class Solution { public void duplicateZeros(int[] arr) { - int n = arr.length; int count = 0; - - for (int i = 0; i < arr.length; i++, count++) { - if (arr[i] == 0) { - count++; - } + for (int i = 0; i < arr.length; i++) { + count += arr[i] == 0 ? 1 : 0; } - - for (int i = n - 1; i >= 0; i--) { - if (--count < n) { - arr[count] = arr[i]; - } - - if (arr[i] == 0 && --count < n) { - arr[count] = 0; + int idxOne = arr.length - 1; + int idxTwo = arr.length + count - 1; + while (idxOne != idxTwo) { + insertAtEnd(arr, idxOne, idxTwo--); + if (arr[idxOne] == 0) { + insertAtEnd(arr, idxOne, idxTwo--); } + idxOne--; + } + } + + private void insertAtEnd(int[] arr, int idxOne, int idxTwo) { + if (idxTwo < arr.length) { + arr[idxTwo] = arr[idxOne]; } } } diff --git a/Easy/Element Appearing More Than 25% In Sorted Array.java b/Easy/Element Appearing More Than 25% In Sorted Array.java new file mode 100644 index 00000000..966f0ce9 --- /dev/null +++ b/Easy/Element Appearing More Than 25% In Sorted Array.java @@ -0,0 +1,42 @@ +class Solution { + + enum Direction {LEFT, RIGHT}; + + public int findSpecialInteger(int[] arr) { + int n = arr.length; + if (n == 1) { + return arr[0]; + } + List list = Arrays.asList(arr[n / 4], arr[n / 2], arr[3 * n / 4]); + for (int num : list) { + int firstPosition = getPosition(arr, num, Direction.LEFT); + int lastPosition = getPosition(arr, num, Direction.RIGHT); + if (lastPosition - firstPosition + 1 > n / 4) { + return num; + } + } + return -1; + } + + private int getPosition(int[] nums, int num, Direction direction) { + int left = 0; + int right = nums.length - 1; + int idx = -1; + while (left <= right) { + int mid = (left + right) / 2; + if (nums[mid] == num) { + idx = mid; + if (direction == Direction.LEFT) { + right = mid - 1; + } else { + left = mid + 1; + } + } else if (nums[mid] > num) { + right = mid - 1; + } else { + left = mid + 1; + } + } + return idx; + } +} diff --git a/Easy/Employee Importance.java b/Easy/Employee Importance.java index cb405d7b..03bf2cc2 100644 --- a/Easy/Employee Importance.java +++ b/Easy/Employee Importance.java @@ -1,35 +1,28 @@ /* -// Employee info +// Definition for Employee. class Employee { - // It's the unique id of each node; - // unique id of this employee public int id; - // the importance value of this employee public int importance; - // the id of direct subordinates public List subordinates; }; */ + class Solution { - - public int getImportance(List employees, int id) { - Map map = new HashMap<>(); - - for (int i=0;i employees, int id) { + Map map = new HashMap<>(); + for (Employee employee : employees) { + map.put(employee.id, employee); } - - public int solver(Map map, int id) { - Employee main = map.get(id); - int total = main.importance; - - for(int s : main.subordinates) { - total += solver(map, s); - } - - return total; + int importance = 0; + Queue queue = new LinkedList<>(); + queue.add(map.get(id)); + while (!queue.isEmpty()) { + Employee removed = queue.remove(); + importance += removed.importance; + for (Integer subordinate : removed.subordinates) { + queue.add(map.get(subordinate)); + } } + return importance; + } } diff --git a/Easy/Evaluate Boolean Binary Tree.java b/Easy/Evaluate Boolean Binary Tree.java new file mode 100644 index 00000000..39b6edac --- /dev/null +++ b/Easy/Evaluate Boolean Binary Tree.java @@ -0,0 +1,23 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean evaluateTree(TreeNode root) { + if (root.val == 0 || root.val == 1) { + return root.val == 0 ? false : true; + } + return root.val == 2 ? (evaluateTree(root.left) || evaluateTree(root.right)) : (evaluateTree(root.left) && evaluateTree(root.right)); + } +} diff --git a/Easy/Excel Sheet Column Number.java b/Easy/Excel Sheet Column Number.java new file mode 100644 index 00000000..44720a07 --- /dev/null +++ b/Easy/Excel Sheet Column Number.java @@ -0,0 +1,12 @@ +class Solution { + public int titleToNumber(String columnTitle) { + int numericValue = 0; + int multiplier = 1; + for (int i = columnTitle.length() - 1; i >= 0; i--) { + int currCharNum = columnTitle.charAt(i) - 'A' + 1; + numericValue += multiplier * currCharNum; + multiplier *= 26; + } + return numericValue; + } +} diff --git a/Easy/Excel Sheet Column Title.java b/Easy/Excel Sheet Column Title.java index 4244c70d..fa1ab27d 100644 --- a/Easy/Excel Sheet Column Title.java +++ b/Easy/Excel Sheet Column Title.java @@ -1,12 +1,11 @@ -public class Solution { - public String convertToTitle(int n) { - StringBuilder sb = new StringBuilder(""); - int mod = 0; - while (n > 0) { - mod = (n - 1) % 26; - sb.append(String.valueOf((char) (65 + mod))); - n = (n-mod)/26; - } - return sb.reverse().toString(); +class Solution { + public String convertToTitle(int n) { + StringBuilder sb = new StringBuilder(); + while (n > 0) { + n--; + sb.append((char) ('A' + n % 26)); + n /= 26; } -} \ No newline at end of file + return sb.reverse().toString(); + } +} diff --git a/Easy/Factorial Trailing Zeroes.java b/Easy/Factorial Trailing Zeroes.java index 71b0f24d..74d5b2b0 100644 --- a/Easy/Factorial Trailing Zeroes.java +++ b/Easy/Factorial Trailing Zeroes.java @@ -1,11 +1,10 @@ class Solution { - public int trailingZeroes(int n) { - int count = 0; - while (n > 4) { - count += n/5; - n = n/5; - } - - return count; + public int trailingZeroes(int n) { + int count = 0; + while (n > 4) { + count += n / 5; + n = n / 5; } + return count; + } } diff --git a/Easy/Faulty Keyboard.java b/Easy/Faulty Keyboard.java new file mode 100644 index 00000000..500dc39b --- /dev/null +++ b/Easy/Faulty Keyboard.java @@ -0,0 +1,22 @@ +class Solution { + public String finalString(String s) { + Deque deque = new ArrayDeque<>(); + boolean flip = false; + for (char c : s.toCharArray()) { + if (c == 'i') { + flip = !flip; + } else { + if (flip) { + deque.addFirst(c); + } else { + deque.addLast(c); + } + } + } + StringBuilder sb = new StringBuilder(); + for (char c : deque){ + sb.append(c); + } + return flip ? sb.reverse().toString() : sb.toString(); + } +} diff --git a/Easy/Faulty Sensor.java b/Easy/Faulty Sensor.java new file mode 100644 index 00000000..dabed6c0 --- /dev/null +++ b/Easy/Faulty Sensor.java @@ -0,0 +1,13 @@ +class Solution { + public int badSensor(int[] sensor1, int[] sensor2) { + int idx = 0; + int n = sensor1.length; + while (idx < n && sensor1[idx] == sensor2[idx]) { + idx++; + } + while (idx + 1 < n && sensor1[idx] == sensor2[idx + 1] && sensor1[idx + 1] == sensor2[idx]) { + idx++; + } + return idx >= n - 1 ? -1 : sensor1[idx] == sensor2[idx + 1] ? 1 : 2; + } +} diff --git a/Easy/Fibonacci Number.java b/Easy/Fibonacci Number.java new file mode 100644 index 00000000..dfd1ea21 --- /dev/null +++ b/Easy/Fibonacci Number.java @@ -0,0 +1,14 @@ +class Solution { + public int fib(int n) { + if (n == 0) { + return 0; + } + int[] result = new int[n + 1]; + result[0] = 0; + result[1] = 1; + for (int i = 2; i <= n; i++) { + result[i] = result[i - 1] + result[i - 2]; + } + return result[n]; + } +} diff --git a/Easy/Fibonacci Numbers.java b/Easy/Fibonacci Numbers.java deleted file mode 100644 index 3709df55..00000000 --- a/Easy/Fibonacci Numbers.java +++ /dev/null @@ -1,26 +0,0 @@ -class Solution { - int[] arr; - public int fib(int N) { - arr = new int[N + 1]; - return fibHelper(N); - } - - private int fibHelper(int N) { - if (N == 0) { - return 0; - } - - if (N == 1) { - arr[1] = 1; - return 1; - } - - if (arr[N] != 0) { - return arr[N]; - } - - arr[N] = fibHelper(N - 1) + fibHelper(N - 2); - - return arr[N]; - } -} diff --git a/Easy/Final Array State After K Multiplication Operations I.java b/Easy/Final Array State After K Multiplication Operations I.java new file mode 100644 index 00000000..da5670de --- /dev/null +++ b/Easy/Final Array State After K Multiplication Operations I.java @@ -0,0 +1,25 @@ +class Solution { + public int[] getFinalState(int[] nums, int k, int multiplier) { + int n = nums.length; + PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt((int[] o) -> o[0]) + .thenComparingInt(o -> o[1])); + for (int i = 0; i < n; i++) { + pq.add(new int[]{nums[i], i}); + } + while (k-- > 0) { + int[] removed = pq.remove(); + int value = removed[0]; + int index = removed[1]; + int newValue = value * multiplier; + pq.add(new int[]{newValue, index}); + } + int[] result = new int[n]; + while (!pq.isEmpty()) { + int[] removed = pq.remove(); + int value = removed[0]; + int index = removed[1]; + result[index] = value; + } + return result; + } +} diff --git a/Easy/Final Prices With a Special Discount in a Shop.java b/Easy/Final Prices With a Special Discount in a Shop.java new file mode 100644 index 00000000..4c78e72f --- /dev/null +++ b/Easy/Final Prices With a Special Discount in a Shop.java @@ -0,0 +1,14 @@ +class Solution { + public int[] finalPrices(int[] prices) { + Stack stack = new Stack<>(); + int[] finalPrice = new int[prices.length]; + for (int i = prices.length - 1; i >= 0; i--) { + while (!stack.isEmpty() && prices[stack.peek()] > prices[i]) { + stack.pop(); + } + finalPrice[i] = prices[i] - (stack.isEmpty() ? 0 : prices[stack.peek()]); + stack.push(i); + } + return finalPrice; + } +} diff --git a/Easy/Final Value of Variable After Performing Operations.java b/Easy/Final Value of Variable After Performing Operations.java new file mode 100644 index 00000000..1307fdbd --- /dev/null +++ b/Easy/Final Value of Variable After Performing Operations.java @@ -0,0 +1,9 @@ +class Solution { + public int finalValueAfterOperations(String[] operations) { + int x = 0; + for (String op : operations) { + x += op.indexOf('-') != -1 ? -1 : 1; + } + return x; + } +} diff --git a/Easy/Find All Anagrams in a String.java b/Easy/Find All Anagrams in a String.java deleted file mode 100644 index 8d79ab3b..00000000 --- a/Easy/Find All Anagrams in a String.java +++ /dev/null @@ -1,39 +0,0 @@ -class Solution { - public static List findAnagrams(String s, String p) { - List indexes = new ArrayList<>(); - Map pMap = new TreeMap<>(); - - for (char c : p.toCharArray()) { - pMap.put(c, pMap.getOrDefault(c, 0) + 1); - } - - Map map = new TreeMap<>(); - - for (int i=0; i findKDistantIndices(int[] nums, int key, int k) { + List result = new ArrayList<>(); + for (int i = 0; i < nums.length; i++) { + if (nums[i] == key) { + int start = Math.max(result.size() == 0 ? 0 : result.get(result.size() - 1) + 1, i - k); + for (int j = start; j <= i + k && j < nums.length; j++) { + result.add(j); + } + } + } + return result; + } +} diff --git a/Easy/Find All Numbers Disappeared in an Array.java b/Easy/Find All Numbers Disappeared in an Array.java index b1b53a91..4cab6c67 100644 --- a/Easy/Find All Numbers Disappeared in an Array.java +++ b/Easy/Find All Numbers Disappeared in an Array.java @@ -1,19 +1,17 @@ -public class Solution { - public List findDisappearedNumbers(int[] nums) { - List ans = new ArrayList(); - - for(int i = 0; i < nums.length; i++) { - int val = Math.abs(nums[i]) - 1; - if(nums[val] > 0) { - nums[val] = -nums[val]; - } - } - - for(int i = 0; i < nums.length; i++) { - if(nums[i] > 0) { - ans.add(i+1); - } - } - return ans; +class Solution { + public List findDisappearedNumbers(int[] nums) { + List result = new ArrayList<>(); + for (int i = 0; i < nums.length; i++) { + int idx = Math.abs(nums[i]) - 1; + if (nums[idx] > 0) { + nums[idx] *= -1; + } } -} \ No newline at end of file + for (int i = 0; i < nums.length; i++) { + if (nums[i] > 0) { + result.add(i + 1); + } + } + return result; + } +} diff --git a/Easy/Find All the Lonely Nodes.java b/Easy/Find All the Lonely Nodes.java new file mode 100644 index 00000000..1cae56ab --- /dev/null +++ b/Easy/Find All the Lonely Nodes.java @@ -0,0 +1,40 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List getLonelyNodes(TreeNode root) { + List lonelyNodes = new ArrayList<>(); + Queue queue = new LinkedList<>(); + queue.add(new TreeNode[]{root, null}); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeNode[] removed = queue.remove(); + TreeNode node = removed[0]; + TreeNode parent = removed[1]; + if (parent != null && ((parent.left == node && parent.right == null) || (parent.right == node && parent.left == null))) { + lonelyNodes.add(node.val); + } + if (node.left != null) { + queue.add(new TreeNode[]{node.left, node}); + } + if (node.right != null) { + queue.add(new TreeNode[]{node.right, node}); + } + } + } + return lonelyNodes; + } +} diff --git a/Easy/Find Anagram Mappings.java b/Easy/Find Anagram Mappings.java new file mode 100644 index 00000000..3650db78 --- /dev/null +++ b/Easy/Find Anagram Mappings.java @@ -0,0 +1,13 @@ +class Solution { + public int[] anagramMappings(int[] nums1, int[] nums2) { + Map indexMap = new HashMap<>(); + for (int i = 0; i < nums2.length; i++) { + indexMap.putIfAbsent(nums2[i], i); + } + int[] result = new int[nums1.length]; + for (int i = 0; i < nums1.length; i++) { + result[i] = indexMap.get(nums1[i]); + } + return result; + } +} diff --git a/Easy/Find Champion I.java b/Easy/Find Champion I.java new file mode 100644 index 00000000..4728f452 --- /dev/null +++ b/Easy/Find Champion I.java @@ -0,0 +1,20 @@ +import java.util.Map.Entry; + +class Solution { + public int findChampion(int[][] grid) { + Map map = new HashMap<>(); + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 1) { + map.put(i, map.getOrDefault(i, 0) + 1); + } + } + } + return map.entrySet() + .stream() + .filter(entry -> entry.getValue() == grid.length - 1) + .findFirst() + .map(Entry::getKey) + .orElse(-1); + } +} diff --git a/Easy/Find Closest Number to Zero.java b/Easy/Find Closest Number to Zero.java new file mode 100644 index 00000000..ecb13d9f --- /dev/null +++ b/Easy/Find Closest Number to Zero.java @@ -0,0 +1,17 @@ +class Solution { + public int findClosestNumber(int[] nums) { + int[] result = {Integer.MAX_VALUE, Integer.MIN_VALUE}; + for (int num : nums) { + int distance = Math.abs(num); + if (distance <= result[0]) { + if (distance < result[0]) { + result[0] = distance; + result[1] = num; + } else { + result[1] = Math.max(num, result[1]); + } + } + } + return result[1]; + } +} diff --git a/Easy/Find Closest Person.java b/Easy/Find Closest Person.java new file mode 100644 index 00000000..0d178230 --- /dev/null +++ b/Easy/Find Closest Person.java @@ -0,0 +1,7 @@ +class Solution { + public int findClosest(int x, int y, int z) { + int diffOne = Math.abs(x - z); + int diffTwo = Math.abs(y - z); + return diffOne == diffTwo ? 0 : (diffOne < diffTwo ? 1 : 2); + } +} diff --git a/Easy/Find Common Characters.java b/Easy/Find Common Characters.java new file mode 100644 index 00000000..e9fa97e4 --- /dev/null +++ b/Easy/Find Common Characters.java @@ -0,0 +1,23 @@ +class Solution { + public List commonChars(String[] words) { + int[] commonFrequency = new int[26]; + Arrays.fill(commonFrequency, Integer.MAX_VALUE); + for (String word : words) { + int[] wordFreq = new int[26]; + for (char c : word.toCharArray()) { + wordFreq[c - 'a']++; + } + for (int i = 0; i < 26; i++) { + commonFrequency[i] = Math.min(commonFrequency[i], wordFreq[i]); + } + } + List result = new ArrayList<>(); + for (int i = 0; i < 26; i++) { + int count = commonFrequency[i]; + while (count-- > 0) { + result.add(String.valueOf((char) (97 + i))); + } + } + return result; + } +} diff --git a/Easy/Find Common Elements Between Two Arrays.java b/Easy/Find Common Elements Between Two Arrays.java new file mode 100644 index 00000000..4a6041ba --- /dev/null +++ b/Easy/Find Common Elements Between Two Arrays.java @@ -0,0 +1,26 @@ +class Solution { + public int[] findIntersectionValues(int[] nums1, int[] nums2) { + Map map1 = buildFrequencyMap(nums1); + Map map2 = buildFrequencyMap(nums2); + int[] result = new int[2]; + for (Integer key : map1.keySet()) { + if (map2.containsKey(key)) { + result[0] += map1.get(key); + } + } + for (Integer key : map2.keySet()) { + if (map1.containsKey(key)) { + result[1] += map2.get(key); + } + } + return result; + } + + private static Map buildFrequencyMap(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + return map; + } +} diff --git a/Easy/Find First Palindromic String in the Array.java b/Easy/Find First Palindromic String in the Array.java new file mode 100644 index 00000000..e215ab8d --- /dev/null +++ b/Easy/Find First Palindromic String in the Array.java @@ -0,0 +1,8 @@ +class Solution { + public String firstPalindrome(String[] words) { + return Arrays.stream(words) + .filter(word -> word.equals(new StringBuilder(word).reverse().toString())) + .findFirst() + .orElse(""); + } +} diff --git a/Easy/Find Greatest Common Divisor of Array.java b/Easy/Find Greatest Common Divisor of Array.java new file mode 100644 index 00000000..9e41f8fc --- /dev/null +++ b/Easy/Find Greatest Common Divisor of Array.java @@ -0,0 +1,9 @@ +import java.math.BigInteger; + + +class Solution { + public int findGCD(int[] nums) { + return BigInteger.valueOf(Arrays.stream(nums).max().orElse(1)) + .gcd(BigInteger.valueOf(Arrays.stream(nums).min().orElse(1))).intValue(); + } +} diff --git a/Easy/Find Indices of Stable Mountains.java b/Easy/Find Indices of Stable Mountains.java new file mode 100644 index 00000000..3e0fbd79 --- /dev/null +++ b/Easy/Find Indices of Stable Mountains.java @@ -0,0 +1,11 @@ +class Solution { + public List stableMountains(int[] height, int threshold) { + List result = new ArrayList<>(); + for (int i = 1; i < height.length; i++) { + if (height[i - 1] > threshold) { + result.add(i); + } + } + return result; + } +} diff --git a/Easy/Find Lucky Integer in an Array.java b/Easy/Find Lucky Integer in an Array.java new file mode 100644 index 00000000..d5ad2b50 --- /dev/null +++ b/Easy/Find Lucky Integer in an Array.java @@ -0,0 +1,14 @@ +class Solution { + public int findLucky(int[] arr) { + int[] counter = new int[501]; + for (int num : arr) { + counter[num]++; + } + for (int i = 500; i > 0; i--) { + if (counter[i] == i) { + return i; + } + } + return -1; + } +} diff --git a/Easy/Find Maximum Number of String Pairs.java b/Easy/Find Maximum Number of String Pairs.java new file mode 100644 index 00000000..f2673fbe --- /dev/null +++ b/Easy/Find Maximum Number of String Pairs.java @@ -0,0 +1,13 @@ +class Solution { + public int maximumNumberOfStringPairs(String[] words) { + Set set = new HashSet<>(); + int pairCount = 0; + for (String word : words) { + if (set.contains(new StringBuilder(word).reverse().toString())) { + pairCount++; + } + set.add(word); + } + return pairCount; + } +} diff --git a/Easy/Find Minimum Log Transportation Cost.java b/Easy/Find Minimum Log Transportation Cost.java new file mode 100644 index 00000000..3820474e --- /dev/null +++ b/Easy/Find Minimum Log Transportation Cost.java @@ -0,0 +1,12 @@ +class Solution { + public long minCuttingCost(int n, int m, int k) { + long cost = 0; + if (n > k) { + cost += ((long) (n - k)) * (k); + } + if (m > k) { + cost += ((long) (m - k)) * (k); + } + return cost; + } +} diff --git a/Easy/Find Minimum Operations to Make All Elements Divisible by Three.java b/Easy/Find Minimum Operations to Make All Elements Divisible by Three.java new file mode 100644 index 00000000..c8d6f59e --- /dev/null +++ b/Easy/Find Minimum Operations to Make All Elements Divisible by Three.java @@ -0,0 +1,11 @@ +class Solution { + public int minimumOperations(int[] nums) { + int count = 0; + for (int num : nums) { + if (num % 3 != 0) { + count++; + } + } + return count; + } +} diff --git a/Easy/Find Missing and Repeated Values.java b/Easy/Find Missing and Repeated Values.java new file mode 100644 index 00000000..52cf256e --- /dev/null +++ b/Easy/Find Missing and Repeated Values.java @@ -0,0 +1,21 @@ +class Solution { + public int[] findMissingAndRepeatedValues(int[][] grid) { + int n = grid.length; + int[] frequency = new int[n * n + 1]; + for (int[] row : grid) { + for (int num : row) { + frequency[num]++; + } + } + int[] result = new int[2]; + for (int i = 1; i <= n * n; i++) { + if (frequency[i] == 0) { + result[1] = i; + } + if (frequency[i] == 2) { + result[0] = i; + } + } + return result; + } +} diff --git a/Easy/Find Mode in Binary Search Tree.java b/Easy/Find Mode in Binary Search Tree.java index b88f9d7e..2b1f2fa0 100644 --- a/Easy/Find Mode in Binary Search Tree.java +++ b/Easy/Find Mode in Binary Search Tree.java @@ -4,46 +4,63 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public int[] findMode(TreeNode root) { - Map map = new HashMap<>(); - inorderTraversal(root, map); - - int maxVal = 0; - int count = 0; - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() > maxVal) { - maxVal = entry.getValue(); - count = 1; - } - else if (entry.getValue() == maxVal) { - count++; - } + ResultWrapper resultWrapper = new ResultWrapper(); + inorder(root, resultWrapper); + return resultWrapper.result.stream().mapToInt(Integer::intValue).toArray(); + } + + private void inorder(TreeNode node, ResultWrapper resultWrapper) { + if (node == null) { + return; + } + inorder(node.left, resultWrapper); + int val = node.val; + resultWrapper.recordStreak(val); + resultWrapper.updateResult(val); + inorder(node.right, resultWrapper); + } + + private static class ResultWrapper { + private int maxStreak; + private int currStreak; + private Integer curr; + private List result; + + public ResultWrapper() { + this.maxStreak = 0; + this.currStreak = 0; + this.curr = 0; + this.result = new ArrayList<>(); } - - int[] ans = new int[count]; - int i = 0; - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == maxVal) { - ans[i++] = entry.getKey(); + + public void recordStreak(int num) { + if (num == curr) { + currStreak++; + } else { + currStreak = 1; + curr = num; + } + } + + public void updateResult(int num) { + if (currStreak > maxStreak) { + result.clear(); + maxStreak = currStreak; + } + if (currStreak == maxStreak) { + result.add(num); } } - - return ans; - - } - - public void inorderTraversal(TreeNode root, Map map) { - - if (root == null) return; - - inorderTraversal(root.left, map); - map.put(root.val, map.getOrDefault(root.val, 0) + 1); - inorderTraversal(root.right, map); } } diff --git a/Easy/Find N Unique Integers Sum up to Zero.java b/Easy/Find N Unique Integers Sum up to Zero.java new file mode 100644 index 00000000..1b1de933 --- /dev/null +++ b/Easy/Find N Unique Integers Sum up to Zero.java @@ -0,0 +1,17 @@ +class Solution { + public int[] sumZero(int n) { + int[] result = new int[n]; + int idx = 0; + int half = n / 2; + for (int i = -1 * half; i < 0; i++) { + result[idx++] = i; + } + if (n % 2 != 0) { + result[idx++] = 0; + } + for (int i = 1; i <= half; i++) { + result[idx++] = i; + } + return result; + } +} diff --git a/Easy/Find Nearest Point That Has the Same X or Y Coordinate.java b/Easy/Find Nearest Point That Has the Same X or Y Coordinate.java new file mode 100644 index 00000000..4a1e5eb4 --- /dev/null +++ b/Easy/Find Nearest Point That Has the Same X or Y Coordinate.java @@ -0,0 +1,34 @@ +class Solution { + public int nearestValidPoint(int x, int y, int[][] points) { + int[] basePoint = new int[]{x, y}; + return IntStream.range(0, points.length).mapToObj(i -> new Point(basePoint, i, points[i])) + .filter( + Point::isMatch) + .sorted(Comparator.comparingInt(Point::getManhattanDistance).thenComparing(Point::getIdx)) + .map(Point::getIdx).findFirst().orElse(-1); + } + + private static class Point { + int[] basePoint; + int idx; + int[] currPoint; + + public Point(int[] basePoint, int idx, int[] currPoint) { + this.basePoint = basePoint; + this.idx = idx; + this.currPoint = currPoint; + } + + public int getIdx() { + return idx; + } + + public int getManhattanDistance() { + return Math.abs(currPoint[0] - basePoint[0]) + Math.abs(currPoint[1] - basePoint[1]); + } + + public boolean isMatch() { + return currPoint[0] == basePoint[0] || currPoint[1] == basePoint[1]; + } + } +} diff --git a/Easy/Find Numbers with Even Number of Digits.java b/Easy/Find Numbers with Even Number of Digits.java new file mode 100644 index 00000000..961f9ec5 --- /dev/null +++ b/Easy/Find Numbers with Even Number of Digits.java @@ -0,0 +1,9 @@ +class Solution { + public int findNumbers(int[] nums) { + int count = 0; + for (int num : nums) { + count += String.valueOf(num).length() % 2 == 0 ? 1 : 0; + } + return count; + } +} diff --git a/Easy/Find Pivot Index.java b/Easy/Find Pivot Index.java index 9965ed44..0bc7b234 100644 --- a/Easy/Find Pivot Index.java +++ b/Easy/Find Pivot Index.java @@ -1,21 +1,17 @@ class Solution { - public int pivotIndex(int[] nums) { - int left = 0; - int sum = 0; - - for (int i=0;i> findSolution(CustomFunction customfunction, int z) { + List> list = new ArrayList<>(); + for (int i = 1; i <= z; i++) { + for (int j = 1; j <= z; j++) { + int val = customfunction.f(i, j); + if (val == z) { + list.add(Arrays.asList(i, j)); + } + if (val > z) { + break; + } + } + } + return list; + } +} diff --git a/Easy/Find Resultant Array After Removing Anagrams.java b/Easy/Find Resultant Array After Removing Anagrams.java new file mode 100644 index 00000000..c2f0a9b0 --- /dev/null +++ b/Easy/Find Resultant Array After Removing Anagrams.java @@ -0,0 +1,31 @@ +class Solution { + public List removeAnagrams(String[] words) { + List result = new ArrayList<>(); + int startIdx = 0; + for (int i = 1; i < words.length; i++) { + if (!isAnagram(words[i], words[startIdx])) { + result.add(words[startIdx]); + startIdx = i; + } + } + result.add(words[startIdx]); + return result; + } + + private boolean isAnagram(String wordOne, String wordTwo) { + if (wordOne.length() != wordTwo.length()) { + return false; + } + int[] counter = new int[26]; + for (int i = 0; i < wordOne.length(); i++) { + counter[wordOne.charAt(i) - 'a']++; + counter[wordTwo.charAt(i) - 'a']--; + } + for (int i = 0; i < 26; i++) { + if (counter[i] != 0) { + return false; + } + } + return true; + } +} diff --git a/Easy/Find Smallest Letter Greater Than Target.java b/Easy/Find Smallest Letter Greater Than Target.java new file mode 100644 index 00000000..6cdfb73a --- /dev/null +++ b/Easy/Find Smallest Letter Greater Than Target.java @@ -0,0 +1,17 @@ +class Solution { + public char nextGreatestLetter(char[] letters, char target) { + int start = 0; + int end = letters.length - 1; + int idx = -1; + while (start <= end) { + int mid = (start + end) / 2; + if (letters[mid] > target) { + idx = mid; + end = mid - 1; + } else { + start = mid + 1; + } + } + return idx == -1 ? letters[0] : letters[idx]; + } +} diff --git a/Easy/Find Subarrays With Equal Sum.java b/Easy/Find Subarrays With Equal Sum.java new file mode 100644 index 00000000..834989a0 --- /dev/null +++ b/Easy/Find Subarrays With Equal Sum.java @@ -0,0 +1,13 @@ +class Solution { + public boolean findSubarrays(int[] nums) { + Set set = new HashSet<>(); + for (int i = 0; i < nums.length - 1; i++) { + int sum = nums[i] + nums[i + 1]; + if (set.contains(sum)) { + return true; + } + set.add(sum); + } + return false; + } +} diff --git a/Easy/Find Target Indices After Sorting Array.java b/Easy/Find Target Indices After Sorting Array.java new file mode 100644 index 00000000..d000c8ad --- /dev/null +++ b/Easy/Find Target Indices After Sorting Array.java @@ -0,0 +1,15 @@ +class Solution { + public List targetIndices(int[] nums, int target) { + int count = 0; + int lessThanCount = 0; + for (int num : nums) { + count += num == target ? 1 : 0; + lessThanCount += num < target ? 1 : 0; + } + List result = new ArrayList<>(); + while (count-- > 0) { + result.add(lessThanCount++); + } + return result; + } +} diff --git a/Easy/Find Winner on a Tic Tac Toe Game.java b/Easy/Find Winner on a Tic Tac Toe Game.java new file mode 100644 index 00000000..4fc97260 --- /dev/null +++ b/Easy/Find Winner on a Tic Tac Toe Game.java @@ -0,0 +1,38 @@ +class Solution { + public String tictactoe(int[][] moves) { + int n = 3; + Map> rowMap = new HashMap<>(); + Map> colMap = new HashMap<>(); + Map rightDiagMap = new HashMap<>(); + Map leftDiagMap = new HashMap<>(); + for (int i = 0; i < moves.length; i++) { + int x = moves[i][0]; + int y = moves[i][1]; + char move = i % 2 == 0 ? 'X' : 'O'; + String player = i % 2 == 0 ? "A" : "B"; + Map row = rowMap.computeIfAbsent(x, k -> new HashMap<>()); + row.put(move, row.getOrDefault(move, 0) + 1); + if (row.get(move) == 3) { + return player; + } + Map col = colMap.computeIfAbsent(y, k -> new HashMap<>()); + col.put(move, col.getOrDefault(move, 0) + 1); + if (col.get(move) == 3) { + return player; + } + if (x == y) { + leftDiagMap.put(move, leftDiagMap.getOrDefault(move, 0) + 1); + if (leftDiagMap.get(move) == 3) { + return player; + } + } + if (x + y == n - 1) { + rightDiagMap.put(move, rightDiagMap.getOrDefault(move, 0) + 1); + if (rightDiagMap.get(move) == 3) { + return player; + } + } + } + return moves.length == n * n ? "Draw" : "Pending"; + } +} diff --git a/Easy/Find Words Containing Character.java b/Easy/Find Words Containing Character.java new file mode 100644 index 00000000..ba268c41 --- /dev/null +++ b/Easy/Find Words Containing Character.java @@ -0,0 +1,8 @@ +class Solution { + public List findWordsContaining(String[] words, char x) { + return IntStream.range(0, words.length) + .filter(i -> words[i].indexOf(x) != -1) + .boxed() + .collect(Collectors.toList()); + } +} diff --git a/Easy/Find Words That Can Be Formed by Characters.java b/Easy/Find Words That Can Be Formed by Characters.java new file mode 100644 index 00000000..23550740 --- /dev/null +++ b/Easy/Find Words That Can Be Formed by Characters.java @@ -0,0 +1,24 @@ +class Solution { + public int countCharacters(String[] words, String chars) { + Map targetMap = buildFrequencyMap(chars); + return Arrays.stream(words) + .filter(word -> doesIntersect(buildFrequencyMap(word), targetMap)) + .mapToInt(String::length) + .sum(); + } + + private static boolean doesIntersect(Map currMap, Map targetMap) { + for (Character key : currMap.keySet()) { + if (targetMap.getOrDefault(key, 0L) < currMap.get(key)) { + return false; + } + } + return true; + } + + private static Map buildFrequencyMap(String s) { + return s.chars() + .mapToObj(c -> (char) c) + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())); + } +} diff --git a/Easy/Find if Digit Game Can Be Won.java b/Easy/Find if Digit Game Can Be Won.java new file mode 100644 index 00000000..22c76892 --- /dev/null +++ b/Easy/Find if Digit Game Can Be Won.java @@ -0,0 +1,14 @@ +class Solution { + public boolean canAliceWin(int[] nums) { + int singleDigitSum = 0; + int doubleDigitSum = 0; + for (int num : nums) { + if (String.valueOf(num).length() > 1) { + doubleDigitSum += num; + } else { + singleDigitSum += num; + } + } + return singleDigitSum > doubleDigitSum || doubleDigitSum > singleDigitSum; + } +} diff --git a/Easy/Find if Path Exists in Graph.java b/Easy/Find if Path Exists in Graph.java new file mode 100644 index 00000000..7a0c6a47 --- /dev/null +++ b/Easy/Find if Path Exists in Graph.java @@ -0,0 +1,26 @@ +class Solution { + public boolean validPath(int n, int[][] edges, int source, int destination) { + Map> graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]); + graph.computeIfAbsent(edge[1], k -> new ArrayList<>()).add(edge[0]); + } + Queue queue = new LinkedList<>(); + queue.add(source); + Set visited = new HashSet<>(); + visited.add(source); + while (!queue.isEmpty()) { + Integer removed = queue.remove(); + if (removed == destination) { + return true; + } + for (Integer connection : graph.getOrDefault(removed, new ArrayList<>())) { + if (!visited.contains(connection)) { + queue.add(connection); + visited.add(connection); + } + } + } + return false; + } +} diff --git a/Easy/Find the Array Concatenation Value.java b/Easy/Find the Array Concatenation Value.java new file mode 100644 index 00000000..974ca82b --- /dev/null +++ b/Easy/Find the Array Concatenation Value.java @@ -0,0 +1,13 @@ +class Solution { + public long findTheArrayConcVal(int[] nums) { + long concatenatedValue = 0; + int start = 0; + int end = nums.length - 1; + while (start <= end) { + concatenatedValue += start == end ? nums[start] : Integer.parseInt(nums[start] + "" + nums[end]); + start++; + end--; + } + return concatenatedValue; + } +} diff --git a/Easy/Find the Child Who Has the Ball After K Seconds.java b/Easy/Find the Child Who Has the Ball After K Seconds.java new file mode 100644 index 00000000..6a4c8193 --- /dev/null +++ b/Easy/Find the Child Who Has the Ball After K Seconds.java @@ -0,0 +1,7 @@ +class Solution { + public int numberOfChild(int n, int k) { + int factor = k / (n - 1); + int remainder = k % (n - 1); + return factor % 2 == 0 ? remainder : n - 1 - remainder; + } +} diff --git a/Easy/Find the Difference of Two Arrays.java b/Easy/Find the Difference of Two Arrays.java new file mode 100644 index 00000000..fa061f5f --- /dev/null +++ b/Easy/Find the Difference of Two Arrays.java @@ -0,0 +1,9 @@ +class Solution { + public List> findDifference(int[] nums1, int[] nums2) { + Set setOne = Arrays.stream(nums1).boxed().collect(Collectors.toSet()); + Set setTwo = Arrays.stream(nums2).boxed().collect(Collectors.toSet()); + return Arrays.asList( + setOne.stream().filter(e -> !setTwo.contains(e)).collect(Collectors.toList()), + setTwo.stream().filter(e -> !setOne.contains(e)).collect(Collectors.toList())); + } +} diff --git a/Easy/Find the Distance Value Between Two Arrays.java b/Easy/Find the Distance Value Between Two Arrays.java new file mode 100644 index 00000000..0fb09098 --- /dev/null +++ b/Easy/Find the Distance Value Between Two Arrays.java @@ -0,0 +1,28 @@ +class Solution { + public int findTheDistanceValue(int[] arr1, int[] arr2, int d) { + Arrays.sort(arr2); + int distance = 0; + for (int i = 0; i < arr1.length; i++) { + if (outsideRange(arr2, arr1[i] - d, arr1[i] + d)) { + distance++; + } + } + return distance; + } + + private static boolean outsideRange(int[] arr, int from, int to) { + int start = 0; + int end = arr.length - 1; + while (start <= end) { + int mid = start + (end - start) / 2; + if (arr[mid] >= from && arr[mid] <= to) { + return false; + } else if (arr[mid] < from) { + start = mid + 1; + } else { + end = mid - 1; + } + } + return true; + } +} diff --git a/Easy/Find the Distinct Difference Array.java b/Easy/Find the Distinct Difference Array.java new file mode 100644 index 00000000..5578427f --- /dev/null +++ b/Easy/Find the Distinct Difference Array.java @@ -0,0 +1,17 @@ +class Solution { + public int[] distinctDifferenceArray(int[] nums) { + int[] rightToLeft = new int[nums.length]; + Set set = new HashSet<>(); + for (int i = nums.length - 1; i >= 0; i--) { + set.add(nums[i]); + rightToLeft[i] = set.size(); + } + int[] diff = new int[nums.length]; + set.clear(); + for (int i = 0; i < nums.length; i++) { + set.add(nums[i]); + diff[i] = set.size() - (i == nums.length - 1 ? 0 : rightToLeft[i + 1]); + } + return diff; + } +} diff --git a/Easy/Find the Highest Altitude.java b/Easy/Find the Highest Altitude.java new file mode 100644 index 00000000..aa7d12e5 --- /dev/null +++ b/Easy/Find the Highest Altitude.java @@ -0,0 +1,11 @@ +class Solution { + public int largestAltitude(int[] gain) { + int highestAltitude = 0; + int currAltitude = 0; + for (int i = 0; i < gain.length; i++) { + currAltitude = currAltitude + gain[i]; + highestAltitude = Math.max(highestAltitude, currAltitude); + } + return highestAltitude; + } +} diff --git a/Easy/Find the Integer Added to Array I.java b/Easy/Find the Integer Added to Array I.java new file mode 100644 index 00000000..c5d551e3 --- /dev/null +++ b/Easy/Find the Integer Added to Array I.java @@ -0,0 +1,11 @@ +class Solution { + public int addedInteger(int[] nums1, int[] nums2) { + int minOne = nums1[0]; + int minTwo = nums2[0]; + for (int i = 0; i < nums1.length; i++) { + minOne = Math.min(minOne, nums1[i]); + minTwo = Math.min(minTwo, nums2[i]); + } + return minTwo - minOne; + } +} diff --git a/Easy/Find the K-Beauty of a Number.java b/Easy/Find the K-Beauty of a Number.java new file mode 100644 index 00000000..a2a1b9f6 --- /dev/null +++ b/Easy/Find the K-Beauty of a Number.java @@ -0,0 +1,13 @@ +class Solution { + public int divisorSubstrings(int num, int k) { + String numString = String.valueOf(num); + int count = 0; + for (int i = 0; i <= numString.length() - k; i++) { + int substringNum = Integer.parseInt(numString.substring(i, i + k)); + if (substringNum != 0 && num % substringNum == 0) { + count++; + } + } + return count; + } +} diff --git a/Easy/Find the K-or of an Array.java b/Easy/Find the K-or of an Array.java new file mode 100644 index 00000000..48343d5e --- /dev/null +++ b/Easy/Find the K-or of an Array.java @@ -0,0 +1,31 @@ +class Solution { + public int findKOr(int[] nums, int k) { + Map map = new HashMap<>(); + for (int num : nums) { + List setBits = getSetBits(num); + for (Integer setBit : setBits) { + map.put(setBit, map.getOrDefault(setBit, 0) + 1); + } + } + int result = 0; + for (int i = 0, p = 1; i < 32; i++, p *= 2) { + if (map.getOrDefault(i, 0) >= k) { + result += p; + } + } + return result; + } + + private static List getSetBits(int num) { + List bits = new ArrayList<>(); + int bit = 0; + while (num > 0) { + if (num % 2 == 1) { + bits.add(bit); + } + num = num / 2; + bit++; + } + return bits; + } +} diff --git a/Easy/Find the Longest Balanced Substring of a Binary String.java b/Easy/Find the Longest Balanced Substring of a Binary String.java new file mode 100644 index 00000000..2b1d3f2a --- /dev/null +++ b/Easy/Find the Longest Balanced Substring of a Binary String.java @@ -0,0 +1,25 @@ +class Solution { + public int findTheLongestBalancedSubstring(String s) { + int maxLength = 0; + int idx = 0; + while (idx < s.length()) { + if (s.charAt(idx) != '0') { + idx++; + continue; + } + int zeroCount = 0; + while (idx < s.length() && s.charAt(idx) == '0') { + idx++; + zeroCount++; + } + int oneCount = 0; + while (idx < s.length() && s.charAt(idx) == '1') { + idx++; + oneCount++; + } + maxLength = Math.max(maxLength, 2 * Math.min(zeroCount, oneCount)); + + } + return maxLength; + } +} diff --git a/Easy/Find the Losers of the Circular Game.java b/Easy/Find the Losers of the Circular Game.java new file mode 100644 index 00000000..aaa8c059 --- /dev/null +++ b/Easy/Find the Losers of the Circular Game.java @@ -0,0 +1,19 @@ +class Solution { + public int[] circularGameLosers(int n, int k) { + Set set = new HashSet<>(); + int player = 1; + int multiple = k; + while (set.add(player)) { + player = (player + k) % n; + player = player == 0 ? n : player; + k += multiple; + } + int[] result = new int[n - set.size()]; + for (int i = 1, j = 0; i <= n; i++) { + if (!set.contains(i)) { + result[j++] = i; + } + } + return result; + } +} diff --git a/Easy/Find the Maximum Achievable Number.java b/Easy/Find the Maximum Achievable Number.java new file mode 100644 index 00000000..841862be --- /dev/null +++ b/Easy/Find the Maximum Achievable Number.java @@ -0,0 +1,5 @@ +class Solution { + public int theMaximumAchievableX(int num, int t) { + return num + 2 * t; + } +} diff --git a/Easy/Find the Middle Index in Array.java b/Easy/Find the Middle Index in Array.java new file mode 100644 index 00000000..4ad9ddbf --- /dev/null +++ b/Easy/Find the Middle Index in Array.java @@ -0,0 +1,20 @@ +class Solution { + public int findMiddleIndex(int[] nums) { + int n = nums.length; + int[] rightSum = new int[n]; + int currSum = 0; + for (int i = n - 1; i >= 0; i--) { + currSum += nums[i]; + rightSum[i] = currSum; + } + currSum = 0; + for (int i = 0; i < n; i++) { + int rightCurrSum = i != n - 1 ? rightSum[i + 1] : 0; + if (currSum == rightCurrSum) { + return i; + } + currSum += nums[i]; + } + return -1; + } +} diff --git a/Easy/Find the Number of Good Pairs I.java b/Easy/Find the Number of Good Pairs I.java new file mode 100644 index 00000000..143d6abd --- /dev/null +++ b/Easy/Find the Number of Good Pairs I.java @@ -0,0 +1,13 @@ +class Solution { + public int numberOfPairs(int[] nums1, int[] nums2, int k) { + int count = 0; + for (int i = 0; i < nums1.length; i++) { + for (int j = 0; j < nums2.length; j++) { + if (nums1[i] % (nums2[j] * k) == 0) { + count++; + } + } + } + return count; + } +} diff --git a/Easy/Find the Number of Winning Players.java b/Easy/Find the Number of Winning Players.java new file mode 100644 index 00000000..fd4ea2ba --- /dev/null +++ b/Easy/Find the Number of Winning Players.java @@ -0,0 +1,14 @@ +class Solution { + public int winningPlayerCount(int n, int[][] pick) { + Map> map = new HashMap<>(); + Set winners = new HashSet<>(); + for (int[] p : pick) { + map.computeIfAbsent(p[0], k -> new HashMap<>()); + map.get(p[0]).put(p[1], map.get(p[0]).getOrDefault(p[1], 0) + 1); + if (map.get(p[0]).get(p[1]) > p[0]) { + winners.add(p[0]); + } + } + return winners.size(); + } +} diff --git a/Easy/Find the Original Typed String I.java b/Easy/Find the Original Typed String I.java new file mode 100644 index 00000000..dd6a5177 --- /dev/null +++ b/Easy/Find the Original Typed String I.java @@ -0,0 +1,17 @@ +class Solution { + public int possibleStringCount(String word) { + int idx = 0; + int result = 1; + while (idx < word.length()) { + int currIdx = idx; + char c = word.charAt(currIdx); + while (currIdx < word.length() && word.charAt(currIdx) == c) { + currIdx++; + } + int segement = currIdx - idx; + result += segement - 1; + idx = currIdx; + } + return result; + } +} diff --git a/Easy/Find the Peaks.java b/Easy/Find the Peaks.java new file mode 100644 index 00000000..f6120cd5 --- /dev/null +++ b/Easy/Find the Peaks.java @@ -0,0 +1,11 @@ +class Solution { + public List findPeaks(int[] mountain) { + List result = new ArrayList<>(); + for (int i = 1; i < mountain.length - 1; i++) { + if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i + 1]) { + result.add(i); + } + } + return result; + } +} diff --git a/Easy/Find the Pivot Integer.java b/Easy/Find the Pivot Integer.java new file mode 100644 index 00000000..3cad5e0b --- /dev/null +++ b/Easy/Find the Pivot Integer.java @@ -0,0 +1,18 @@ +class Solution { + public int pivotInteger(int n) { + int[] leftToRightSum = new int[n]; + int currSum = 0; + for (int i = 0; i < n; i++) { + currSum += i + 1; + leftToRightSum[i] = currSum; + } + int rightToLeftSum = 0; + for (int i = n - 1; i >= 0; i--) { + rightToLeftSum += i + 1; + if (leftToRightSum[i] == rightToLeftSum) { + return i + 1; + } + } + return -1; + } +} diff --git a/Easy/Find the Power of K-Size Subarrays I.java b/Easy/Find the Power of K-Size Subarrays I.java new file mode 100644 index 00000000..975c1a3a --- /dev/null +++ b/Easy/Find the Power of K-Size Subarrays I.java @@ -0,0 +1,18 @@ +class Solution { + public int[] resultsArray(int[] nums, int k) { + if (k == 1) { + return nums; + } + int n = nums.length; + int[] result = new int[n - k + 1]; + Arrays.fill(result, -1); + int count = 1; + for (int i = 0; i < nums.length - 1; i++) { + count = (nums[i + 1] - nums[i] == 1) ? count + 1 : 1; + if (count >= k) { + result[i - k + 2] = nums[i + 1]; + } + } + return result; + } +} diff --git a/Easy/Find the Sum of Encrypted Integers.java b/Easy/Find the Sum of Encrypted Integers.java new file mode 100644 index 00000000..6cee31bc --- /dev/null +++ b/Easy/Find the Sum of Encrypted Integers.java @@ -0,0 +1,21 @@ +class Solution { + public int sumOfEncryptedInt(int[] nums) { + int sum = 0; + for (int num : nums) { + sum += getEncryptedSum(num); + } + return sum; + } + + private static int getEncryptedSum(int num) { + int count = 0; + int max = 0; + while (num > 0) { + int digit = num % 10; + num /= 10; + count++; + max = Math.max(digit, max); + } + return Integer.parseInt(String.join("", Collections.nCopies(count, String.valueOf(max)))); + } +} diff --git a/Easy/Find the Town Judge.java b/Easy/Find the Town Judge.java index 60c4a84f..8605e848 100644 --- a/Easy/Find the Town Judge.java +++ b/Easy/Find the Town Judge.java @@ -1,18 +1,15 @@ class Solution { - public int findJudge(int N, int[][] trust) { - int[] count = new int[N + 1]; - - for (int[] item : trust) { - count[item[0]]--; - count[item[1]]++; - } - - for (int i = 1; i <= N; i++) { - if (count[i] == N - 1) { - return i; - } - } - - return -1; + public int findJudge(int n, int[][] trust) { + int[] trustScore = new int[n + 1]; + for (int[] trustPair : trust) { + trustScore[trustPair[1]]++; + trustScore[trustPair[0]]--; } + for (int i = 1; i <= n; i++) { + if (trustScore[i] == n - 1) { + return i; + } + } + return -1; + } } diff --git a/Easy/Find the Width of Columns of a Grid.java b/Easy/Find the Width of Columns of a Grid.java new file mode 100644 index 00000000..843813b9 --- /dev/null +++ b/Easy/Find the Width of Columns of a Grid.java @@ -0,0 +1,13 @@ +class Solution { + public int[] findColumnWidth(int[][] grid) { + int[] result = new int[grid[0].length]; + for (int i = 0; i < grid[0].length; i++) { + int maxLength = 0; + for (int j = 0; j < grid.length; j++) { + maxLength = Math.max(maxLength, String.valueOf(grid[j][i]).length()); + } + result[i] = maxLength; + } + return result; + } +} diff --git a/Easy/Find the XOR of Numbers Which Appear Twice.java b/Easy/Find the XOR of Numbers Which Appear Twice.java new file mode 100644 index 00000000..baa845bc --- /dev/null +++ b/Easy/Find the XOR of Numbers Which Appear Twice.java @@ -0,0 +1,12 @@ +class Solution { + public int duplicateNumbersXOR(int[] nums) { + Set set = new HashSet<>(); + int xor = 0; + for (int num : nums) { + if (!set.add(num)) { + xor = xor ^ num; + } + } + return xor; + } +} diff --git a/Easy/Find the difference.java b/Easy/Find the difference.java index cef03549..ca12be6d 100644 --- a/Easy/Find the difference.java +++ b/Easy/Find the difference.java @@ -1,25 +1,15 @@ -public class Solution { +class Solution { public char findTheDifference(String s, String t) { - String s1 = s; - String s2 = t; - s1 = sortString(s1); - s2 = sortString(s2); - - char ans = '0'; - - for (int i=0;i< s1.length();i++) { - if (s2.charAt(i) != s1.charAt(i)) { - ans = s2.charAt(i); - break; + int[] frequency = new int[26]; + for (char c : s.toCharArray()) { + frequency[c - 'a']++; + } + for (char c : t.toCharArray()) { + if (frequency[c - 'a'] == 0) { + return c; } + frequency[c - 'a']--; } - return ans == '0' ? s2.charAt(s2.length()-1) : ans; - } - - public String sortString(String s) { - char[] chars = s.toCharArray(); - Arrays.sort(chars); - String sorted = new String(chars); - return sorted; + return ' '; } -} \ No newline at end of file +} diff --git a/Easy/Finding 3-Digit Even Numbers.java b/Easy/Finding 3-Digit Even Numbers.java new file mode 100644 index 00000000..e8feb4aa --- /dev/null +++ b/Easy/Finding 3-Digit Even Numbers.java @@ -0,0 +1,33 @@ +class Solution { + public int[] findEvenNumbers(int[] digits) { + List list = new ArrayList<>(); + int[] counter = new int[10]; + for (int digit : digits) { + counter[digit]++; + } + for (int digitOne = 1; digitOne <= 9; digitOne++) { + if (counter[digitOne] > 0) { + counter[digitOne]--; + for (int digitTwo = 0; digitTwo <= 9; digitTwo++) { + if (counter[digitTwo] > 0) { + counter[digitTwo]--; + for (int digitThree = 0; digitThree <= 8; digitThree += 2) { + if (counter[digitThree] > 0) { + list.add(digitOne * 100 + digitTwo * 10 + digitThree); + } + } + counter[digitTwo]++; + } + } + counter[digitOne]++; + } + } + int[] result = new int[list.size()]; + int idx = 0; + for (int num : list) { + result[idx++] = num; + } + Arrays.sort(result); + return result; + } +} diff --git a/Easy/First Bad Version.java b/Easy/First Bad Version.java index 7e86899b..649a6430 100644 --- a/Easy/First Bad Version.java +++ b/Easy/First Bad Version.java @@ -2,18 +2,23 @@ boolean isBadVersion(int version); */ public class Solution extends VersionControl { - public int firstBadVersion(int n) { - int start = 1; - int end = n; - while (start < end) { - int mid = start + (end - start)/2; - if (!isBadVersion(mid)) { - start = mid + 1; - } - else { - end = mid; - } - } - return start; + public int firstBadVersion(int n) { + if (n == 1) { + return 1; } + int start = 1; + int end = n; + int minIdx = Integer.MAX_VALUE; + while (start <= end) { + int mid = start + (end - start) / 2; + if (isBadVersion(mid)) { + minIdx = Math.min(minIdx, mid); + end = mid - 1; + } + else { + start = mid + 1; + } + } + return minIdx; + } } diff --git a/Easy/First Letter to Appear Twice.java b/Easy/First Letter to Appear Twice.java new file mode 100644 index 00000000..23a3f653 --- /dev/null +++ b/Easy/First Letter to Appear Twice.java @@ -0,0 +1,12 @@ +class Solution { + public char repeatedCharacter(String s) { + boolean[] seen = new boolean[26]; + for (char c : s.toCharArray()) { + if (seen[c - 'a']) { + return c; + } + seen[c - 'a'] = true; + } + return ' '; + } +} diff --git a/Easy/First Unique Character in a String.java b/Easy/First Unique Character in a String.java new file mode 100644 index 00000000..1659cbb5 --- /dev/null +++ b/Easy/First Unique Character in a String.java @@ -0,0 +1,14 @@ +class Solution { + public int firstUniqChar(String s) { + int[] count = new int[26]; + for (char c : s.toCharArray()) { + count[c - 'a']++; + } + for (int i = 0; i < s.length(); i++) { + if (count[s.charAt(i) - 'a'] == 1) { + return i; + } + } + return -1; + } +} diff --git a/Easy/Fixed Point.java b/Easy/Fixed Point.java index e1dd818d..c2ac5a56 100644 --- a/Easy/Fixed Point.java +++ b/Easy/Fixed Point.java @@ -1,18 +1,21 @@ class Solution { - public int fixedPoint(int[] A) { - int low = 0; - int high = A.length - 1; - - while (low < high) { - int mid = (low + high) / 2; - if (A[mid] - mid < 0) { - low = mid + 1; - } - else { - high = mid; - } - } - - return low == A[low] ? low : -1; + public int fixedPoint(int[] A) { + int start = 0; + int end = A.length - 1; + int minIdx = Integer.MAX_VALUE; + while (start <= end) { + int mid = (start + end) / 2; + if (A[mid] == mid) { + minIdx = Math.min(minIdx, mid); + end = mid - 1; + } + else if (A[mid] > mid) { + end = mid - 1; + } + else { + start = mid + 1; + } } + return minIdx == Integer.MAX_VALUE ? -1 : minIdx; + } } diff --git a/Easy/Fizz Buzz.java b/Easy/Fizz Buzz.java new file mode 100644 index 00000000..c28fabc9 --- /dev/null +++ b/Easy/Fizz Buzz.java @@ -0,0 +1,17 @@ +class Solution { + public List fizzBuzz(int n) { + List result = new ArrayList<>(); + for (int i = 1; i <= n; i++) { + if (i % 15 == 0) { + result.add("FizzBuzz"); + } else if (i % 3 == 0) { + result.add("Fizz"); + } else if (i % 5 == 0) { + result.add("Buzz"); + } else { + result.add(String.valueOf(i)); + } + } + return result; + } +} diff --git a/Easy/FizzBuzz.java b/Easy/FizzBuzz.java deleted file mode 100644 index 7af5e630..00000000 --- a/Easy/FizzBuzz.java +++ /dev/null @@ -1,11 +0,0 @@ -class Solution { - public List fizzBuzz(int n) { - List list = new ArrayList<>(); - - for (int i=1; i <= n; i++) { - list.add((i%3 != 0 && i % 5 != 0) ? String.valueOf(i) : (i % 3 == 0 ? "Fizz" : "") + (i % 5 == 0 ? "Buzz" : "")); - } - - return list; - } -} diff --git a/Easy/Flip Game.java b/Easy/Flip Game.java index 727227e2..097acf18 100644 --- a/Easy/Flip Game.java +++ b/Easy/Flip Game.java @@ -1,30 +1,11 @@ class Solution { - public static List generatePossibleNextMoves(String s) { - List ans = new ArrayList<>(); - - if (s.length() < 2) { - return ans; - } - - if (s.equals("--")) { - return ans; - } - - int i = 0; - while (i < s.length()-1) { - if (s.charAt(i) == s.charAt(i+1) && s.charAt(i) == '+') { - StringBuilder sb = new StringBuilder(); - sb.append(s.substring(0, i)); - sb.append('-'); - sb.append('-'); - sb.append(s.substring(i+2)); - - ans.add(sb.toString()); + public List generatePossibleNextMoves(String currentState) { + List moves = new ArrayList<>(); + for (int i = 0; i < currentState.length() - 1; i++) { + if (currentState.substring(i, i + 2).equals("++")) { + moves.add(currentState.substring(0, i) + "--" + currentState.substring(i + 2)); } - - i++; } - - return ans; + return moves; } } diff --git a/Easy/Flipping an Image.java b/Easy/Flipping an Image.java index ffb6fb5a..0e5d44f3 100644 --- a/Easy/Flipping an Image.java +++ b/Easy/Flipping an Image.java @@ -1,22 +1,16 @@ class Solution { - public int[][] flipAndInvertImage(int[][] A) { - int[][] ans = new int[A.length][A[0].length]; - - for (int i=0; i temp = Arrays.stream(A[i]). - boxed(). - collect(Collectors.toList()); - - Collections.reverse(temp); - ans[i] = temp.stream().mapToInt(e -> e).toArray(); - } - - for (int i=0;i= 1) dfs(image, sr-1, sc, color, newColor); - if (sc >= 1) dfs(image, sr, sc-1, color, newColor); - if (sr+1 < image.length) dfs(image, sr+1, sc, color, newColor); - if (sc+1 < image[0].length) dfs(image, sr, sc+1, color, newColor); + Queue queue = new LinkedList<>(); + queue.add(new int[]{sr, sc}); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] coordinate = queue.remove(); + int xPoint = coordinate[0]; + int yPoint = coordinate[1]; + image[xPoint][yPoint] = newColor; + for (int[] dir : DIRS) { + int newXPoint = xPoint + dir[0]; + int newYPoint = yPoint + dir[1]; + if (newXPoint >= 0 && newYPoint >= 0 && newXPoint < numOfRows && newYPoint < numOfCols && image[newXPoint][newYPoint] == originalColor) { + queue.add(new int[]{newXPoint, newYPoint}); + } } - } + } + } + return image; + } } diff --git a/Easy/Flower Planting With No Adjacent.java b/Easy/Flower Planting With No Adjacent.java new file mode 100644 index 00000000..88bf6a8b --- /dev/null +++ b/Easy/Flower Planting With No Adjacent.java @@ -0,0 +1,22 @@ +class Solution { + public int[] gardenNoAdj(int n, int[][] paths) { + Map> map = new HashMap<>(); + for (int[] path : paths) { + map.computeIfAbsent(path[0], k -> new HashSet<>()).add(path[1]); + map.computeIfAbsent(path[1], k -> new HashSet<>()).add(path[0]); + } + int[] result = new int[n]; + for (int i = 1; i <= n; i++) { + int[] colors = new int[5]; + for (int neighbor : map.getOrDefault(i, new HashSet<>())) { + colors[result[neighbor - 1]] = 1; + } + for (int c = 4; c > 0; c--) { + if (colors[c] != 1) { + result[i - 1] = c; + } + } + } + return result; + } +} diff --git a/Easy/Form Smallest Number From Two Digit Arrays.java b/Easy/Form Smallest Number From Two Digit Arrays.java new file mode 100644 index 00000000..5ae6bd94 --- /dev/null +++ b/Easy/Form Smallest Number From Two Digit Arrays.java @@ -0,0 +1,21 @@ +class Solution { + public int minNumber(int[] nums1, int[] nums2) { + int[] counter = new int[10]; + int smallestOne = nums1[0]; + int smallestTwo = nums2[0]; + for (int num : nums1) { + counter[num]++; + smallestOne = Math.min(smallestOne, num); + } + for (int num : nums2) { + counter[num]++; + smallestTwo = Math.min(smallestTwo, num); + } + for (int i = 1; i < counter.length; i++) { + if (counter[i] == 2) { + return i; + } + } + return Math.min(smallestOne, smallestTwo) * 10 + Math.max(smallestOne, smallestTwo); + } +} diff --git a/Easy/Fruits Into Baskets II.java b/Easy/Fruits Into Baskets II.java new file mode 100644 index 00000000..e0afa848 --- /dev/null +++ b/Easy/Fruits Into Baskets II.java @@ -0,0 +1,20 @@ +class Solution { + public int numOfUnplacedFruits(int[] fruits, int[] baskets) { + int count = 0; + for (int fruit : fruits) { + int idx = -1; + for (int i = 0; i < baskets.length; i++) { + if (baskets[i] >= fruit) { + idx = i; + break; + } + } + if (idx == -1) { + count++; + } else { + baskets[idx] = -1; + } + } + return count; + } +} diff --git a/Easy/Furthest Point From Origin.java b/Easy/Furthest Point From Origin.java new file mode 100644 index 00000000..d7abca92 --- /dev/null +++ b/Easy/Furthest Point From Origin.java @@ -0,0 +1,14 @@ +class Solution { + public int furthestDistanceFromOrigin(String moves) { + int emptyCount = 0; + int direction = 0; + for (char c : moves.toCharArray()) { + if (c == '_') { + emptyCount++; + } else { + direction += c == 'L' ? -1 : 1; + } + } + return Math.abs(direction) + emptyCount; + } +} diff --git a/Easy/Generate Tag for Video Caption.java b/Easy/Generate Tag for Video Caption.java new file mode 100644 index 00000000..420bce85 --- /dev/null +++ b/Easy/Generate Tag for Video Caption.java @@ -0,0 +1,26 @@ +class Solution { + public String generateTag(String caption) { + StringBuilder sb = new StringBuilder(); + sb.append('#'); + int idx = 0; + int n = caption.length(); + while (idx < n && caption.charAt(idx) == ' ') { + idx++; + } + boolean upperCase = false; + while (idx < n) { + if (Character.isLetter(caption.charAt(idx))) { + if (upperCase) { + sb.append(Character.toUpperCase(caption.charAt(idx))); + upperCase = false; + } else { + sb.append(Character.toLowerCase(caption.charAt(idx))); + } + } else if (caption.charAt(idx) == ' ') { + upperCase = true; + } + idx++; + } + return sb.toString().substring(0, Math.min(sb.length(), 100)); + } +} diff --git a/Easy/Generate a String With Characters That Have Odd Counts.java b/Easy/Generate a String With Characters That Have Odd Counts.java new file mode 100644 index 00000000..c820746c --- /dev/null +++ b/Easy/Generate a String With Characters That Have Odd Counts.java @@ -0,0 +1,17 @@ +class Solution { + public String generateTheString(int n) { + StringBuilder sb = new StringBuilder(); + if (n % 2 == 0) { + sb.append('a'); + for (int i = 0; i < n - 1; i++) { + sb.append('b'); + } + } + else { + for (int i = 0; i < n; i++) { + sb.append('a'); + } + } + return sb.toString(); + } +} diff --git a/Easy/Get Maximum in Generated Array.java b/Easy/Get Maximum in Generated Array.java new file mode 100644 index 00000000..58ae1efe --- /dev/null +++ b/Easy/Get Maximum in Generated Array.java @@ -0,0 +1,20 @@ +class Solution { + public int getMaximumGenerated(int n) { + if (n == 0) { + return 0; + } + int[] nums = new int[n + 1]; + nums[0] = 0; + nums[1] = 1; + int max = 1; + for (int i = 2; i <= n; i++) { + if (i % 2 == 0) { + nums[i] = nums[i / 2]; + } else { + nums[i] = nums[i / 2] + nums[i / 2 + 1]; + } + max = Math.max(nums[i], max); + } + return max; + } +} diff --git a/Easy/Goal Parser Interpretation.java b/Easy/Goal Parser Interpretation.java new file mode 100644 index 00000000..f5c1fb24 --- /dev/null +++ b/Easy/Goal Parser Interpretation.java @@ -0,0 +1,23 @@ +class Solution { + public String interpret(String command) { + StringBuilder sb = new StringBuilder(); + int idx = 0; + while (idx < command.length()) { + if (command.charAt(idx) == '(') { + if (command.charAt(idx + 1) == ')') { + sb.append('o'); + idx++; + } else { + idx++; + while (command.charAt(idx) != ')') { + sb.append(command.charAt(idx++)); + } + } + idx++; + } else { + sb.append(command.charAt(idx++)); + } + } + return sb.toString(); + } +} diff --git a/Easy/Goat Latin.java b/Easy/Goat Latin.java index 59e3e20e..83417b2f 100644 --- a/Easy/Goat Latin.java +++ b/Easy/Goat Latin.java @@ -1,24 +1,19 @@ class Solution { - public static String toGoatLatin(String S) { - - StringBuilder sb = new StringBuilder(""); - String[] strs = S.split("\\s+"); - - String vowels = "aeiou"; - StringBuilder suffix = new StringBuilder("a"); - - for (String s : strs) { - if (vowels.indexOf(s.toLowerCase().charAt(0)) != -1) { - sb.append(s).append("ma").append(suffix).append(" "); - } - else { - sb.append(s.substring(1, s.length())).append(s.charAt(0)).append("ma").append(suffix).append(" "); - } - - suffix.append("a"); - } - - return sb.toString().trim(); + public String toGoatLatin(String sentence) { + String[] words = sentence.split("\\s+"); + StringBuilder result = new StringBuilder(); + StringBuilder aWord = new StringBuilder(); + Set vowels = Set.of('a', 'e', 'i', 'o', 'u'); + for (String word : words) { + aWord.append('a'); + char firstChar = word.charAt(0); + if (vowels.contains(Character.toLowerCase(firstChar))) { + result.append(word).append("ma"); + } else { + result.append(word.substring(1)).append(firstChar).append("ma"); + } + result.append(aWord.toString()).append(" "); } + return result.toString().trim(); + } } - diff --git a/Easy/Greatest Common Divisor of Strings.java b/Easy/Greatest Common Divisor of Strings.java new file mode 100644 index 00000000..f817725a --- /dev/null +++ b/Easy/Greatest Common Divisor of Strings.java @@ -0,0 +1,13 @@ +class Solution { + public String gcdOfStrings(String str1, String str2) { + if (!(str1 + str2).equals(str2 + str1)) { + return ""; + } + int gcdLength = gcd(str1.length(), str2.length()); + return str1.substring(0, gcdLength); + } + + private int gcd(int x, int y) { + return y == 0 ? x : gcd(y, x % y); + } +} diff --git a/Easy/Greatest English Letter in Upper and Lower Case.java b/Easy/Greatest English Letter in Upper and Lower Case.java new file mode 100644 index 00000000..2b7028ad --- /dev/null +++ b/Easy/Greatest English Letter in Upper and Lower Case.java @@ -0,0 +1,19 @@ +class Solution { + public String greatestLetter(String s) { + boolean[] upperCasePresent = new boolean[26]; + boolean[] lowerCasePresent = new boolean[26]; + for (char c : s.toCharArray()) { + if (Character.isUpperCase(c)) { + upperCasePresent[c - 'A'] = true; + } else { + lowerCasePresent[c - 'a'] = true; + } + } + for (int i = 25; i >= 0; i--) { + if (upperCasePresent[i] && lowerCasePresent[i]) { + return String.valueOf((char) ('A' + i)); + } + } + return ""; + } +} diff --git a/Easy/Guess Number Higher or Lower.java b/Easy/Guess Number Higher or Lower.java index 36b0fa0d..91b9aeb0 100644 --- a/Easy/Guess Number Higher or Lower.java +++ b/Easy/Guess Number Higher or Lower.java @@ -1,25 +1,27 @@ -/* The guess API is defined in the parent class GuessGame. - @param num, your guess - @return -1 if my number is lower, 1 if my number is higher, otherwise return 0 - int guess(int num); */ +/** + * Forward declaration of guess API. + * @param num your guess + * @return -1 if num is lower than the guess number + * 1 if num is higher than the guess number + * otherwise return 0 + * int guess(int num); + */ public class Solution extends GuessGame { - public int guessNumber(int n) { - int start = 1; - int end = n; - int mid = -1; - while (true) { - mid = start + (end-start)/2; - if (guess(mid) == -1) { - end = mid-1; - } - else if (guess(mid) == 1) { - start = mid+1; - } - else { - break; - } - } + public int guessNumber(int n) { + int start = 1; + int end = n; + while (start <= end) { + int mid = start + (end - start) / 2; + int result = guess(mid); + if (result == -1) { + end = mid - 1; + } else if (result == 1) { + start = mid + 1; + } else { return mid; + } } + return -1; + } } diff --git a/Easy/Hamming Distance.java b/Easy/Hamming Distance.java index d6e0a284..ce060325 100644 --- a/Easy/Hamming Distance.java +++ b/Easy/Hamming Distance.java @@ -1,46 +1,13 @@ class Solution { - public int hammingDistance(int x, int y) { - return findCount(x,y); + public int hammingDistance(int x, int y) { + int xor = x ^ y; + int count = 0; + while (xor != 0) { + if (xor % 2 == 1) { + count++; + } + xor = xor >> 1; } - public int findCount(int x, int y) { - StringBuilder sbX = new StringBuilder(""); - StringBuilder sbY = new StringBuilder(""); - - while (x>0) { - sbX.append(String.valueOf(x%2)); - x /= 2; - } - - while (y>0) { - sbY.append(String.valueOf(y%2)); - y /= 2; - } - - String binX = sbX.reverse().toString(); - String binY = sbY.reverse().toString(); - - if (binX.length() > binY.length()) { - int d = binX.length() - binY.length(); - while (d>0) { - binY = "0" + binY; - d--; - } - } - else if (binX.length() < binY.length()) { - int d = binY.length() - binX.length(); - while (d>0) { - binX = "0" + binX; - d--; - } - } - - int count = 0; - for (int i=0;i set = new HashSet<>(); - - while (n != 1) { - int sumOfDigitSquare = getSumOfDigitSquare(n); - if (set.contains(sumOfDigitSquare)) { - return false; - } - - set.add(sumOfDigitSquare); - n = sumOfDigitSquare; - } - - return true; + public boolean isHappy(int n) { + int slow = n; + int fast = getSquareDigitSum(n); + while (fast != 1 && slow != fast) { + slow = getSquareDigitSum(slow); + fast = getSquareDigitSum(getSquareDigitSum(fast)); } - - private int getSumOfDigitSquare(int n) { - int sum = 0; - while (n > 0) { - sum += Math.pow(n % 10, 2); - n /= 10; - } - - return sum; + return fast == 1; + } + + private int getSquareDigitSum(int n) { + int squareDigitSum = 0; + while (n > 0) { + int digit = n % 10; + squareDigitSum += digit * digit; + n /= 10; } + return squareDigitSum; + } } diff --git a/Easy/Harshad Number.java b/Easy/Harshad Number.java new file mode 100644 index 00000000..c02c40bf --- /dev/null +++ b/Easy/Harshad Number.java @@ -0,0 +1,15 @@ +class Solution { + public int sumOfTheDigitsOfHarshadNumber(int x) { + int digitSum = getDigitSum(x); + return x % digitSum == 0 ? digitSum : -1; + } + + private static int getDigitSum(int num) { + int sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum; + } +} diff --git a/Easy/Height Checker.java b/Easy/Height Checker.java index 09efad95..97bc01d0 100644 --- a/Easy/Height Checker.java +++ b/Easy/Height Checker.java @@ -1,15 +1,20 @@ class Solution { - public int heightChecker(int[] heights) { - int[] copy = Arrays.copyOf(heights, heights.length); - Arrays.sort(copy); - - int count = 0; - for (int i = 0; i < heights.length; i++) { - if (copy[i] != heights[i]) { - count++; - } - } - - return count; + public int heightChecker(int[] heights) { + int[] frequencies = new int[101]; + for (int height : heights) { + frequencies[height]++; } + int currHeight = 1; + int mismatchCount = 0; + for (int height : heights) { + while (frequencies[currHeight] == 0) { + currHeight++; + } + if (currHeight != height) { + mismatchCount++; + } + frequencies[currHeight]--; + } + return mismatchCount; + } } diff --git a/Easy/Hexspeak.java b/Easy/Hexspeak.java new file mode 100644 index 00000000..dee2210a --- /dev/null +++ b/Easy/Hexspeak.java @@ -0,0 +1,24 @@ +class Solution { + Integer[] keys = {0, 1, 10, 11, 12, 13, 14, 15}; + String[] values = {"O", "I", "A", "B", "C", "D", "E", "F"}; + Map map; + public String toHexspeak(String num) { + map = new HashMap<>(); + for (int i = 0; i < keys.length; i++) { + map.put((long) keys[i], values[i]); + } + StringBuilder sb = new StringBuilder(); + Long n = Long.parseLong(num); + while (n > 0) { + Long quot = n % 16; + n /= 16; + if (map.containsKey(quot)) { + sb.append(map.get(quot)); + } + else { + return "ERROR"; + } + } + return sb.reverse().toString(); + } +} diff --git a/Easy/High Five.java b/Easy/High Five.java index 31eb4999..86635d5a 100644 --- a/Easy/High Five.java +++ b/Easy/High Five.java @@ -1,37 +1,23 @@ class Solution { - public int[][] highFive(int[][] items) { - final int COUNT = 5; - Map> map = new HashMap<>(); - Set set = new TreeSet<>(); - - for (int[] item : items) { - int id = item[0]; - int score = item[1]; - - map.computeIfAbsent(id, k -> new PriorityQueue<>(COUNT, Comparator.naturalOrder())).add(score); - - if (map.get(id).size() > COUNT) { - map.get(id).poll(); - } - - set.add(id); - } - - int[][] ans = new int[map.size()][2]; - int idx = 0; - Iterator iterator = set.iterator(); - while (iterator.hasNext()) { - int id = iterator.next(); - PriorityQueue scores = map.get(id); - int sum = 0; - - while (!scores.isEmpty()) { - sum += scores.poll(); - } - - ans[idx++] = new int[]{id, sum / COUNT}; - } - - return ans; + public int[][] highFive(int[][] items) { + Map> map = new HashMap<>(); + for (int[] item : items) { + int id = item[0]; + int score = item[1]; + map.computeIfAbsent(id, k -> new PriorityQueue<>((a, b) -> b - a)).add(score); } + int[][] result = new int[map.size()][2]; + int idx = 0; + for (Integer id : map.keySet()) { + PriorityQueue scoresInOrder = map.get(id); + int totalScore = 0; + int count = Math.min(5, scoresInOrder.size()); + for (int i = 0; i < 5 && !scoresInOrder.isEmpty(); i++) { + totalScore += scoresInOrder.poll(); + } + result[idx++] = new int[]{id, totalScore / count}; + } + Arrays.sort(result, (a, b) -> a[0] - b[0]); + return result; + } } diff --git a/Easy/House Robber.java b/Easy/House Robber.java deleted file mode 100644 index cbef9ca9..00000000 --- a/Easy/House Robber.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public int rob(int[] nums) { - int[] dp = new int[nums.length]; - Arrays.fill(dp, -1); - - return robImpl(nums, 0, dp); - } - - private int robImpl(int[] nums, int start, int[] dp) { - if (start > nums.length-1) { - return 0; - } - - if (dp[start] != -1) { - return dp[start]; - } - - dp[start] = Math.max(nums[start] + robImpl(nums, start+2, dp), robImpl(nums, start+1, dp)); - - return dp[start]; - } -} diff --git a/Easy/How Many Apples Can You Put into the Basket.java b/Easy/How Many Apples Can You Put into the Basket.java new file mode 100644 index 00000000..5e6b8543 --- /dev/null +++ b/Easy/How Many Apples Can You Put into the Basket.java @@ -0,0 +1,18 @@ +class Solution { + public int maxNumberOfApples(int[] weight) { + int[] counter = new int[1001]; + for (int w : weight) { + counter[w]++; + } + int numberOfApples = 0; + int totalWeight = 0; + for (int i = 1; i < counter.length && totalWeight <= 5000; i++) { + int count = counter[i]; + while (count-- > 0 && totalWeight + i <= 5000) { + numberOfApples++; + totalWeight += i; + } + } + return numberOfApples; + } +} diff --git a/Easy/How Many Numbers Are Smaller Than the Current Number.java b/Easy/How Many Numbers Are Smaller Than the Current Number.java new file mode 100644 index 00000000..5696318a --- /dev/null +++ b/Easy/How Many Numbers Are Smaller Than the Current Number.java @@ -0,0 +1,19 @@ +class Solution { + public int[] smallerNumbersThanCurrent(int[] nums) { + int[] counter = new int[101]; + for (int num : nums) { + counter[num]++; + } + int sum = 0; + int[] preSum = new int[101]; + for (int i = 0; i < 101; i++) { + preSum[i] = sum; + sum += counter[i]; + } + int[] ans = new int[nums.length]; + for (int i = 0; i < nums.length; i++) { + ans[i] = preSum[nums[i]]; + } + return ans; + } +} diff --git a/Easy/Image Smoother.java b/Easy/Image Smoother.java index 9f0d68f0..ede06daf 100644 --- a/Easy/Image Smoother.java +++ b/Easy/Image Smoother.java @@ -1,49 +1,27 @@ class Solution { - public int[][] imageSmoother(int[][] M) { - - int[][] res = new int[M.length][M[0].length]; - for (int i=0;i= 0) { - count++; - sum += M[i][j-1]; - } - if(j+1 < M[0].length) { - count++; - sum += M[i][j+1]; - } - if(i-1 >= 0) { - count++; - sum += M[i-1][j]; - } - if(i+1 < M.length) { - count++; - sum += M[i+1][j]; - } - if(i+1 < M.length && j+1 < M[0].length) { - count++; - sum += M[i+1][j+1]; - } - if(i+1 < M.length && j-1 >= 0) { - count++; - sum += M[i+1][j-1]; - } - if(i-1 >= 0 && j-1 >= 0) { - count++; - sum += M[i-1][j-1]; - } - if(i-1 >= 0 && j+1 < M[0].length) { - count++; - sum += M[i-1][j+1]; - } - - res[i][j] = (int)Math.floor(sum/count); + for (int[] dir : DIRS) { + int row = i + dir[0]; + int col = j + dir[1]; + if (row >= 0 && row < rows && col >= 0 && col < cols) { + sum += img[row][col]; + count++; + } + } + double smoothImage = sum / count; + result[i][j] = (int) smoothImage; } } - - return res; + return result; } } diff --git a/Easy/Implement Queue using Stacks.java b/Easy/Implement Queue using Stacks.java index d42922a9..a84da8b6 100644 --- a/Easy/Implement Queue using Stacks.java +++ b/Easy/Implement Queue using Stacks.java @@ -1,36 +1,39 @@ class MyQueue { - /** Initialize your data structure here. */ - Stack oldStack = new Stack<>(); - Stack newStack = new Stack<>(); + private final Stack first; + private final Stack second; + + public MyQueue() { + this.first = new Stack<>(); + this.second = new Stack<>(); + } - /** Push element x to the back of queue. */ public void push(int x) { - while (!newStack.isEmpty()) { - oldStack.push(newStack.pop()); - } - oldStack.push(x); + first.push(x); } - /** Removes the element from in front of queue and returns that element. */ public int pop() { - while (!oldStack.isEmpty()) { - newStack.push(oldStack.pop()); - } - return newStack.pop(); + move(first, second); + int result = second.pop(); + move(second, first); + return result; } - /** Get the front element. */ public int peek() { - while (!oldStack.isEmpty()) { - newStack.push(oldStack.pop()); - } - return newStack.peek(); + move(first, second); + int result = second.peek(); + move(second, first); + return result; } - /** Returns whether the queue is empty. */ public boolean empty() { - return oldStack.isEmpty() && newStack.isEmpty(); + return first.isEmpty(); + } + + private void move(Stack from, Stack to) { + while (!from.isEmpty()) { + to.push(from.pop()); + } } } diff --git a/Easy/Implement Stack using Queues.java b/Easy/Implement Stack using Queues.java index 08df7392..d93ce3ae 100644 --- a/Easy/Implement Stack using Queues.java +++ b/Easy/Implement Stack using Queues.java @@ -1,43 +1,50 @@ -import java.util.ArrayList; - class MyStack { + + private final Queue mainQueue; + private final Queue backupQueue; - /** Initialize your data structure here. */ - ArrayList arrNew = new ArrayList<>(); - ArrayList arrOld = new ArrayList<>(); - - - /** Push element x onto stack. */ + public MyStack() { + this.mainQueue = new LinkedList<>(); + this.backupQueue = new LinkedList<>(); + } + public void push(int x) { - arrOld.add(x); + this.mainQueue.add(x); } - - /** Removes the element on top of the stack and returns that element. */ + public int pop() { - for (int i=0;i<=arrOld.size()-1;i++) { - arrNew.add(arrOld.get(i)); - } - int k = arrNew.get(arrNew.size()-1); - arrNew.remove(arrNew.indexOf(k)); - - arrOld.clear(); - return k; + int lastElement = moveToBackupQueue(); + moveToMainQueue(true); + return lastElement; } - - /** Get the top element. */ + public int top() { - for (int i=0;i<=arrOld.size()-1;i++) { - arrNew.add(arrOld.get(i)); - } - int k = arrNew.get(arrNew.size()-1); - - arrOld.clear(); - return k; + int lastElement = moveToBackupQueue(); + moveToMainQueue(false); + return lastElement; } - - /** Returns whether the stack is empty. */ + public boolean empty() { - return arrNew.size() == 0 && arrOld.size() == 0; + return this.mainQueue.isEmpty(); + } + + private int moveToBackupQueue() { + int lastElement = this.mainQueue.peek(); + while (!this.mainQueue.isEmpty()) { + lastElement = this.mainQueue.peek(); + this.backupQueue.add(this.mainQueue.poll()); + } + return lastElement; + } + + private void moveToMainQueue(boolean removeLast) { + int sizeLimit = removeLast ? 1 : 0; + while (this.backupQueue.size() > sizeLimit) { + this.mainQueue.add(this.backupQueue.poll()); + } + if (removeLast) { + this.backupQueue.remove(); + } } } diff --git a/Easy/Implement strStr.java b/Easy/Implement strStr.java index a823b793..ea05ba6f 100644 --- a/Easy/Implement strStr.java +++ b/Easy/Implement strStr.java @@ -1,16 +1,10 @@ class Solution { - public int strStr(String haystack, String needle) { - int start = 0; - int end = haystack.length() - needle.length() + 1; - - while (start < end) { - if (haystack.substring(start, start + needle.length()).equals(needle)) { - return start; - } - - start++; - } - - return -1; + public int strStr(String haystack, String needle) { + for (int i = 0; i < haystack.length() - needle.length() + 1; i++) { + if (haystack.substring(i, i + needle.length()).equals(needle)) { + return i; + } } + return -1; + } } diff --git a/Easy/Increasing Decreasing String.java b/Easy/Increasing Decreasing String.java new file mode 100644 index 00000000..9aa71d09 --- /dev/null +++ b/Easy/Increasing Decreasing String.java @@ -0,0 +1,32 @@ +class Solution { + public String sortString(String s) { + int[] counter = new int[26]; + for (char c : s.toCharArray()) { + counter[c - 'a']++; + } + StringBuilder sb = new StringBuilder(); + while (sb.length() != s.length()) { + addLowerToHiger(sb, counter); + addHigherToLower(sb, counter); + } + return sb.toString(); + } + + private void addLowerToHiger(StringBuilder sb, int[] counter) { + for (int i = 0; i < 26; i++) { + if (counter[i] != 0) { + sb.append((char) (97 + i)); + counter[i]--; + } + } + } + + private void addHigherToLower(StringBuilder sb, int[] counter) { + for (int i = 25; i >= 0; i--) { + if (counter[i] != 0) { + sb.append((char) (97 + i)); + counter[i]--; + } + } + } +} diff --git a/Easy/Increasing Order Search Tree.java b/Easy/Increasing Order Search Tree.java index c4a487b7..1ca57c9b 100644 --- a/Easy/Increasing Order Search Tree.java +++ b/Easy/Increasing Order Search Tree.java @@ -4,36 +4,36 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - - public List list = new ArrayList<>(); - public TreeNode increasingBST(TreeNode root) { - inorderTraversal(root); - - if (list.size() == 0) return null; - - TreeNode ans = list.get(0); - TreeNode curr = ans; - - for (int i=1; i stack = new Stack<>(); + while (root != null) { + stack.push(root); + root = root.left; } - - public void inorderTraversal(TreeNode root) { - if (root == null) return; - - inorderTraversal(root.left); - list.add(root); - inorderTraversal(root.right); + TreeNode newHead = null; + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + if (newHead == null) { + newHead = removed; + } + TreeNode rightNode = removed.right; + while (rightNode != null) { + stack.push(rightNode); + rightNode = rightNode.left; + } + removed.right = stack.isEmpty() ? null : stack.peek(); + removed.left = null; } + return newHead; + } } diff --git a/Easy/Index Pairs of a String.java b/Easy/Index Pairs of a String.java new file mode 100644 index 00000000..5fd32b1e --- /dev/null +++ b/Easy/Index Pairs of a String.java @@ -0,0 +1,14 @@ +class Solution { + public int[][] indexPairs(String text, String[] words) { + List pairs = new ArrayList<>(); + for (String word : words) { + for (int i = 0; i < text.length() - word.length() + 1; i++) { + if (text.startsWith(word, i)) { + pairs.add(new int[]{i, i + word.length() - 1}); + } + } + } + pairs.sort(Comparator.comparingInt((int[] o) -> o[0]).thenComparingInt(o -> o[1])); + return pairs.toArray(new int[0][]); + } +} diff --git a/Easy/Intersection of Multiple Arrays.java b/Easy/Intersection of Multiple Arrays.java new file mode 100644 index 00000000..f06c30b8 --- /dev/null +++ b/Easy/Intersection of Multiple Arrays.java @@ -0,0 +1,19 @@ +import java.util.Map.Entry; + + +class Solution { + public List intersection(int[][] nums) { + Map counter = new HashMap<>(); + for (int[] num : nums) { + for (int element : num) { + counter.put(element, counter.getOrDefault(element, 0) + 1); + } + } + return counter.entrySet() + .stream() + .filter(entry -> entry.getValue() == nums.length) + .map(Entry::getKey) + .sorted() + .collect(Collectors.toList()); + } +} diff --git a/Easy/Intersection of Three Sorted Arrays.java b/Easy/Intersection of Three Sorted Arrays.java new file mode 100644 index 00000000..d7dc12e5 --- /dev/null +++ b/Easy/Intersection of Three Sorted Arrays.java @@ -0,0 +1,28 @@ +class Solution { + public List arraysIntersection(int[] arr1, int[] arr2, int[] arr3) { + int idxOne = 0; + int idxTwo = 0; + int idxThree = 0; + List result = new ArrayList<>(); + while (idxOne < arr1.length && idxTwo < arr2.length && idxThree < arr3.length) { + if (arr1[idxOne] == arr2[idxTwo] && arr2[idxTwo] == arr3[idxThree]) { + result.add(arr1[idxOne]); + idxOne++; + idxTwo++; + idxThree++; + } else { + int max = Math.max(arr1[idxOne], Math.max(arr2[idxTwo], arr3[idxThree])); + if (arr1[idxOne] < max) { + idxOne++; + } + if (arr2[idxTwo] < max) { + idxTwo++; + } + if (arr3[idxThree] < max) { + idxThree++; + } + } + } + return result; + } +} diff --git a/Easy/Intersection of Two Arrays II.java b/Easy/Intersection of Two Arrays II.java new file mode 100644 index 00000000..6a6b143d --- /dev/null +++ b/Easy/Intersection of Two Arrays II.java @@ -0,0 +1,14 @@ +class Solution { + public int[] intersect(int[] nums1, int[] nums2) { + Map map = Arrays.stream(nums1).boxed() + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())); + List result = new ArrayList<>(); + for (int num : nums2) { + if (map.getOrDefault(num, 0L) > 0) { + result.add(num); + map.put(num, map.get(num) - 1); + } + } + return result.stream().mapToInt(Integer::valueOf).toArray(); + } +} diff --git a/Easy/Intersection of Two Arrays.java b/Easy/Intersection of Two Arrays.java new file mode 100644 index 00000000..24a47d60 --- /dev/null +++ b/Easy/Intersection of Two Arrays.java @@ -0,0 +1,8 @@ +class Solution { + public int[] intersection(int[] nums1, int[] nums2) { + Set set1 = Arrays.stream(nums1).boxed().collect(Collectors.toSet()); + Set set2 = Arrays.stream(nums2).boxed().collect(Collectors.toSet()); + set1.retainAll(set2); + return set1.stream().mapToInt(Integer::intValue).toArray(); + } +} diff --git a/Easy/Intersection of two Linked Lists.java b/Easy/Intersection of two Linked Lists.java index e2fd8de5..2da135fb 100644 --- a/Easy/Intersection of two Linked Lists.java +++ b/Easy/Intersection of two Linked Lists.java @@ -10,19 +10,13 @@ * } */ public class Solution { - public ListNode getIntersectionNode(ListNode headA, ListNode headB) { - if (headA == null || headB == null) return null; - while (headA != null && headB != null) { - if (headA.val == headB.val) { - return headA; - } - else if (headA.val < headB.val) { - headA = headA.next; - } - else if (headA.val > headB.val) { - headB = headB.next; - } - } - return null; + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + ListNode copyA = headA; + ListNode copyB = headB; + while (copyA != copyB) { + copyA = copyA == null ? headB : copyA.next; + copyB = copyB == null ? headA : copyB.next; } -} \ No newline at end of file + return copyA; + } +} diff --git a/Easy/Intersection of two arrays II.java b/Easy/Intersection of two arrays II.java deleted file mode 100644 index 17c4fe8d..00000000 --- a/Easy/Intersection of two arrays II.java +++ /dev/null @@ -1,24 +0,0 @@ -class Solution { - public int[] intersect(int[] nums1, int[] nums2) { - HashMap map = new HashMap(); - ArrayList result = new ArrayList(); - for(int i = 0; i < nums1.length; i++) { - if(map.containsKey(nums1[i])) map.put(nums1[i], map.get(nums1[i])+1); - else map.put(nums1[i], 1); - } - - for(int i = 0; i < nums2.length; i++) { - if(map.containsKey(nums2[i]) && map.get(nums2[i]) > 0) { - result.add(nums2[i]); - map.put(nums2[i], map.get(nums2[i])-1); - } - } - - int[] r = new int[result.size()]; - for(int i = 0; i < result.size(); i++) { - r[i] = result.get(i); - } - - return r; - } -} diff --git a/Easy/Invert Binary Tree.java b/Easy/Invert Binary Tree.java new file mode 100644 index 00000000..d2c3c6ab --- /dev/null +++ b/Easy/Invert Binary Tree.java @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return null; + } + TreeNode leftNode = root.left; + root.left = invertTree(root.right); + root.right = invertTree(leftNode); + return root; + } +} diff --git a/Easy/Invert a binary tree.java b/Easy/Invert a binary tree.java deleted file mode 100644 index 15a9dc3d..00000000 --- a/Easy/Invert a binary tree.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public TreeNode invertTree(TreeNode root) { - if (root == null) return null; - - TreeNode right = invertTree(root.right); - TreeNode left = invertTree(root.left); - - root.right = left; - root.left = right; - - return root; - } -} diff --git a/Easy/Is Subsequence.java b/Easy/Is Subsequence.java new file mode 100644 index 00000000..2d67a698 --- /dev/null +++ b/Easy/Is Subsequence.java @@ -0,0 +1,13 @@ +class Solution { + public boolean isSubsequence(String s, String t) { + int sIdx = 0; + int tIdx = 0; + while (sIdx < s.length() && tIdx < t.length()) { + if (s.charAt(sIdx) == t.charAt(tIdx)) { + sIdx++; + } + tIdx++; + } + return sIdx == s.length(); + } +} diff --git a/Easy/Island Perimeter.java b/Easy/Island Perimeter.java index 6d21edc1..fbf4ac41 100644 --- a/Easy/Island Perimeter.java +++ b/Easy/Island Perimeter.java @@ -1,47 +1,20 @@ class Solution { - public int islandPerimeter(int[][] grid) { - int n = grid.length; - int m = grid[0].length; - - int p = 0; - for (int i=0;i= 0) { - if (grid[i-1][j] == 0) { - p++; - } - } - else { - p++; - } - if (i+1 < n) { - if (grid[i+1][j] == 0) { - p++; - } - } - else { - p++; - } - if (j-1 >= 0) { - if (grid[i][j-1] == 0) { - p++; - } - } - else { - p++; - } - if (j+1 < m) { - if (grid[i][j+1] == 0) { - p++; - } - } - else { - p++; - } - } - } + int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + public int islandPerimeter(int[][] grid) { + int sum = 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 1) { + for (int[] dir : dirs) { + sum += isBoundary(grid, i + dir[0], j + dir[1]) ? 1 : 0; + } } - return p; + } } + return sum; + } + + private boolean isBoundary(int[][] grid, int x, int y) { + return x < 0 || x >= grid.length || y < 0 || y >= grid[0].length || grid[x][y] == 0; + } } diff --git a/Easy/Isomorphic Strings.java b/Easy/Isomorphic Strings.java index 365f4ce6..b9813b64 100644 --- a/Easy/Isomorphic Strings.java +++ b/Easy/Isomorphic Strings.java @@ -1,10 +1,18 @@ class Solution { - public boolean isIsomorphic(String s1, String s2) { - int[] m = new int[512]; - for (int i = 0; i < s1.length(); i++) { - if (m[s1.charAt(i)] != m[s2.charAt(i)+256]) return false; - m[s1.charAt(i)] = m[s2.charAt(i)+256] = i+1; + public boolean isIsomorphic(String s, String t) { + return mapString(s).equals(mapString(t)); + } + + private static String mapString(String s) { + Map map = new HashMap<>(); + int count = 0; + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + if (!map.containsKey(c)) { + map.put(c, count++); + } + sb.append(map.get(c)).append("|"); } - return true; + return sb.toString(); } } diff --git a/Easy/Jewels and Stones.java b/Easy/Jewels and Stones.java index 199feb24..f37c51ca 100644 --- a/Easy/Jewels and Stones.java +++ b/Easy/Jewels and Stones.java @@ -1,23 +1,15 @@ class Solution { - public int numJewelsInStones(String J, String S) { - boolean[] isSet = new boolean[52]; - for (char c : J.toCharArray()) { - isSet[getIdx(c)] = true; - } - - int count = 0; - for (char c : S.toCharArray()) { - count += isSet[getIdx(c)] ? 1 : 0; - } - - return count; + public int numJewelsInStones(String J, String S) { + Set set = new HashSet<>(); + for (char c : J.toCharArray()) { + set.add(c); } - - private int getIdx(char c) { - if (Character.isUpperCase(c)) { - return 26 + c - 'A'; - } - - return c - 'a'; + int count = 0; + for (char c : S.toCharArray()) { + if (set.contains(c)) { + count++; + } } + return count; + } } diff --git a/Easy/K Closest Points to Origin.java b/Easy/K Closest Points to Origin.java deleted file mode 100644 index 950e2783..00000000 --- a/Easy/K Closest Points to Origin.java +++ /dev/null @@ -1,36 +0,0 @@ -class Solution { - public int[][] kClosest(int[][] points, int K) { - int[][] ans = new int[K][2]; - PriorityQueue pq = new PriorityQueue<>(new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - double dist1 = getDistance(o1); - double dist2 = getDistance(o2); - - if (dist1 > dist2) { - return 1; - } - else if (dist1 < dist2) { - return -1; - } - else { - return 0; - } - } - }); - - for (int[] point : points) { - pq.add(point); - } - - for (int i=0; i map = new HashMap<>(); - int count = 0; - for (int i:nums) { - if (map.containsKey(i)) { - map.put(i, map.get(i)+1); - } - else { - map.put(i,1); - } + public int findPairs(int[] nums, int k) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int count = 0; + for (Map.Entry entry : map.entrySet()) { + if (k == 0) { + if (entry.getValue() >= 2) { + count++; } - - for (Map.Entry entry : map.entrySet()) { - if (k==0) { - if (entry.getValue() >= 2) { - count++; - } - } - else { - if (map.containsKey(entry.getKey() + k)) { - count++; - } - } + } else { + if (map.containsKey(entry.getKey() + k)) { + count++; } - return count; + } } + return count; + } } diff --git a/Easy/Keep Multiplying Found Values by Two.java b/Easy/Keep Multiplying Found Values by Two.java new file mode 100644 index 00000000..165e4b74 --- /dev/null +++ b/Easy/Keep Multiplying Found Values by Two.java @@ -0,0 +1,12 @@ +class Solution { + public int findFinalValue(int[] nums, int original) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + while (set.contains(original)) { + original *= 2; + } + return original; + } +} diff --git a/Easy/Keyboard Row.java b/Easy/Keyboard Row.java index 80b4aaa1..e83946aa 100644 --- a/Easy/Keyboard Row.java +++ b/Easy/Keyboard Row.java @@ -1,42 +1,35 @@ class Solution { - public String[] findWords(String[] words) { - ArrayList ans = new ArrayList(); - - for (int i=0;i map = new HashMap<>(); + update(map, "qwertyuiop", 1); + update(map, "asdfghjkl", 2); + update(map, "zxcvbnm", 3); + List list = new ArrayList<>(); + for (int i = 0; i < words.length; i++) { + int rowIdx = -1; + for (char c : words[i].toCharArray()) { + if (rowIdx == -1) { + rowIdx = map.get(Character.toLowerCase(c)); } - - String[] ansArr = new String[ans.size()]; - for (int i=0;i map, String s, int row) { + for (char c : s.toCharArray()) { + map.put(c, row); } + } } diff --git a/Easy/Kids With the Greatest Number of Candies.java b/Easy/Kids With the Greatest Number of Candies.java new file mode 100644 index 00000000..67e2441d --- /dev/null +++ b/Easy/Kids With the Greatest Number of Candies.java @@ -0,0 +1,10 @@ +class Solution { + public List kidsWithCandies(int[] candies, int extraCandies) { + final int maxCandy = Arrays.stream(candies) + .max() + .orElse(0); + return Arrays.stream(candies) + .mapToObj(candy -> candy + extraCandies >= maxCandy) + .collect(Collectors.toList()); + } +} diff --git a/Easy/Kth Distinct String in an Array.java b/Easy/Kth Distinct String in an Array.java new file mode 100644 index 00000000..31a474f7 --- /dev/null +++ b/Easy/Kth Distinct String in an Array.java @@ -0,0 +1,11 @@ +import java.util.Map.Entry; + +class Solution { + public String kthDistinct(String[] arr, int k) { + return Arrays.stream(arr).collect( + Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting())) + .entrySet().stream().filter(entry -> entry.getValue().equals(1L)).map(Entry::getKey) + .skip(k - 1) + .findFirst().orElse(""); + } +} diff --git a/Easy/Kth Largest Element in a Stream.java b/Easy/Kth Largest Element in a Stream.java index 5e701906..4b1868f3 100644 --- a/Easy/Kth Largest Element in a Stream.java +++ b/Easy/Kth Largest Element in a Stream.java @@ -1,26 +1,27 @@ class KthLargest { - PriorityQueue priorityQueue; - int k; + + private final PriorityQueue pq; + private final int k; public KthLargest(int k, int[] nums) { this.k = k; - priorityQueue = new PriorityQueue<>(k); - + this.pq = new PriorityQueue<>((a, b) -> a - b); for (int num : nums) { - priorityQueue.offer(num); - if (priorityQueue.size() > k) { - priorityQueue.poll(); - } + pq.add(num); + checkLength(); } } - + public int add(int val) { - priorityQueue.offer(val); - if (priorityQueue.size() > k) { - priorityQueue.poll(); + pq.add(val); + checkLength(); + return pq.peek(); + } + + private void checkLength() { + if (pq.size() > k) { + pq.poll(); } - - return priorityQueue.peek(); } } diff --git a/Easy/Kth Missing Positive Number.java b/Easy/Kth Missing Positive Number.java new file mode 100644 index 00000000..6f662c97 --- /dev/null +++ b/Easy/Kth Missing Positive Number.java @@ -0,0 +1,15 @@ +class Solution { + public int findKthPositive(int[] arr, int k) { + int left = 0; + int right = arr.length - 1; + while (left <= right) { + int mid = left + (right - left) / 2; + if (arr[mid] - mid - 1 < k) { + left = mid + 1; + } else { + right = mid - 1; + } + } + return left + k; + } +} diff --git a/Easy/Largest 3-Same-Digit Number in String.java b/Easy/Largest 3-Same-Digit Number in String.java new file mode 100644 index 00000000..6d0b2680 --- /dev/null +++ b/Easy/Largest 3-Same-Digit Number in String.java @@ -0,0 +1,13 @@ +class Solution { + public String largestGoodInteger(String num) { + int largestIdx = -1; + for (int i = 0; i < num.length() - 2; i++) { + if (num.charAt(i) == num.charAt(i + 1) && num.charAt(i + 1) == num.charAt(i + 2)) { + if (largestIdx == -1 || num.substring(largestIdx, largestIdx + 3).compareTo(num.substring(i, i + 3)) < 0) { + largestIdx = i; + } + } + } + return largestIdx == -1 ? "" : num.substring(largestIdx, largestIdx + 3); + } +} diff --git a/Easy/Largest Local Values in a Matrix.java b/Easy/Largest Local Values in a Matrix.java new file mode 100644 index 00000000..570443a9 --- /dev/null +++ b/Easy/Largest Local Values in a Matrix.java @@ -0,0 +1,17 @@ +class Solution { + public int[][] largestLocal(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + int[][] result = new int[rows - 2][cols - 2]; + for (int i = 0; i < rows - 2; i++) { + for (int j = 0; j < cols - 2; j++) { + for (int k = i; k < i + 3; k++) { + for (int l = j; l < j + 3; l++) { + result[i][j] = Math.max(result[i][j], grid[k][l]); + } + } + } + } + return result; + } +} diff --git a/Easy/Largest Number After Digit Swaps by Parity.java b/Easy/Largest Number After Digit Swaps by Parity.java new file mode 100644 index 00000000..1959ca40 --- /dev/null +++ b/Easy/Largest Number After Digit Swaps by Parity.java @@ -0,0 +1,28 @@ +class Solution { + public int largestInteger(int num) { + char[] digits = String.valueOf(num).toCharArray(); + int[] frequency = new int[10]; + for (int i = 0; i < digits.length; i++) { + frequency[digits[i] - '0']++; + } + int largestNumber = 0; + int evenIdx = 8; + int oddIdx = 9; + for (int i = 0; i < digits.length; i++) { + if (digits[i] % 2 == 0) { + while (frequency[evenIdx] == 0) { + evenIdx -= 2; + } + frequency[evenIdx]--; + largestNumber = largestNumber * 10 + evenIdx; + } else { + while (frequency[oddIdx] == 0) { + oddIdx -= 2; + } + frequency[oddIdx]--; + largestNumber = largestNumber * 10 + oddIdx; + } + } + return largestNumber; + } +} diff --git a/Easy/Largest Odd Number in String.java b/Easy/Largest Odd Number in String.java new file mode 100644 index 00000000..b43d4726 --- /dev/null +++ b/Easy/Largest Odd Number in String.java @@ -0,0 +1,10 @@ +class Solution { + public String largestOddNumber(String num) { + for (int i = num.length() - 1; i >= 0; i--) { + if (Character.getNumericValue(num.charAt(i)) % 2 != 0) { + return num.substring(0, i + 1); + } + } + return ""; + } +} diff --git a/Easy/Largest Perimeter Triangle.java b/Easy/Largest Perimeter Triangle.java index bc9803f5..c298121d 100644 --- a/Easy/Largest Perimeter Triangle.java +++ b/Easy/Largest Perimeter Triangle.java @@ -1,14 +1,11 @@ class Solution { - public int largestPerimeter(int[] A) { - Arrays.sort(A); - int n = A.length; - - for (int i=n-1; i>1; i--) { - if (A[i] < A[i - 1] + A[i - 2]) { - return A[i] + A[i - 1] + A[i - 2]; - } - } - - return 0; + public int largestPerimeter(int[] nums) { + Arrays.sort(nums); + for (int i = nums.length - 3; i >= 0; i--) { + if (nums[i] + nums[i + 1] > nums[i + 2]) { + return nums[i] + nums[i + 1] + nums[i + 2]; + } } + return 0; + } } diff --git a/Easy/Largest Positive Integer That Exists With Its Negative.java b/Easy/Largest Positive Integer That Exists With Its Negative.java new file mode 100644 index 00000000..b6789be7 --- /dev/null +++ b/Easy/Largest Positive Integer That Exists With Its Negative.java @@ -0,0 +1,13 @@ +class Solution { + public int findMaxK(int[] nums) { + int largestNumber = -1; + Set set = new HashSet<>(); + for (int num : nums) { + if (set.contains(-1 * num)) { + largestNumber = Math.max(Math.abs(num), largestNumber); + } + set.add(num); + } + return largestNumber; + } +} diff --git a/Easy/Largest Substring Between Two Equal Characters.java b/Easy/Largest Substring Between Two Equal Characters.java new file mode 100644 index 00000000..24371003 --- /dev/null +++ b/Easy/Largest Substring Between Two Equal Characters.java @@ -0,0 +1,11 @@ +class Solution { + public int maxLengthBetweenEqualCharacters(String s) { + Map map = new HashMap<>(); + int maxLength = -1; + for (int i = 0; i < s.length(); i++) { + map.putIfAbsent(s.charAt(i), i); + maxLength = Math.max(maxLength, i - map.get(s.charAt(i)) - 1); + } + return maxLength; + } +} diff --git a/Easy/Largest Triangle Area.java b/Easy/Largest Triangle Area.java new file mode 100644 index 00000000..92b281d4 --- /dev/null +++ b/Easy/Largest Triangle Area.java @@ -0,0 +1,20 @@ +class Solution { + public double largestTriangleArea(int[][] points) { + int n = points.length; + double maxArea = 0; + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + for (int k = j + 1; k < n; k++) { + maxArea = Math.max(maxArea, getArea(points[i], points[j], points[k])); + } + } + } + + return maxArea; + } + + private double getArea(int[] P, int[] Q, int[] R) { + return 0.5 * Math.abs(P[0] * Q[1] + Q[0] * R[1] + R[0] * P[1] + -P[1] * Q[0] - Q[1] * R[0] - R[1] * P[0]); + } +} diff --git a/Easy/Largest Unique Number.java b/Easy/Largest Unique Number.java new file mode 100644 index 00000000..0c6df9b9 --- /dev/null +++ b/Easy/Largest Unique Number.java @@ -0,0 +1,15 @@ +class Solution { + public int largestUniqueNumber(int[] A) { + Map map = new HashMap<>(); + for (int num : A) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int max = -1; + for (Integer key : map.keySet()) { + if (map.get(key) == 1) { + max = Math.max(key, max); + } + } + return max; + } +} diff --git a/Easy/Last Stone Weight.java b/Easy/Last Stone Weight.java index 8fba7ba5..afb35b41 100644 --- a/Easy/Last Stone Weight.java +++ b/Easy/Last Stone Weight.java @@ -1,27 +1,16 @@ class Solution { public int lastStoneWeight(int[] stones) { - PriorityQueue pq = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o2.compareTo(o1); - } - }); - + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); for (int stone : stones) { pq.add(stone); } - while (pq.size() > 1) { - int stone1 = pq.poll(); - int stone2 = pq.poll(); - - int resSize = Math.max(stone1, stone2) - Math.min(stone1, stone2); - - if (resSize > 0) { - pq.add(resSize); + int stoneOne = pq.poll(); + int stoneTwo = pq.poll(); + if (stoneOne != stoneTwo) { + pq.add(stoneOne - stoneTwo); } } - - return pq.size() == 1 ? pq.poll() : 0; + return pq.isEmpty() ? 0 : pq.poll(); } } diff --git a/Easy/Last Visited Integers.java b/Easy/Last Visited Integers.java new file mode 100644 index 00000000..e6a59e34 --- /dev/null +++ b/Easy/Last Visited Integers.java @@ -0,0 +1,17 @@ +class Solution { + public List lastVisitedIntegers(List words) { + List result = new ArrayList<>(); + List numbers = new ArrayList<>(); + int cursor = -1; + for (String word : words) { + if (word.equals("prev")) { + result.add(cursor == -1 ? -1 : numbers.get(cursor)); + cursor = cursor == -1 ? -1 : (cursor - 1); + } else { + numbers.add(Integer.parseInt(word)); + cursor = numbers.size() - 1; + } + } + return result; + } +} diff --git a/Easy/Latest Time by Replacing Hidden Digits.java b/Easy/Latest Time by Replacing Hidden Digits.java new file mode 100644 index 00000000..2bb4a840 --- /dev/null +++ b/Easy/Latest Time by Replacing Hidden Digits.java @@ -0,0 +1,30 @@ +class Solution { + public String maximumTime(String time) { + char[] digits = time.toCharArray(); + if (digits[0] == '?' || digits[1] == '?') { + if (digits[0] == '?') { + if (digits[1] == '?' || Character.getNumericValue(digits[1]) <= 3) { + digits[0] = '2'; + } else { + digits[0] = '1'; + } + } + if (digits[1] == '?') { + if (Character.getNumericValue(digits[0]) <= 1) { + digits[1] = '9'; + } else { + digits[1] = '3'; + } + } + } + if (digits[3] == '?' || digits[4] == '?') { + if (digits[3] == '?') { + digits[3] = '5'; + } + if (digits[4] == '?') { + digits[4] = '9'; + } + } + return String.valueOf(digits); + } +} diff --git a/Easy/Leaf-Similar Trees.java b/Easy/Leaf-Similar Trees.java index 150afbbe..082f6583 100644 --- a/Easy/Leaf-Similar Trees.java +++ b/Easy/Leaf-Similar Trees.java @@ -4,31 +4,39 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public boolean leafSimilar(TreeNode root1, TreeNode root2) { - StringBuilder sb1 = new StringBuilder(); - StringBuilder sb2 = new StringBuilder(); - - updateSB(root1, sb1); - updateSB(root2, sb2); - - return sb1.toString().equals(sb2.toString()); + return getLeaves(root1).equals(getLeaves(root2)); } - - private void updateSB(TreeNode root, StringBuilder sb) { + + private static List getLeaves(TreeNode root) { if (root == null) { - return; + return new ArrayList<>(); } - - if (root.left == null && root.right == null) { - sb.append(String.valueOf(root.val)).append("-"); + List result = new ArrayList<>(); + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + if (removed.left == null && removed.right == null) { + result.add(removed.val); + } + if (removed.right != null) { + stack.push(removed.right); + } + if (removed.left != null) { + stack.push(removed.left); + } } - - updateSB(root.left, sb); - updateSB(root.right, sb); + return result; } } diff --git a/Easy/Left and Right Sum Differences.java b/Easy/Left and Right Sum Differences.java new file mode 100644 index 00000000..99a5338a --- /dev/null +++ b/Easy/Left and Right Sum Differences.java @@ -0,0 +1,17 @@ +class Solution { + public int[] leftRigthDifference(int[] nums) { + int n = nums.length; + int leftToRightSum = 0; + for (int i = 0; i < n; i++) { + leftToRightSum += nums[i]; + } + int[] result = new int[n]; + int rightToLeftSum = 0; + for (int i = n - 1; i >= 0; i--) { + leftToRightSum -= nums[i]; + result[i] = Math.abs(rightToLeftSum - leftToRightSum); + rightToLeftSum += nums[i]; + } + return result; + } +} diff --git a/Easy/Lemonade Change.java b/Easy/Lemonade Change.java new file mode 100644 index 00000000..acddd319 --- /dev/null +++ b/Easy/Lemonade Change.java @@ -0,0 +1,23 @@ +class Solution { + public boolean lemonadeChange(int[] bills) { + int[] billCount = new int[3]; + for (int bill : bills) { + int returnAmount = bill - 5; + for (int i = 2; i >= 0 && returnAmount > 0; i--) { + int amount = i == 2 ? 20 : (i == 1 ? 10 : 5); + if (returnAmount >= amount) { + int billsRequired = returnAmount / amount; + int billsAvailable = billCount[i]; + returnAmount -= Math.min(billsRequired, billsAvailable) * amount; + billCount[i] -= Math.min(billsRequired, billsAvailable); + } + } + if (returnAmount != 0) { + return false; + } + int amountIdx = bill == 20 ? 2 : (bill == 10 ? 1 : 0); + billCount[amountIdx]++; + } + return true; + } +} diff --git a/Easy/Length of last word.java b/Easy/Length of last word.java index 5126a352..a351538e 100644 --- a/Easy/Length of last word.java +++ b/Easy/Length of last word.java @@ -1,6 +1,13 @@ class Solution { - public int lengthOfLastWord(String s) { - String[] strs = s.split("\\s"); - return strs.length > 0 ? strs[strs.length-1].length() : 0; + public int lengthOfLastWord(String s) { + int idx = s.length() - 1; + while (idx >= 0 && s.charAt(idx) == ' ') { + idx--; } + int currIdx = idx; + while (idx >= 0 && s.charAt(idx) != ' ') { + idx--; + } + return currIdx - idx; + } } diff --git a/Easy/Letter Case Permutation.java b/Easy/Letter Case Permutation.java index a9f2b640..eb1f7d74 100644 --- a/Easy/Letter Case Permutation.java +++ b/Easy/Letter Case Permutation.java @@ -1,23 +1,26 @@ class Solution { - public List letterCasePermutation(String S) { - List ans = new ArrayList<>(); - letterCasePermutationHelper(ans, S.toCharArray(), 0); - - return ans; - } - - private void letterCasePermutationHelper(List ans, char[] chars, int index) { - if (index == chars.length) { - ans.add(new String(chars)); - } - else { - if (Character.isLetter(chars[index])) { - chars[index] = Character.toLowerCase(chars[index]); - letterCasePermutationHelper(ans, chars, index+1); - chars[index] = Character.toUpperCase(chars[index]); - } - - letterCasePermutationHelper(ans, chars, index+1); - } + public List letterCasePermutation(String S) { + List result = new ArrayList<>(); + helper(S, 0, new StringBuilder(), result); + return result; + } + + private void helper(String s, int idx, StringBuilder sb, List result) { + if (idx == s.length()) { + result.add(new String(sb.toString())); + } else { + if (Character.isDigit(s.charAt(idx))) { + sb.append(s.charAt(idx)); + helper(s, idx + 1, sb, result); + sb.deleteCharAt(sb.length() - 1); + } else { + sb.append(Character.toLowerCase(s.charAt(idx))); + helper(s, idx + 1, sb, result); + sb.deleteCharAt(sb.length() - 1); + sb.append(Character.toUpperCase(s.charAt(idx))); + helper(s, idx + 1, sb, result); + sb.deleteCharAt(sb.length() - 1); + } } + } } diff --git a/Easy/Linked List Cycle.java b/Easy/Linked List Cycle.java index 8de7f13c..6c55e388 100644 --- a/Easy/Linked List Cycle.java +++ b/Easy/Linked List Cycle.java @@ -10,15 +10,16 @@ * } */ public class Solution { - public boolean hasCycle(ListNode head) { - ListNode fast = head; - ListNode slow = head; - - while (fast != null && fast.next != null) { - slow = slow.next; - fast = fast.next.next; - if (slow == fast) return true; - } - return false; + public boolean hasCycle(ListNode head) { + ListNode slow = head; + ListNode fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + if (slow == fast) { + return true; + } } + return false; + } } diff --git a/Easy/Logger Rate Limiter.java b/Easy/Logger Rate Limiter.java index b63decd4..6cdc1665 100644 --- a/Easy/Logger Rate Limiter.java +++ b/Easy/Logger Rate Limiter.java @@ -1,24 +1,18 @@ class Logger { + + private final Map logger; + + public Logger() { + this.logger = new HashMap<>(); + } - /** Initialize your data structure here. */ - Map map; - public Logger() { - map = new HashMap<>(); - } - - /** Returns true if the message should be printed in the given timestamp, otherwise returns false. - If this method returns false, the message will not be printed. - The timestamp is in seconds granularity. */ - public boolean shouldPrintMessage(int timestamp, String message) { - - if (map.containsKey(message) && timestamp - map.get(message) < 10) { - return false; - } - - map.put(message, timestamp); - - return true; + public boolean shouldPrintMessage(int timestamp, String message) { + if (this.logger.containsKey(message) && timestamp - this.logger.get(message) < 10) { + return false; } + this.logger.put(message, timestamp); + return true; + } } /** diff --git a/Easy/Long Pressed Name.java b/Easy/Long Pressed Name.java new file mode 100644 index 00000000..3e134aa3 --- /dev/null +++ b/Easy/Long Pressed Name.java @@ -0,0 +1,27 @@ +class Solution { + public boolean isLongPressedName(String name, String typed) { + int idxName = 0; + int idxTyped = 0; + while (idxName < name.length() && idxTyped < typed.length()) { + if (name.charAt(idxName) != typed.charAt(idxTyped)) { + return false; + } + char c = name.charAt(idxName); + int nameFreq = 0; + while (idxName < name.length() && name.charAt(idxName) == c) { + idxName++; + nameFreq++; + } + c = typed.charAt(idxTyped); + int typedFreq = 0; + while (idxTyped < typed.length() && typed.charAt(idxTyped) == c) { + idxTyped++; + typedFreq++; + } + if (nameFreq > typedFreq) { + return false; + } + } + return idxName == name.length() && idxTyped == typed.length(); + } +} diff --git a/Easy/Longer Contiguous Segments of Ones than Zeros.java b/Easy/Longer Contiguous Segments of Ones than Zeros.java new file mode 100644 index 00000000..9a7d40c5 --- /dev/null +++ b/Easy/Longer Contiguous Segments of Ones than Zeros.java @@ -0,0 +1,22 @@ +class Solution { + public boolean checkZeroOnes(String s) { + int zeroBlock = 0; + int oneBlock = 0; + int idx = 0; + int n = s.length(); + while (idx < n) { + char c = s.charAt(idx); + int currCount = 0; + while (idx < n && s.charAt(idx) == c) { + currCount++; + idx++; + } + if (c == '0') { + zeroBlock = Math.max(zeroBlock, currCount); + } else { + oneBlock = Math.max(oneBlock, currCount); + } + } + return oneBlock > zeroBlock; + } +} diff --git a/Easy/Longest Alternating Subarray.java b/Easy/Longest Alternating Subarray.java new file mode 100644 index 00000000..65de425c --- /dev/null +++ b/Easy/Longest Alternating Subarray.java @@ -0,0 +1,21 @@ +class Solution { + public int alternatingSubarray(int[] nums) { + int start = 0; + int maxLength = -1; + int expectedDiff = 1; + for (int i = 1; i < nums.length;) { + if (nums[i] - nums[i - 1] != expectedDiff) { + if (nums[i] - nums[i - 1] != 1) { + i++; + } + start = i - 1; + expectedDiff = 1; + continue; + } + expectedDiff *= -1; + maxLength = Math.max(maxLength, i - start + 1); + i++; + } + return maxLength; + } +} diff --git a/Easy/Longest Common Prefix.java b/Easy/Longest Common Prefix.java index ed905d22..fb655701 100644 --- a/Easy/Longest Common Prefix.java +++ b/Easy/Longest Common Prefix.java @@ -1,15 +1,22 @@ class Solution { - public String longestCommonPrefix(String[] strs) { - if (strs == null || strs.length == 0) return ""; - - String ans = strs[0]; - - for (int i=1;i threshold) { + idx++; + start = idx; + evenRequired = true; + continue; + } + if (nums[idx] % 2 == 0 && !evenRequired) { + start = idx; + evenRequired = true; + continue; + } + if (nums[idx] % 2 != 0 && evenRequired) { + idx++; + start = idx; + evenRequired = true; + continue; + } + idx++; + maxLength = Math.max(maxLength, idx - start); + evenRequired = !evenRequired; + } + return maxLength; + } +} diff --git a/Easy/Longest Harmonious Subsequence.java b/Easy/Longest Harmonious Subsequence.java index 98729d86..73f54d43 100644 --- a/Easy/Longest Harmonious Subsequence.java +++ b/Easy/Longest Harmonious Subsequence.java @@ -1,20 +1,16 @@ class Solution { - public int findLHS(int[] nums) { - - int max = 0; - - Map map = new HashMap<>(); - - for (int n : nums) { - map.put(n, map.getOrDefault(n,0)+1); - } - - for (int key : map.keySet()) { - if (map.containsKey(key+1)) { - max = Math.max(max, map.get(key) + map.get(key+1)); - } - } - - return max; + public int findLHS(int[] nums) { + int maxSubarraySize = 0; + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + if (map.containsKey(num + 1)) { + maxSubarraySize = Math.max(maxSubarraySize, map.get(num) + map.get(num + 1)); + } + if (map.containsKey(num - 1)) { + maxSubarraySize = Math.max(maxSubarraySize, map.get(num) + map.get(num - 1)); + } } + return maxSubarraySize; + } } diff --git a/Easy/Longest Nice Substring.java b/Easy/Longest Nice Substring.java new file mode 100644 index 00000000..0795b833 --- /dev/null +++ b/Easy/Longest Nice Substring.java @@ -0,0 +1,14 @@ +class Solution { + public String longestNiceSubstring(String s) { + Set set = s.chars().mapToObj(c -> (char) c).collect(Collectors.toSet()); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (!(set.contains(Character.toLowerCase(c)) && set.contains(Character.toUpperCase(c)))) { + String left = longestNiceSubstring(s.substring(0, i)); + String right = longestNiceSubstring(s.substring(i + 1)); + return left.length() >= right.length() ? left : right; + } + } + return s; + } +} diff --git a/Easy/Longest Palindrome.java b/Easy/Longest Palindrome.java index c6c3f662..aa91e564 100644 --- a/Easy/Longest Palindrome.java +++ b/Easy/Longest Palindrome.java @@ -1,28 +1,18 @@ class Solution { - public int longestPalindrome(String s) { - int[] count = new int[52]; - - for (int i=0;i= 97) { - ind -= 97; - } - else { - ind = ind + 26 - 65; - } - count[ind]++; - } - - int l = 0; - for (int i=0;i<52;i++) { - if (count[i]%2 == 0) { - l += count[i]; - } - else { - l += count[i]-1; - } - } - - return s.length() > l ? l+1 : l; + public int longestPalindrome(String s) { + Map map = new HashMap<>(); + for (char c : s.toCharArray()) { + map.put(c, map.getOrDefault(c, 0) + 1); } + int totalLength = 0; + boolean oddTaken = false; + for (Character key : map.keySet()) { + totalLength += (map.get(key) / 2) * 2; + if (!oddTaken && map.get(key) % 2 != 0) { + totalLength++; + oddTaken = !oddTaken; + } + } + return totalLength; + } } diff --git a/Easy/Longest Strictly Increasing or Strictly Decreasing Subarray.java b/Easy/Longest Strictly Increasing or Strictly Decreasing Subarray.java new file mode 100644 index 00000000..c1ed1c36 --- /dev/null +++ b/Easy/Longest Strictly Increasing or Strictly Decreasing Subarray.java @@ -0,0 +1,22 @@ +class Solution { + public int longestMonotonicSubarray(int[] nums) { + int max = 1; + int idx = 0; + int n = nums.length; + while (idx < n) { + if (idx == n - 1 || nums[idx + 1] == nums[idx]) { + idx++; + continue; + } + boolean increase = nums[idx + 1] > nums[idx]; + int start = idx; + while (idx + 1 < n && ( + (increase && nums[idx + 1] > nums[idx]) || + (!increase && nums[idx + 1] < nums[idx]))) { + idx++; + } + max = Math.max(max, idx - start + 1); + } + return max; + } +} diff --git a/Easy/Longest Subsequence With Limited Sum.java b/Easy/Longest Subsequence With Limited Sum.java new file mode 100644 index 00000000..5dd527a5 --- /dev/null +++ b/Easy/Longest Subsequence With Limited Sum.java @@ -0,0 +1,11 @@ +class Solution { + public int[] answerQueries(int[] nums, int[] queries) { + Arrays.sort(nums); + Arrays.parallelPrefix(nums, Integer::sum); + for (int i = 0; i < queries.length; i++) { + int idx = Arrays.binarySearch(nums, queries[i]); + queries[i] = Math.abs(idx + 1); + } + return queries; + } +} diff --git a/Easy/Longest Univalue Path.java b/Easy/Longest Univalue Path.java index 5d152248..4409e7bf 100644 --- a/Easy/Longest Univalue Path.java +++ b/Easy/Longest Univalue Path.java @@ -4,23 +4,37 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - - public int longestUnivaluePath(TreeNode root) { - int[] res = new int[1]; - if (root != null) dfs(root, res); - return res[0]; + public int longestUnivaluePath(TreeNode root) { + int[] max = {0}; + helper(root, max); + return max[0]; + } + + private int helper(TreeNode root, int[] max) { + if (root == null) { + return 0; } - - private int dfs(TreeNode node, int[] res) { - int l = node.left != null ? dfs(node.left, res) : 0; - int r = node.right != null ? dfs(node.right, res) : 0; - int resl = node.left != null && node.left.val == node.val ? l + 1 : 0; - int resr = node.right != null && node.right.val == node.val ? r + 1 : 0; - res[0] = Math.max(res[0], resl + resr); - return Math.max(resl, resr); + int left = helper(root.left, max); + int right = helper(root.right, max); + int leftVal = 0; + int rightVal = 0; + if (root.left != null && root.val == root.left.val) { + leftVal = left + 1; } + if (root.right != null && root.val == root.right.val) { + rightVal = right + 1; + } + max[0] = Math.max(max[0], leftVal + rightVal); + return Math.max(leftVal, rightVal); + } } diff --git a/Easy/Longest Word in Dictionary.java b/Easy/Longest Word in Dictionary.java index 8a8a99ee..f83e2d62 100644 --- a/Easy/Longest Word in Dictionary.java +++ b/Easy/Longest Word in Dictionary.java @@ -1,16 +1,51 @@ class Solution { - public String longestWord(String[] words) { - Arrays.sort(words); - - Set built = new HashSet(); - String ans = ""; - - for (String word : words) { - if (word.length() == 1 || built.contains(word.substring(0, word.length() - 1))) { - ans = word.length() > ans.length() ? word : ans; - built.add(word); - } - } - return ans; + Map> map; + int maxVal; + public String longestWord(String[] words) { + map = new HashMap<>(); + maxVal = Integer.MIN_VALUE; + Node root = new Node('-'); + Arrays.sort(words); + for (String word : words) { + addWord(word, root, 0); } + if (maxVal == Integer.MIN_VALUE) { + return ""; + } + List possibleAns = map.get(maxVal); + Collections.sort(possibleAns); + return possibleAns.get(0); + } + + private void addWord(String word, Node root, int idx) { + char c = word.charAt(idx); + if (!root.children.containsKey(c) && idx != word.length() - 1) { + return; + } + if (!root.children.containsKey(c)) { + root.children.put(c, new Node(c)); + } + root = root.children.get(c); + if (idx == word.length() - 1) { + root.isWord = true; + int wordLength = word.length(); + map.computeIfAbsent(wordLength, k -> new ArrayList<>()).add(word); + maxVal = Math.max(maxVal, wordLength); + } + else { + addWord(word, root, idx + 1); + } + } +} + +class Node { + char val; + boolean isWord; + Map children; + + public Node(char val) { + this.val = val; + isWord = true; + children = new HashMap<>(); + } } diff --git a/Easy/Lowest Common Ancestor of a Binary Search Tree.java b/Easy/Lowest Common Ancestor of a Binary Search Tree.java index cc700bd2..d2a407b3 100644 --- a/Easy/Lowest Common Ancestor of a Binary Search Tree.java +++ b/Easy/Lowest Common Ancestor of a Binary Search Tree.java @@ -7,17 +7,19 @@ * TreeNode(int x) { val = x; } * } */ + class Solution { - public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { - - if (root.val < p.val && root.val < q.val) { - return lowestCommonAncestor(root.right, p, q); - } - else if (root.val > p.val && root.val > q.val) { - return lowestCommonAncestor(root.left, p, q); - } - else { - return root; - } + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) { + return root; } + if (root == p || root == q) { + return root; + } + if ((root.val > p.val && root.val < q.val) || (root.val < p.val && root.val > q.val)) { + return root; + } + TreeNode left = lowestCommonAncestor(root.left, p, q); + return left == null ? lowestCommonAncestor(root.right, p, q) : left; + } } diff --git a/Easy/Lucky Numbers in a Matrix.java b/Easy/Lucky Numbers in a Matrix.java new file mode 100644 index 00000000..01b0bed3 --- /dev/null +++ b/Easy/Lucky Numbers in a Matrix.java @@ -0,0 +1,24 @@ +class Solution { + public List luckyNumbers (int[][] matrix) { + int numRows = matrix.length; + int numCols = matrix[0].length; + int[] rowMin = new int[numRows]; + int[] colMax = new int[numCols]; + Arrays.fill(rowMin, Integer.MAX_VALUE); + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + rowMin[i] = Math.min(matrix[i][j], rowMin[i]); + colMax[j] = Math.max(matrix[i][j], colMax[j]); + } + } + List list = new ArrayList<>(); + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + if (rowMin[i] == colMax[j]) { + list.add(matrix[i][j]); + } + } + } + return list; + } +} diff --git a/Easy/Magic Squares In Grid.java b/Easy/Magic Squares In Grid.java index 1ec774c5..fea5b550 100644 --- a/Easy/Magic Squares In Grid.java +++ b/Easy/Magic Squares In Grid.java @@ -1,49 +1,46 @@ class Solution { - public int numMagicSquaresInside(int[][] grid) { - int rows = grid.length; - int col = grid[0].length; - int count = 0; - - for (int i=0; i<=rows-3; i++) { - for (int j=0; j<=col-3; j++) { - if(checker(i, j, grid)) { - count++; - } - } + public int numMagicSquaresInside(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + int count = 0; + for (int i = 0; i < rows - 2; i++) { + for (int j = 0; j < cols - 2; j++) { + if (grid[i + 1][j + 1] != 5) { + continue; } - - return count; - } - - private boolean checker(int x,int y,int[][] grid){ - if(grid[x+1][y+1]!=5) { - return false; - } - - int[] valid=new int[16]; - - for(int i=x;i<=x+2;i++) { - for(int j=y;j<=y+2;j++) { - valid[grid[i][j]]++; - } - } - - for (int v = 1; v <= 9; v++) { - if (valid[v] != 1) { - return false; - } + if ( + magic( + grid[i][j], grid[i][j + 1], grid[i][j + 2], + grid[i + 1][j], grid[i + 1][j + 1], grid[i + 1][j + 2], + grid[i + 2][j], grid[i + 2][j + 1], grid[i + 2][j + 2] + ) + ) { + count++; } - - if ((grid[x][y]+grid[x][y+1]+grid[x][y+2])!=15 || - (grid[x][y]+grid[x+1][y+1]+grid[x+2][y+2])!=15 || - (grid[x][y]+grid[x+1][y]+grid[x+2][y])!=15 || - (grid[x+2][y]+grid[x+2][y+1]+grid[x+2][y+2])!=15 || - (grid[x][y+2]+grid[x+1][y+2]+grid[x+2][y+2])!=15 || - (grid[x][y+2]+grid[x+1][y+1]+grid[x+2][y])!=15) { - - return false; - } - - return true; + } + } + return count; + } + + private boolean magic(int... vals) { + int[] count = new int[16]; + for (int v : vals) { + count[v]++; + } + for (int v = 1; v <= 9; v++) { + if (count[v] != 1) { + return false; + } } + return ( + vals[0] + vals[1] + vals[2] == 15 && + vals[3] + vals[4] + vals[5] == 15 && + vals[6] + vals[7] + vals[8] == 15 && + vals[0] + vals[3] + vals[6] == 15 && + vals[1] + vals[4] + vals[7] == 15 && + vals[2] + vals[5] + vals[8] == 15 && + vals[0] + vals[4] + vals[8] == 15 && + vals[2] + vals[4] + vals[6] == 15 + ); + } } diff --git a/Easy/Majority Element.java b/Easy/Majority Element.java new file mode 100644 index 00000000..0fc7be1d --- /dev/null +++ b/Easy/Majority Element.java @@ -0,0 +1,13 @@ +class Solution { + public int majorityElement(int[] nums) { + int majorityElement = nums[0]; + int count = 0; + for (int num : nums) { + if (count == 0) { + majorityElement = num; + } + count += num == majorityElement ? 1 : -1; + } + return majorityElement; + } +} diff --git a/Easy/Make Array Zero by Subtracting Equal Amounts.java b/Easy/Make Array Zero by Subtracting Equal Amounts.java new file mode 100644 index 00000000..304e3e92 --- /dev/null +++ b/Easy/Make Array Zero by Subtracting Equal Amounts.java @@ -0,0 +1,5 @@ +class Solution { + public int minimumOperations(int[] nums) { + return Arrays.stream(nums).boxed().filter(n -> n > 0).collect(Collectors.toSet()).size(); + } +} diff --git a/Easy/Make The String Great.java b/Easy/Make The String Great.java new file mode 100644 index 00000000..32b4684a --- /dev/null +++ b/Easy/Make The String Great.java @@ -0,0 +1,24 @@ +class Solution { + public String makeGood(String s) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (!stack.isEmpty() && isBad(c, stack.peek())) { + stack.pop(); + continue; + } + stack.push(c); + } + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + sb.append(stack.pop()); + } + return sb.reverse().toString(); + } + + private static boolean isBad(char c1, char c2) { + if (c1 == c2) { + return false; + } + return Character.toLowerCase(c1) == Character.toLowerCase(c2); + } +} diff --git a/Easy/Make Three Strings Equal.java b/Easy/Make Three Strings Equal.java new file mode 100644 index 00000000..a1e7477f --- /dev/null +++ b/Easy/Make Three Strings Equal.java @@ -0,0 +1,13 @@ +class Solution { + public int findMinimumOperations(String s1, String s2, String s3) { + int idx = 0; + while (idx < s1.length() && idx < s2.length() && idx < s3.length() && + s1.charAt(idx) == s2.charAt(idx) && s1.charAt(idx) == s3.charAt(idx)) { + idx++; + } + if (idx == 0) { + return -1; + } + return s1.length() + s2.length() + s3.length() - 3 * idx; + } +} diff --git a/Easy/Make Two Arrays Equal by Reversing Subarrays.java b/Easy/Make Two Arrays Equal by Reversing Subarrays.java new file mode 100644 index 00000000..62ce7dca --- /dev/null +++ b/Easy/Make Two Arrays Equal by Reversing Subarrays.java @@ -0,0 +1,18 @@ +class Solution { + public boolean canBeEqual(int[] target, int[] arr) { + Map map = new HashMap<>(); + for (int num : target) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + for (int num : arr) { + if (!map.containsKey(num)) { + return false; + } + map.put(num, map.get(num) - 1); + if (map.get(num) == 0) { + map.remove(num); + } + } + return map.isEmpty(); + } +} diff --git a/Easy/Make a Square with the Same Color.java b/Easy/Make a Square with the Same Color.java new file mode 100644 index 00000000..2f5524d8 --- /dev/null +++ b/Easy/Make a Square with the Same Color.java @@ -0,0 +1,40 @@ +class Solution { + + int[][] DIRS = {{0, 0}, {0, 1}, {1, 0}, {1, 1}}; + + public boolean canMakeSquare(char[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (isPossible(grid, i, j, rows, cols)) { + return true; + } + } + } + return false; + } + + private boolean isPossible(char[][] grid, int i, int j, int rows, int cols) { + int white = 0; + int black = 0; + int invalid = 0; + for (int[] dir : DIRS) { + int newX = i + dir[0]; + int newY = j + dir[1]; + if (newX >= 0 && newY >= 0 && newX < rows && newY < cols) { + white += grid[newX][newY] == 'W' ? 1 : 0; + black += grid[newX][newY] == 'B' ? 1 : 0; + } else { + invalid++; + } + } + if (invalid > 0) { + return false; + } + if (white == 4 || black == 4) { + return true; + } + return white == 1 || black == 1; + } +} diff --git a/Easy/Matrix Diagonal Sum.java b/Easy/Matrix Diagonal Sum.java new file mode 100644 index 00000000..32e2a58f --- /dev/null +++ b/Easy/Matrix Diagonal Sum.java @@ -0,0 +1,10 @@ +class Solution { + public int diagonalSum(int[][] mat) { + int n = mat.length; + int sum = 0; + for (int i = 0; i < n; i++) { + sum += mat[i][i] + mat[i][n - i - 1]; + } + return sum - (n % 2 == 0 ? 0 : mat[n / 2][n / 2]); + } +} diff --git a/Easy/Matrix Similarity After Cyclic Shifts.java b/Easy/Matrix Similarity After Cyclic Shifts.java new file mode 100644 index 00000000..624bcf08 --- /dev/null +++ b/Easy/Matrix Similarity After Cyclic Shifts.java @@ -0,0 +1,17 @@ +class Solution { + public boolean areSimilar(int[][] mat, int k) { + for (int j = 0; j < mat.length; j++) { + if (j % 2 != 0) { + continue; + } + int[] row = mat[j]; + int n = row.length; + for (int i = 0; i < n; i++) { + if (row[i] != row[(i + k) % n]) { + return false; + } + } + } + return true; + } +} diff --git a/Easy/Max Area of Island.java b/Easy/Max Area of Island.java deleted file mode 100644 index d8afa8fe..00000000 --- a/Easy/Max Area of Island.java +++ /dev/null @@ -1,25 +0,0 @@ -class Solution { - int[][] grid; - boolean[][] seen; - - public int area(int r, int c) { - if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length || - seen[r][c] || grid[r][c] == 0) - return 0; - seen[r][c] = true; - return (1 + area(r+1, c) + area(r-1, c) - + area(r, c-1) + area(r, c+1)); - } - - public int maxAreaOfIsland(int[][] grid) { - this.grid = grid; - seen = new boolean[grid.length][grid[0].length]; - int ans = 0; - for (int r = 0; r < grid.length; r++) { - for (int c = 0; c < grid[0].length; c++) { - ans = Math.max(ans, area(r, c)); - } - } - return ans; - } -} diff --git a/Easy/Max Consecutive Ones.java b/Easy/Max Consecutive Ones.java index a9ef2478..6f3f557a 100644 --- a/Easy/Max Consecutive Ones.java +++ b/Easy/Max Consecutive Ones.java @@ -1,20 +1,16 @@ class Solution { - public int findMaxConsecutiveOnes(int[] nums) { - int i = 0; - int maxOnes = Integer.MIN_VALUE; - int temp = 0; - while (i < nums.length) { - if (nums[i] == 1) { - temp++; - } - else { - maxOnes = Math.max(maxOnes, temp); - temp = 0; - } - - i++; + public int findMaxConsecutiveOnes(int[] nums) { + int maxCount = 0; + for (int i = 0; i < nums.length; ) { + if (nums[i] == 1) { + int currIdx = i; + while (i < nums.length && nums[i] == 1) { + i++; } - - return Math.max(maxOnes, temp); + maxCount = Math.max(maxCount, i - currIdx); + } + i++; } + return maxCount; + } } diff --git a/Easy/Max Pair Sum in an Array.java b/Easy/Max Pair Sum in an Array.java new file mode 100644 index 00000000..e7f6332e --- /dev/null +++ b/Easy/Max Pair Sum in an Array.java @@ -0,0 +1,54 @@ +class Solution { + public int maxSum(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + int maxDigit = getMaxDigit(num); + if (!map.containsKey(maxDigit)) { + map.put(maxDigit, new Pair()); + } + map.get(maxDigit).record(num); + } + int result = -1; + for (Integer key : map.keySet()) { + result = Math.max(result, map.get(key).getPairSum()); + } + return result; + } + + private int getMaxDigit(int num) { + int maxDigit = 0; + while (num > 0) { + maxDigit = Math.max(maxDigit, num % 10); + num /= 10; + } + return maxDigit; + } + + private static class Pair { + int maximum; + int secondMaximum; + + public Pair() { + maximum = -1; + secondMaximum = -1; + } + + public void record(int num) { + if (maximum < num) { + if (secondMaximum < maximum) { + secondMaximum = maximum; + } + maximum = num; + } else if (secondMaximum < num) { + secondMaximum = num; + } + } + + public int getPairSum() { + if (maximum == -1 || secondMaximum == -1) { + return -1; + } + return maximum + secondMaximum; + } + } +} diff --git a/Easy/Max Stack.java b/Easy/Max Stack.java deleted file mode 100644 index 8040a2c0..00000000 --- a/Easy/Max Stack.java +++ /dev/null @@ -1,70 +0,0 @@ -class MaxStack { - - /** initialize your data structure here. */ - Stack stack; - Stack maxStack; - - public MaxStack() { - stack = new Stack<>(); - maxStack = new Stack<>(); - } - - public void push(int x) { - stack.push(x); - if (maxStack.isEmpty()) { - maxStack.push(x); - } - else { - maxStack.push(Math.max(maxStack.peek(), x)); - } - } - - public int pop() { - int val = stack.pop(); - maxStack.pop(); - return val; - } - - public int top() { - return stack.peek(); - } - - public int peekMax() { - return maxStack.peek(); - } - - public int popMax() { - int maxOnTop = maxStack.peek(); - Stack temp = new Stack<>(); - while (stack.peek() != maxOnTop) { - temp.add(stack.pop()); - maxStack.pop(); - } - - stack.pop(); - maxStack.pop(); - - while (!temp.isEmpty()) { - int popped = temp.pop(); - stack.push(popped); - if (maxStack.isEmpty()) { - maxStack.push(popped); - } - else { - maxStack.push(Math.max(popped, maxStack.peek())); - } - } - - return maxOnTop; - } -} - -/** - * Your MaxStack object will be instantiated and called as such: - * MaxStack obj = new MaxStack(); - * obj.push(x); - * int param_2 = obj.pop(); - * int param_3 = obj.top(); - * int param_4 = obj.peekMax(); - * int param_5 = obj.popMax(); - */ diff --git a/Easy/Maximize Distance to Closest Person.java b/Easy/Maximize Distance to Closest Person.java deleted file mode 100644 index c9ba8bfe..00000000 --- a/Easy/Maximize Distance to Closest Person.java +++ /dev/null @@ -1,28 +0,0 @@ -class Solution { - public static int maxDistToClosest(int[] seats) { - int left = -1; - int max = 0; - int length = seats.length; - - for (int i=0; i pq = new PriorityQueue<>(); + int sum = 0; + for (int num : nums) { + pq.add(num); + sum += num; + } + while (k-- > 0) { + sum -= pq.peek(); + sum += -1 * pq.peek(); + pq.add(-1 * pq.poll()); + } + return sum; + } +} diff --git a/Easy/Maximum 69 Number.java b/Easy/Maximum 69 Number.java new file mode 100644 index 00000000..400bf663 --- /dev/null +++ b/Easy/Maximum 69 Number.java @@ -0,0 +1,11 @@ +class Solution { + public int maximum69Number (int num) { + String numString = String.valueOf(num); + for (int i = 0; i < numString.length(); i++) { + if (numString.charAt(i) == '6') { + return Integer.parseInt(numString.substring(0, i) + '9' + numString.substring(i + 1)); + } + } + return num; + } +} diff --git a/Easy/Maximum Ascending Subarray Sum.java b/Easy/Maximum Ascending Subarray Sum.java new file mode 100644 index 00000000..fd64c04c --- /dev/null +++ b/Easy/Maximum Ascending Subarray Sum.java @@ -0,0 +1,15 @@ +class Solution { + public int maxAscendingSum(int[] nums) { + int maxSum = 0; + int idx = 0; + int n = nums.length; + while (idx < n) { + int currSum = nums[idx++]; + while (idx < n && nums[idx] > nums[idx - 1]) { + currSum += nums[idx++]; + } + maxSum = Math.max(maxSum, currSum); + } + return maxSum; + } +} diff --git a/Easy/Maximum Average Subarray I.java b/Easy/Maximum Average Subarray I.java new file mode 100644 index 00000000..bdd6206e --- /dev/null +++ b/Easy/Maximum Average Subarray I.java @@ -0,0 +1,15 @@ +class Solution { + public double findMaxAverage(int[] nums, int k) { + double sum = 0; + for (int i = 0; i < k; i++) { + sum += nums[i]; + } + double maxAverage = sum / k; + for (int i = k; i < nums.length; i++) { + sum -= nums[i - k]; + sum += nums[i]; + maxAverage = Math.max(maxAverage, sum / k); + } + return maxAverage; + } +} diff --git a/Easy/Maximum Containers on a Ship.java b/Easy/Maximum Containers on a Ship.java new file mode 100644 index 00000000..e113027d --- /dev/null +++ b/Easy/Maximum Containers on a Ship.java @@ -0,0 +1,8 @@ +class Solution { + public int maxContainers(int n, int w, int maxWeight) { + if (n * n * w <= maxWeight) { + return n * n; + } + return maxWeight / w; + } +} diff --git a/Easy/Maximum Count of Positive Integer and Negative Integer.java b/Easy/Maximum Count of Positive Integer and Negative Integer.java new file mode 100644 index 00000000..73e0dba8 --- /dev/null +++ b/Easy/Maximum Count of Positive Integer and Negative Integer.java @@ -0,0 +1,11 @@ +class Solution { + public int maximumCount(int[] nums) { + int positiveCount = 0; + int negativeCount = 0; + for (int num : nums) { + positiveCount += num > 0 ? 1 : 0; + negativeCount += num < 0 ? 1 : 0; + } + return Math.max(positiveCount, negativeCount); + } +} diff --git a/Easy/Maximum Difference Between Even and Odd Frequency I.java b/Easy/Maximum Difference Between Even and Odd Frequency I.java new file mode 100644 index 00000000..ec68c06f --- /dev/null +++ b/Easy/Maximum Difference Between Even and Odd Frequency I.java @@ -0,0 +1,19 @@ +class Solution { + public int maxDifference(String s) { + Map map = new HashMap<>(); + for (char c : s.toCharArray()) { + map.put(c, map.getOrDefault(c, 0) + 1); + } + int maxOdd = Integer.MIN_VALUE; + int minEven = Integer.MAX_VALUE; + for (Character key : map.keySet()) { + Integer value = map.get(key); + if (value % 2 == 0) { + minEven = Math.min(minEven, value); + } else { + maxOdd = Math.max(maxOdd, value); + } + } + return maxOdd - minEven; + } +} diff --git a/Easy/Maximum Difference Between Increasing Elements.java b/Easy/Maximum Difference Between Increasing Elements.java new file mode 100644 index 00000000..edb343d1 --- /dev/null +++ b/Easy/Maximum Difference Between Increasing Elements.java @@ -0,0 +1,13 @@ +class Solution { + public int maximumDifference(int[] nums) { + int currMin = nums[0]; + int maxDiff = -1; + for (int i = 0; i < nums.length; i++) { + currMin = Math.min(currMin, nums[i]); + if (nums[i] != currMin) { + maxDiff = Math.max(maxDiff, nums[i] - currMin); + } + } + return maxDiff; + } +} diff --git a/Easy/Maximum Difference by Remapping a Digit.java b/Easy/Maximum Difference by Remapping a Digit.java new file mode 100644 index 00000000..5241297f --- /dev/null +++ b/Easy/Maximum Difference by Remapping a Digit.java @@ -0,0 +1,25 @@ +class Solution { + public int minMaxDifference(int num) { + char digitsOne[] = String.valueOf(num).toCharArray(); + char digitsTwo[] = String.valueOf(num).toCharArray(); + char firstDigitOne = digitsOne[0]; + char firstDigitTwo = digitsOne[0]; + for (int i = 0; i < digitsOne.length; i++) { + if (digitsOne[i] != '9') { + firstDigitOne = digitsOne[i]; + break; + } + } + for (int i = 0; i < digitsOne.length; i++) { + if (digitsOne[i] == firstDigitOne) { + digitsOne[i] = '9'; + } + } + for(int i = 0; i < digitsOne.length; i++) { + if (digitsTwo[i] == firstDigitTwo) { + digitsTwo[i] = '0'; + } + } + return Integer.parseInt(String.valueOf(digitsOne)) - Integer.parseInt(String.valueOf(digitsTwo)); + } +} diff --git a/Easy/Maximum Distance in Arrays.java b/Easy/Maximum Distance in Arrays.java deleted file mode 100644 index 71a4581d..00000000 --- a/Easy/Maximum Distance in Arrays.java +++ /dev/null @@ -1,17 +0,0 @@ -class Solution { - public static int maxDistance(List> arrays) { - int min = arrays.get(0).get(0); - int max = arrays.get(0).get(arrays.get(0).size()-1); - int result = Integer.MIN_VALUE; - - for (int i=1; i map = new HashMap<>(); + int start = 0; + int end = 0; + int n = s.length(); + int result = 0; + while (end < n) { + map.put(s.charAt(end), map.getOrDefault(s.charAt(end), 0) + 1); + while (start <= end && map.get(s.charAt(end)) > 2) { + map.put(s.charAt(start), map.get(s.charAt(start)) - 1); + start++; + } + end++; + result = Math.max(result, end - start); + } + return result; + } +} diff --git a/Easy/Maximum Nesting Depth of the Parentheses.java b/Easy/Maximum Nesting Depth of the Parentheses.java new file mode 100644 index 00000000..8ce9eac2 --- /dev/null +++ b/Easy/Maximum Nesting Depth of the Parentheses.java @@ -0,0 +1,13 @@ +class Solution { + public int maxDepth(String s) { + int count = 0; + int result = 0; + for (char c : s.toCharArray()) { + if (c == '(' || c == ')') { + count += c == '(' ? 1 : -1; + } + result = Math.max(result, count); + } + return result; + } +} diff --git a/Easy/Maximum Number of Balloons.java b/Easy/Maximum Number of Balloons.java new file mode 100644 index 00000000..018f048c --- /dev/null +++ b/Easy/Maximum Number of Balloons.java @@ -0,0 +1,17 @@ +class Solution { + public int maxNumberOfBalloons(String text) { + Map textFrequencyMap = getFrequencyMap(text); + Map ballonFrequencyMap = getFrequencyMap("balloon"); + return ballonFrequencyMap.keySet().stream() + .map(k -> + (int) (textFrequencyMap.getOrDefault(k, 0L) / ballonFrequencyMap.get(k))) + .min(Integer::compare) + .orElse(0); + } + + private Map getFrequencyMap(String s) { + return s.chars() + .mapToObj(c -> (char) c) + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())); + } +} diff --git a/Easy/Maximum Number of Balls in a Box.java b/Easy/Maximum Number of Balls in a Box.java new file mode 100644 index 00000000..1cde1b06 --- /dev/null +++ b/Easy/Maximum Number of Balls in a Box.java @@ -0,0 +1,21 @@ +class Solution { + public int countBalls(int lowLimit, int highLimit) { + Map map = new HashMap<>(); + int maxCount = 0; + for (int num = lowLimit; num <= highLimit; num++) { + int digitSum = getDigitSum(num); + map.put(digitSum, map.getOrDefault(digitSum, 0) + 1); + maxCount = Math.max(maxCount, map.get(digitSum)); + } + return maxCount; + } + + private int getDigitSum(int num) { + int sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum; + } +} diff --git a/Easy/Maximum Number of Operations With the Same Score I.java b/Easy/Maximum Number of Operations With the Same Score I.java new file mode 100644 index 00000000..22f6648d --- /dev/null +++ b/Easy/Maximum Number of Operations With the Same Score I.java @@ -0,0 +1,15 @@ +class Solution { + public int maxOperations(int[] nums) { + int score = -1; + int operations = 0; + for (int i = 0; i <= nums.length - 2; i += 2) { + int currScore = nums[i] + nums[i + 1]; + if (score != -1 && score != currScore) { + break; + } + score = currScore; + operations++; + } + return operations; + } +} diff --git a/Easy/Maximum Number of Pairs in Array.java b/Easy/Maximum Number of Pairs in Array.java new file mode 100644 index 00000000..38db03b0 --- /dev/null +++ b/Easy/Maximum Number of Pairs in Array.java @@ -0,0 +1,14 @@ +class Solution { + public int[] numberOfPairs(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int[] result = new int[2]; + for (Integer key : map.keySet()) { + result[0] += map.get(key) / 2; + result[1] += map.get(key) % 2; + } + return result; + } +} diff --git a/Easy/Maximum Number of Words Found in Sentences.java b/Easy/Maximum Number of Words Found in Sentences.java new file mode 100644 index 00000000..78b2af40 --- /dev/null +++ b/Easy/Maximum Number of Words Found in Sentences.java @@ -0,0 +1,6 @@ +class Solution { + public int mostWordsFound(String[] sentences) { + return Arrays.stream(sentences).map(sentence -> sentence.split("\\s").length) + .max(Integer::compare).orElse(0); + } +} diff --git a/Easy/Maximum Number of Words You Can Type.java b/Easy/Maximum Number of Words You Can Type.java new file mode 100644 index 00000000..dd3afc70 --- /dev/null +++ b/Easy/Maximum Number of Words You Can Type.java @@ -0,0 +1,9 @@ +class Solution { + public int canBeTypedWords(String text, String brokenLetters) { + return (int) Arrays.stream(text.split("\\s+")) + .filter(e -> e.chars() + .mapToObj(c -> (char) c) + .noneMatch(c -> brokenLetters.indexOf(c) != -1)) + .count(); + } +} diff --git a/Easy/Maximum Odd Binary Number.java b/Easy/Maximum Odd Binary Number.java new file mode 100644 index 00000000..861a3fd1 --- /dev/null +++ b/Easy/Maximum Odd Binary Number.java @@ -0,0 +1,13 @@ +class Solution { + public String maximumOddBinaryNumber(String s) { + int oneCount = 0; + for (char c : s.toCharArray()) { + oneCount += c == '1' ? 1 : 0; + } + if (oneCount == 0) { + return s; + } + int zeroCount = s.length() - oneCount; + return "1".repeat(oneCount - 1) + "0".repeat(zeroCount) + "1"; + } +} diff --git a/Easy/Maximum Population Year.java b/Easy/Maximum Population Year.java new file mode 100644 index 00000000..93766873 --- /dev/null +++ b/Easy/Maximum Population Year.java @@ -0,0 +1,15 @@ +class Solution { + public int maximumPopulation(int[][] logs) { + int[] population = new int[2051]; + for (int[] log : logs) { + population[log[0]]++; + population[log[1]]--; + } + int maxPopulationYear = 0; + for (int i = 1950; i <= 2050; i++) { + population[i] += population[i - 1]; + maxPopulationYear = population[i] > population[maxPopulationYear] ? i : maxPopulationYear; + } + return maxPopulationYear; + } +} diff --git a/Easy/Maximum Product Difference Between Two Pairs.java b/Easy/Maximum Product Difference Between Two Pairs.java new file mode 100644 index 00000000..3c3edf02 --- /dev/null +++ b/Easy/Maximum Product Difference Between Two Pairs.java @@ -0,0 +1,6 @@ +class Solution { + public int maxProductDifference(int[] nums) { + Arrays.sort(nums); + return nums[nums.length - 1] * nums[nums.length - 2] - nums[0] * nums[1]; + } +} diff --git a/Easy/Maximum Product of Three Numbers.java b/Easy/Maximum Product of Three Numbers.java new file mode 100644 index 00000000..981fbf96 --- /dev/null +++ b/Easy/Maximum Product of Three Numbers.java @@ -0,0 +1,9 @@ +class Solution { + public int maximumProduct(int[] nums) { + Arrays.sort(nums); + int n = nums.length; + int lastThree = nums[n - 1] * nums[n - 2] * nums[n - 3]; + int firstTwoAndLast = nums[0] * nums[1] * nums[n - 1]; + return Math.max(lastThree, firstTwoAndLast); + } +} diff --git a/Easy/Maximum Product of Two Digits.java b/Easy/Maximum Product of Two Digits.java new file mode 100644 index 00000000..c61f3c3a --- /dev/null +++ b/Easy/Maximum Product of Two Digits.java @@ -0,0 +1,17 @@ +class Solution { + public int maxProduct(int n) { + int maximum = Integer.MIN_VALUE; + int secondMaximum = Integer.MIN_VALUE; + while (n > 0) { + int num = n % 10; + n /= 10; + if (num > maximum) { + secondMaximum = maximum; + maximum = num; + } else if (num > secondMaximum) { + secondMaximum = num; + } + } + return maximum * secondMaximum; + } +} diff --git a/Easy/Maximum Product of Two Elements in an Array.java b/Easy/Maximum Product of Two Elements in an Array.java new file mode 100644 index 00000000..afc4e858 --- /dev/null +++ b/Easy/Maximum Product of Two Elements in an Array.java @@ -0,0 +1,16 @@ +class Solution { + int maxOne = Integer.MIN_VALUE; + int maxTwo = Integer.MIN_VALUE; + public int maxProduct(int[] nums) { + for (int num : nums) { + if (maxOne < num) { + maxTwo = maxOne; + maxOne = num; + } + else if (maxTwo < num) { + maxTwo = num; + } + } + return (maxOne - 1) * (maxTwo - 1); + } +} diff --git a/Easy/Maximum Product of three numbers.java b/Easy/Maximum Product of three numbers.java deleted file mode 100644 index 0f183fcd..00000000 --- a/Easy/Maximum Product of three numbers.java +++ /dev/null @@ -1,76 +0,0 @@ -class Solution { - public int maximumProduct(int[] nums) { - int max1 = Integer.MIN_VALUE; - int max2 = Integer.MIN_VALUE; - int max3 = Integer.MIN_VALUE; - int min1 = Integer.MAX_VALUE; - int min2 = Integer.MAX_VALUE; - - for (int num : nums) { - if (max1 == Integer.MIN_VALUE) { - max1 = num; - } - else if (max2 == Integer.MIN_VALUE) { - if (num > max1) { - max2 = max1; - max1 = num; - } - else { - max2 = num; - } - } - else if (max3 == Integer.MIN_VALUE) { - if (num > max1) { - max3 = max2; - max2 = max1; - max1 = num; - } - else if (num > max2) { - max3 = max2; - max2 = num; - } - else { - max3 = num; - } - } - else { - if (num > max1) { - max3 = max2; - max2 = max1; - max1 = num; - } - else if (num > max2) { - max3 = max2; - max2 = num; - } - else { - max3 = Math.max(max3, num); - } - } - - if (min1 == Integer.MIN_VALUE) { - min1 = num; - } - else if (min2 == Integer.MIN_VALUE) { - if (min1 > num) { - min2 = min1; - min1 = num; - } - else { - min2 = num; - } - } - else { - if (min1 > num) { - min2 = min1; - min1 = num; - } - else { - min2 = Math.min(min2, num); - } - } - } - - return Math.max(min1 * min2 * max1, max1 * max2 * max3); - } -} diff --git a/Easy/Maximum Repeating Substring.java b/Easy/Maximum Repeating Substring.java new file mode 100644 index 00000000..9b1ae019 --- /dev/null +++ b/Easy/Maximum Repeating Substring.java @@ -0,0 +1,18 @@ +class Solution { + public int maxRepeating(String sequence, String word) { + int maxCount = 0; + int idx = 0; + int wordLength = word.length(); + int limitLength = sequence.length() - wordLength + 1; + while (idx < limitLength) { + int currCount = 0; + while (idx < limitLength && sequence.substring(idx, idx + wordLength).equals(word)) { + currCount++; + idx += wordLength; + } + maxCount = Math.max(maxCount, currCount); + idx++; + } + return maxCount; + } +} diff --git a/Easy/Maximum Score After Splitting a String.java b/Easy/Maximum Score After Splitting a String.java new file mode 100644 index 00000000..60649ebf --- /dev/null +++ b/Easy/Maximum Score After Splitting a String.java @@ -0,0 +1,17 @@ +class Solution { + public int maxScore(String s) { + int n = s.length(); + int ones = 0; + for (int i = 0; i < n; i++) { + ones += s.charAt(i) == '1' ? 1 : 0; + } + int score = 0; + int zeros = 0; + for (int i = 0; i < n - 1; i++) { + ones -= s.charAt(i) == '1' ? 1 : 0; + zeros += s.charAt(i) == '0' ? 1 : 0; + score = Math.max(score, zeros + ones); + } + return score; + } +} diff --git a/Easy/Maximum Subarray.java b/Easy/Maximum Subarray.java deleted file mode 100644 index e6b70103..00000000 --- a/Easy/Maximum Subarray.java +++ /dev/null @@ -1,19 +0,0 @@ -class Solution { - public int maxSubArray(int[] nums) { - int max = Integer.MIN_VALUE; - int sum = 0; - for (int i=0;i max) { - max = sum; - } - } - return max; - } -} diff --git a/Easy/Maximum Sum With Exactly K Elements.java b/Easy/Maximum Sum With Exactly K Elements.java new file mode 100644 index 00000000..ad738207 --- /dev/null +++ b/Easy/Maximum Sum With Exactly K Elements.java @@ -0,0 +1,13 @@ +class Solution { + public int maximizeSum(int[] nums, int k) { + int maxNum = 0; + for (int num : nums) { + maxNum = Math.max(num, maxNum); + } + int score = 0; + while (k-- > 0) { + score += maxNum++; + } + return score; + } +} diff --git a/Easy/Maximum Unique Subarray Sum After Deletion.java b/Easy/Maximum Unique Subarray Sum After Deletion.java new file mode 100644 index 00000000..e0a6a2ae --- /dev/null +++ b/Easy/Maximum Unique Subarray Sum After Deletion.java @@ -0,0 +1,17 @@ +class Solution { + public int maxSum(int[] nums) { + int max = nums[0]; + int sum = 0; + Set set = new HashSet<>(); + for (int num : nums) { + max = Math.max(num, max); + if (num > 0 && set.add(num)) { + sum += num; + } + } + if (max < 0) { + return max; + } + return sum; + } +} diff --git a/Easy/Maximum Units on a Truck.java b/Easy/Maximum Units on a Truck.java new file mode 100644 index 00000000..ce5198f0 --- /dev/null +++ b/Easy/Maximum Units on a Truck.java @@ -0,0 +1,15 @@ +class Solution { + public int maximumUnits(int[][] boxTypes, int truckSize) { + Arrays.sort(boxTypes, (o1, o2) -> o2[1] - o1[1]); + int maxUnits = 0; + for (int[] boxType : boxTypes) { + if (truckSize == 0) { + break; + } + int numberOfBoxesLoaded = Math.min(truckSize, boxType[0]); + maxUnits += numberOfBoxesLoaded * boxType[1]; + truckSize -= numberOfBoxesLoaded; + } + return maxUnits; + } +} diff --git a/Easy/Maximum Value of a String in an Array.java b/Easy/Maximum Value of a String in an Array.java new file mode 100644 index 00000000..29b0ec25 --- /dev/null +++ b/Easy/Maximum Value of a String in an Array.java @@ -0,0 +1,17 @@ +class Solution { + public int maximumValue(String[] strs) { + return Arrays.stream(strs) + .mapToInt(Solution::getStringValue) + .max() + .orElse(0); + } + + private static int getStringValue(String s) { + for (char c : s.toCharArray()) { + if (!Character.isDigit(c)) { + return s.length(); + } + } + return Integer.parseInt(s); + } +} diff --git a/Easy/Maximum Value of an Ordered Triplet I.java b/Easy/Maximum Value of an Ordered Triplet I.java new file mode 100644 index 00000000..870e4602 --- /dev/null +++ b/Easy/Maximum Value of an Ordered Triplet I.java @@ -0,0 +1,22 @@ +class Solution { + public long maximumTripletValue(int[] nums) { + int n = nums.length; + int[] maxLeft = new int[n]; + int[] maxRight = new int[n]; + maxLeft[0] = nums[0]; + for (int i = 1; i < n; i++) { + maxLeft[i] = Math.max(maxLeft[i - 1], nums[i]); + } + maxRight[n - 1] = nums[n - 1]; + for (int i = n - 2; i >= 0; i--) { + maxRight[i] = Math.max(maxRight[i + 1], nums[i]); + } + long maxValue = -1; + for (int i = 1; i < n - 1; i++) { + long left = (long) maxLeft[i - 1]; + long right = (long) maxRight[i + 1]; + maxValue = Math.max(maxValue, (left - nums[i]) * right); + } + return maxValue == -1 ? 0 : maxValue; + } +} diff --git a/Easy/Maximum depth of Binary tree.java b/Easy/Maximum depth of Binary tree.java index 98bfb842..8661d52e 100644 --- a/Easy/Maximum depth of Binary tree.java +++ b/Easy/Maximum depth of Binary tree.java @@ -4,14 +4,20 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int maxDepth(TreeNode root) { - if (root == null) { - return 0; - } - return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; } + return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); + } } diff --git a/Easy/Mean of Array After Removing Some Elements.java b/Easy/Mean of Array After Removing Some Elements.java new file mode 100644 index 00000000..ef025364 --- /dev/null +++ b/Easy/Mean of Array After Removing Some Elements.java @@ -0,0 +1,10 @@ +class Solution { + public double trimMean(int[] arr) { + Arrays.sort(arr); + int n = arr.length; + double sum = 0; + for (int idx = n / 20; idx < n - n / 20; idx++) + sum += arr[idx]; + return sum / (n - n / 10); + } +} diff --git a/Easy/Meeting Rooms.java b/Easy/Meeting Rooms.java index 5b3b806c..53af36c7 100644 --- a/Easy/Meeting Rooms.java +++ b/Easy/Meeting Rooms.java @@ -1,30 +1,11 @@ -/** - * Definition for an interval. - * public class Interval { - * int start; - * int end; - * Interval() { start = 0; end = 0; } - * Interval(int s, int e) { start = s; end = e; } - * } - */ class Solution { - public static boolean canAttendMeetings(Interval[] intervals) { - Arrays.sort(intervals, new Comparator() { - @Override - public int compare(Interval o1, Interval o2) { - return o1.start - o2.start; - } - }); - - int i=0; - while (i < intervals.length - 1) { - if (intervals[i].end > intervals[i+1].start) { - return false; - } - - i++; - } - - return true; + public boolean canAttendMeetings(int[][] intervals) { + Arrays.sort(intervals, Comparator.comparingInt((int[] o) -> o[0])); + for (int i = 1; i < intervals.length; i++) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } } + return true; + } } diff --git a/Easy/Merge Similar Items.java b/Easy/Merge Similar Items.java new file mode 100644 index 00000000..d9f95996 --- /dev/null +++ b/Easy/Merge Similar Items.java @@ -0,0 +1,17 @@ +class Solution { + public List> mergeSimilarItems(int[][] items1, int[][] items2) { + Map map = new HashMap<>(); + for (int[] item : items1) { + map.put(item[0], map.getOrDefault(item[0], 0) + item[1]); + } + for (int[] item : items2) { + map.put(item[0], map.getOrDefault(item[0], 0) + item[1]); + } + List> result = new ArrayList<>(); + for (Integer key : map.keySet()) { + result.add(Arrays.asList(key, map.get(key))); + } + Collections.sort(result, Comparator.comparing(o -> o.get(0))); + return result; + } +} diff --git a/Easy/Merge Sorted Array.java b/Easy/Merge Sorted Array.java new file mode 100644 index 00000000..e99999f0 --- /dev/null +++ b/Easy/Merge Sorted Array.java @@ -0,0 +1,20 @@ +class Solution { + public void merge(int[] nums1, int m, int[] nums2, int n) { + int endIdxOne = m - 1; + int endIdxTwo = n - 1; + int currIdx = m + n - 1; + while (endIdxOne >= 0 || endIdxTwo >= 0) { + if (endIdxOne >= 0 && endIdxTwo >= 0) { + if (nums1[endIdxOne] > nums2[endIdxTwo]) { + nums1[currIdx--] = nums1[endIdxOne--]; + } else { + nums1[currIdx--] = nums2[endIdxTwo--]; + } + } else if (endIdxOne >= 0 && endIdxTwo < 0) { + nums1[currIdx--] = nums1[endIdxOne--]; + } else { + nums1[currIdx--] = nums2[endIdxTwo--]; + } + } + } +} diff --git a/Easy/Merge Sorted Arrays.java b/Easy/Merge Sorted Arrays.java deleted file mode 100644 index 816d814c..00000000 --- a/Easy/Merge Sorted Arrays.java +++ /dev/null @@ -1,15 +0,0 @@ -class Solution { - public void merge(int[] nums1, int m, int[] nums2, int n) { - int i = m-1; - int j = n-1; - int k = m+n-1; - - while (i>-1 && j>-1) { - nums1[k--] = nums1[i] > nums2[j] ? nums1[i--] : nums2[j--]; - } - - while (j>-1) { - nums1[k--] = nums2[j--]; - } - } -} diff --git a/Easy/Merge Strings Alternately.java b/Easy/Merge Strings Alternately.java new file mode 100644 index 00000000..7b851597 --- /dev/null +++ b/Easy/Merge Strings Alternately.java @@ -0,0 +1,16 @@ +class Solution { + public String mergeAlternately(String word1, String word2) { + StringBuilder sb = new StringBuilder(); + int idxOne = 0; + int idxTwo = 0; + while (idxOne < word1.length() || idxTwo < word2.length()) { + if (idxOne < word1.length()) { + sb.append(word1.charAt(idxOne++)); + } + if (idxTwo < word2.length()) { + sb.append(word2.charAt(idxTwo++)); + } + } + return sb.toString(); + } +} diff --git a/Easy/Merge Two 2D Arrays by Summing Values.java b/Easy/Merge Two 2D Arrays by Summing Values.java new file mode 100644 index 00000000..87d07080 --- /dev/null +++ b/Easy/Merge Two 2D Arrays by Summing Values.java @@ -0,0 +1,27 @@ +class Solution { + public int[][] mergeArrays(int[][] nums1, int[][] nums2) { + int[] totalSum = new int[1001]; + int count = nums1.length; + for (int i = 0; i < nums1.length; i++) { + int id = nums1[i][0]; + int val = nums1[i][1]; + totalSum[id] = val; + } + for (int i = 0; i < nums2.length; i++) { + int id = nums2[i][0]; + int val = nums2[i][1]; + if (totalSum[id] == 0) { + count++; + } + totalSum[id] += val; + } + int[][] result = new int[count][2]; + int idx = 0; + for (int i = 1; i <= 1000; i++) { + if (totalSum[i] != 0) { + result[idx++] = new int[]{i, totalSum[i]}; + } + } + return result; + } +} diff --git a/Easy/Merge Two Sorted Lists.java b/Easy/Merge Two Sorted Lists.java index e65f0827..e594a670 100644 --- a/Easy/Merge Two Sorted Lists.java +++ b/Easy/Merge Two Sorted Lists.java @@ -3,33 +3,35 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { - - if (l1 == null && l2 == null) { - return null; + ListNode dummy = new ListNode(); + ListNode curr = dummy; + while (l1 != null || l2 != null) { + int val = -1; + if (l1 != null && l2 != null) { + if (l1.val > l2.val) { + val = l2.val; + l2 = l2.next; + } else { + val = l1.val; + l1 = l1.next; + } + } else if (l1 != null && l2 == null) { + val = l1.val; + l1 = l1.next; + } else { + val = l2.val; + l2 = l2.next; + } + curr.next = new ListNode(val); + curr = curr.next; } - - if (l1 == null && l2 != null) { - return l2; - } - - if (l1 != null && l2 == null) { - return l1; - } - - ListNode head; - if(l1.val < l2.val){ - head = l1; - head.next = mergeTwoLists(l1.next, l2); - } - else{ - head = l2; - head.next = mergeTwoLists(l1, l2.next); - } - return head; + return dummy.next; } } diff --git a/Easy/Merge two binary trees.java b/Easy/Merge two binary trees.java index c3ba2dfa..1a487c2c 100644 --- a/Easy/Merge two binary trees.java +++ b/Easy/Merge two binary trees.java @@ -4,21 +4,24 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { - if (t1 == null && t2 == null) { - return null; - } - - int v = (t1 == null ? 0 : t1.val) + (t2 == null ? 0 : t2.val); - TreeNode newNode = new TreeNode(v); - - newNode.left = mergeTrees(t1==null ? null : t1.left, t2==null ? null : t2.left); - newNode.right = mergeTrees(t1==null ? null : t1.right, t2==null ? null : t2.right); - - return newNode; + public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { + if (root1 == null && root2 == null) { + return null; } + int value = (root1 == null ? 0 : root1.val) + (root2 == null ? 0 : root2.val); + TreeNode root = new TreeNode(value); + root.left = mergeTrees((root1 == null ? null : root1.left), (root2 == null ? null : root2.left)); + root.right = mergeTrees((root1 == null ? null : root1.right), (root2 == null ? null : root2.right)); + return root; + } } diff --git a/Easy/Middle of the linked list.java b/Easy/Middle of the linked list.java index 09182730..8601522e 100644 --- a/Easy/Middle of the linked list.java +++ b/Easy/Middle of the linked list.java @@ -7,25 +7,13 @@ * } */ class Solution { - public ListNode middleNode(ListNode head) { - int l = getLengthOfLinkedList(head); - int mid = l/2; - - while (mid > 0) { - head = head.next; - mid--; - } - - return head; - } - - private int getLengthOfLinkedList(ListNode head) { - int c = 0; - while(head != null) { - head = head.next; - c++; - } - - return c; + public ListNode middleNode(ListNode head) { + ListNode slow = head; + ListNode fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; } + return slow; + } } diff --git a/Easy/Min Cost Climbing Stairs.java b/Easy/Min Cost Climbing Stairs.java index 2f6a50fb..1db8f19d 100644 --- a/Easy/Min Cost Climbing Stairs.java +++ b/Easy/Min Cost Climbing Stairs.java @@ -1,10 +1,12 @@ class Solution { public int minCostClimbingStairs(int[] cost) { - int[] dp = new int[cost.length + 1]; - - for (int i = 2; i <= cost.length; i++) - dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]); - - return dp[cost.length]; + int stepOneCost = cost[0]; + int stepTwoCost = cost[1]; + for (int i = 2; i < cost.length; i++) { + int currCost = cost[i] + Math.min(stepOneCost, stepTwoCost); + stepOneCost = stepTwoCost; + stepTwoCost = currCost; + } + return Math.min(stepOneCost, stepTwoCost); } } diff --git a/Easy/Min Max Game.java b/Easy/Min Max Game.java new file mode 100644 index 00000000..f2405c20 --- /dev/null +++ b/Easy/Min Max Game.java @@ -0,0 +1,21 @@ +class Solution { + public int minMaxGame(int[] nums) { + Queue queue = new LinkedList<>(); + for (int num : nums) { + queue.add(num); + } + while (queue.size() > 1) { + int size = queue.size(); + boolean even = true; + for (int i = 0; i < size; i += 2) { + if (even) { + queue.add(Math.min(queue.remove(), queue.remove())); + } else { + queue.add(Math.max(queue.remove(), queue.remove())); + } + even = !even; + } + } + return queue.remove(); + } +} diff --git a/Easy/Min Stack.java b/Easy/Min Stack.java deleted file mode 100644 index 9cd99eb9..00000000 --- a/Easy/Min Stack.java +++ /dev/null @@ -1,40 +0,0 @@ -class MinStack { - - public int min = Integer.MAX_VALUE; - public Stack stack = new Stack(); - /** initialize your data structure here. */ - public MinStack() { - - } - - public void push(int x) { - if (x<=min) { - stack.push(min); - min = x; - } - stack.push(x); - } - - public void pop() { - if(stack.pop() == min) { - min=stack.pop(); - } - } - - public int top() { - return stack.peek(); - } - - public int getMin() { - return min; - } -} - -/** - * Your MinStack object will be instantiated and called as such: - * MinStack obj = new MinStack(); - * obj.push(x); - * obj.pop(); - * int param_3 = obj.top(); - * int param_4 = obj.getMin(); - */ diff --git a/Easy/Minimize String Length.java b/Easy/Minimize String Length.java new file mode 100644 index 00000000..48d8ab26 --- /dev/null +++ b/Easy/Minimize String Length.java @@ -0,0 +1,7 @@ +class Solution { + public int minimizedStringLength(String s) { + return (int) s.chars() + .distinct() + .count(); + } +} diff --git a/Easy/Minimum Absolute Difference in BST.java b/Easy/Minimum Absolute Difference in BST.java index 9d87b1df..80248dc1 100644 --- a/Easy/Minimum Absolute Difference in BST.java +++ b/Easy/Minimum Absolute Difference in BST.java @@ -4,28 +4,32 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - ArrayList values = new ArrayList<>(); public int getMinimumDifference(TreeNode root) { - inOrder(root); - - int min = Integer.MAX_VALUE; - for (int i=1;i nodeValues = new ArrayList<>(); + inorder(root, nodeValues); + int minDifference = Integer.MAX_VALUE; + for (int i = 1; i < nodeValues.size(); i++) { + minDifference = Math.min(minDifference, nodeValues.get(i) - nodeValues.get(i - 1)); } - - return min; + return minDifference; } - - public void inOrder(TreeNode root) { + + private void inorder(TreeNode root, List nodeValues) { if (root == null) { return; } - inOrder(root.left); - values.add(root.val); - inOrder(root.right); + inorder(root.left, nodeValues); + nodeValues.add(root.val); + inorder(root.right, nodeValues); } } diff --git a/Easy/Minimum Absolute Difference.java b/Easy/Minimum Absolute Difference.java new file mode 100644 index 00000000..793dd171 --- /dev/null +++ b/Easy/Minimum Absolute Difference.java @@ -0,0 +1,16 @@ +class Solution { + public List> minimumAbsDifference(int[] arr) { + int minDiff = Integer.MAX_VALUE; + Arrays.sort(arr); + for (int i = 0; i < arr.length - 1; i++) { + minDiff = Math.min(minDiff, arr[i + 1] - arr[i]); + } + List> result = new ArrayList<>(); + for (int i = 0; i < arr.length - 1; i++) { + if (arr[i + 1] - arr[i] == minDiff) { + result.add(Arrays.asList(arr[i], arr[i + 1])); + } + } + return result; + } +} diff --git a/Easy/Minimum Amount of Time to Fill Cups.java b/Easy/Minimum Amount of Time to Fill Cups.java new file mode 100644 index 00000000..b772c001 --- /dev/null +++ b/Easy/Minimum Amount of Time to Fill Cups.java @@ -0,0 +1,25 @@ +class Solution { + public int fillCups(int[] amount) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + for (int count : amount) { + updateQueue(pq, count); + } + int totalTime = 0; + while (!pq.isEmpty()) { + int removedOne = pq.poll(); + int removedTwo = pq.isEmpty() ? 0 : pq.poll(); + removedOne--; + removedTwo--; + updateQueue(pq, removedOne); + updateQueue(pq, removedTwo); + totalTime++; + } + return totalTime; + } + + private void updateQueue(PriorityQueue pq, int count) { + if (count > 0) { + pq.add(count); + } + } +} diff --git a/Easy/Minimum Average of Smallest and Largest Elements.java b/Easy/Minimum Average of Smallest and Largest Elements.java new file mode 100644 index 00000000..f1fd9e2d --- /dev/null +++ b/Easy/Minimum Average of Smallest and Largest Elements.java @@ -0,0 +1,15 @@ +class Solution { + public double minimumAverage(int[] nums) { + double minAverage = Double.MAX_VALUE; + Arrays.sort(nums); + int left = 0; + int right = nums.length - 1; + while (left < right) { + double average = (nums[left] + nums[right]) / 2.0; + minAverage = Math.min(minAverage, average); + left++; + right--; + } + return minAverage; + } +} diff --git a/Easy/Minimum Bit Flips to Convert Number.java b/Easy/Minimum Bit Flips to Convert Number.java new file mode 100644 index 00000000..d3e2da78 --- /dev/null +++ b/Easy/Minimum Bit Flips to Convert Number.java @@ -0,0 +1,19 @@ +class Solution { + public int minBitFlips(int start, int goal) { + int numOfFlips = 0; + while (start > 0 && goal > 0) { + numOfFlips += start % 2 != goal % 2 ? 1 : 0; + start /= 2; + goal /= 2; + } + while (start > 0) { + numOfFlips += start % 2; + start /= 2; + } + while (goal > 0) { + numOfFlips += goal % 2; + goal /= 2; + } + return numOfFlips; + } +} diff --git a/Easy/Minimum Changes To Make Alternating Binary String.java b/Easy/Minimum Changes To Make Alternating Binary String.java new file mode 100644 index 00000000..95f9aaae --- /dev/null +++ b/Easy/Minimum Changes To Make Alternating Binary String.java @@ -0,0 +1,16 @@ +class Solution { + public int minOperations(String s) { + int startZero = 0; + int startOne = 0; + for (int i = 0; i < s.length(); i++) { + if (i % 2 == 0) { + startOne += s.charAt(i) == '0' ? 1 : 0; + startZero += s.charAt(i) == '1' ? 1 : 0; + } else { + startOne += s.charAt(i) == '1' ? 1 : 0; + startZero += s.charAt(i) == '0' ? 1 : 0; + } + } + return Math.min(startZero, startOne); + } +} diff --git a/Easy/Minimum Common Value.java b/Easy/Minimum Common Value.java new file mode 100644 index 00000000..5062e9a3 --- /dev/null +++ b/Easy/Minimum Common Value.java @@ -0,0 +1,16 @@ +class Solution { + public int getCommon(int[] nums1, int[] nums2) { + int idxOne = 0; + int idxTwo = 0; + while (idxOne < nums1.length && idxTwo < nums2.length) { + if (nums1[idxOne] < nums2[idxTwo]) { + idxOne++; + } else if (nums2[idxTwo] < nums1[idxOne]) { + idxTwo++; + } else { + return nums1[idxOne]; + } + } + return -1; + } +} diff --git a/Easy/Minimum Cost of Buying Candies With Discount.java b/Easy/Minimum Cost of Buying Candies With Discount.java new file mode 100644 index 00000000..71a2492b --- /dev/null +++ b/Easy/Minimum Cost of Buying Candies With Discount.java @@ -0,0 +1,19 @@ +class Solution { + public int minimumCost(int[] cost) { + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> o2 - o1); + for (int price : cost) { + pq.add(price); + } + int totalCost = 0; + while (!pq.isEmpty()) { + totalCost += pq.poll(); + if (!pq.isEmpty()) { + totalCost += pq.poll(); + } + if (!pq.isEmpty()) { + pq.poll(); + } + } + return totalCost; + } +} diff --git a/Easy/Minimum Cost to Move Chips to The Same Position.java b/Easy/Minimum Cost to Move Chips to The Same Position.java new file mode 100644 index 00000000..7208148a --- /dev/null +++ b/Easy/Minimum Cost to Move Chips to The Same Position.java @@ -0,0 +1,14 @@ +class Solution { + public int minCostToMoveChips(int[] position) { + int evenCount = 0; + int oddCount = 0; + for (int p : position) { + if (p % 2 == 0) { + evenCount++; + } else { + oddCount++; + } + } + return Math.min(evenCount, oddCount); + } +} diff --git a/Easy/Minimum Cost to Reach Every Position.java b/Easy/Minimum Cost to Reach Every Position.java new file mode 100644 index 00000000..1b142d2c --- /dev/null +++ b/Easy/Minimum Cost to Reach Every Position.java @@ -0,0 +1,13 @@ +class Solution { + public int[] minCosts(int[] cost) { + int n = cost.length; + int[] result = new int[n]; + int minCost = Integer.MAX_VALUE; + for (int i = 0; i < n; i++) { + int curr = cost[i]; + minCost = Math.min(minCost, curr); + result[i] = minCost; + } + return result; + } +} diff --git a/Easy/Minimum Cuts to Divide a Circle.java b/Easy/Minimum Cuts to Divide a Circle.java new file mode 100644 index 00000000..16540797 --- /dev/null +++ b/Easy/Minimum Cuts to Divide a Circle.java @@ -0,0 +1,5 @@ +class Solution { + public int numberOfCuts(int n) { + return n == 1 ? 0 : (n % 2 == 0 ? n / 2 : n); + } +} diff --git a/Easy/Minimum Depth of a Binary Tree.java b/Easy/Minimum Depth of a Binary Tree.java index e7edccd5..0da04114 100644 --- a/Easy/Minimum Depth of a Binary Tree.java +++ b/Easy/Minimum Depth of a Binary Tree.java @@ -4,16 +4,39 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public int minDepth(TreeNode root) { - if (root == null) return 0; - - int lDepth = minDepth(root.left); - int rDepth = minDepth(root.right); - - return (lDepth == 0 || rDepth == 0) ? lDepth + rDepth + 1 : Math.min(lDepth,rDepth) + 1; + if (root == null) { + return 0; + } + int level = 1; + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + if (removed.left == null && removed.right == null) { + return level; + } + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + level++; + } + return level; } } diff --git a/Easy/Minimum Difference Between Highest and Lowest of K Scores.java b/Easy/Minimum Difference Between Highest and Lowest of K Scores.java new file mode 100644 index 00000000..e9b93530 --- /dev/null +++ b/Easy/Minimum Difference Between Highest and Lowest of K Scores.java @@ -0,0 +1,12 @@ +class Solution { + public int minimumDifference(int[] nums, int k) { + Arrays.sort(nums); + int left = 0; + int right = k - 1; + int minDiff = Integer.MAX_VALUE; + while (right < nums.length) { + minDiff = Math.min(minDiff, nums[right++] - nums[left++]); + } + return minDiff; + } +} diff --git a/Easy/Minimum Distance Between BST Nodes.java b/Easy/Minimum Distance Between BST Nodes.java index 00f91729..af92feb0 100644 --- a/Easy/Minimum Distance Between BST Nodes.java +++ b/Easy/Minimum Distance Between BST Nodes.java @@ -4,31 +4,32 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - - int t = Integer.MAX_VALUE; - int prev = Integer.MAX_VALUE; - public int minDiffInBST(TreeNode root) { - inorder(root); - - return t; + int[] minDiff = {Integer.MAX_VALUE}; + Integer[] prevVal = {null}; + inorder(root, minDiff, prevVal); + return minDiff[0]; } - public void inorder(TreeNode root) { - if (root == null) { + private void inorder(TreeNode node, int[] minDiff, Integer[] prevValue) { + if (node == null) { return; } - - inorder(root.left); - if (prev != Integer.MAX_VALUE) { - t = Math.min(t, Math.abs(root.val - prev)); + inorder(node.left, minDiff, prevValue); + if (prevValue[0] != null) { + minDiff[0] = Math.min(minDiff[0], node.val - prevValue[0]); } - - prev = root.val; - inorder(root.right); + prevValue[0] = node.val; + inorder(node.right, minDiff, prevValue); } } diff --git a/Easy/Minimum Distance to the Target Element.java b/Easy/Minimum Distance to the Target Element.java new file mode 100644 index 00000000..e182a20d --- /dev/null +++ b/Easy/Minimum Distance to the Target Element.java @@ -0,0 +1,11 @@ +class Solution { + public int getMinDistance(int[] nums, int target, int start) { + int minDistance = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + if (nums[i] == target) { + minDistance = Math.min(minDistance, Math.abs(i - start)); + } + } + return minDistance; + } +} diff --git a/Easy/Minimum Hours of Training to Win a Competition.java b/Easy/Minimum Hours of Training to Win a Competition.java new file mode 100644 index 00000000..1e9f0c90 --- /dev/null +++ b/Easy/Minimum Hours of Training to Win a Competition.java @@ -0,0 +1,15 @@ +class Solution { + public int minNumberOfHours(int initialEnergy, int initialExperience, int[] energy, int[] experience) { + int totalEnergy = 0; + int experienceDeficit = 0; + for (int i = 0; i < energy.length; i++) { + totalEnergy += energy[i]; + if (initialExperience <= experience[i]) { + experienceDeficit += experience[i] - initialExperience + 1; + initialExperience = experience[i] + 1; + } + initialExperience += experience[i]; + } + return experienceDeficit + (totalEnergy >= initialEnergy ? totalEnergy - initialEnergy + 1 : 0); + } +} diff --git a/Easy/Minimum Index Sum of Two Lists.java b/Easy/Minimum Index Sum of Two Lists.java new file mode 100644 index 00000000..0333614d --- /dev/null +++ b/Easy/Minimum Index Sum of Two Lists.java @@ -0,0 +1,28 @@ +class Solution { + public String[] findRestaurant(String[] list1, String[] list2) { + Map map = new HashMap<>(); + for (int i = 0; i < list1.length; i++) { + map.put(list1[i], i); + } + int minIndexSum = Integer.MAX_VALUE; + Map stringToIndexSum = new HashMap<>(); + for (int i = 0; i < list2.length; i++) { + if (map.containsKey(list2[i])) { + int indexSum = i + map.get(list2[i]); + minIndexSum = Math.min(minIndexSum, indexSum); + stringToIndexSum.put(list2[i], indexSum); + } + } + List result = new ArrayList<>(); + for (String key : stringToIndexSum.keySet()) { + if (stringToIndexSum.get(key) == minIndexSum) { + result.add(key); + } + } + String[] resultArr = new String[result.size()]; + for (int i = 0; i < result.size(); i++) { + resultArr[i] = result.get(i); + } + return resultArr; + } +} diff --git a/Easy/Minimum Moves to Convert String.java b/Easy/Minimum Moves to Convert String.java new file mode 100644 index 00000000..cc4cb2b2 --- /dev/null +++ b/Easy/Minimum Moves to Convert String.java @@ -0,0 +1,15 @@ +class Solution { + public int minimumMoves(String s) { + int numOfMoves = 0; + int idx = 0; + while (idx < s.length()) { + if (s.charAt(idx) == 'X') { + idx += 3; + numOfMoves++; + } else { + idx++; + } + } + return numOfMoves; + } +} diff --git a/Easy/Minimum Number Game.java b/Easy/Minimum Number Game.java new file mode 100644 index 00000000..a3377cb7 --- /dev/null +++ b/Easy/Minimum Number Game.java @@ -0,0 +1,11 @@ +class Solution { + public int[] numberGame(int[] nums) { + int[] result = new int[nums.length]; + Arrays.sort(nums); + for (int i = 0; i < nums.length; i += 2) { + result[i] = nums[i + 1]; + result[i + 1] = nums[i]; + } + return result; + } +} diff --git a/Easy/Minimum Number of Chairs in a Waiting Room.java b/Easy/Minimum Number of Chairs in a Waiting Room.java new file mode 100644 index 00000000..d7db8060 --- /dev/null +++ b/Easy/Minimum Number of Chairs in a Waiting Room.java @@ -0,0 +1,11 @@ +class Solution { + public int minimumChairs(String s) { + int requiredChairCount = 0; + int currChairCount = 0; + for (char c : s.toCharArray()) { + currChairCount += c == 'E' ? 1 : -1; + requiredChairCount = Math.max(requiredChairCount, currChairCount); + } + return requiredChairCount; + } +} diff --git a/Easy/Minimum Number of Moves to Seat Everyone.java b/Easy/Minimum Number of Moves to Seat Everyone.java new file mode 100644 index 00000000..be3f18c1 --- /dev/null +++ b/Easy/Minimum Number of Moves to Seat Everyone.java @@ -0,0 +1,11 @@ +class Solution { + public int minMovesToSeat(int[] seats, int[] students) { + Arrays.sort(seats); + Arrays.sort(students); + int moves = 0; + for (int i = 0; i < seats.length; i++) { + moves += Math.abs(seats[i] - students[i]); + } + return moves; + } +} diff --git a/Easy/Minimum Number of Operations to Convert Time.java b/Easy/Minimum Number of Operations to Convert Time.java new file mode 100644 index 00000000..8a5f1db2 --- /dev/null +++ b/Easy/Minimum Number of Operations to Convert Time.java @@ -0,0 +1,17 @@ +class Solution { + public int convertTime(String current, String correct) { + int minutesDiff = getMinutes(correct) - getMinutes(current); + int numOfOperations = 0; + int[] incrementFactors = {60, 15, 5, 1}; + for (int i = 0; i < incrementFactors.length; i++) { + numOfOperations += minutesDiff / incrementFactors[i]; + minutesDiff %= incrementFactors[i]; + } + return numOfOperations; + } + + private int getMinutes(String time) { + String[] split = time.split(":"); + return Integer.parseInt(split[0]) * 60 + Integer.parseInt(split[1]); + } +} diff --git a/Easy/Minimum Number of Operations to Make Elements in Array Distinct.java b/Easy/Minimum Number of Operations to Make Elements in Array Distinct.java new file mode 100644 index 00000000..a61239e7 --- /dev/null +++ b/Easy/Minimum Number of Operations to Make Elements in Array Distinct.java @@ -0,0 +1,18 @@ +class Solution { + public int minimumOperations(int[] nums) { + Set set = new HashSet<>(); + int index = -1; + for (int i = nums.length - 1; i >= 0; i--) { + if (set.contains(nums[i])) { + index = i; + break; + } + set.add(nums[i]); + } + if (index == -1) { + return 0; + } + index++; + return index % 3 == 0 ? index / 3 : (index / 3) + 1; + } +} diff --git a/Easy/Minimum Number of Pushes to Type Word I.java b/Easy/Minimum Number of Pushes to Type Word I.java new file mode 100644 index 00000000..0a6bbc24 --- /dev/null +++ b/Easy/Minimum Number of Pushes to Type Word I.java @@ -0,0 +1,14 @@ +class Solution { + public int minimumPushes(String word) { + int pushes = 0; + int idx = 0; + int multiple = 1; + while (idx < word.length()) { + int count = Math.min(8, word.length() - idx); + pushes += count * multiple; + multiple++; + idx += count; + } + return pushes; + } +} diff --git a/Easy/Minimum Operations to Collect Elements.java b/Easy/Minimum Operations to Collect Elements.java new file mode 100644 index 00000000..59e9d7c4 --- /dev/null +++ b/Easy/Minimum Operations to Collect Elements.java @@ -0,0 +1,16 @@ +class Solution { + public int minOperations(List nums, int k) { + boolean[] found = new boolean[k]; + int foundCount = 0; + for (int i = nums.size() - 1; i >= 0; i--) { + if (nums.get(i) <= k && !found[nums.get(i) - 1]) { + found[nums.get(i) - 1] = true; + foundCount++; + } + if (foundCount == k) { + return nums.size() - i; + } + } + return -1; + } +} diff --git a/Easy/Minimum Operations to Exceed Threshold Value I.java b/Easy/Minimum Operations to Exceed Threshold Value I.java new file mode 100644 index 00000000..6f792f07 --- /dev/null +++ b/Easy/Minimum Operations to Exceed Threshold Value I.java @@ -0,0 +1,15 @@ +class Solution { + public int minOperations(int[] nums, int k) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + PriorityQueue pq = new PriorityQueue<>(); + pq.addAll(map.keySet()); + int count = 0; + while (!pq.isEmpty() && pq.peek() < k) { + count += map.get(pq.poll()); + } + return count; + } +} diff --git a/Easy/Minimum Operations to Make Array Sum Divisible by K.java b/Easy/Minimum Operations to Make Array Sum Divisible by K.java new file mode 100644 index 00000000..c941b50a --- /dev/null +++ b/Easy/Minimum Operations to Make Array Sum Divisible by K.java @@ -0,0 +1,9 @@ +class Solution { + public int minOperations(int[] nums, int k) { + int sum = 0; + for (int num : nums) { + sum += num; + } + return sum % k; + } +} diff --git a/Easy/Minimum Operations to Make the Array Increasing.java b/Easy/Minimum Operations to Make the Array Increasing.java new file mode 100644 index 00000000..99bdf2f7 --- /dev/null +++ b/Easy/Minimum Operations to Make the Array Increasing.java @@ -0,0 +1,15 @@ +class Solution { + public int minOperations(int[] nums) { + int prev = nums[0]; + int totalOperations = 0; + for (int i = 1; i < nums.length; i++) { + if (nums[i] <= prev) { + totalOperations += prev - nums[i] + 1; + prev++; + } else { + prev = nums[i]; + } + } + return totalOperations; + } +} diff --git a/Easy/Minimum Recolors to Get K Consecutive Black Blocks.java b/Easy/Minimum Recolors to Get K Consecutive Black Blocks.java new file mode 100644 index 00000000..596297cd --- /dev/null +++ b/Easy/Minimum Recolors to Get K Consecutive Black Blocks.java @@ -0,0 +1,17 @@ +class Solution { + public int minimumRecolors(String blocks, int k) { + int minRecolors = Integer.MAX_VALUE; + int blackBlockCount = 0; + for (int i = 0; i < k; i++) { + blackBlockCount += blocks.charAt(i) == 'W' ? 0 : 1; + } + int startIdx = 0; + for (int i = k; i < blocks.length(); i++) { + minRecolors = Math.min(minRecolors, k - blackBlockCount); + blackBlockCount += blocks.charAt(startIdx++) == 'W' ? 0 : -1; + blackBlockCount += blocks.charAt(i) == 'W' ? 0 : 1; + } + minRecolors = Math.min(minRecolors, k - blackBlockCount); + return minRecolors; + } +} diff --git a/Easy/Minimum Right Shifts to Sort the Array.java b/Easy/Minimum Right Shifts to Sort the Array.java new file mode 100644 index 00000000..aad801a0 --- /dev/null +++ b/Easy/Minimum Right Shifts to Sort the Array.java @@ -0,0 +1,19 @@ +class Solution { + public int minimumRightShifts(List nums) { + int mismatchIdx = -1; + int count = 0; + for (int i = 1; i < nums.size(); i++) { + if (nums.get(i - 1) > nums.get(i)) { + mismatchIdx = i; + count++; + } + } + if (count > 1) { + return -1; + } + if (count == 0) { + return 0; + } + return nums.get(nums.size() - 1) > nums.get(0) ? -1 : nums.size() - mismatchIdx; + } +} diff --git a/Easy/Minimum String Length After Removing Substrings.java b/Easy/Minimum String Length After Removing Substrings.java new file mode 100644 index 00000000..606d3394 --- /dev/null +++ b/Easy/Minimum String Length After Removing Substrings.java @@ -0,0 +1,15 @@ +class Solution { + public int minLength(String s) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (!stack.isEmpty() && c == 'B' && stack.peek() == 'A') { + stack.pop(); + } else if (!stack.isEmpty() && c == 'D' && stack.peek() == 'C') { + stack.pop(); + } else { + stack.push(c); + } + } + return stack.size(); + } +} diff --git a/Easy/Minimum Subsequence in Non-Increasing Order.java b/Easy/Minimum Subsequence in Non-Increasing Order.java new file mode 100644 index 00000000..8494bb24 --- /dev/null +++ b/Easy/Minimum Subsequence in Non-Increasing Order.java @@ -0,0 +1,23 @@ +class Solution { + public List minSubsequence(int[] nums) { + PriorityQueue pq = new PriorityQueue<>(new Comparator(){ + public int compare(Integer o1, Integer o2) { + return o2 - o1; + } + }); + int totalSum = 0; + for (int num : nums) { + pq.add(num); + totalSum += num; + } + List list = new ArrayList<>(); + int currSum = 0; + while (currSum <= totalSum) { + int num = pq.poll(); + currSum += num; + totalSum -= num; + list.add(num); + } + return list; + } +} diff --git a/Easy/Minimum Sum of Four Digit Number After Splitting Digits.java b/Easy/Minimum Sum of Four Digit Number After Splitting Digits.java new file mode 100644 index 00000000..5929e314 --- /dev/null +++ b/Easy/Minimum Sum of Four Digit Number After Splitting Digits.java @@ -0,0 +1,11 @@ +class Solution { + public int minimumSum(int num) { + int[] digits = new int[4]; + for (int i = 0; i < 4; i++) { + digits[i] = num % 10; + num /= 10; + } + Arrays.sort(digits); + return (digits[0] * 10 + digits[2]) + (digits[1] * 10 + digits[3]); + } +} diff --git a/Easy/Minimum Sum of Mountain Triplets I.java b/Easy/Minimum Sum of Mountain Triplets I.java new file mode 100644 index 00000000..cabcd870 --- /dev/null +++ b/Easy/Minimum Sum of Mountain Triplets I.java @@ -0,0 +1,19 @@ +class Solution { + public int minimumSum(int[] nums) { + int n = nums.length; + int[] smallestRight = new int[n]; + smallestRight[n - 1] = nums[n - 1]; + for (int i = n - 2; i >= 0; i--) { + smallestRight[i] = Math.min(smallestRight[i + 1], nums[i]); + } + int smallestLeft = nums[0]; + int result = Integer.MAX_VALUE; + for (int i = 1; i < n; i++) { + if (smallestLeft < nums[i] && smallestRight[i] < nums[i]) { + result = Math.min(result, nums[i] + smallestRight[i] + smallestLeft); + } + smallestLeft = Math.min(smallestLeft, nums[i]); + } + return result == Integer.MAX_VALUE ? -1 : result; + } +} diff --git a/Easy/Minimum Time Visiting All Points.java b/Easy/Minimum Time Visiting All Points.java new file mode 100644 index 00000000..ee1a85b1 --- /dev/null +++ b/Easy/Minimum Time Visiting All Points.java @@ -0,0 +1,17 @@ +class Solution { + public int minTimeToVisitAllPoints(int[][] points) { + int time = 0; + int idx = 0; + while (idx < points.length - 1) { + time += calculateTime(points[idx], points[idx + 1]); + idx++; + } + return time; + } + + private static int calculateTime(int[] p1, int[] p2) { + int x = Math.abs(p1[0] - p2[0]); + int y = Math.abs(p1[1] - p2[1]); + return Math.max(x, y); + } +} diff --git a/Easy/Minimum Time to Type Word Using Special Typewriter.java b/Easy/Minimum Time to Type Word Using Special Typewriter.java new file mode 100644 index 00000000..e804f716 --- /dev/null +++ b/Easy/Minimum Time to Type Word Using Special Typewriter.java @@ -0,0 +1,12 @@ +class Solution { + public int minTimeToType(String word) { + int totalTime = 0; + char currentChar = 'a'; + for (char c : word.toCharArray()) { + int difference = Math.abs(c - currentChar); + totalTime += 1 + Math.min(difference, 26 - difference); + currentChar = c; + } + return totalTime; + } +} diff --git a/Easy/Minimum Value to Get Positive Step by Step Sum.java b/Easy/Minimum Value to Get Positive Step by Step Sum.java new file mode 100644 index 00000000..e8b91b93 --- /dev/null +++ b/Easy/Minimum Value to Get Positive Step by Step Sum.java @@ -0,0 +1,15 @@ +class Solution { + public int minStartValue(int[] nums) { + int startingValue = 1; + int currSum = 1; + for (int num : nums) { + if (currSum + num < 1) { + int diff = 1 - (currSum + num); + startingValue += diff; + currSum += diff; + } + currSum += num; + } + return startingValue; + } +} diff --git a/Easy/Missing Number In Arithmetic Progression.java b/Easy/Missing Number In Arithmetic Progression.java new file mode 100644 index 00000000..fa657f76 --- /dev/null +++ b/Easy/Missing Number In Arithmetic Progression.java @@ -0,0 +1,12 @@ +class Solution { + public int missingNumber(int[] arr) { + int n = arr.length; + int d = (arr[n - 1] - arr[0]) / n; + for (int i = 1; i < n; i++) { + if (arr[i] - arr[i - 1] != d) { + return arr[i - 1] + d; + } + } + return d; + } +} diff --git a/Easy/Missing Number.java b/Easy/Missing Number.java new file mode 100644 index 00000000..5d737295 --- /dev/null +++ b/Easy/Missing Number.java @@ -0,0 +1,11 @@ +class Solution { + public int missingNumber(int[] nums) { + int totalSum = 0; + for (int num : nums) { + totalSum += num; + } + int n = nums.length; + int expectedSum = (n * (n + 1)) / 2; + return expectedSum - totalSum; + } +} diff --git a/Easy/Missing Numbers.java b/Easy/Missing Numbers.java deleted file mode 100644 index 88e09784..00000000 --- a/Easy/Missing Numbers.java +++ /dev/null @@ -1,21 +0,0 @@ -public class Solution { - public int missingNumber(int[] nums) { - Arrays.sort(nums); - if (nums.length > 1 && nums[0] == 0) { - for (int i=0;i findMissingRanges(int[] nums, int lower, int upper) { + List ranges = new ArrayList<>(); + for (int i = 0; i < nums.length; i++) { + if (nums[i] < lower) { + continue; + } + if (nums[i] == lower) { + lower++; + continue; + } + ranges.add(getRange(lower, ( nums[i] - 1))); + lower = nums[i] + 1; + } + if (lower <= upper) { + ranges.add(getRange(lower, upper)); + } + return ranges; + } + + private String getRange(int down, int up) { + return down == up ? String.valueOf(up) : down + "->" + up; + } +} diff --git a/Easy/Modify the Matrix.java b/Easy/Modify the Matrix.java new file mode 100644 index 00000000..f238aa68 --- /dev/null +++ b/Easy/Modify the Matrix.java @@ -0,0 +1,16 @@ +class Solution { + public int[][] modifiedMatrix(int[][] matrix) { + int rows = matrix.length; + int cols = matrix[0].length; + for (int c = 0; c < cols; c++) { + int max = -1; + for (int r = 0; r < rows; r++) { + max = Math.max(max, matrix[r][c]); + } + for (int r = 0; r < rows; r++) { + matrix[r][c] = matrix[r][c] == -1 ? max : matrix[r][c]; + } + } + return matrix; + } +} diff --git a/Easy/Monotonic Array.java b/Easy/Monotonic Array.java index e05fe225..e460648c 100644 --- a/Easy/Monotonic Array.java +++ b/Easy/Monotonic Array.java @@ -1,15 +1,18 @@ class Solution { - public boolean isMonotonic(int[] A) { - if (A.length <= 2) return true; - boolean pattern = A[A.length-1] > A[0] ? true : false; - - for (int i=1; i nums[idx + 1] && increasing) { return false; } - if (A[i] > A[i-1] && pattern == false) { + if (nums[idx] < nums[idx + 1] && !increasing) { return false; } + idx++; } return true; } diff --git a/Easy/Most Frequent Even Element.java b/Easy/Most Frequent Even Element.java new file mode 100644 index 00000000..75879d03 --- /dev/null +++ b/Easy/Most Frequent Even Element.java @@ -0,0 +1,23 @@ +class Solution { + public int mostFrequentEven(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + if (num % 2 == 0) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + } + int maxValue = 0; + int maxKey = -1; + for (Integer key : map.keySet()) { + if (map.get(key) >= maxValue) { + if (map.get(key) > maxValue) { + maxKey = key; + } else { + maxKey = Math.min(maxKey, key); + } + maxValue = map.get(key); + } + } + return maxKey; + } +} diff --git a/Easy/Most Frequent Number Following Key In an Array.java b/Easy/Most Frequent Number Following Key In an Array.java new file mode 100644 index 00000000..4f9b8523 --- /dev/null +++ b/Easy/Most Frequent Number Following Key In an Array.java @@ -0,0 +1,17 @@ +class Solution { + public int mostFrequent(int[] nums, int key) { + Map map = new HashMap<>(); + int maxCount = 0; + int maxCountCandidate = -1; + for (int i = 1; i < nums.length; i++) { + if (nums[i - 1] == key) { + map.put(nums[i], map.getOrDefault(nums[i], 0) + 1); + if (map.get(nums[i]) > maxCount) { + maxCount = map.get(nums[i]); + maxCountCandidate = nums[i]; + } + } + } + return maxCountCandidate; + } +} diff --git a/Easy/Most Visited Sector in a Circular Track.java b/Easy/Most Visited Sector in a Circular Track.java new file mode 100644 index 00000000..012b1c2b --- /dev/null +++ b/Easy/Most Visited Sector in a Circular Track.java @@ -0,0 +1,21 @@ +class Solution { + public List mostVisited(int n, int[] rounds) { + List list = new ArrayList<>(); + int from = rounds[0]; + int to = rounds[rounds.length - 1]; + if (to >= from) { + for (int i = from; i <= to; i++) { + list.add(i); + } + } + else { + for (int i = 1; i <= n; i++) { + if (i == to + 1) { + i = from; + } + list.add(i); + } + } + return list; + } +} diff --git a/Easy/Move Zeroes.java b/Easy/Move Zeroes.java new file mode 100644 index 00000000..acd2e2cb --- /dev/null +++ b/Easy/Move Zeroes.java @@ -0,0 +1,15 @@ +class Solution { + public void moveZeroes(int[] nums) { + int startIdx = 0; + int endIdx = 0; + while (endIdx < nums.length) { + if (nums[endIdx] != 0) { + nums[startIdx++] = nums[endIdx]; + } + endIdx++; + } + while (startIdx < nums.length) { + nums[startIdx++] = 0; + } + } +} diff --git a/Easy/Moving Average from Data Stream.java b/Easy/Moving Average from Data Stream.java index 04933639..ec9dca5b 100644 --- a/Easy/Moving Average from Data Stream.java +++ b/Easy/Moving Average from Data Stream.java @@ -1,24 +1,22 @@ class MovingAverage { - /** Initialize your data structure here. */ - Queue queue; - int size; - double total; + private final Queue queue; + private double currSum; + private final int size; + public MovingAverage(int size) { - queue = new LinkedList<>(); + this.queue = new LinkedList<>(); + this.currSum = 0; this.size = size; - this.total = 0.0; } public double next(int val) { - queue.add(val); - this.total += val; - - if (queue.size() > this.size) { - total -= queue.remove(); + this.queue.add(val); + this.currSum += val; + if (this.queue.size() > this.size) { + this.currSum -= this.queue.remove(); } - - return total / queue.size(); + return this.currSum / this.queue.size(); } } diff --git a/Easy/N-Repeated Element in Size 2N Array.java b/Easy/N-Repeated Element in Size 2N Array.java index 5ef779c5..f5ede891 100644 --- a/Easy/N-Repeated Element in Size 2N Array.java +++ b/Easy/N-Repeated Element in Size 2N Array.java @@ -1,15 +1,12 @@ class Solution { - public int repeatedNTimes(int[] A) { - int maxCounter = A.length / 2; - Map map = new HashMap<>(); - for (int num : A) { - map.put(num, map.getOrDefault(num, 0) + 1); - - if (map.get(num) == maxCounter) { - return num; - } + public int repeatedNTimes(int[] nums) { + for (int i = 1; i <= 3; i++) { + for (int j = 0; j < nums.length - i; j++) { + if (nums[j] == nums[j + i]) { + return nums[j]; } - - return -1; + } } + return -1; + } } diff --git a/Easy/N-ary Tree Level Order Traversal.java b/Easy/N-ary Tree Level Order Traversal.java deleted file mode 100644 index 11aac2e6..00000000 --- a/Easy/N-ary Tree Level Order Traversal.java +++ /dev/null @@ -1,42 +0,0 @@ -/* -// Definition for a Node. -class Node { - public int val; - public List children; - - public Node() {} - - public Node(int _val,List _children) { - val = _val; - children = _children; - } -}; -*/ -class Solution { - public List> levelOrder(Node root) { - List> values = new ArrayList<>(); - - if (root == null) { - return values; - } - - Queue queue = new LinkedList<>(); - queue.add(root); - - while (!queue.isEmpty()) { - int n = queue.size(); - List temp = new ArrayList<>(); - - while(n-- > 0) { - Node node = queue.remove(); - temp.add(node.val); - List childrens = node.children; - queue.addAll(childrens); - } - - values.add(temp); - } - - return values; - } -} diff --git a/Easy/N-ary Tree Postorder Traversal.java b/Easy/N-ary Tree Postorder Traversal.java index d0ba1138..3807c509 100644 --- a/Easy/N-ary Tree Postorder Traversal.java +++ b/Easy/N-ary Tree Postorder Traversal.java @@ -6,38 +6,31 @@ class Node { public Node() {} - public Node(int _val,List _children) { + public Node(int _val) { + val = _val; + } + + public Node(int _val, List _children) { val = _val; children = _children; } }; */ -class Solution { - public List postorder(Node root) { - List values = new ArrayList<>(); - if (root == null) { - return values; - } - - - Stack stack1 = new Stack<>(); - Stack stack2 = new Stack<>(); - stack1.push(root); - - while (!stack1.empty()) { - Node temp = stack1.pop(); - stack2.push(temp); - List childrens = temp.children; - for(Node children : childrens) { - stack1.push(children); - } - } - - while (!stack2.empty()) { - values.add(stack2.pop().val); - } - - return values; +class Solution { + public List postorder(Node root) { + List result = new ArrayList<>(); + helper(root, result); + return result; + } + + private void helper(Node root, List result) { + if (root == null) { + return; + } + for (Node child : root.children) { + helper(child, result); } + result.add(root.val); + } } diff --git a/Easy/N-ary Tree Preorder Traversal.java b/Easy/N-ary Tree Preorder Traversal.java index 73d61d32..49fac382 100644 --- a/Easy/N-ary Tree Preorder Traversal.java +++ b/Easy/N-ary Tree Preorder Traversal.java @@ -6,47 +6,33 @@ class Node { public Node() {} - public Node(int _val,List _children) { + public Node(int _val) { + val = _val; + } + + public Node(int _val, List _children) { val = _val; children = _children; } }; */ -class Solution { - List values = new ArrayList<>(); - public List preorder(Node root) { - updateListIterative(root); - return values; - } - - private void updateListIterative(Node root) { - if (root == null) { - return; - } - - Stack stack = new Stack<>(); - stack.push(root); - while (!stack.empty()) { - Node temp = stack.pop(); - values.add(temp.val); - - List childrens = temp.children; - - for (int i=childrens.size()-1; i>=0; i--) { - stack.push(childrens.get(i)); - } - } +class Solution { + public List preorder(Node root) { + if (root == null) { + return new ArrayList<>(); } - - private void updateListRecursive(Node root) { - if (root == null) { - return; - } - - values.add(root.val); - for (Node node : root.children) { - updateListRecursive(node); - } + List list = new ArrayList<>(); + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + Node popped = stack.pop(); + list.add(popped.val); + List children = popped.children; + for (int i = children.size() - 1; i >= 0; i--) { + stack.push(children.get(i)); + } } + return list; + } } diff --git a/Easy/N-th Tribonacci Number.java b/Easy/N-th Tribonacci Number.java new file mode 100644 index 00000000..23a53a62 --- /dev/null +++ b/Easy/N-th Tribonacci Number.java @@ -0,0 +1,13 @@ +class Solution { + public int tribonacci(int n) { + if (n <= 2) { + return n == 0 ? 0 : 1; + } + int[] dp = new int[n + 1]; + dp[1] = dp[2] = 1; + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 2] + dp[i - 1] + dp[i - 3]; + } + return dp[n]; + } +} diff --git a/Easy/Neither Minimum nor Maximum.java b/Easy/Neither Minimum nor Maximum.java new file mode 100644 index 00000000..b5d7a6d1 --- /dev/null +++ b/Easy/Neither Minimum nor Maximum.java @@ -0,0 +1,16 @@ +class Solution { + public int findNonMinOrMax(int[] nums) { + int min = nums[0]; + int max = nums[0]; + for (int num : nums) { + min = Math.min(num, min); + max = Math.max(num, max); + } + final int arrayMin = min; + final int arrayMax = max; + return Arrays.stream(nums) + .filter(num -> num != arrayMin && num != arrayMax) + .findFirst() + .orElse(-1); + } +} diff --git a/Easy/Nested List Weight Sum.java b/Easy/Nested List Weight Sum.java index e5bab7b1..4a98107d 100644 --- a/Easy/Nested List Weight Sum.java +++ b/Easy/Nested List Weight Sum.java @@ -22,26 +22,33 @@ * public void add(NestedInteger ni); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ class Solution { - int sum; - public int depthSum(List nestedList) { - sum = 0; - helper(nestedList, 1); - return sum; + public int depthSum(List nestedList) { + Queue queue = new LinkedList<>(); + int currLevel = 1; + for (NestedInteger nestedInteger : nestedList) { + queue.add(nestedInteger); } - - private void helper(List nestedList, int level) { - for (NestedInteger nested : nestedList) { - if (nested.isInteger()) { - sum += nested.getInteger() * level; - } - else { - helper(nested.getList(), level + 1); - } + int totalSum = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + NestedInteger removed = queue.remove(); + if (removed.isInteger()) { + totalSum += currLevel * removed.getInteger(); + } else { + List nestedIntegers = removed.getList(); + for (NestedInteger nestedInteger : nestedIntegers) { + queue.add(nestedInteger); + } } + } + currLevel++; } + return totalSum; + } } diff --git a/Easy/Next Greater Element I.java b/Easy/Next Greater Element I.java new file mode 100644 index 00000000..35234857 --- /dev/null +++ b/Easy/Next Greater Element I.java @@ -0,0 +1,18 @@ +class Solution { + public int[] nextGreaterElement(int[] nums1, int[] nums2) { + Map map = new HashMap<>(); + Stack stack = new Stack<>(); + for (int i = nums2.length - 1; i >= 0; i--) { + while (!stack.isEmpty() && stack.peek() <= nums2[i]) { + stack.pop(); + } + map.put(nums2[i], stack.isEmpty() ? -1 : stack.peek()); + stack.push(nums2[i]); + } + int[] result = new int[nums1.length]; + for (int i = 0; i < nums1.length; i++) { + result[i] = map.getOrDefault(nums1[i], -1); + } + return result; + } +} diff --git a/Easy/Nim Game.java b/Easy/Nim Game.java new file mode 100644 index 00000000..26f74660 --- /dev/null +++ b/Easy/Nim Game.java @@ -0,0 +1,5 @@ +class Solution { + public boolean canWinNim(int n) { + return n % 4 != 0; + } +} diff --git a/Easy/Non-decreasing Array.java b/Easy/Non-decreasing Array.java deleted file mode 100644 index f291ee0a..00000000 --- a/Easy/Non-decreasing Array.java +++ /dev/null @@ -1,13 +0,0 @@ -class Solution { - public boolean checkPossibility(int[] a) { - int c = 0; - for (int i = 1; i < a.length; i++) { - if (a[i] < a[i - 1]) { - if (c++ > 0) return false; - if (i - 2 < 0 || a[i - 2] <= a[i]) a[i - 1] = a[i]; - else a[i] = a[i - 1]; - } - } - return true; - } -} diff --git a/Easy/Number Complement.java b/Easy/Number Complement.java index 889c873c..10cfc993 100644 --- a/Easy/Number Complement.java +++ b/Easy/Number Complement.java @@ -1,38 +1,21 @@ class Solution { - public int findComplement(int num) { - return getDecimalVal(flip(getBinaryVal(num))); + public int findComplement(int num) { + StringBuilder sb = new StringBuilder(); + while (num > 0) { + int rem = num % 2; + num /= 2; + sb.append(rem); } - - public String getBinaryVal(int n) { - StringBuilder sb = new StringBuilder(); - while (n > 0) { - sb.append(String.valueOf(n%2)); - n /= 2; - } - return sb.reverse().toString(); + StringBuilder complement = new StringBuilder(); + for (int i = 0; i < sb.length(); i++) { + complement.append(sb.charAt(i) == '1' ? '0' : '1'); } - - public String flip(String s) { - StringBuilder sb = new StringBuilder(); - for (int i=0;i map = new HashMap<>(); + for (int[] rectangle : rectangles) { + int currSquareSide = Math.min(rectangle[0], rectangle[1]); + map.put(currSquareSide, map.getOrDefault(currSquareSide, 0) + 1); + maxSquareSide = Math.max(maxSquareSide, currSquareSide); + } + return map.get(maxSquareSide); + } +} diff --git a/Easy/Number of 1 bits.java b/Easy/Number of 1 bits.java index d8ac73f6..698d620b 100644 --- a/Easy/Number of 1 bits.java +++ b/Easy/Number of 1 bits.java @@ -1,15 +1,14 @@ public class Solution { - // you need to treat n as an unsigned value - public int hammingWeight(int n) { - int count = 0; - for (int i=0; i<32; i++) { - if ((n & 1) == 1) { - count++; - } - - n = n >> 1; - } - - return count; + // you need to treat n as an unsigned value + public int hammingWeight(int n) { + int bits = 0; + int mask = 1; + for (int i = 0; i < 32; i++) { + if ((n & mask) != 0) { + bits++; + } + mask <<= 1; } + return bits; + } } diff --git a/Easy/Number of Arithmetic Triplets.java b/Easy/Number of Arithmetic Triplets.java new file mode 100644 index 00000000..8094d932 --- /dev/null +++ b/Easy/Number of Arithmetic Triplets.java @@ -0,0 +1,13 @@ +class Solution { + public int arithmeticTriplets(int[] nums, int diff) { + int count = 0; + Set set = new HashSet<>(); + for (int num : nums) { + if (set.contains(num - diff) && set.contains(num - 2 * diff)) { + count++; + } + set.add(num); + } + return count; + } +} diff --git a/Easy/Number of Beautiful Pairs.java b/Easy/Number of Beautiful Pairs.java new file mode 100644 index 00000000..2993a81e --- /dev/null +++ b/Easy/Number of Beautiful Pairs.java @@ -0,0 +1,29 @@ +class Solution { + public int countBeautifulPairs(int[] nums) { + int pairCount = 0; + for (int i = 0; i < nums.length; i++) { + int lastDigit = nums[i] % 10; + for (int j = 0; j < i; j++) { + int firstDigit = getFirstDigit(nums[j]); + pairCount += gcd(firstDigit, lastDigit) == 1 ? 1 : 0; + } + } + return pairCount; + } + + private static int getFirstDigit(int num) { + while (num >= 10) { + num /= 10; + } + return num; + } + + private static int gcd(int a, int b) { + while (b != 0) { + int temp = a % b; + a = b; + b = temp; + } + return a; + } +} diff --git a/Easy/Number of Changing Keys.java b/Easy/Number of Changing Keys.java new file mode 100644 index 00000000..bb6bc939 --- /dev/null +++ b/Easy/Number of Changing Keys.java @@ -0,0 +1,11 @@ +class Solution { + public int countKeyChanges(String s) { + int changes = 0; + for (int i = 1; i < s.length(); i++) { + if (Character.toLowerCase(s.charAt(i)) != Character.toLowerCase(s.charAt(i - 1))) { + changes++; + } + } + return changes; + } +} diff --git a/Easy/Number of Common Factors.java b/Easy/Number of Common Factors.java new file mode 100644 index 00000000..4ecdf04e --- /dev/null +++ b/Easy/Number of Common Factors.java @@ -0,0 +1,12 @@ +class Solution { + public int commonFactors(int a, int b) { + int count = 0; + int minNum = Math.min(a, b); + for (int i = 1; i <= minNum / 2; i++) { + if (a % i == 0 && b % i == 0) { + count++; + } + } + return count + (a % minNum == 0 && b % minNum == 0 ? 1 : 0); + } +} diff --git a/Easy/Number of Days Between Two Dates.java b/Easy/Number of Days Between Two Dates.java new file mode 100644 index 00000000..e42eb7d4 --- /dev/null +++ b/Easy/Number of Days Between Two Dates.java @@ -0,0 +1,29 @@ +class Solution { + private int[] daysOfMonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + public int daysBetweenDates(String date1, String date2) { + return Math.abs(daysFrom1971(date1) - daysFrom1971(date2)); + } + + private int daysFrom1971(String date) { + String[] dateArr = date.split("-"); + int year = Integer.parseInt(dateArr[0]); + int month = Integer.parseInt(dateArr[1]); + int day = Integer.parseInt(dateArr[2]); + int numOfDays = day; + for (int y = 1971; y < year; y++) { + numOfDays += isLeapYear(y) ? 366 : 365; + } + for (int m = 0; m < month - 1; m++) { + numOfDays += daysOfMonth[m]; + } + if (month > 2 && isLeapYear(year)) { + numOfDays++; + } + return numOfDays; + } + + private boolean isLeapYear(int year) { + return year % 400 == 0 || (year % 100 != 0 && year % 4 == 0); + } +} diff --git a/Easy/Number of Days in a Month.java b/Easy/Number of Days in a Month.java new file mode 100644 index 00000000..d2268cc8 --- /dev/null +++ b/Easy/Number of Days in a Month.java @@ -0,0 +1,7 @@ +class Solution { + final int[] DAY_COUNT = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + public int numberOfDays(int Y, int M) { + boolean isLeapYear = Y % 4 == 0 && ((Y % 100 == 0) ? (Y % 400 == 0) : true); + return DAY_COUNT[M - 1] + (M == 2 ? (isLeapYear ? 1 : 0) : 0); + } +} diff --git a/Easy/Number of Different Integers in a String.java b/Easy/Number of Different Integers in a String.java new file mode 100644 index 00000000..3cdd6557 --- /dev/null +++ b/Easy/Number of Different Integers in a String.java @@ -0,0 +1,18 @@ +class Solution { + public int numDifferentIntegers(String word) { + Set set = new HashSet<>(); + int idx = 0; + int n = word.length(); + while (idx < n) { + if (Character.isDigit(word.charAt(idx))) { + int num = 0; + while (idx < n && Character.isDigit(word.charAt(idx))) { + num = num * 10 + Character.getNumericValue(word.charAt(idx++)); + } + set.add(num); + } + idx++; + } + return set.size(); + } +} diff --git a/Easy/Number of Distinct Averages.java b/Easy/Number of Distinct Averages.java new file mode 100644 index 00000000..cb2f9b34 --- /dev/null +++ b/Easy/Number of Distinct Averages.java @@ -0,0 +1,13 @@ +class Solution { + public int distinctAverages(int[] nums) { + Arrays.sort(nums); + Set averages = new HashSet<>(); + int startIdx = 0; + int endIdx = nums.length - 1; + while (startIdx <= endIdx) { + double total = (double) (nums[startIdx++] + nums[endIdx--]); + averages.add(total / 2); + } + return averages.size(); + } +} diff --git a/Easy/Number of Employees Who Met the Target.java b/Easy/Number of Employees Who Met the Target.java new file mode 100644 index 00000000..64f20287 --- /dev/null +++ b/Easy/Number of Employees Who Met the Target.java @@ -0,0 +1,5 @@ +class Solution { + public int numberOfEmployeesWhoMetTarget(int[] hours, int target) { + return (int) Arrays.stream(hours).filter(hour -> hour >= target).count(); + } +} diff --git a/Easy/Number of Equivalent Domino Pairs.java b/Easy/Number of Equivalent Domino Pairs.java new file mode 100644 index 00000000..422b51e2 --- /dev/null +++ b/Easy/Number of Equivalent Domino Pairs.java @@ -0,0 +1,12 @@ +class Solution { + public int numEquivDominoPairs(int[][] dominoes) { + int numOfPairs = 0; + Map map = new HashMap<>(); + for (int[] dominoe : dominoes) { + int key = Math.min(dominoe[0], dominoe[1]) * 10 + Math.max(dominoe[0], dominoe[1]); + numOfPairs += map.getOrDefault(key, 0); + map.put(key, map.getOrDefault(key, 0) + 1); + } + return numOfPairs; + } +} diff --git a/Easy/Number of Good Pairs.java b/Easy/Number of Good Pairs.java new file mode 100644 index 00000000..edb3a754 --- /dev/null +++ b/Easy/Number of Good Pairs.java @@ -0,0 +1,11 @@ +class Solution { + public int numIdenticalPairs(int[] nums) { + Map map = new HashMap<>(); + int count = 0; + for (int num : nums) { + count += map.getOrDefault(num, 0); + map.put(num, map.getOrDefault(num, 0) + 1); + } + return count; + } +} diff --git a/Easy/Number of Lines To Write String.java b/Easy/Number of Lines To Write String.java index 488bf839..ca5a50bd 100644 --- a/Easy/Number of Lines To Write String.java +++ b/Easy/Number of Lines To Write String.java @@ -1,21 +1,15 @@ class Solution { - public static int[] numberOfLines(int[] widths, String S) { - if (S.isEmpty()) { - return new int[]{0,0}; - } - - int capacity = 100; - char[] chars = S.toCharArray(); - int count = 1; - - for (char c : chars) { - if (capacity - widths[c-'a'] < 0) { - capacity = 100; - count++; - } - capacity -= widths[c-'a']; - } - - return new int[]{count, 100-capacity}; + public int[] numberOfLines(int[] widths, String S) { + int numOfLines = 1; + int currWidth = 0; + for (char c : S.toCharArray()) { + int width = widths[c - 'a']; + currWidth += width; + if (currWidth > 100) { + numOfLines++; + currWidth = width; + } } + return new int[]{numOfLines, currWidth}; + } } diff --git a/Easy/Number of Recent Calls.java b/Easy/Number of Recent Calls.java new file mode 100644 index 00000000..4b039208 --- /dev/null +++ b/Easy/Number of Recent Calls.java @@ -0,0 +1,22 @@ +class RecentCounter { + + private Queue queue; + + public RecentCounter() { + queue = new LinkedList<>(); + } + + public int ping(int t) { + while (!queue.isEmpty() && t - queue.peek() > 3000) { + queue.remove(); + } + queue.add(t); + return queue.size(); + } +} + +/** + * Your RecentCounter object will be instantiated and called as such: + * RecentCounter obj = new RecentCounter(); + * int param_1 = obj.ping(t); + */ diff --git a/Easy/Number of Senior Citizens.java b/Easy/Number of Senior Citizens.java new file mode 100644 index 00000000..cb658ee0 --- /dev/null +++ b/Easy/Number of Senior Citizens.java @@ -0,0 +1,8 @@ +class Solution { + public int countSeniors(String[] details) { + return (int) Arrays.stream(details) + .map(s -> Integer.parseInt(s.substring(11, 13))) + .filter(age -> age > 60) + .count(); + } +} diff --git a/Easy/Number of Steps to Reduce a Number to Zero.java b/Easy/Number of Steps to Reduce a Number to Zero.java new file mode 100644 index 00000000..ddd98ce5 --- /dev/null +++ b/Easy/Number of Steps to Reduce a Number to Zero.java @@ -0,0 +1,10 @@ +class Solution { + public int numberOfSteps (int num) { + int count = 0; + while (num > 0) { + count++; + num = num % 2 == 0 ? num / 2 : num - 1; + } + return count; + } +} diff --git a/Easy/Number of Strings That Appear as Substrings in Word.java b/Easy/Number of Strings That Appear as Substrings in Word.java new file mode 100644 index 00000000..f328158d --- /dev/null +++ b/Easy/Number of Strings That Appear as Substrings in Word.java @@ -0,0 +1,5 @@ +class Solution { + public int numOfStrings(String[] patterns, String word) { + return (int) Arrays.stream(patterns).filter(p -> word.contains(p)).count(); + } +} diff --git a/Easy/Number of Students Doing Homework at a Given Time.java b/Easy/Number of Students Doing Homework at a Given Time.java new file mode 100644 index 00000000..9c1f1bd6 --- /dev/null +++ b/Easy/Number of Students Doing Homework at a Given Time.java @@ -0,0 +1,11 @@ +class Solution { + public int busyStudent(int[] startTime, int[] endTime, int queryTime) { + int count = 0; + for (int i = 0; i < startTime.length; i++) { + if (startTime[i] <= queryTime && endTime[i] >= queryTime) { + count++; + } + } + return count; + } +} diff --git a/Easy/Number of Students Unable to Eat Lunch.java b/Easy/Number of Students Unable to Eat Lunch.java new file mode 100644 index 00000000..3902c4c1 --- /dev/null +++ b/Easy/Number of Students Unable to Eat Lunch.java @@ -0,0 +1,13 @@ +class Solution { + public int countStudents(int[] students, int[] sandwiches) { + int[] preferenceCount = new int[2]; + for (int preference : students) { + preferenceCount[preference]++; + } + int i = 0; + for (i = 0; i < sandwiches.length && preferenceCount[sandwiches[i]] > 0; i++) { + preferenceCount[sandwiches[i]]--; + } + return sandwiches.length - i; + } +} diff --git a/Easy/Number of Unequal Triplets in Array.java b/Easy/Number of Unequal Triplets in Array.java new file mode 100644 index 00000000..fc2fa82a --- /dev/null +++ b/Easy/Number of Unequal Triplets in Array.java @@ -0,0 +1,17 @@ +class Solution { + public int unequalTriplets(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int result = 0; + int left = 0; + int right = nums.length; + for (Integer key : map.keySet()) { + right -= map.get(key); + result += left * map.get(key) * right; + left += map.get(key); + } + return result; + } +} diff --git a/Easy/Number of Valid Words in a Sentence.java b/Easy/Number of Valid Words in a Sentence.java new file mode 100644 index 00000000..686add3b --- /dev/null +++ b/Easy/Number of Valid Words in a Sentence.java @@ -0,0 +1,35 @@ +class Solution { + + public int countValidWords(String sentence) { + return (int) Arrays.stream(sentence.split("\\s+")).filter(Solution::isValidWord).count(); + } + + public static boolean isValidWord(String s) { + if (s.isEmpty() + || s.charAt(0) == '-' + || s.charAt(s.length() - 1) == '-' + || (s.length() > 1 && !Character.isLetter(s.charAt(0)))) { + return false; + } + boolean punctuationFound = false; + boolean hyphenFound = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (Character.isDigit(c)) { + return false; + } + if (c == '-') { + if (hyphenFound || !(Character.isLetter(s.charAt(i - 1)) && Character.isLetter(s.charAt(i + 1)))) { + return false; + } + hyphenFound = true; + } else if (!Character.isLetter(c)) { + if (punctuationFound || i != s.length() - 1) { + return false; + } + punctuationFound = true; + } + } + return true; + } +} diff --git a/Easy/Number of segments in a String.java b/Easy/Number of segments in a String.java index 1ecd407e..2139e560 100644 --- a/Easy/Number of segments in a String.java +++ b/Easy/Number of segments in a String.java @@ -1,14 +1,11 @@ class Solution { - public int countSegments(String str) { - String[] arr = str.split("\\s+"); - - int count = 0; - for (String s : arr) { - if ((!s.equals("\\s+")) && s.length() > 0) { - count++; - } - } - - return count; + public int countSegments(String s) { + int count = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) != ' ' && (i == 0 || s.charAt(i - 1) == ' ')) { + count++; + } } + return count; + } } diff --git a/Easy/Occurrences After Bigram.java b/Easy/Occurrences After Bigram.java index 57ca1d18..4476bfaf 100644 --- a/Easy/Occurrences After Bigram.java +++ b/Easy/Occurrences After Bigram.java @@ -1,19 +1,12 @@ class Solution { - public String[] findOcurrences(String text, String first, String second) { - String[] words = text.split("\\s+"); - List indexes = new ArrayList<>(); - - for (int i = 0; i < words.length - 2; i++) { - if (words[i].equals(first) && words[i + 1].equals(second)) { - indexes.add(i + 2); - } - } - - String[] ans = new String[indexes.size()]; - for (int i = 0; i < indexes.size(); i++) { - ans[i] = words[indexes.get(i)]; - } - - return ans; + public String[] findOcurrences(String text, String first, String second) { + String[] words = text.split("\\s+"); + List list = new ArrayList<>(); + for (int i = 0; i < words.length - 2; i++) { + if (words[i].equals(first) && words[i + 1].equals(second)) { + list.add(words[i + 2]); + } } + return list.toArray(new String[list.size()]); + } } diff --git a/Easy/Odd String Difference.java b/Easy/Odd String Difference.java new file mode 100644 index 00000000..d6fa4b49 --- /dev/null +++ b/Easy/Odd String Difference.java @@ -0,0 +1,23 @@ +class Solution { + public String oddString(String[] words) { + Map> diffCounter = new HashMap<>(); + for (String word : words) { + String key = getDiffCounter(word); + diffCounter.computeIfAbsent(key, k -> new HashSet<>()).add(word); + } + for (String key : diffCounter.keySet()) { + if (diffCounter.get(key).size() == 1) { + return diffCounter.get(key).iterator().next(); + } + } + return ""; + } + + private static String getDiffCounter(String word) { + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < word.length(); i++) { + sb.append(word.charAt(i) - word.charAt(i - 1)).append('|'); + } + return sb.toString(); + } +} diff --git a/Easy/Paint Fence.java b/Easy/Paint Fence.java deleted file mode 100644 index 6c8c1289..00000000 --- a/Easy/Paint Fence.java +++ /dev/null @@ -1,26 +0,0 @@ -class Solution { - public int numWays(int n, int k) { - if (n == 0) { - return 0; - } - - if (n == 1) { - return k; - } - - if (n == 2) { - return k * k; - } - - int[] ways = new int[n + 1]; - ways[0] = 0; - ways[1] = k; - ways[2] = k * k; - - for (int i = 3; i <= n; i++) { - ways[i] = ways[i - 1] * (k - 1) + ways[i - 2] * (k - 1); - } - - return ways[n]; - } -} diff --git a/Easy/Paint House.java b/Easy/Paint House.java deleted file mode 100644 index 797243d2..00000000 --- a/Easy/Paint House.java +++ /dev/null @@ -1,18 +0,0 @@ -class Solution { - public int minCost(int[][] costs) { - if (costs.length == 0) { - return 0; - } - - for (int i=1; i map = new HashMap<>(); - - for (int i = 0; i < time.length; i++) { - if (map.containsKey((60 - time[i] % 60) % 60)) { - count += map.get((60 - time[i] % 60) % 60); - } - - map.put(time[i] % 60, map.getOrDefault(time[i] % 60, 0) + 1); - } - - return count; + public int numPairsDivisibleBy60(int[] time) { + Map map = new HashMap<>(); + int count = 0; + for (int t : time) { + count += map.getOrDefault((60 - t % 60) % 60, 0); + map.put(t % 60, map.getOrDefault(t % 60, 0) + 1); } + return count; + } } diff --git a/Easy/Palindrome Linked List.java b/Easy/Palindrome Linked List.java index 33fcc9f4..11c23754 100644 --- a/Easy/Palindrome Linked List.java +++ b/Easy/Palindrome Linked List.java @@ -3,32 +3,41 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public boolean isPalindrome(ListNode head) { - ArrayList arr = new ArrayList(); - while (head != null) { - arr.add(head.val); - head = head.next; + ListNode slow = head; + ListNode fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; } - - if (arr.size() < 2) return true; - - int i=0; - int j = arr.size()-1; - - while (true) { - - if (arr.get(i).equals(arr.get(j)) == false) return false; - - if (arr.size()%2 == 0 && j - i == 1) break; - if (arr.size()%2 != 0 && j - i == 2) break; - - i++; - j--; + ListNode secondHalf = slow; + secondHalf = reverse(secondHalf); + ListNode firstHalf = head; + while (secondHalf != null && firstHalf != null) { + if (firstHalf.val != secondHalf.val) { + return false; + } + firstHalf = firstHalf.next; + secondHalf = secondHalf.next; } return true; } + + private ListNode reverse(ListNode node) { + ListNode curr = node; + ListNode prev = null; + while (curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } } diff --git a/Easy/Palindrome Number.java b/Easy/Palindrome Number.java index 54341864..a3206088 100644 --- a/Easy/Palindrome Number.java +++ b/Easy/Palindrome Number.java @@ -1,15 +1,15 @@ class Solution { - public boolean isPalindrome(int x) { - return x < 0 ? false : x == getReverseDigit(x); + public boolean isPalindrome(int x) { + if (x < 0) { + return false; } - - private int getReverseDigit(int x) { - int num = 0; - while (x > 0) { - num = num * 10 + x % 10; - x /= 10; - } - - return num; + int reversedNum = 0; + int xCopy = x; + while (x > 0) { + int rem = x % 10; + reversedNum = reversedNum * 10 + rem; + x /= 10; } + return reversedNum == xCopy; + } } diff --git a/Easy/Palindrome Permutation.java b/Easy/Palindrome Permutation.java index 5ff21be3..ce4bccb8 100644 --- a/Easy/Palindrome Permutation.java +++ b/Easy/Palindrome Permutation.java @@ -1,24 +1,18 @@ class Solution { - public static boolean canPermutePalindrome(String s) { - Map map = new HashMap<>(); - char[] chars = s.toCharArray(); - - for (char c : chars) { - map.put(c, map.getOrDefault(c, 0) + 1); - } - - int oddVal = 0; - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue()%2 != 0) { - oddVal++; - } - - if (oddVal == 2) { - return false; - } + public boolean canPermutePalindrome(String s) { + Map frequencyMap = new HashMap<>(); + for (char c : s.toCharArray()) { + frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1); + } + boolean oddFound = false; + for (Character key : frequencyMap.keySet()) { + if (frequencyMap.get(key) % 2 != 0) { + if (oddFound) { + return false; } - - return true; + oddFound = true; + } } + return true; + } } diff --git a/Easy/Partition Array Into Three Parts With Equal Sum.java b/Easy/Partition Array Into Three Parts With Equal Sum.java new file mode 100644 index 00000000..afcf6574 --- /dev/null +++ b/Easy/Partition Array Into Three Parts With Equal Sum.java @@ -0,0 +1,22 @@ +class Solution { + public boolean canThreePartsEqualSum(int[] A) { + int totalSum = 0; + for (int num : A) { + totalSum += num; + } + if (totalSum % 3 != 0) { + return false; + } + totalSum = totalSum / 3; + int currSum = 0; + int segmentCount = 0; + for (int num : A) { + currSum += num; + if (currSum == totalSum) { + segmentCount++; + currSum = 0; + } + } + return segmentCount >= 3; + } +} diff --git a/Easy/Pascal's Triangle II.java b/Easy/Pascal's Triangle II.java index 66ec5767..9890275c 100644 --- a/Easy/Pascal's Triangle II.java +++ b/Easy/Pascal's Triangle II.java @@ -1,14 +1,17 @@ class Solution { - public List getRow(int rowIndex) { - List res = new ArrayList(); - - for(int i = 0;i0;j--) { - res.set(j, res.get(j-1) + res.get(j)); - } + public List getRow(int rowIndex) { + List lastRow = new ArrayList<>(); + for (int i = 0; i <= rowIndex; i++) { + List copy = new ArrayList<>(lastRow); + lastRow.clear(); + for (int j = 0; j <= i; j++) { + if (j == 0 || j == i) { + lastRow.add(1); + } else { + lastRow.add(copy.get(j - 1) + copy.get(j)); } - - return res; + } } + return lastRow; + } } diff --git a/Easy/Pascal's Triangle.java b/Easy/Pascal's Triangle.java index ac462848..86ea8bdb 100644 --- a/Easy/Pascal's Triangle.java +++ b/Easy/Pascal's Triangle.java @@ -1,23 +1,17 @@ class Solution { - public List> generate(int numRows) { - - List> ans = new ArrayList<>(); - - for (int i=0;i> result = new ArrayList<>(); + for (int i = 0; i < numRows; i++) { List temp = new ArrayList<>(); - for(int j = 0;j<=i;j++) { - if (i == j || j == 0) { + for (int j = 0; j <= i; j++) { + if (j == 0 || j == i) { temp.add(1); - } - else { - temp.add(ans.get(i-1).get(j-1) + ans.get(i-1).get(j)); + } else { + temp.add(result.get(i - 1).get(j - 1) + result.get(i - 1).get(j)); } } - - ans.add(temp); + result.add(temp); } - - return ans; + return result; } } diff --git a/Easy/Pass the Pillow.java b/Easy/Pass the Pillow.java new file mode 100644 index 00000000..e9ae16ea --- /dev/null +++ b/Easy/Pass the Pillow.java @@ -0,0 +1,7 @@ +class Solution { + public int passThePillow(int n, int time) { + int factor = time / (n - 1); + int remainder = time % (n - 1); + return factor % 2 != 0 ? (n - remainder) : (1 + remainder); + } +} diff --git a/Easy/Path Crossing.java b/Easy/Path Crossing.java new file mode 100644 index 00000000..e3f7d9a9 --- /dev/null +++ b/Easy/Path Crossing.java @@ -0,0 +1,29 @@ +class Solution { + public boolean isPathCrossing(String path) { + Set visited = new HashSet<>(); + visited.add("0|0"); + int x = 0; + int y = 0; + for (Character step : path.toCharArray()) { + switch (step) { + case 'N': + x++; + break; + case 'S': + x--; + break; + case 'E': + y--; + break; + case 'W': + y++; + break; + } + String key = x + "|" + y; + if (!visited.add(key)) { + return true; + } + } + return false; + } +} diff --git a/Easy/Path Sum III.java b/Easy/Path Sum III.java deleted file mode 100644 index 03bdaa77..00000000 --- a/Easy/Path Sum III.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public int pathSum(TreeNode root, int sum) { - if(root == null) { - return 0; - } - - return pathSumFrom(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum); - } - - private int pathSumFrom(TreeNode root, int sum) { - if (root == null) return 0; - - return (root.val == sum ? 1 : 0) + pathSumFrom(root.left, sum - root.val) + pathSumFrom(root.right, sum - root.val); - } -} diff --git a/Easy/Path Sum.java b/Easy/Path Sum.java index 537ec4bb..dc77aafe 100644 --- a/Easy/Path Sum.java +++ b/Easy/Path Sum.java @@ -4,17 +4,39 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public boolean hasPathSum(TreeNode root, int sum) { - - if (root == null) return false; - if (root.left == null && root.right == null) { - return sum - root.val == 0; - } - - return (root.left != null ? hasPathSum(root.left, sum-root.val) : false) | (root.right != null ? hasPathSum(root.right, sum-root.val) : false); + public boolean hasPathSum(TreeNode root, int targetSum) { + if (root == null) { + return false; } + Queue sumQueue = new LinkedList<>(); + Queue nodeQueue = new LinkedList<>(); + sumQueue.add(targetSum - root.val); + nodeQueue.add(root); + while (!nodeQueue.isEmpty()) { + TreeNode removedNode = nodeQueue.remove(); + int removedSum = sumQueue.remove(); + if (removedNode.left == null && removedNode.right == null && removedSum == 0) { + return true; + } + if (removedNode.left != null) { + nodeQueue.add(removedNode.left); + sumQueue.add(removedSum - removedNode.left.val); + } + if (removedNode.right != null) { + nodeQueue.add(removedNode.right); + sumQueue.add(removedSum - removedNode.right.val); + } + } + return false; + } } diff --git a/Easy/Peak Index in a Mountain Array.java b/Easy/Peak Index in a Mountain Array.java deleted file mode 100644 index a72454fd..00000000 --- a/Easy/Peak Index in a Mountain Array.java +++ /dev/null @@ -1,21 +0,0 @@ -class Solution { - public int peakIndexInMountainArray(int[] A) { - return peakIndexInMountainArrayImpl(A, 0, A.length-1); - } - - private int peakIndexInMountainArrayImpl(int[] arr, int start, int end) { - if (start > end) return -1; - - int mid = (start + end)/2; - - if (arr[mid] > arr[mid-1] && arr[mid] > arr[mid+1]) { - return mid; - } - else if (arr[mid] < arr[mid-1]) { - return peakIndexInMountainArrayImpl(arr, start, mid-1); - } - else { - return peakIndexInMountainArrayImpl(arr, mid+1, end); - } - } -} diff --git a/Easy/Percentage of Letter in String.java b/Easy/Percentage of Letter in String.java new file mode 100644 index 00000000..96c0526c --- /dev/null +++ b/Easy/Percentage of Letter in String.java @@ -0,0 +1,11 @@ +class Solution { + public int percentageLetter(String s, char letter) { + int letterCount = 0; + for (char c : s.toCharArray()) { + if (c == letter) { + letterCount++; + } + } + return (letterCount * 100) / s.length(); + } +} diff --git a/Easy/Perfect Number.java b/Easy/Perfect Number.java index 5afc8d1c..6ce680f2 100644 --- a/Easy/Perfect Number.java +++ b/Easy/Perfect Number.java @@ -1,16 +1,18 @@ class Solution { - public boolean checkPerfectNumber(int num) { - if (num == 1) return false; - int sum = 0; - int i = 2; - while (i <= Math.sqrt(num)) { - if (num%i == 0) { - sum += i + num/i; - } - i++; - } - sum++; - - return sum == num; + public boolean checkPerfectNumber(int num) { + if (num == 1) { + return false; + } + return getDivisorSum(num) == num; + } + + private int getDivisorSum(int num) { + int sum = 0; + for (int i = 2; i <= Math.sqrt(num); i++) { + if (num % i == 0) { + sum += i + num / i; + } } + return sum + 1; + } } diff --git a/Easy/Perform String Shifts.java b/Easy/Perform String Shifts.java new file mode 100644 index 00000000..acd5d6fc --- /dev/null +++ b/Easy/Perform String Shifts.java @@ -0,0 +1,48 @@ +class Solution { + public String stringShift(String s, int[][] shifts) { + int leftShiftAmount = 0; + int rightShiftAmount = 0; + for (int[] shift : shifts) { + if (shift[0] == 0) { + leftShiftAmount += shift[1]; + } + else { + rightShiftAmount += shift[1]; + } + } + if (leftShiftAmount > rightShiftAmount) { + return shiftLeft(s, leftShiftAmount - rightShiftAmount); + } + else if (rightShiftAmount > leftShiftAmount) { + return shiftRight(s, rightShiftAmount - leftShiftAmount); + } + else { + return s; + } + } + + private String shiftLeft(String s, int n) { + StringBuilder sb = new StringBuilder(); + n %= s.length(); + for (int i = n; i < s.length(); i++) { + sb.append(s.charAt(i)); + } + for (int i = 0; i < n; i++) { + sb.append(s.charAt(i)); + } + return sb.toString(); + } + + private String shiftRight(String s, int n) { + StringBuilder sb = new StringBuilder(); + n %= s.length(); + int len = s.length(); + for (int i = 0; i < len - n; i++) { + sb.append(s.charAt(i)); + } + for (int i = s.length() - 1; i >= len - n; i--) { + sb.insert(0, s.charAt(i)); + } + return sb.toString(); + } +} diff --git a/Easy/Plus One.java b/Easy/Plus One.java index 75f6ff58..adc57cdd 100644 --- a/Easy/Plus One.java +++ b/Easy/Plus One.java @@ -1,35 +1,20 @@ class Solution { - public int[] plusOne(int[] digits) { - - int carry = 1; - List ans = new ArrayList<>(); - - for (int i=digits.length-1;i>=0;i--) { - if (digits[i] == 9 && carry == 1) { - ans.add(0); - carry = 1; - } - else if (carry == 1) { - ans.add(digits[i]+carry); - carry = 0; - } - else { - ans.add(digits[i]+carry); - } - } - - if (carry!=0) { - ans.add(carry); - } - - Collections.reverse(ans); - - int [] a = new int[ans.size()]; - - for (int k=0; k= 0; i--) { + int temp = digits[i] + carry; + if (temp <= 9) { + digits[i] = temp; + return digits; + } + digits[i] = temp % 10; } + int[] newDigits = new int[n + 1]; + newDigits[0] = 1; + for (int i = 1; i < n + 1; i++) { + newDigits[i] = digits[i - 1]; + } + return newDigits; + } } diff --git a/Easy/Points That Intersect With Cars.java b/Easy/Points That Intersect With Cars.java new file mode 100644 index 00000000..8443505c --- /dev/null +++ b/Easy/Points That Intersect With Cars.java @@ -0,0 +1,20 @@ +class Solution { + public int numberOfPoints(List> coordinates) { + coordinates.sort(Comparator.comparingInt((List o) -> o.get(0)).thenComparingInt(o -> o.get(1))); + int points = 0; + int intervalStart = -1; + int intervalEnd = -1; + for (List coordinate : coordinates) { + if (intervalStart == -1) { + intervalStart = coordinate.get(0); + } else { + if (intervalEnd < coordinate.get(0)) { + points += intervalEnd - intervalStart + 1; + intervalStart = coordinate.get(0); + } + } + intervalEnd = Math.max(intervalEnd, coordinate.get(1)); + } + return points + intervalEnd - intervalStart + 1; + } +} diff --git a/Easy/Positions of Large Groups.java b/Easy/Positions of Large Groups.java index 0e54382f..7258f529 100644 --- a/Easy/Positions of Large Groups.java +++ b/Easy/Positions of Large Groups.java @@ -1,32 +1,17 @@ class Solution { - public List> largeGroupPositions(String S) { - List> positions = new ArrayList<>(); - - int i = 1; - int count = 1; - int start = 0; - - while (i < S.length()) { - if (S.charAt(i) == S.charAt(i-1)) { - count++; + public List> largeGroupPositions(String s) { + List> result = new ArrayList<>(); + int idx = 0; + while (idx < s.length()) { + int startIdx = idx; + char c = s.charAt(idx); + while (idx < s.length() && s.charAt(idx) == c) { + idx++; } - else { - if (count >= 3) { - List temp = Arrays.asList(start, i-1); - positions.add(temp); - } - - start = i; - count = 1; + if (idx - startIdx >= 3) { + result.add(Arrays.asList(startIdx, idx - 1)); } - - i++; } - - if (count >= 3) { - positions.add(Arrays.asList(start, i-1)); - } - - return positions; + return result; } } diff --git a/Easy/Power of Four.java b/Easy/Power of Four.java new file mode 100644 index 00000000..269c7bd7 --- /dev/null +++ b/Easy/Power of Four.java @@ -0,0 +1,5 @@ +class Solution { + public boolean isPowerOfFour(int n) { + return n > 0 && Math.log(n) / Math.log(2) % 2 == 0; + } +} diff --git a/Easy/Power of Three.java b/Easy/Power of Three.java new file mode 100644 index 00000000..2fbe03e5 --- /dev/null +++ b/Easy/Power of Three.java @@ -0,0 +1,19 @@ +class Solution { + public boolean isPowerOfThree(int n) { + int left = 0; + int right = n / 3; + while (left <= right) { + int mid = (left + right) / 2; + double powValue = Math.pow(3, mid); + if (powValue == n) { + return true; + } + if (powValue > n) { + right = mid - 1; + } else { + left = mid + 1; + } + } + return false; + } +} diff --git a/Easy/Power of Two.java b/Easy/Power of Two.java new file mode 100644 index 00000000..caf0d77a --- /dev/null +++ b/Easy/Power of Two.java @@ -0,0 +1,21 @@ +class Solution { + public boolean isPowerOfTwo(int n) { + if (n > 1 && n % 2 != 0) { + return false; + } + int start = 0; + int end = n / 2; + while (start <= end) { + int mid = (start + end) / 2; + int pow = (int) Math.pow(2, mid); + if (pow == n) { + return true; + } else if (pow > n) { + end = mid - 1; + } else { + start = mid + 1; + } + } + return false; + } +} diff --git a/Easy/Power of four.java b/Easy/Power of four.java deleted file mode 100644 index 04e93000..00000000 --- a/Easy/Power of four.java +++ /dev/null @@ -1,5 +0,0 @@ -class Solution { - public boolean isPowerOfFour(int num) { - return num>0 && (num&(num - 1))== 0 && (num-1)%3 == 0; - } -} diff --git a/Easy/Power of three.java b/Easy/Power of three.java deleted file mode 100644 index 4e99c550..00000000 --- a/Easy/Power of three.java +++ /dev/null @@ -1,5 +0,0 @@ -class Solution { - public boolean isPowerOfThree(int n) { - return n>0 && 1162261467%n==0; - } -} diff --git a/Easy/Prime In Diagonal.java b/Easy/Prime In Diagonal.java new file mode 100644 index 00000000..16b34fda --- /dev/null +++ b/Easy/Prime In Diagonal.java @@ -0,0 +1,30 @@ +class Solution { + public int diagonalPrime(int[][] nums) { + int n = nums.length; + int maxPrime = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if ((i == j || i + j == n - 1) && isPrime(nums[i][j])) { + maxPrime = Math.max(maxPrime, nums[i][j]); + } + } + } + return maxPrime; + } + + private static boolean isPrime(int n) { + if (n <= 1) { + return false; + } + if (n == 2) { + return true; + } + int midPoint = ((int) Math.sqrt(n)) + 1; + for (int i = 2; i <= midPoint; i++) { + if (n % i == 0) { + return false; + } + } + return true; + } +} diff --git a/Easy/README.md b/Easy/README.md new file mode 100644 index 00000000..ff578ea7 --- /dev/null +++ b/Easy/README.md @@ -0,0 +1,609 @@ +# Easy LeetCode-Java-Solutions +S.no | Coding Problem +--- | --- +1|[Count Binary Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Binary%20Substrings.java) +2|[Check if All A's Appears Before All B's](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20All%20A's%20Appears%20Before%20All%20B's.java) +3|[Longest Harmonious Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Harmonious%20Subsequence.java) +4|[Missing Ranges](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Missing%20Ranges.java) +5|[High Five](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/High%20Five.java) +6|[Binary Tree Tilt](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Tree%20Tilt.java) +7|[Number of Boomerangs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Boomerangs.java) +8|[Count the Number of Consistent Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20the%20Number%20of%20Consistent%20Strings.java) +9|[Sentence Similarity](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sentence%20Similarity.java) +10|[Strong Password Checker II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Strong%20Password%20Checker%20II.java) +11|[Perform String Shifts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Perform%20String%20Shifts.java) +12|[Kth Largest Element in a Stream](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Kth%20Largest%20Element%20in%20a%20Stream.java) +13|[Kth Missing Positive Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Kth%20Missing%20Positive%20Number.java) +14|[Check If String Is a Prefix of Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20If%20String%20Is%20a%20Prefix%20of%20Array.java) +15|[Capitalize the Title](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Capitalize%20the%20Title.java) +16|[The K Weakest Rows in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/The%20K%20Weakest%20Rows%20in%20a%20Matrix.java) +17|[Missing Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Missing%20Number.java) +18|[Remove Duplicates from Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Duplicates%20from%20Sorted%20Array.java) +19|[Implement strStr](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Implement%20strStr.java) +20|[Reverse String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20String.java) +21|[Create Target Array in the Given Order](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Create%20Target%20Array%20in%20the%20Given%20Order.java) +22|[Increasing Order Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Increasing%20Order%20Search%20Tree.java) +23|[Minimum Number of Moves to Seat Everyone](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Number%20of%20Moves%20to%20Seat%20Everyone.java) +24|[Minimum Absolute Difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Absolute%20Difference.java) +25|[Maximum 69 Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%2069%20Number.java) +26|[Largest Perimeter Triangle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Perimeter%20Triangle.java) +27|[Minimum Cost of Buying Candies With Discount](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Cost%20of%20Buying%20Candies%20With%20Discount.java) +28|[Number of Equivalent Domino Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Equivalent%20Domino%20Pairs.java) +29|[Summary Ranges](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Summary%20Ranges.java) +30|[Binary Number with Alternating Bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Number%20with%20Alternating%20Bits.java) +31|[Find the Distinct Difference Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Distinct%20Difference%20Array.java) +32|[Buy Two Chocolates](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Buy%20Two%20Chocolates.java) +33|[Intersection of Multiple Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Intersection%20of%20Multiple%20Arrays.java) +34|[Palindrome Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Palindrome%20Linked%20List.java) +35|[Rectangle Overlap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Rectangle%20Overlap.java) +36|[Intersection of Three Sorted Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Intersection%20of%20Three%20Sorted%20Arrays.java) +37|[Minimum Changes To Make Alternating Binary String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Changes%20To%20Make%20Alternating%20Binary%20String.java) +38|[Jewels and Stones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Jewels%20and%20Stones.java) +39|[Number of Valid Words in a Sentence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Valid%20Words%20in%20a%20Sentence.java) +40|[Greatest English Letter in Upper and Lower Case](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Greatest%20English%20Letter%20in%20Upper%20and%20Lower%20Case.java) +41|[Unique Email Addresses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Unique%20Email%20Addresses.java) +42|[X of a Kind in a Deck of Cards](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/X%20of%20a%20Kind%20in%20a%20Deck%20of%20Cards.java) +43|[Longest Nice Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Nice%20Substring.java) +44|[Count Primes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Primes.java) +45|[Positions of Large Groups](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Positions%20of%20Large%20Groups.java) +46|[Maximum Population Year](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Population%20Year.java) +47|[Min Cost Climbing Stairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Min%20Cost%20Climbing%20Stairs.java) +48|[Number of Days Between Two Dates](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Days%20Between%20Two%20Dates.java) +49|[Minimum Distance to the Target Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Distance%20to%20the%20Target%20Element.java) +50|[Path Crossing](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Path%20Crossing.java) +51|[Check If N and Its Double Exist](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20If%20N%20and%20Its%20Double%20Exist.java) +52|[Word Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Word%20Pattern.java) +53|[Maximum Nesting Depth of the Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Nesting%20Depth%20of%20the%20Parentheses.java) +54|[Two Sum IV - Input is a BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Two%20Sum%20IV%20-%20Input%20is%20a%20BST.java) +55|[Find Positive Integer Solution for a Given Equation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Positive%20Integer%20Solution%20for%20a%20Given%20Equation.java) +56|[Hamming Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Hamming%20Distance.java) +57|[Defuse the Bomb](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Defuse%20the%20Bomb.java) +58|[Check if The Number is Fascinating](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20The%20Number%20is%20Fascinating.java) +59|[Minimum Common Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Common%20Value.java) +60|[Final Prices With a Special Discount in a Shop](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Final%20Prices%20With%20a%20Special%20Discount%20in%20a%20Shop.java) +61|[Plus One](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Plus%20One.java) +62|[Submission Detail](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Submission%20Detail.java) +63|[Rotate String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Rotate%20String.java) +64|[Minimum Depth of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Depth%20of%20a%20Binary%20Tree.java) +65|[Power of Four](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Power%20of%20Four.java) +66|[Valid Perfect Square](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Perfect%20Square.java) +67|[Find N Unique Integers Sum up to Zero](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20N%20Unique%20Integers%20Sum%20up%20to%20Zero.java) +68|[Remove Trailing Zeros From a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Trailing%20Zeros%20From%20a%20String.java) +69|[Paint Fence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Paint%20Fence.java) +70|[Detect Capital](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Detect%20Capital.java) +71|[XOR Operation in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/XOR%20Operation%20in%20an%20Array.java) +72|[Divide a String Into Groups of Size k](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Divide%20a%20String%20Into%20Groups%20of%20Size%20k.java) +73|[Flipping an Image](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Flipping%20an%20Image.java) +74|[Subtract the Product and Sum of Digits of an Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Subtract%20the%20Product%20and%20Sum%20of%20Digits%20of%20an%20Integer.java) +75|[Two Sum III - Data Structure Design](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Two%20Sum%20III%20-%20Data%20Structure%20Design.java) +76|[Check if Binary String Has at Most One Segment of Ones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Binary%20String%20Has%20at%20Most%20One%20Segment%20of%20Ones.java) +77|[Number Complement](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20Complement.java) +78|[Longer Contiguous Segments of Ones than Zeros](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longer%20Contiguous%20Segments%20of%20Ones%20than%20Zeros.java) +79|[Design HashSet](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20HashSet.java) +80|[Convert 1D Array Into 2D Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Convert%201D%20Array%20Into%202D%20Array.java) +81|[Odd String Difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Odd%20String%20Difference.java) +82|[Remove Digit From Number to Maximize Result](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Digit%20From%20Number%20to%20Maximize%20Result.java) +83|[Find Mode in Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Mode%20in%20Binary%20Search%20Tree.java) +84|[Count Hills and Valleys in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Hills%20and%20Valleys%20in%20an%20Array.java) +85|[Maximum Repeating Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Repeating%20Substring.java) +86|[Number of Unequal Triplets in Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Unequal%20Triplets%20in%20Array.java) +87|[Split Strings by Separator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Split%20Strings%20by%20Separator.java) +88|[Find Closest Number to Zero](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Closest%20Number%20to%20Zero.java) +89|[1-bit and 2-bit Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/1-bit%20and%202-bit%20Characters.java) +90|[Binary Gap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Gap.java) +91|[Subtree of Another Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Subtree%20of%20Another%20Tree.java) +92|[Binary Tree Level Order Traversal II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Tree%20Level%20Order%20Traversal%20II.java) +93|[Count Prefixes of a Given String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Prefixes%20of%20a%20Given%20String.java) +94|[Find the Width of Columns of a Grid](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Width%20of%20Columns%20of%20a%20Grid.java) +95|[Defanging an IP Address](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Defanging%20an%20IP%20Address.java) +96|[Find Target Indices After Sorting Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Target%20Indices%20After%20Sorting%20Array.java) +97|[Truncate Sentence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Truncate%20Sentence.java) +98|[Diameter of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Diameter%20of%20Binary%20Tree.java) +99|[Best Poker Hand](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Best%20Poker%20Hand.java) +100|[Range Sum of BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Range%20Sum%20of%20BST.java) +101|[Maximum Average Subarray I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Average%20Subarray%20I.java) +102|[Fizz Buzz](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Fizz%20Buzz.java) +103|[Check if All the Integers in a Range Are Covered](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20All%20the%20Integers%20in%20a%20Range%20Are%20Covered.java) +104|[Find First Palindromic String in the Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20First%20Palindromic%20String%20in%20the%20Array.java) +105|[Duplicate Zeros](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Duplicate%20Zeros.java) +106|[Minimum Subsequence in Non-Increasing Order](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Subsequence%20in%20Non-Increasing%20Order.java) +107|[Smallest Range I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Smallest%20Range%20I.java) +108|[Employee Importance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Employee%20Importance.java) +109|[Minimum_index_sum_of_two_lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum_index_sum_of_two_lists.java) +110|[Points That Intersect With Cars](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Points%20That%20Intersect%20With%20Cars.java) +111|[Number of segments in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20segments%20in%20a%20String.java) +112|[Delete Columns to Make Sorted](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Delete%20Columns%20to%20Make%20Sorted.java) +113|[Reverse Only Letters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20Only%20Letters.java) +114|[Evaluate Boolean Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Evaluate%20Boolean%20Binary%20Tree.java) +115|[Repeated String Match](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Repeated%20String%20Match.java) +116|[Neither Minimum nor Maximum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Neither%20Minimum%20nor%20Maximum.java) +117|[Maximum Value of an Ordered Triplet I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Value%20of%20an%20Ordered%20Triplet%20I.java) +118|[Uncommon Words from Two Sentences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Uncommon%20Words%20from%20Two%20Sentences.java) +119|[Assign Cookies](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Assign%20Cookies.java) +120|[Most Frequent Number Following Key In an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Most%20Frequent%20Number%20Following%20Key%20In%20an%20Array.java) +121|[Element Appearing More Than 25% In Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Element%20Appearing%20More%20Than%2025%%20In%20Sorted%20Array.java) +122|[Find the Town Judge](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Town%20Judge.java) +123|[Buddy Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Buddy%20Strings.java) +124|[Teoplitz Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Teoplitz%20Matrix.java) +125|[Leaf-Similar Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Leaf-Similar%20Trees.java) +126|[Minimum Hours of Training to Win a Competition](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Hours%20of%20Training%20to%20Win%20a%20Competition.java) +127|[Goat Latin](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Goat%20Latin.java) +128|[Flower Planting With No Adjacent](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Flower%20Planting%20With%20No%20Adjacent.java) +129|[Largest Triangle Area](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Triangle%20Area.java) +130|[Row With Maximum Ones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Row%20With%20Maximum%20Ones.java) +131|[Determine Color of a Chessboard Square](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Determine%20Color%20of%20a%20Chessboard%20Square.java) +132|[Richest Customer Wealth](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Richest%20Customer%20Wealth.java) +133|[Consecutive Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Consecutive%20Characters.java) +134|[Latest Time by Replacing Hidden Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Latest%20Time%20by%20Replacing%20Hidden%20Digits.java) +135|[Robot Return to Origin](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Robot%20Return%20to%20Origin.java) +136|[Determine Whether Matrix Can Be Obtained By Rotation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Determine%20Whether%20Matrix%20Can%20Be%20Obtained%20By%20Rotation.java) +137|[Flip Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Flip%20Game.java) +138|[Minimum Value to Get Positive Step by Step Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Value%20to%20Get%20Positive%20Step%20by%20Step%20Sum.java) +139|[Average Value of Even Numbers That Are Divisible by Three](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Average%20Value%20of%20Even%20Numbers%20That%20Are%20Divisible%20by%20Three.java) +140|[Reshape the matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reshape%20the%20matrix.java) +141|[Valid Anagram](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Anagram.java) +142|[Number of Strings That Appear as Substrings in Word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Strings%20That%20Appear%20as%20Substrings%20in%20Word.java) +143|[DI String Match](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/DI%20String%20Match.java) +144|[Running Sum of 1d Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Running%20Sum%20of%201d%20Array.java) +145|[Special Array With X Elements Greater Than or Equal X](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Special%20Array%20With%20X%20Elements%20Greater%20Than%20or%20Equal%20X.java) +146|[Number of Distinct Averages](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Distinct%20Averages.java) +147|[Check if an Array Is Consecutive](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20an%20Array%20Is%20Consecutive.java) +148|[Backspace String Compare](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Backspace%20String%20Compare.java) +149|[Rings and Rods](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Rings%20and%20Rods.java) +150|[Implement Stack using Queues](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Implement%20Stack%20using%20Queues.java) +151|[Baseball Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Baseball%20Game.java) +152|[Pairs of Songs With Total Durations Divisible by 60](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Pairs%20of%20Songs%20With%20Total%20Durations%20Divisible%20by%2060.java) +153|[Destination City](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Destination%20City.java) +154|[Maximum Product of Three Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Product%20of%20Three%20Numbers.java) +155|[Three Consecutive Odds](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Three%20Consecutive%20Odds.java) +156|[Set Mismatch](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Set%20Mismatch.java) +157|[Sort Array by Increasing Frequency](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sort%20Array%20by%20Increasing%20Frequency.java) +158|[Find the Distance Value Between Two Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Distance%20Value%20Between%20Two%20Arrays.java) +159|[Find Anagram Mappings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Anagram%20Mappings.java) +160|[Check if Array is Good](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Array%20is%20Good.java) +161|[Decompress Run-Length Encoded List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Decompress%20Run-Length%20Encoded%20List.java) +162|[Flood Fill](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Flood%20Fill.java) +163|[Magic Squares In Grid](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Magic%20Squares%20In%20Grid.java) +164|[Smallest Even Multiple](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Smallest%20Even%20Multiple.java) +165|[Hexspeak](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Hexspeak.java) +166|[Diet Plan Performance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Diet%20Plan%20Performance.java) +167|[Maximum Number of Balloons](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Number%20of%20Balloons.java) +168|[Find Smallest Letter Greater Than Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Smallest%20Letter%20Greater%20Than%20Target.java) +169|[Check if Array Is Sorted and Rotated](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Array%20Is%20Sorted%20and%20Rotated.java) +170|[Maximum Enemy Forts That Can Be Captured](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Enemy%20Forts%20That%20Can%20Be%20Captured.java) +171|[Path Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Path%20Sum.java) +172|[Day of the Year](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Day%20of%20the%20Year.java) +173|[Number of Beautiful Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Beautiful%20Pairs.java) +174|[Can Make Arithmetic Progression From Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Can%20Make%20Arithmetic%20Progression%20From%20Sequence.java) +175|[Furthest Point From Origin](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Furthest%20Point%20From%20Origin.java) +176|[Find the Highest Altitude](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Highest%20Altitude.java) +177|[Root Equals Sum of Children](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Root%20Equals%20Sum%20of%20Children.java) +178|[Powerful Integers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Powerful%20Integers.java) +179|[Merge Two Sorted Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Merge%20Two%20Sorted%20Lists.java) +180|[Binary Search](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Search.java) +181|[K-diff Pairs in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/K-diff%20Pairs%20in%20an%20Array.java) +182|[Repeated Substring Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Repeated%20Substring%20Pattern.java) +183|[Calculate Digit Sum of a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Calculate%20Digit%20Sum%20of%20a%20String.java) +184|[Reformat Phone Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reformat%20Phone%20Number.java) +185|[Longest Continuous Increasing Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Continuous%20Increasing%20Subsequence.java) +186|[Shuffle the Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Shuffle%20the%20Array.java) +187|[Count Pairs Of Similar Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Pairs%20Of%20Similar%20Strings.java) +188|[Ransom Note](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Ransom%20Note.java) +189|[trailing_zeroes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/trailing_zeroes.java) +190|[Height Checker](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Height%20Checker.java) +191|[License Key Formatting](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/License%20Key%20Formatting.java) +192|[Sum of Values at Indices With K Set Bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Values%20at%20Indices%20With%20K%20Set%20Bits.java) +193|[Balanced Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Balanced%20Binary%20Tree.java) +194|[Check If It Is a Straight Line](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20If%20It%20Is%20a%20Straight%20Line.java) +195|[Binary Watch](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Watch.java) +196|[Count Special Quadruplets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Special%20Quadruplets.java) +197|[Three Divisors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Three%20Divisors.java) +198|[Make Array Zero by Subtracting Equal Amounts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Make%20Array%20Zero%20by%20Subtracting%20Equal%20Amounts.java) +199|[Maximum Number of Words You Can Type](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Number%20of%20Words%20You%20Can%20Type.java) +200|[Contains Duplicate](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Contains%20Duplicate.java) +201|[Decode the Message](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Decode%20the%20Message.java) +202|[String Matching in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/String%20Matching%20in%20an%20Array.java) +203|[Count the Digits That Divide a Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20the%20Digits%20That%20Divide%20a%20Number.java) +204|[Distance Between Bus Stops](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Distance%20Between%20Bus%20Stops.java) +205|[Ugly Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Ugly%20Number.java) +206|[Faulty Keyboard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Faulty%20Keyboard.java) +207|[Find the Pivot Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Pivot%20Integer.java) +208|[Pascal's Triangle II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Pascal's%20Triangle%20II.java) +209|[Maximum Count of Positive Integer and Negative Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Count%20of%20Positive%20Integer%20and%20Negative%20Integer.java) +210|[Count Symmetric Integers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Symmetric%20Integers.java) +211|[Pascal's Triangle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Pascal's%20Triangle.java) +212|[Binary Prefix Divisible By 5](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Prefix%20Divisible%20By%205.java) +213|[Number Of Rectangles That Can Form The Largest Square](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20Of%20Rectangles%20That%20Can%20Form%20The%20Largest%20Square.java) +214|[Separate the Digits in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Separate%20the%20Digits%20in%20an%20Array.java) +215|[Count Negative Numbers in a Sorted Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Negative%20Numbers%20in%20a%20Sorted%20Matrix.java) +216|[Remove One Element to Make the Array Strictly Increasing](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20One%20Element%20to%20Make%20the%20Array%20Strictly%20Increasing.java) +217|[Two Furthest Houses With Different Colors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Two%20Furthest%20Houses%20With%20Different%20Colors.java) +218|[Special Positions in a Binary Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Special%20Positions%20in%20a%20Binary%20Matrix.java) +219|[Check if All Characters Have Equal Number of Occurrences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20All%20Characters%20Have%20Equal%20Number%20of%20Occurrences.java) +220|[Valid Word Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Word%20Sequence.java) +221|[Counting Words With a Given Prefix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Counting%20Words%20With%20a%20Given%20Prefix.java) +222|[Binary Tree Inorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Tree%20Inorder%20Traversal.java) +223|[Minimum Moves to Convert String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Moves%20to%20Convert%20String.java) +224|[Design Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20Linked%20List.java) +225|[Kth Distinct String in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Kth%20Distinct%20String%20in%20an%20Array.java) +226|[Count Good Triplets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Good%20Triplets.java) +227|[Design an Ordered System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20an%20Ordered%20System.java) +228|[Get Maximum in Generated Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Get%20Maximum%20in%20Generated%20Array.java) +229|[Convert the Temperature](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Convert%20the%20Temperature.java) +230|[Arranging Coins](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Arranging%20Coins.java) +231|[Count Pairs Whose Sum is Less than Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Pairs%20Whose%20Sum%20is%20Less%20than%20Target.java) +232|[Check if Word Equals Summation of Two Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Word%20Equals%20Summation%20of%20Two%20Words.java) +233|[Fair Candy Swap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Fair%20Candy%20Swap.java) +234|[Design Parking System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20Parking%20System.java) +235|[Transpose Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Transpose%20Matrix.java) +236|[Delete Greatest Value in Each Row](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Delete%20Greatest%20Value%20in%20Each%20Row.java) +237|[Excel Sheet Column Title](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Excel%20Sheet%20Column%20Title.java) +238|[First Letter to Appear Twice](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/First%20Letter%20to%20Appear%20Twice.java) +239|[Linked List Cycle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Linked%20List%20Cycle.java) +240|[Find All the Lonely Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20All%20the%20Lonely%20Nodes.java) +241|[Find the Maximum Achievable Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Maximum%20Achievable%20Number.java) +242|[Base 7](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Base%207.java) +243|[Reverse Bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20Bits.java) +244|[SqrtX](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/SqrtX.java) +245|[Check if Strings Can be Made Equal With Operations I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Strings%20Can%20be%20Made%20Equal%20With%20Operations%20I.java) +246|[Similar RGB Color](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Similar%20RGB%20Color.java) +247|[Sort the People](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sort%20the%20People.java) +248|[Is Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Is%20Subsequence.java) +249|[Longest Even Odd Subarray With Threshold](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Even%20Odd%20Subarray%20With%20Threshold.java) +250|[Reverse Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20Linked%20List.java) +251|[Shortest Distance to a Character](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Shortest%20Distance%20to%20a%20Character.java) +252|[Count of Matches in Tournament](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20of%20Matches%20in%20Tournament.java) +253|[Valid Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Parentheses.java) +254|[Convert Sorted Array To Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Convert%20Sorted%20Array%20To%20Binary%20Search%20Tree.java) +255|[Count Vowel Substrings of a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Vowel%20Substrings%20of%20a%20String.java) +256|[Construct the rectangle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Construct%20the%20rectangle.java) +257|[Maximum Units on a Truck](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Units%20on%20a%20Truck.java) +258|[Sum of Left Leaves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Left%20Leaves.java) +259|[Decrypt String from Alphabet to Integer Mapping](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Decrypt%20String%20from%20Alphabet%20to%20Integer%20Mapping.java) +260|[Number of Employees Who Met the Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Employees%20Who%20Met%20the%20Target.java) +261|[Find Pivot Index](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Pivot%20Index.java) +262|[Factorial Trailing Zeroes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Factorial%20Trailing%20Zeroes.java) +263|[Build an Array With Stack Operations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Build%20an%20Array%20With%20Stack%20Operations.java) +264|[Last Stone Weight](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Last%20Stone%20Weight.java) +265|[range_addition_II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/range_addition_II.java) +266|[Isomorphic Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Isomorphic%20Strings.java) +267|[Longest Subsequence With Limited Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Subsequence%20With%20Limited%20Sum.java) +268|[Split a String in Balanced Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Split%20a%20String%20in%20Balanced%20Strings.java) +269|[To Lower Case](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/To%20Lower%20Case.java) +270|[Sum of Digits of String After Convert](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Digits%20of%20String%20After%20Convert.java) +271|[Number of Senior Citizens](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Senior%20Citizens.java) +272|[Minimum Cost to Move Chips to The Same Position](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Cost%20to%20Move%20Chips%20to%20The%20Same%20Position.java) +273|[Read N characters Given Read4](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Read%20N%20characters%20Given%20Read4.java) +274|[Longest Alternating Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Alternating%20Subarray.java) +275|[Delete N Nodes After M Nodes of a Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Delete%20N%20Nodes%20After%20M%20Nodes%20of%20a%20Linked%20List.java) +276|[Count Items Matching a Rule](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Items%20Matching%20a%20Rule.java) +277|[Reverse Vowels of a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20Vowels%20of%20a%20String.java) +278|[Largest Local Values in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Local%20Values%20in%20a%20Matrix.java) +279|[A Number After a Double Reversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/A%20Number%20After%20a%20Double%20Reversal.java) +280|[Roman to Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Roman%20to%20Integer.java) +281|[Cousins in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Cousins%20in%20Binary%20Tree.java) +282|[Binary Tree Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Tree%20Paths.java) +283|[Complement of Base 10 Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Complement%20of%20Base%2010%20Integer.java) +284|[Find if Path Exists in Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20if%20Path%20Exists%20in%20Graph.java) +285|[Minimum Difference Between Highest and Lowest of K Scores](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Difference%20Between%20Highest%20and%20Lowest%20of%20K%20Scores.java) +286|[Number of Days in a Month](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Days%20in%20a%20Month.java) +287|[Find Resultant Array After Removing Anagrams](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Resultant%20Array%20After%20Removing%20Anagrams.java) +288|[Minimum String Length After Removing Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20String%20Length%20After%20Removing%20Substrings.java) +289|[Palindrome Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Palindrome%20Number.java) +290|[Find Subarrays With Equal Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Subarrays%20With%20Equal%20Sum.java) +291|[Account Balance After Rounded Purchase](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Account%20Balance%20After%20Rounded%20Purchase.java) +292|[Minimum Amount of Time to Fill Cups](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Amount%20of%20Time%20to%20Fill%20Cups.java) +293|[Detect Pattern of Length M Repeated K or More Times](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Detect%20Pattern%20of%20Length%20M%20Repeated%20K%20or%20More%20Times.java) +294|[Largest Positive Integer That Exists With Its Negative](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Positive%20Integer%20That%20Exists%20With%20Its%20Negative.java) +295|[Univalued Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Univalued%20Binary%20Tree.java) +296|[Single-Row Keyboard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Single-Row%20Keyboard.java) +297|[Remove Linked List Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Linked%20List%20Elements.java) +298|[How Many Numbers Are Smaller Than the Current Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/How%20Many%20Numbers%20Are%20Smaller%20Than%20the%20Current%20Number.java) +299|[Most Frequent Even Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Most%20Frequent%20Even%20Element.java) +300|[Maximum Odd Binary Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Odd%20Binary%20Number.java) +301|[Armstrong Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Armstrong%20Number.java) +302|[Counting Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Counting%20Elements.java) +303|[Make The String Great](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Make%20The%20String%20Great.java) +304|[Cells with Odd Values in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Cells%20with%20Odd%20Values%20in%20a%20Matrix.java) +305|[Power of Two](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Power%20of%20Two.java) +306|[Decode XORed Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Decode%20XORed%20Array.java) +307|[Long Pressed Name](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Long%20Pressed%20Name.java) +308|[Kids With the Greatest Number of Candies](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Kids%20With%20the%20Greatest%20Number%20of%20Candies.java) +309|[N-ary Tree Postorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/N-ary%20Tree%20Postorder%20Traversal.java) +310|[Max Consecutive Ones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Max%20Consecutive%20Ones.java) +311|[Find Words That Can Be Formed by Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Words%20That%20Can%20Be%20Formed%20by%20Characters.java) +312|[Number of 1 bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%201%20bits.java) +313|[Largest Unique Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Unique%20Number.java) +314|[The Employee That Worked on the Longest Task](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/The%20Employee%20That%20Worked%20on%20the%20Longest%20Task.java) +315|[Paint House](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Paint%20House.java) +316|[Logger Rate Limiter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Logger%20Rate%20Limiter.java) +317|[Substrings of Size Three with Distinct Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Substrings%20of%20Size%20Three%20with%20Distinct%20Characters.java) +318|[Maximum Difference by Remapping a Digit](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Difference%20by%20Remapping%20a%20Digit.java) +319|[Monotonic Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Monotonic%20Array.java) +320|[Check if One String Swap Can Make Strings Equal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20One%20String%20Swap%20Can%20Make%20Strings%20Equal.java) +321|[Valid Palindrome II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Palindrome%20II.java) +322|[Occurrences After Bigram](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Occurrences%20After%20Bigram.java) +323|[Minimum Sum of Four Digit Number After Splitting Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Sum%20of%20Four%20Digit%20Number%20After%20Splitting%20Digits.java) +324|[Move Zeroes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Move%20Zeroes.java) +325|[Number of Arithmetic Triplets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Arithmetic%20Triplets.java) +326|[Count Number of Pairs With Absolute Difference K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Number%20of%20Pairs%20With%20Absolute%20Difference%20K.java) +327|[Number of Lines To Write String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Lines%20To%20Write%20String.java) +328|[First Unique Character in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/First%20Unique%20Character%20in%20a%20String.java) +329|[Maximum depth of Binary tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20depth%20of%20Binary%20tree.java) +330|[Largest Number At Least Twice of Others](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Number%20At%20Least%20Twice%20of%20Others.java) +331|[Reverse String II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20String%20II.java) +332|[Letter Case Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Letter%20Case%20Permutation.java) +333|[Two Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Two%20Sum.java) +334|[Climbing Stairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Climbing%20Stairs.java) +335|[Projection Area of 3D Shapes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Projection%20Area%20of%203D%20Shapes.java) +336|[Maximize Sum Of Array After K Negations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximize%20Sum%20Of%20Array%20After%20K%20Negations.java) +337|[Third Maximum Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Third%20Maximum%20Number.java) +338|[Sign of the Product of an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sign%20of%20the%20Product%20of%20an%20Array.java) +339|[Heaters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Heaters.java) +340|[Remove Palindromic Subsequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Palindromic%20Subsequences.java) +341|[Time Needed to Buy Tickets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Time%20Needed%20to%20Buy%20Tickets.java) +342|[Find the K-Beauty of a Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20K-Beauty%20of%20a%20Number.java) +343|[Find All K-Distant Indices in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20All%20K-Distant%20Indices%20in%20an%20Array.java) +344|[Student Attendance Record I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Student%20Attendance%20Record%20I.java) +345|[Delete Characters to Make Fancy String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Delete%20Characters%20to%20Make%20Fancy%20String.java) +346|[Longest Uncommon Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Uncommon%20Subsequence.java) +347|[Check Distances Between Same Letters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20Distances%20Between%20Same%20Letters.java) +348|[Valid Mountain Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Mountain%20Array.java) +349|[Shortest Word Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Shortest%20Word%20Distance.java) +350|[Check if String Is Decomposable Into Value-Equal Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20String%20Is%20Decomposable%20Into%20Value-Equal%20Substrings.java) +351|[Matrix Cells in Distance Order](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Matrix%20Cells%20in%20Distance%20Order.java) +352|[Final Value of Variable After Performing Operations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Final%20Value%20of%20Variable%20After%20Performing%20Operations.java) +353|[Shuffle String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Shuffle%20String.java) +354|[Sum of Square Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Square%20Numbers.java) +355|[Percentage of Letter in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Percentage%20of%20Letter%20in%20String.java) +356|[Intersection of Two Arrays II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Intersection%20of%20Two%20Arrays%20II.java) +357|[Most Common Word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Most%20Common%20Word.java) +358|[Count Asterisks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Asterisks.java) +359|[Sum of Squares of Special Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Squares%20of%20Special%20Elements.java) +360|[Largest 3-Same-Digit Number in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%203-Same-Digit%20Number%20in%20String.java) +361|[Number of Students Doing Homework at a Given Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Students%20Doing%20Homework%20at%20a%20Given%20Time.java) +362|[Invert Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Invert%20Binary%20Tree.java) +363|[Check if the Sentence Is Pangram](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20the%20Sentence%20Is%20Pangram.java) +364|[Island Perimeter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Island%20Perimeter.java) +365|[Available Captures for Rook](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Available%20Captures%20for%20Rook.java) +366|[Count Common Words With One Occurrence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Common%20Words%20With%20One%20Occurrence.java) +367|[Degree of an array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Degree%20of%20an%20array.java) +368|[Sum of Root To Leaf Binary Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Root%20To%20Leaf%20Binary%20Numbers.java) +369|[Circular Sentence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Circular%20Sentence.java) +370|[Sort Array By Parity](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sort%20Array%20By%20Parity.java) +371|[Number of Good Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Good%20Pairs.java) +372|[Convert a number to hexadecimal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Convert%20a%20number%20to%20hexadecimal.java) +373|[Check If a Word Occurs As a Prefix of Any Word in a Sentence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20If%20a%20Word%20Occurs%20As%20a%20Prefix%20of%20Any%20Word%20in%20a%20Sentence.java) +374|[Calculate Delayed Arrival Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Calculate%20Delayed%20Arrival%20Time.java) +375|[Concatenation of Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Concatenation%20of%20Array.java) +376|[Number of Recent Calls](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Recent%20Calls.java) +377|[Fixed Point](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Fixed%20Point.java) +378|[Valid Boomerang](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Boomerang.java) +379|[Minimum Moves to Equal an Array Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Moves%20to%20Equal%20an%20Array%20Element.java) +380|[Calculate Money in Leetcode Bank](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Calculate%20Money%20in%20Leetcode%20Bank.java) +381|[Check If Two String Arrays are Equivalent](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20If%20Two%20String%20Arrays%20are%20Equivalent.java) +382|[Find Nearest Point That Has the Same X or Y Coordinate](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Nearest%20Point%20That%20Has%20the%20Same%20X%20or%20Y%20Coordinate.java) +383|[Maximum Product Difference Between Two Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Product%20Difference%20Between%20Two%20Pairs.java) +384|[Goal Parser Interpretation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Goal%20Parser%20Interpretation.java) +385|[Find the Losers of the Circular Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Losers%20of%20the%20Circular%20Game.java) +386|[Judge Route Cycle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Judge%20Route%20Cycle.java) +387|[K Items With the Maximum Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/K%20Items%20With%20the%20Maximum%20Sum.java) +388|[Middle of the linked list](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Middle%20of%20the%20linked%20list.java) +389|[Maximum Number of Pairs in Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Number%20of%20Pairs%20in%20Array.java) +390|[Check if Matrix Is X-Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Matrix%20Is%20X-Matrix.java) +391|[Compare Strings by Frequency of the Smallest Character](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Compare%20Strings%20by%20Frequency%20of%20the%20Smallest%20Character.java) +392|[Intersection of Two Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Intersection%20of%20Two%20Arrays.java) +393|[Bulls and Cows](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Bulls%20and%20Cows.java) +394|[Slowest Key](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Slowest%20Key.java) +395|[Count Equal and Divisible Pairs in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Equal%20and%20Divisible%20Pairs%20in%20an%20Array.java) +396|[nim_game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/nim_game.java) +397|[Min Max Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Min%20Max%20Game.java) +398|[Groups of Special-Equivalent Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Groups%20of%20Special-Equivalent%20Strings.java) +399|[Reformat The String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reformat%20The%20String.java) +400|[Minimum Number of Operations to Convert Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Number%20of%20Operations%20to%20Convert%20Time.java) +401|[Form Smallest Number From Two Digit Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Form%20Smallest%20Number%20From%20Two%20Digit%20Arrays.java) +402|[Minimum Operations to Collect Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Operations%20to%20Collect%20Elements.java) +403|[Count Elements With Strictly Smaller and Greater Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Elements%20With%20Strictly%20Smaller%20and%20Greater%20Elements.java) +404|[Determine the Winner of a Bowling Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Determine%20the%20Winner%20of%20a%20Bowling%20Game.java) +405|[Minimum Operations to Make the Array Increasing](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Operations%20to%20Make%20the%20Array%20Increasing.java) +406|[Minimum Right Shifts to Sort the Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Right%20Shifts%20to%20Sort%20the%20Array.java) +407|[Index Pairs of a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Index%20Pairs%20of%20a%20String.java) +408|[Number of Steps to Reduce a Number to Zero](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Steps%20to%20Reduce%20a%20Number%20to%20Zero.java) +409|[Confusing Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Confusing%20Number.java) +410|[Convert BST to Greater Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Convert%20BST%20to%20Greater%20Tree.java) +411|[Find All Numbers Disappeared in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20All%20Numbers%20Disappeared%20in%20an%20Array.java) +412|[Largest Number After Digit Swaps by Parity](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Number%20After%20Digit%20Swaps%20by%20Parity.java) +413|[Merge Two 2D Arrays by Summing Values](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Merge%20Two%202D%20Arrays%20by%20Summing%20Values.java) +414|[Reformat Date](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reformat%20Date.java) +415|[Largest Odd Number in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Odd%20Number%20in%20String.java) +416|[Build Array from Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Build%20Array%20from%20Permutation.java) +417|[Find Lucky Integer in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Lucky%20Integer%20in%20an%20Array.java) +418|[Reverse Prefix of Word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20Prefix%20of%20Word.java) +419|[Nested List Weight Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Nested%20List%20Weight%20Sum.java) +420|[Relative ranks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Relative%20ranks.java) +421|[Palindrome Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Palindrome%20Permutation.java) +422|[Find Winner on a Tic Tac Toe Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Winner%20on%20a%20Tic%20Tac%20Toe%20Game.java) +423|[Merge two binary trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Merge%20two%20binary%20trees.java) +424|[Check if Numbers Are Ascending in a Sentence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Numbers%20Are%20Ascending%20in%20a%20Sentence.java) +425|[Power of Three](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Power%20of%20Three.java) +426|[Remove Letter To Equalize Frequency](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Letter%20To%20Equalize%20Frequency.java) +427|[Lemonade Change](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Lemonade%20Change.java) +428|[Length of last word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Length%20of%20last%20word.java) +429|[Increasing Decreasing String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Increasing%20Decreasing%20String.java) +430|[N-th Tribonacci Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/N-th%20Tribonacci%20Number.java) +431|[Longest Common Prefix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Common%20Prefix.java) +432|[Minimum Time Visiting All Points](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Time%20Visiting%20All%20Points.java) +433|[Calculate Amount Paid in Taxes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Calculate%20Amount%20Paid%20in%20Taxes.java) +434|[Number of Different Integers in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Different%20Integers%20in%20a%20String.java) +435|[Minimize String Length](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimize%20String%20Length.java) +436|[Add Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Add%20Strings.java) +437|[Maximum Ascending Subarray Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Ascending%20Subarray%20Sum.java) +438|[Best Time to Buy and Sell Stock](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Best%20Time%20to%20Buy%20and%20Sell%20Stock.java) +439|[Lowest Common Ancestor of a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Lowest%20Common%20Ancestor%20of%20a%20Binary%20Search%20Tree.java) +440|[Determine if String Halves Are Alike](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Determine%20if%20String%20Halves%20Are%20Alike.java) +441|[Find the difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20difference.java) +442|[Check if Every Row and Column Contains All Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Every%20Row%20and%20Column%20Contains%20All%20Numbers.java) +443|[Replace All Digits with Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Replace%20All%20Digits%20with%20Characters.java) +444|[Largest Substring Between Two Equal Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Largest%20Substring%20Between%20Two%20Equal%20Characters.java) +445|[Strobogrammatic Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Strobogrammatic%20Number.java) +446|[Rearrange Characters to Make Target String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Rearrange%20Characters%20to%20Make%20Target%20String.java) +447|[Next Greater Element I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Next%20Greater%20Element%20I.java) +448|[Counting Bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Counting%20Bits.java) +449|[Remove Outermost Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Outermost%20Parentheses.java) +450|[Count the Number of Vowel Strings in Range](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20the%20Number%20of%20Vowel%20Strings%20in%20Range.java) +451|[Determine if Two Events Have Conflict](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Determine%20if%20Two%20Events%20Have%20Conflict.java) +452|[Replace All ?'s to Avoid Consecutive Repeating Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Replace%20All%20?'s%20to%20Avoid%20Consecutive%20Repeating%20Characters.java) +453|[Two Sum Less Than K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Two%20Sum%20Less%20Than%20K.java) +454|[Majority Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Majority%20Element.java) +455|[Merge Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Merge%20Sorted%20Array.java) +456|[Unique Morse Code Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Unique%20Morse%20Code%20Words.java) +457|[Divisor Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Divisor%20Game.java) +458|[Find Numbers with Even Number of Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Numbers%20with%20Even%20Number%20of%20Digits.java) +459|[Categorize Box According to Criteria](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Categorize%20Box%20According%20to%20Criteria.java) +460|[Implement Queue using Stacks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Implement%20Queue%20using%20Stacks.java) +461|[N-ary Tree Preorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/N-ary%20Tree%20Preorder%20Traversal.java) +462|[Smallest Index With Equal Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Smallest%20Index%20With%20Equal%20Value.java) +463|[Total Distance Traveled](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Total%20Distance%20Traveled.java) +464|[Delete Node in a Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Delete%20Node%20in%20a%20Linked%20List.java) +465|[Sort Array By Parity II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sort%20Array%20By%20Parity%20II.java) +466|[Most Visited Sector in a Circular Track](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Most%20Visited%20Sector%20in%20a%20Circular%20Track.java) +467|[Greatest Common Divisor of Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Greatest%20Common%20Divisor%20of%20Strings.java) +468|[Remove Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Element.java) +469|[Maximum Subarray Sum I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Subarray%20Sum%20I.java) +470|[Partition Array Into Three Parts With Equal Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Partition%20Array%20Into%20Three%20Parts%20With%20Equal%20Sum.java) +471|[Remove Duplicates From Sorted Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Duplicates%20From%20Sorted%20Lists.java) +472|[Minimum Bit Flips to Convert Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Bit%20Flips%20to%20Convert%20Number.java) +473|[Sort Even and Odd Indices Independently](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sort%20Even%20and%20Odd%20Indices%20Independently.java) +474|[Meeting Rooms](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Meeting%20Rooms.java) +475|[Crawler Log Folder](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Crawler%20Log%20Folder.java) +476|[Maximum Difference Between Increasing Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Difference%20Between%20Increasing%20Elements.java) +477|[Left and Right Sum Differences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Left%20and%20Right%20Sum%20Differences.java) +478|[Find the Middle Index in Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Middle%20Index%20in%20Array.java) +479|[Range Sum Query Immutable](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Range%20Sum%20Query%20Immutable.java) +480|[Intersection of two Linked Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Intersection%20of%20two%20Linked%20Lists.java) +481|[Merge Similar Items](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Merge%20Similar%20Items.java) +482|[Can Place Flowers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Can%20Place%20Flowers.java) +483|[Generate a String With Characters That Have Odd Counts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Generate%20a%20String%20With%20Characters%20That%20Have%20Odd%20Counts.java) +484|[Count Operations to Obtain Zero](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Operations%20to%20Obtain%20Zero.java) +485|[Array Partition I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Array%20Partition%20I.java) +486|[Next Greater Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Next%20Greater%20Element.java) +487|[Perfect Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Perfect%20Number.java) +488|[Sum of Digits in the Minimum Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Digits%20in%20the%20Minimum%20Number.java) +489|[Guess Number Higher or Lower](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Guess%20Number%20Higher%20or%20Lower.java) +490|[Find the Array Concatenation Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Array%20Concatenation%20Value.java) +491|[Self Dividing Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Self%20Dividing%20Number.java) +492|[Design HashMap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20HashMap.java) +493|[Minimum Time to Type Word Using Special Typewriter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Time%20to%20Type%20Word%20Using%20Special%20Typewriter.java) +494|[Check Whether Two Strings are Almost Equivalent](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20Whether%20Two%20Strings%20are%20Almost%20Equivalent.java) +495|[Shortest Distance to Target String in a Circular Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Shortest%20Distance%20to%20Target%20String%20in%20a%20Circular%20Array.java) +496|[Cells in a Range on an Excel Sheet](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Cells%20in%20a%20Range%20on%20an%20Excel%20Sheet.java) +497|[Number of Common Factors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Common%20Factors.java) +498|[Keep Multiplying Found Values by Two](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Keep%20Multiplying%20Found%20Values%20by%20Two.java) +499|[Search in a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Search%20in%20a%20Binary%20Search%20Tree.java) +500|[Count Largest Group](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Largest%20Group.java) +501|[Sum of Unique Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Unique%20Elements.java) +502|[Moving Average from Data Stream](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Moving%20Average%20from%20Data%20Stream.java) +503|[Symmetric Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Symmetric%20Tree.java) +504|[Maximum Product of Two Elements in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Product%20of%20Two%20Elements%20in%20an%20Array.java) +505|[Difference Between Element Sum and Digit Sum of an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Difference%20Between%20Element%20Sum%20and%20Digit%20Sum%20of%20an%20Array.java) +506|[Find Common Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Common%20Characters.java) +507|[Lucky Numbers in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Lucky%20Numbers%20in%20a%20Matrix.java) +508|[Remove Vowels from a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20Vowels%20from%20a%20String.java) +509|[Add Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Add%20Digits.java) +510|[Teemo Attacking](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Teemo%20Attacking.java) +511|[Contains Duplicate II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Contains%20Duplicate%20II.java) +512|[Count Integers With Even Digit Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Integers%20With%20Even%20Digit%20Sum.java) +513|[Minimum Index Sum of Two Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Index%20Sum%20of%20Two%20Lists.java) +514|[Two Out of Three](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Two%20Out%20of%20Three.java) +515|[Closest Binary Search Tree Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Closest%20Binary%20Search%20Tree%20Value.java) +516|[Distribute Money to Maximum Children](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Distribute%20Money%20to%20Maximum%20Children.java) +517|[Sum of Digits in Base K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20Digits%20in%20Base%20K.java) +518|[Fibonacci Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Fibonacci%20Number.java) +519|[Distribute Candies to People](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Distribute%20Candies%20to%20People.java) +520|[Valid Word Square](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Word%20Square.java) +521|[Distribute Candies](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Distribute%20Candies.java) +522|[Check If a Number Is Majority Element in a Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20If%20a%20Number%20Is%20Majority%20Element%20in%20a%20Sorted%20Array.java) +523|[Alternating Digit Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Alternating%20Digit%20Sum.java) +524|[Take Gifts From the Richest Pile](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Take%20Gifts%20From%20the%20Richest%20Pile.java) +525|[Verifying an Alien Dictionary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Verifying%20an%20Alien%20Dictionary.java) +526|[Longest Palindrome](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Palindrome.java) +527|[Sum of All Odd Length Subarrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20of%20All%20Odd%20Length%20Subarrays.java) +528|[Average Salary Excluding the Minimum and Maximum Salary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Average%20Salary%20Excluding%20the%20Minimum%20and%20Maximum%20Salary.java) +529|[Apply Operations to an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Apply%20Operations%20to%20an%20Array.java) +530|[Single Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Single%20Number.java) +531|[Keyboard Row](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Keyboard%20Row.java) +532|[Count Distinct Numbers on Board](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Distinct%20Numbers%20on%20Board.java) +533|[Squares of a Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Squares%20of%20a%20Sorted%20Array.java) +534|[Find the Longest Balanced Substring of a Binary String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Longest%20Balanced%20Substring%20of%20a%20Binary%20String.java) +535|[Binary Tree Postorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Binary%20Tree%20Postorder%20Traversal.java) +536|[Rearrange Spaces Between Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Rearrange%20Spaces%20Between%20Words.java) +537|[Minimum Recolors to Get K Consecutive Black Blocks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Recolors%20to%20Get%20K%20Consecutive%20Black%20Blocks.java) +538|[Count Square Sum Triples](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Square%20Sum%20Triples.java) +539|[Maximum Distance in Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Distance%20in%20Arrays.java) +540|[Unique Number of Occurrences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Unique%20Number%20of%20Occurrences.java) +541|[Day of the Week](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Day%20of%20the%20Week.java) +542|[Design an Ordered Stream](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20an%20Ordered%20Stream.java) +543|[Minimum Distance Between BST Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Distance%20Between%20BST%20Nodes.java) +544|[Maximum Sum With Exactly K Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Sum%20With%20Exactly%20K%20Elements.java) +545|[Number of Students Unable to Eat Lunch](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Number%20of%20Students%20Unable%20to%20Eat%20Lunch.java) +546|[Check if Number Has Equal Digit Count and Digit Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20Number%20Has%20Equal%20Digit%20Count%20and%20Digit%20Value.java) +547|[Sum Of Two Integers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sum%20Of%20Two%20Integers.java) +548|[Check if a String Is an Acronym of Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20if%20a%20String%20Is%20an%20Acronym%20of%20Words.java) +549|[Search Insert Position](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Search%20Insert%20Position.java) +550|[Max Pair Sum in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Max%20Pair%20Sum%20in%20an%20Array.java) +551|[Longest Univalue Path](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Univalue%20Path.java) +552|[Maximum Depth of N-ary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Depth%20of%20N-ary%20Tree.java) +553|[Thousand Separator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Thousand%20Separator.java) +554|[Add Binary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Add%20Binary.java) +555|[Convert Binary Number in a Linked List to Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Convert%20Binary%20Number%20in%20a%20Linked%20List%20to%20Integer.java) +556|[Sorting the Sentence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sorting%20the%20Sentence.java) +557|[Replace Elements with Greatest Element on Right Side](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Replace%20Elements%20with%20Greatest%20Element%20on%20Right%20Side.java) +558|[Matrix Diagonal Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Matrix%20Diagonal%20Sum.java) +559|[Check Array Formation Through Concatenation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Check%20Array%20Formation%20Through%20Concatenation.java) +560|[Water Bottles](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Water%20Bottles.java) +561|[Add to Array-Form of Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Add%20to%20Array-Form%20of%20Integer.java) +562|[Prime In Diagonal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Prime%20In%20Diagonal.java) +563|[Pass the Pillow](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Pass%20the%20Pillow.java) +564|[Missing Number In Arithmetic Progression](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Missing%20Number%20In%20Arithmetic%20Progression.java) +565|[Divide Array Into Equal Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Divide%20Array%20Into%20Equal%20Pairs.java) +566|[Maximum Value of a String in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Value%20of%20a%20String%20in%20an%20Array.java) +567|[Maximum Number of Balls in a Box](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Number%20of%20Balls%20in%20a%20Box.java) +568|[Mean of Array After Removing Some Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Mean%20of%20Array%20After%20Removing%20Some%20Elements.java) +569|[N-Repeated Element in Size 2N Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/N-Repeated%20Element%20in%20Size%202N%20Array.java) +570|[Redistribute Characters to Make All Strings Equal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Redistribute%20Characters%20to%20Make%20All%20Strings%20Equal.java) +571|[Remove All Adjacent Duplicates In String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Remove%20All%20Adjacent%20Duplicates%20In%20String.java) +572|[Minimum Absolute Difference in BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20%20Absolute%20Difference%20in%20BST.java) +573|[Image Smoother](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Image%20Smoother.java) +574|[Find the Difference of Two Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20the%20Difference%20of%20Two%20Arrays.java) +575|[How Many Apples Can You Put into the Basket](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/How%20Many%20Apples%20Can%20You%20Put%20into%20the%20Basket.java) +576|[Second Minimum Node in a binary tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Second%20Minimum%20Node%20in%20a%20binary%20tree.java) +577|[Excel Sheet Column Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Excel%20Sheet%20Column%20Number.java) +578|[Same Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Same%20Tree.java) +579|[Count Odd Numbers in an Interval Range](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Odd%20Numbers%20in%20an%20Interval%20Range.java) +580|[String Without AAA or BBB](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/String%20Without%20AAA%20or%20BBB.java) +581|[Find Greatest Common Divisor of Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Greatest%20Common%20Divisor%20of%20Array.java) +582|[Longest Word in Dictionary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Longest%20Word%20in%20Dictionary.java) +583|[Happy Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Happy%20Number.java) +584|[Array Transformation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Array%20Transformation.java) +585|[Design Compressed String Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Design%20Compressed%20String%20Iterator.java) +586|[Reverse words in a String III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Reverse%20words%20in%20a%20String%20III.java) +587|[Rank Transform of an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Rank%20Transform%20of%20an%20Array.java) +588|[First Bad Version](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/First%20Bad%20Version.java) +589|[Sort Integers by The Number of 1 Bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Sort%20Integers%20by%20The%20Number%20of%201%20Bits.java) +590|[Split With Minimum Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Split%20With%20Minimum%20Sum.java) +591|[Construct String from Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Construct%20String%20from%20Binary%20Tree.java) +592|[Maximum Number of Words Found in Sentences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Maximum%20Number%20of%20Words%20Found%20in%20Sentences.java) +593|[Toeplitz Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Toeplitz%20Matrix.java) +594|[Find Maximum Number of String Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Find%20Maximum%20Number%20of%20String%20Pairs.java) +595|[Finding 3-Digit Even Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Finding%203-Digit%20Even%20Numbers.java) +596|[Valid Word Abbreviation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Word%20Abbreviation.java) +597|[Second Largest Digit in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Second%20Largest%20Digit%20in%20a%20String.java) +598|[Valid Palindrome](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Valid%20Palindrome.java) +599|[Relative Sort Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Relative%20Sort%20Array.java) +600|[Minimum Cuts to Divide a Circle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Minimum%20Cuts%20to%20Divide%20a%20Circle.java) +601|[Path In Zigzag Labelled Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Path%20In%20Zigzag%20Labelled%20Binary%20Tree.java) +602|[Shortest Completing Word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Shortest%20Completing%20Word.java) +603|[Nim Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Nim%20Game.java) +604|[Count Substrings with Only One Distinct Letter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Count%20Substrings%20with%20Only%20One%20Distinct%20Letter.java) +605|[Average of Levels in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Average%20of%20Levels%20in%20Binary%20Tree.java) +606|[Merge Strings Alternately](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Easy/Merge%20Strings%20Alternately.java) diff --git a/Easy/Range Sum Query Immutable.java b/Easy/Range Sum Query Immutable.java new file mode 100644 index 00000000..5318818c --- /dev/null +++ b/Easy/Range Sum Query Immutable.java @@ -0,0 +1,23 @@ +class NumArray { + + int[] sumArray; + + public NumArray(int[] nums) { + sumArray = new int[nums.length]; + int currSum = 0; + for (int i = 0; i < nums.length; i++) { + currSum += nums[i]; + sumArray[i] = currSum; + } + } + + public int sumRange(int left, int right) { + return sumArray[right] - (left == 0 ? 0 : sumArray[left - 1]); + } +} + +/** + * Your NumArray object will be instantiated and called as such: + * NumArray obj = new NumArray(nums); + * int param_1 = obj.sumRange(left,right); + */ diff --git a/Easy/Range Sum Query_Immutable.java b/Easy/Range Sum Query_Immutable.java deleted file mode 100644 index 14c50db7..00000000 --- a/Easy/Range Sum Query_Immutable.java +++ /dev/null @@ -1,24 +0,0 @@ -class NumArray { - int[] nums; - - public NumArray(int[] nums) { - for(int i = 1; i < nums.length; i++) - nums[i] += nums[i - 1]; - - this.nums = nums; - } - - public int sumRange(int i, int j) { - if(i == 0) - return nums[j]; - - return nums[j] - nums[i - 1]; - } - -} - -/** - * Your NumArray object will be instantiated and called as such: - * NumArray obj = new NumArray(nums); - * int param_1 = obj.sumRange(i,j); - */ diff --git a/Easy/Range Sum of BST.java b/Easy/Range Sum of BST.java new file mode 100644 index 00000000..3ed8dfdd --- /dev/null +++ b/Easy/Range Sum of BST.java @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int rangeSumBST(TreeNode root, int low, int high) { + int sum = 0; + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + TreeNode removed = queue.remove(); + if (removed.val >= low && removed.val <= high) { + sum += removed.val; + } + if (removed.val >= low && removed.left != null) { + queue.add(removed.left); + } + if (removed.val <= high && removed.right != null) { + queue.add(removed.right); + } + } + return sum; + } +} diff --git a/Easy/Rank Transform of an Array.java b/Easy/Rank Transform of an Array.java new file mode 100644 index 00000000..3f9192fd --- /dev/null +++ b/Easy/Rank Transform of an Array.java @@ -0,0 +1,19 @@ +class Solution { + public int[] arrayRankTransform(int[] arr) { + int[] copyArr = Arrays.copyOf(arr, arr.length); + Arrays.sort(arr); + int rank = 1; + Map numToRank = new HashMap<>(); + for (int num : arr) { + if (numToRank.containsKey(num)) { + continue; + } + numToRank.put(num, rank++); + } + int[] result = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + result[i] = numToRank.get(copyArr[i]); + } + return result; + } +} diff --git a/Easy/Ransom Note.java b/Easy/Ransom Note.java index 9536cf51..21a532c5 100644 --- a/Easy/Ransom Note.java +++ b/Easy/Ransom Note.java @@ -1,35 +1,15 @@ class Solution { - public boolean canConstruct(String ransomNote, String magazine) { - Map noteMap = new HashMap<>(); - Map magMap = new HashMap<>(); - - for(char c: ransomNote.toCharArray()) { - if (noteMap.containsKey(c)) { - noteMap.put(c, noteMap.get(c) + 1); - } - else { - noteMap.put(c, 1); - } - } - - for(char c: magazine.toCharArray()) { - if (magMap.containsKey(c)) { - magMap.put(c, magMap.get(c) + 1); - } - else { - magMap.put(c, 1); - } - } - - for (Map.Entry entry: noteMap.entrySet()) { - if (magMap.containsKey(entry.getKey()) && magMap.get(entry.getKey()) >= entry.getValue()) { - continue; - } - else { - return false; - } - } - - return true; + public boolean canConstruct(String ransomNote, String magazine) { + int[] count = new int[26]; + for (char c : magazine.toCharArray()) { + count[c - 'a']++; } + for (char c: ransomNote.toCharArray()) { + if (count[c - 'a'] == 0) { + return false; + } + count[c - 'a']--; + } + return true; + } } diff --git a/Easy/Read N characters Given Read4.java b/Easy/Read N characters Given Read4.java index 69eae7c2..d8507075 100644 --- a/Easy/Read N characters Given Read4.java +++ b/Easy/Read N characters Given Read4.java @@ -1,26 +1,28 @@ -/* The read4 API is defined in the parent class Reader4. - int read4(char[] buf); */ +/** + * The read4 API is defined in the parent class Reader4. + * int read4(char[] buf4); + */ public class Solution extends Reader4 { - /** - * @param buf Destination buffer - * @param n Maximum number of characters to read - * @return The number of characters read - */ - public int read(char[] buf, int n) { - int count = 0; - int total = 0; - int read = 4; - while(total <= n && read == 4){ - char[] temp = new char[4]; - read = read4(temp); - total += read; - - for(int i = 0; i < read && count < n; i++) { - buf[count++] = temp[i]; - } + /** + * @param buf Destination buffer + * @param n Number of characters to read + * @return The number of actual characters read + */ + public int read(char[] buf, int n) { + int copied = 0; + int readLength = 4; + char[] buf4 = new char[4]; + while (copied < n && readLength == 4) { + readLength = read4(buf4); + for (int i = 0; i < readLength; i++) { + if (copied == n) { + return copied; } - - return count; + buf[copied] = buf4[i]; + copied++; + } } + return copied; + } } diff --git a/Easy/Rearrange Characters to Make Target String.java b/Easy/Rearrange Characters to Make Target String.java new file mode 100644 index 00000000..352e45f9 --- /dev/null +++ b/Easy/Rearrange Characters to Make Target String.java @@ -0,0 +1,17 @@ +class Solution { + public int rearrangeCharacters(String s, String target) { + int[] frequencyS = new int[26]; + int[] frequencyTarget = new int[26]; + for(char ch : s.toCharArray()) { + frequencyS[ch-'a']++; + } + for(char ch : target.toCharArray()) { + frequencyTarget[ch-'a']++; + } + int maxCopies = Integer.MAX_VALUE; + for(char ch : target.toCharArray()) { + maxCopies = Math.min(maxCopies, frequencyS[ch - 'a'] / frequencyTarget[ch - 'a']); + } + return maxCopies; + } +} diff --git a/Easy/Rearrange Spaces Between Words.java b/Easy/Rearrange Spaces Between Words.java new file mode 100644 index 00000000..25cc28e2 --- /dev/null +++ b/Easy/Rearrange Spaces Between Words.java @@ -0,0 +1,34 @@ +class Solution { + public String reorderSpaces(String text) { + int totalSpaces = 0; + StringBuilder sb = new StringBuilder(); + List words = new ArrayList<>(); + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (c == ' ') { + totalSpaces++; + if (sb.length() > 0) { + words.add(sb.toString()); + sb.setLength(0); + } + } + else { + sb.append(c); + } + if (i == text.length() - 1 && sb.length() > 0) { + words.add(sb.toString()); + sb.setLength(0); + } + } + int batchSize = totalSpaces / (words.size() > 1 ? (words.size() - 1) : 1); + int remainingSpace = words.size() > 1 ? totalSpaces % (words.size() - 1) : totalSpaces; + String space = String.join("", Collections.nCopies(batchSize, " ")); + sb.append(words.get(0)); + for (int i = 1; i < words.size(); i++) { + sb.append(space.toString()); + sb.append(words.get(i)); + } + sb.append(String.join("", Collections.nCopies(remainingSpace, " "))); + return sb.toString(); + } +} diff --git a/Easy/Rectangle Overlap.java b/Easy/Rectangle Overlap.java new file mode 100644 index 00000000..cd471934 --- /dev/null +++ b/Easy/Rectangle Overlap.java @@ -0,0 +1,6 @@ +class Solution { + public boolean isRectangleOverlap(int[] rec1, int[] rec2) { + return (Math.min(rec1[2], rec2[2]) > Math.max(rec1[0], rec2[0]) && + Math.min(rec1[3], rec2[3]) > Math.max(rec1[1], rec2[1])); + } +} diff --git a/Easy/Redistribute Characters to Make All Strings Equal.java b/Easy/Redistribute Characters to Make All Strings Equal.java new file mode 100644 index 00000000..e034cce7 --- /dev/null +++ b/Easy/Redistribute Characters to Make All Strings Equal.java @@ -0,0 +1,10 @@ +class Solution { + public boolean makeEqual(String[] words) { + return Arrays.stream(words) + .reduce((a, b) -> a + b).orElse("") // Merge all strings + .chars().mapToObj(c -> (char) c) + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())) // Build a frequency map + .values().stream() + .allMatch(v -> v % words.length == 0); // Predicate logic to check frequency of each character + } +} diff --git a/Easy/Reformat Date.java b/Easy/Reformat Date.java new file mode 100644 index 00000000..2230d7a6 --- /dev/null +++ b/Easy/Reformat Date.java @@ -0,0 +1,22 @@ +class Solution { + private static final String[] MONTHS = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + public String reformatDate(String date) { + String[] split = date.split("\\s+"); + StringBuilder sb = new StringBuilder(); + sb.append(split[2]).append("-"); + int monthIdx = getMonthIdx(split[1]); + sb.append(monthIdx > 9 ? "" : "0").append(monthIdx).append("-"); + sb.append(Character.isDigit(split[0].charAt(1)) ? split[0].substring(0, 2) : ("0" + split[0].charAt(0))); + return sb.toString(); + } + + private int getMonthIdx(String month) { + for (int i = 0; i < MONTHS.length; i++) { + if (month.equals(MONTHS[i])) { + return i + 1; + } + } + return -1; + } +} diff --git a/Easy/Reformat Phone Number.java b/Easy/Reformat Phone Number.java new file mode 100644 index 00000000..a2f9dfa6 --- /dev/null +++ b/Easy/Reformat Phone Number.java @@ -0,0 +1,29 @@ +class Solution { + public String reformatNumber(String number) { + List digits = number.chars().mapToObj(c -> (char) c).filter(Character::isDigit) + .collect(Collectors.toList()); + StringBuilder sb = new StringBuilder(); + int remainingCharacter = digits.size(); + int idx = 0; + while (remainingCharacter > 4) { + for (int i = 0; i < 3; i++) { + sb.append(digits.get(idx++)); + } + remainingCharacter -= 3; + sb.append("-"); + } + if (remainingCharacter > 3) { + for (int i = 0; i < 4; i++) { + sb.append(digits.get(idx++)); + if (i == 1) { + sb.append('-'); + } + } + } else { + for (; idx < digits.size(); idx++) { + sb.append(digits.get(idx)); + } + } + return sb.toString(); + } +} diff --git a/Easy/Reformat The String.java b/Easy/Reformat The String.java new file mode 100644 index 00000000..8c91c9a5 --- /dev/null +++ b/Easy/Reformat The String.java @@ -0,0 +1,36 @@ +class Solution { + public String reformat(String s) { + List letters = new ArrayList<>(); + List digits = new ArrayList<>(); + for (char c : s.toCharArray()) { + if (Character.isLetter(c)) { + letters.add(c); + } + else { + digits.add(c); + } + } + if (Math.abs(letters.size() - digits.size()) > 1) { + return ""; + } + return letters.size() > digits.size() ? formPermutation(letters, digits) : formPermutation(digits, letters); + } + + private String formPermutation(List l1, List l2) { + StringBuilder sb = new StringBuilder(); + int idx1 = 0; + int idx2 = 0; + boolean isL1 = true; + while (idx1 < l1.size() && idx2 < l2.size()) { + sb.append(isL1 ? l1.get(idx1++) : l2.get(idx2++)); + isL1 = !isL1; + } + if (idx1 < l1.size()) { + sb.append(l1.get(idx1)); + } + if (idx2 < l2.size()) { + sb.append(l2.get(idx2)); + } + return sb.toString(); + } +} diff --git a/Easy/Relative Sort Array.java b/Easy/Relative Sort Array.java new file mode 100644 index 00000000..efee0153 --- /dev/null +++ b/Easy/Relative Sort Array.java @@ -0,0 +1,21 @@ +class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + int[] frequency = new int[1001]; + for (int num : arr1) { + frequency[num]++; + } + int[] result = new int[arr1.length]; + int idx = 0; + for (int num : arr2) { + while (frequency[num]-- > 0) { + result[idx++] = num; + } + } + for (int i = 0; i < 1001; i++) { + while (frequency[i]-- > 0) { + result[idx++] = i; + } + } + return result; + } +} diff --git a/Easy/Relative ranks.java b/Easy/Relative ranks.java index 211226ea..94e12902 100644 --- a/Easy/Relative ranks.java +++ b/Easy/Relative ranks.java @@ -1,34 +1,20 @@ -import java.util.Arrays; - -public class Solution { - public String[] findRelativeRanks(int[] nums) { - int[] nums_copy = nums.clone(); - Arrays.sort(nums); - for (int i = 0; i < nums.length / 2; i++) { - int temp = nums[i]; - nums[i] = nums[nums.length - 1 - i]; - nums[nums.length - 1 - i] = temp; - } - - String[] rank = {"Gold Medal", "Silver Medal", "Bronze Medal"}; - - String[] ans = new String[nums.length]; - for (int i=0;i orderedRanking = new PriorityQueue<>((o1, o2) -> nums[o2] - nums[o1]); + orderedRanking.addAll(IntStream.range(0, nums.length).boxed().collect(Collectors.toList())); + String[] relativeRanks = new String[nums.length]; + int currentRank = 1; + while (!orderedRanking.isEmpty()) { + int removed = orderedRanking.poll(); + if (currentRank > 3) { + relativeRanks[removed] = String.valueOf(currentRank++); + } else { + relativeRanks[removed] = ( + currentRank == 1 ? "Gold Medal" : (currentRank == 2 ? "Silver Medal" : "Bronze Medal") + ); + currentRank++; + } } - public int findIndex(int[] nums, int elem) { - for (int i=0;i 0 && sb.charAt(sb.length() - 1) == c) { - sb.deleteCharAt(sb.length() - 1); - } - else { - sb.append(c); + public String removeDuplicates(String s) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (!stack.isEmpty() && stack.peek() == c) { + stack.pop(); + } else { + stack.push(c); } } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + sb.append(stack.pop()); + } + return sb.reverse().toString(); } } diff --git a/Easy/Remove Digit From Number to Maximize Result.java b/Easy/Remove Digit From Number to Maximize Result.java new file mode 100644 index 00000000..b789ea2c --- /dev/null +++ b/Easy/Remove Digit From Number to Maximize Result.java @@ -0,0 +1,14 @@ +class Solution { + public String removeDigit(String number, char digit) { + int lastOccurrence = -1; + for (int i = 0; i < number.length(); i++) { + if (number.charAt(i) == digit) { + if (i + 1 < number.length() && number.charAt(i + 1) > digit) { + return number.substring(0, i) + number.substring(i + 1); + } + lastOccurrence = i; + } + } + return number.substring(0, lastOccurrence) + number.substring(lastOccurrence + 1); + } +} diff --git a/Easy/Remove Duplicates From Sorted Lists.java b/Easy/Remove Duplicates From Sorted Lists.java index 8fb4fc2a..fbd899d4 100644 --- a/Easy/Remove Duplicates From Sorted Lists.java +++ b/Easy/Remove Duplicates From Sorted Lists.java @@ -3,27 +3,20 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode deleteDuplicates(ListNode head) { - if (head == null) return head; - ListNode copyHead = head; - while (head.next != null) { - if (head.val == head.next.val) { - if(head.next.next == null) { - head.next = null; - break; - } - else { - head.next = head.next.next; - } - } - else { - head = head.next; - } - } - return copyHead; + public ListNode deleteDuplicates(ListNode head) { + ListNode curr = head; + while (curr != null) { + while (curr.next != null && curr.next.val == curr.val) { + curr.next = curr.next.next; + } + curr = curr.next; } + return head; + } } diff --git a/Easy/Remove Duplicates from Sorted Array.java b/Easy/Remove Duplicates from Sorted Array.java new file mode 100644 index 00000000..7c285a36 --- /dev/null +++ b/Easy/Remove Duplicates from Sorted Array.java @@ -0,0 +1,14 @@ +class Solution { + public int removeDuplicates(int[] nums) { + int startIdx = 0; + int endIdx = 0; + while (endIdx < nums.length) { + int currValue = nums[endIdx]; + while (endIdx < nums.length && nums[endIdx] == currValue) { + endIdx++; + } + nums[startIdx++] = currValue; + } + return startIdx; + } +} diff --git a/Easy/Remove Element.java b/Easy/Remove Element.java new file mode 100644 index 00000000..c75e9bb7 --- /dev/null +++ b/Easy/Remove Element.java @@ -0,0 +1,11 @@ +class Solution { + public int removeElement(int[] nums, int val) { + int idx = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] != val) { + nums[idx++] = nums[i]; + } + } + return idx; + } +} diff --git a/Easy/Remove Letter To Equalize Frequency.java b/Easy/Remove Letter To Equalize Frequency.java new file mode 100644 index 00000000..05c950c2 --- /dev/null +++ b/Easy/Remove Letter To Equalize Frequency.java @@ -0,0 +1,27 @@ +class Solution { + public boolean equalFrequency(String word) { + int[] frequency = new int[26]; + int maxFrequency = 0; + for (char c : word.toCharArray()) { + frequency[c - 'a']++; + maxFrequency = Math.max(maxFrequency, frequency[c - 'a']); + } + int maxCount = 0; + int maxMinusOneCount = 0; + for (int i = 0; i < 26; i++) { + if (frequency[i] == 0) { + continue; + } + if (frequency[i] == maxFrequency) { + maxCount++; + } + if (frequency[i] == maxFrequency - 1) { + maxMinusOneCount++; + } + if (frequency[i] < maxFrequency - 1) { + return false; + } + } + return maxMinusOneCount == 1 || maxCount == 1 || (maxMinusOneCount == 0 && maxFrequency == 1); + } +} diff --git a/Easy/Remove Linked List Elements.java b/Easy/Remove Linked List Elements.java index 5f4b5c21..41684468 100644 --- a/Easy/Remove Linked List Elements.java +++ b/Easy/Remove Linked List Elements.java @@ -3,23 +3,26 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode removeElements(ListNode head, int val) { - if (head == null) { - return null; - } - ListNode current = head; - while (current.next != null) { - if (current.next.val == val) { - current.next = current.next.next; - } - else { - current = current.next; - } - } - return head.val == val ? head.next : head; + public ListNode removeElements(ListNode head, int val) { + ListNode newHead = null; + ListNode curr = head; + while (curr != null && curr.val == val) { + curr = curr.next; } -} \ No newline at end of file + newHead = curr; + while (curr != null && curr.next != null) { + if (curr.next.val == val) { + curr.next = curr.next.next; + } else { + curr = curr.next; + } + } + return newHead; + } +} diff --git a/Easy/Remove One Element to Make the Array Strictly Increasing.java b/Easy/Remove One Element to Make the Array Strictly Increasing.java new file mode 100644 index 00000000..74c4bf1d --- /dev/null +++ b/Easy/Remove One Element to Make the Array Strictly Increasing.java @@ -0,0 +1,17 @@ +class Solution { + public boolean canBeIncreasing(int[] nums) { + boolean removed = false; + for (int i = 1; i < nums.length; i++) { + if (nums[i] <= nums[i - 1]) { + if (removed) { + return false; + } + removed = true; + if (i > 1 && nums[i] <= nums[i - 2]) { + nums[i] = nums[i - 1]; + } + } + } + return true; + } +} diff --git a/Easy/Remove Outermost Parentheses.java b/Easy/Remove Outermost Parentheses.java new file mode 100644 index 00000000..1eef6edb --- /dev/null +++ b/Easy/Remove Outermost Parentheses.java @@ -0,0 +1,25 @@ +class Solution { + public String removeOuterParentheses(String S) { + Stack stack = new Stack<>(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < S.length(); i++) { + char c = S.charAt(i); + if (stack.isEmpty() && c == '(') { + stack.push(c); + continue; + } + if (stack.size() == 1 && c == ')') { + stack.pop(); + continue; + } + if (c == '(') { + stack.push(c); + } + else { + stack.pop(); + } + sb.append(c); + } + return sb.toString(); + } +} diff --git a/Easy/Remove Palindromic Subsequences.java b/Easy/Remove Palindromic Subsequences.java new file mode 100644 index 00000000..e4e10845 --- /dev/null +++ b/Easy/Remove Palindromic Subsequences.java @@ -0,0 +1,17 @@ +class Solution { + public int removePalindromeSub(String s) { + if (s.length() == 0) { + return 0; + } + int start = 0; + int end = s.length() - 1; + while (start <= end) { + if (s.charAt(start) != s.charAt(end)) { + return 2; + } + start++; + end--; + } + return 1; + } +} diff --git a/Easy/Remove Trailing Zeros From a String.java b/Easy/Remove Trailing Zeros From a String.java new file mode 100644 index 00000000..996c079e --- /dev/null +++ b/Easy/Remove Trailing Zeros From a String.java @@ -0,0 +1,9 @@ +class Solution { + public String removeTrailingZeros(String num) { + int idx = num.length() - 1; + while (idx >= 0 && num.charAt(idx) == '0') { + idx--; + } + return num.substring(0, idx + 1); + } +} diff --git a/Easy/Remove Vowels from a String.java b/Easy/Remove Vowels from a String.java new file mode 100644 index 00000000..d5c24c1b --- /dev/null +++ b/Easy/Remove Vowels from a String.java @@ -0,0 +1,11 @@ +class Solution { + public String removeVowels(String s) { + return s.chars() + .mapToObj(c -> (char) c) + .filter(c -> "aeiou".indexOf(c) == -1) + .collect(Collector.of(StringBuilder::new, + StringBuilder::append, + StringBuilder::append, + StringBuilder::toString)); + } +} diff --git a/Easy/Repeated Substring Pattern.java b/Easy/Repeated Substring Pattern.java index b47d5001..fc817f7e 100644 --- a/Easy/Repeated Substring Pattern.java +++ b/Easy/Repeated Substring Pattern.java @@ -1,8 +1,16 @@ class Solution { public boolean repeatedSubstringPattern(String s) { - String s1 = s + s; - String s2 = s1.substring(1,s1.length()-1); - - return s2.contains(s); + int n = s.length(); + for (int i = n / 2; i > 0; i--) { + if (n % i == 0) { + int count = n / i; + String substring = s.substring(0, i); + String repeatedString = substring.repeat(count); + if (repeatedString.equals(s)) { + return true; + } + } + } + return false; } } diff --git a/Easy/Replace All ?'s to Avoid Consecutive Repeating Characters.java b/Easy/Replace All ?'s to Avoid Consecutive Repeating Characters.java new file mode 100644 index 00000000..57c5a54c --- /dev/null +++ b/Easy/Replace All ?'s to Avoid Consecutive Repeating Characters.java @@ -0,0 +1,22 @@ +class Solution { + private final char[] ALL_CHARACTERS = "abcdefghijklmnopqrstuvwxyz".toCharArray(); + public String modifyString(String s) { + char[] charArray = s.toCharArray(); + for (int idx = 0; idx < charArray.length; idx++) { + if (charArray[idx] == '?') { + charArray[idx] = getNonRepeatingChar(charArray, idx); + } + } + return String.valueOf(charArray); + } + + private char getNonRepeatingChar(char[] charArray, int idx) { + for (char c : ALL_CHARACTERS) { + if ((idx == 0 || charArray[idx - 1] == '?' || charArray[idx - 1] != c) && + (idx == charArray.length - 1 || charArray[idx + 1] == '?' || charArray[idx + 1] != c)) { + return c; + } + } + return charArray[idx]; + } +} diff --git a/Easy/Replace All Digits with Characters.java b/Easy/Replace All Digits with Characters.java new file mode 100644 index 00000000..92047d4e --- /dev/null +++ b/Easy/Replace All Digits with Characters.java @@ -0,0 +1,11 @@ +class Solution { + public String replaceDigits(String s) { + StringBuilder sb = new StringBuilder(); + int n = s.length(); + for (int i = 1; i < n; i += 2) { + char c = s.charAt(i - 1); + sb.append(c).append((char) (((int) c) + Character.getNumericValue(s.charAt(i)))); + } + return n % 2 != 0 ? sb.append(s.charAt(n - 1)).toString() : sb.toString(); + } +} diff --git a/Easy/Replace Elements with Greatest Element on Right Side.java b/Easy/Replace Elements with Greatest Element on Right Side.java new file mode 100644 index 00000000..12e4405a --- /dev/null +++ b/Easy/Replace Elements with Greatest Element on Right Side.java @@ -0,0 +1,11 @@ +class Solution { + public int[] replaceElements(int[] arr) { + int maxVal = -1; + for (int i = arr.length - 1; i >= 0; i--) { + int temp = arr[i]; + arr[i] = maxVal; + maxVal = Math.max(maxVal, temp); + } + return arr; + } +} diff --git a/Easy/Reshape the matrix.java b/Easy/Reshape the matrix.java index 1093a616..ca61f4e4 100644 --- a/Easy/Reshape the matrix.java +++ b/Easy/Reshape the matrix.java @@ -1,31 +1,22 @@ class Solution { - public int[][] matrixReshape(int[][] nums, int r, int c) { - int numOfElem = nums.length*nums[0].length; - if (numOfElem != r*c) { - return nums; + public int[][] matrixReshape(int[][] mat, int r, int c) { + int m = mat.length; + int n = mat[0].length; + if (m * n != r * c) { + return mat; } - - int[] expandedArray = new int[numOfElem]; - int k = 0; - - for (int i=0;i>>= 1; - if (i < 31) - result <<= 1; - } - return result; + // you need treat n as an unsigned value + public int reverseBits(int n) { + if (n == 0) { + return 0; } -} \ No newline at end of file + int result = 0; + for (int i = 0; i < 32; i++) { + result <<= 1; + if ((n & 1) == 1) { + result++; + } + n >>= 1; + } + return result; + } +} diff --git a/Easy/Reverse Degree of a String.java b/Easy/Reverse Degree of a String.java new file mode 100644 index 00000000..db8f4e91 --- /dev/null +++ b/Easy/Reverse Degree of a String.java @@ -0,0 +1,9 @@ +class Solution { + public int reverseDegree(String s) { + int result = 0; + for (int i = 0; i < s.length(); i++) { + result += (i + 1) * (26 - (s.charAt(i) - 'a')); + } + return result; + } +} diff --git a/Easy/Reverse Integer.java b/Easy/Reverse Integer.java deleted file mode 100644 index 330bbff2..00000000 --- a/Easy/Reverse Integer.java +++ /dev/null @@ -1,17 +0,0 @@ -public class Solution { - public int reverse(int x) { - int result = 0; - - while (x != 0) - { - int tail = x % 10; - int newResult = result * 10 + tail; - if ((newResult - tail) / 10 != result) - { return 0; } - result = newResult; - x = x / 10; - } - - return result; - } -} \ No newline at end of file diff --git a/Easy/Reverse Linked List.java b/Easy/Reverse Linked List.java index e729c133..61877d65 100644 --- a/Easy/Reverse Linked List.java +++ b/Easy/Reverse Linked List.java @@ -3,22 +3,22 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode reverseList(ListNode head) { - ListNode prev = null; - ListNode curr = head; - ListNode next = null; - - while (curr != null) { - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - - return prev; + public ListNode reverseList(ListNode head) { + ListNode prev = null; + ListNode next = null; + ListNode curr = head; + while (curr != null) { + next = curr.next; + curr.next = prev; + prev = curr; + curr = next; } + return prev; + } } diff --git a/Easy/Reverse Only Letters.java b/Easy/Reverse Only Letters.java new file mode 100644 index 00000000..acdd5168 --- /dev/null +++ b/Easy/Reverse Only Letters.java @@ -0,0 +1,21 @@ +class Solution { + public String reverseOnlyLetters(String s) { + int start = 0; + int end = s.length() - 1; + char[] letters = s.toCharArray(); + while (start <= end) { + while (start <= end && !Character.isLetter(s.charAt(start))) { + start++; + } + while (end >= start && !Character.isLetter(s.charAt(end))) { + end--; + } + if (start <= end) { + char temp = letters[start]; + letters[start++] = letters[end]; + letters[end--] = temp; + } + } + return String.valueOf(letters); + } +} diff --git a/Easy/Reverse Prefix of Word.java b/Easy/Reverse Prefix of Word.java new file mode 100644 index 00000000..3799c707 --- /dev/null +++ b/Easy/Reverse Prefix of Word.java @@ -0,0 +1,10 @@ +class Solution { + public String reversePrefix(String word, char ch) { + for (int i = 0; i < word.length(); i++) { + if (word.charAt(i) == ch) { + return new StringBuilder().append(word.substring(0, i + 1)).reverse().toString() + word.substring(i + 1); + } + } + return word; + } +} diff --git a/Easy/Reverse String II.java b/Easy/Reverse String II.java index 6534c687..168f553d 100644 --- a/Easy/Reverse String II.java +++ b/Easy/Reverse String II.java @@ -1,21 +1,16 @@ class Solution { - public String reverseStr(String s, int k) { - char[] arr = s.toCharArray(); - int n = arr.length; - int i = 0; - while(i < n) { - int j = Math.min(i + k - 1, n - 1); - swap(arr, i, j); - i += 2 * k; - } - return String.valueOf(arr); - } - - private void swap(char[] arr, int l, int r) { - while (l < r) { - char temp = arr[l]; - arr[l++] = arr[r]; - arr[r--] = temp; - } + public String reverseStr(String s, int k) { + boolean reverse = true; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i += k) { + String substring = s.substring(i, Math.min(i + k, s.length())); + if (reverse) { + sb.append(new StringBuilder().append(substring).reverse().toString()); + } else { + sb.append(substring); + } + reverse = !reverse; } + return sb.toString(); + } } diff --git a/Easy/Reverse String.java b/Easy/Reverse String.java index 18a51725..959b5bed 100644 --- a/Easy/Reverse String.java +++ b/Easy/Reverse String.java @@ -1,8 +1,11 @@ -public class Solution { - public String reverseString(String s) { - StringBuilder input1 = new StringBuilder(); - input1.append(s); - input1 = input1.reverse(); - return input1.toString(); +class Solution { + public void reverseString(char[] s) { + int start = 0; + int end = s.length - 1; + while (start < end) { + char temp = s[start]; + s[start++] = s[end]; + s[end--] = temp; } -} \ No newline at end of file + } +} diff --git a/Easy/Reverse Vowels of a String.java b/Easy/Reverse Vowels of a String.java index b5202be8..ea10d13c 100644 --- a/Easy/Reverse Vowels of a String.java +++ b/Easy/Reverse Vowels of a String.java @@ -1,28 +1,24 @@ class Solution { + + private static final Set VOWELS = Set.of('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'); + public String reverseVowels(String s) { - ArrayList indexArr = new ArrayList(); - String vowel = "aeiouAEIOU"; - char[] charArray = s.toCharArray(); - - for (int i=0;i Arrays.stream(e).sum()) + .max(Integer::compareTo) + .orElse(0); + } +} diff --git a/Easy/Rings and Rods.java b/Easy/Rings and Rods.java new file mode 100644 index 00000000..fd98b60a --- /dev/null +++ b/Easy/Rings and Rods.java @@ -0,0 +1,11 @@ +class Solution { + public int countPoints(String rings) { + Map> map = new HashMap<>(); + for (int i = 0; i < rings.length(); i += 2) { + char ring = rings.charAt(i); + int rod = Character.getNumericValue(rings.charAt(i + 1)); + map.computeIfAbsent(rod, k -> new HashSet()).add(ring); + } + return (int) map.values().stream().filter(v -> v.size() == 3).count(); + } +} diff --git a/Easy/Robot Return to Origin.java b/Easy/Robot Return to Origin.java new file mode 100644 index 00000000..e5661ac0 --- /dev/null +++ b/Easy/Robot Return to Origin.java @@ -0,0 +1,15 @@ +class Solution { + public boolean judgeCircle(String moves) { + int x = 0; + int y = 0; + for (char move : moves.toCharArray()) { + if (move == 'U' || move == 'D') { + y += move == 'U' ? 1 : -1; + } + else { + x += move == 'L' ? -1 : 1; + } + } + return x == 0 && y == 0; + } +} diff --git a/Easy/Roman to Integer.java b/Easy/Roman to Integer.java index 42b44427..c0c047ee 100644 --- a/Easy/Roman to Integer.java +++ b/Easy/Roman to Integer.java @@ -1,42 +1,23 @@ class Solution { - public int romanToInt(String s) { - int nums[] = new int[s.length()]; - for(int i = 0; i < s.length(); i++) { - switch (s.charAt(i)){ - case 'M': - nums[i]=1000; - break; - case 'D': - nums[i]=500; - break; - case 'C': - nums[i]=100; - break; - case 'L': - nums[i]=50; - break; - case 'X' : - nums[i]=10; - break; - case 'V': - nums[i]=5; - break; - case 'I': - nums[i]=1; - break; - } - } - - int sum = 0; - for(int i = 0; i < nums.length - 1; i++){ - if(nums[i] < nums[i + 1]) { - sum -= nums[i]; - } - else { - sum += nums[i]; - } - } - - return sum + nums[nums.length - 1]; + + public int romanToInt(String s) { + String[] strings = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"}; + int[] value = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000}; + Map map = new HashMap<>(); + for (int i = 0; i < strings.length; i++) { + map.put(strings[i], value[i]); + } + int idx = 0; + int num = 0; + while (idx < s.length()) { + if (idx + 1 < s.length() && map.containsKey(s.substring(idx, idx + 2))) { + num += map.get(s.substring(idx, idx + 2)); + idx += 2; + } else { + num += map.get(s.substring(idx, idx + 1)); + idx++; + } } + return num; + } } diff --git a/Easy/Root Equals Sum of Children.java b/Easy/Root Equals Sum of Children.java new file mode 100644 index 00000000..a354dc1a --- /dev/null +++ b/Easy/Root Equals Sum of Children.java @@ -0,0 +1,20 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean checkTree(TreeNode root) { + return root.val == (root.left.val + root.right.val); + } +} diff --git a/Easy/Rotate Array.java b/Easy/Rotate Array.java deleted file mode 100644 index 80e108e3..00000000 --- a/Easy/Rotate Array.java +++ /dev/null @@ -1,12 +0,0 @@ -public class Solution { - public void rotate(int[] nums, int k) { - int[] n = new int[nums.length]; - for (int i=0;i maxOnes) { + maxOnes = oneCount; + maxOnesRow = i; + } + } + return new int[]{maxOnesRow, maxOnes}; + } +} diff --git a/Easy/Running Sum of 1d Array.java b/Easy/Running Sum of 1d Array.java new file mode 100644 index 00000000..bc5f422a --- /dev/null +++ b/Easy/Running Sum of 1d Array.java @@ -0,0 +1,10 @@ +class Solution { + public int[] runningSum(int[] nums) { + int sum = 0; + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + nums[i] = sum; + } + return nums; + } +} diff --git a/Easy/Same Tree.java b/Easy/Same Tree.java index 603a65f7..b5d41af0 100644 --- a/Easy/Same Tree.java +++ b/Easy/Same Tree.java @@ -4,19 +4,26 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - - public boolean isSameTree(TreeNode p, TreeNode q) { - - if (p == null && q == null) return true; - if (p == null || q == null) return false; - - if (p.val == q.val) { - return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); - } - return false; + public boolean isSameTree(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; } + if (p == null || q == null) { + return false; + } + if (p.val != q.val) { + return false; + } + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); + } } diff --git a/Easy/Score of a String.java b/Easy/Score of a String.java new file mode 100644 index 00000000..fafcca05 --- /dev/null +++ b/Easy/Score of a String.java @@ -0,0 +1,9 @@ +class Solution { + public int scoreOfString(String s) { + int score = 0; + for (int i = 1; i < s.length(); i++) { + score += Math.abs(s.charAt(i) - s.charAt(i - 1)); + } + return score; + } +} diff --git a/Easy/Search Insert Position.java b/Easy/Search Insert Position.java index bc1adfee..3e2f930c 100644 --- a/Easy/Search Insert Position.java +++ b/Easy/Search Insert Position.java @@ -1,26 +1,17 @@ class Solution { - public int searchInsert(int[] nums, int target) { - int low = 0; - int high = nums.length-1; - - if (nums[low] >= target) { - return 0; - } - - if (nums[high] < target) { - return high + 1; - } - - while (low < high) { - int mid = (low + high)/2; - if (nums[mid] < target) { - low = mid+1; - } - else { - high = mid; - } - } - - return low; + public int searchInsert(int[] nums, int target) { + int left = 0; + int right = nums.length - 1; + while (left <= right) { + int mid = (left + right) / 2; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] > target) { + right = mid - 1; + } else { + left = mid + 1; + } } + return left; + } } diff --git a/Easy/Search in a Binary Search Tree.java b/Easy/Search in a Binary Search Tree.java index 8df18f2e..e3c00460 100644 --- a/Easy/Search in a Binary Search Tree.java +++ b/Easy/Search in a Binary Search Tree.java @@ -4,23 +4,31 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public TreeNode searchBST(TreeNode root, int val) { - if (root == null) { - return null; - } - - if(root.val == val) { - return root; - } - else if (root.val < val) { - return searchBST(root.right, val); - } - else { - return searchBST(root.left, val); + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + TreeNode removed = queue.remove(); + if (removed.val == val) { + return removed; + } + if (removed.val > val && removed.left != null) { + queue.add(removed.left); + } + if (removed.val < val && removed.right != null) { + queue.add(removed.right); + } } + return null; } } diff --git a/Easy/Second Largest Digit in a String.java b/Easy/Second Largest Digit in a String.java new file mode 100644 index 00000000..c4930136 --- /dev/null +++ b/Easy/Second Largest Digit in a String.java @@ -0,0 +1,20 @@ +class Solution { + public int secondHighest(String s) { + int maximumNum = -1; + int secondMaximumNum = -1; + for (char c : s.toCharArray()) { + if (Character.isDigit(c)) { + int num = Character.getNumericValue(c); + if (maximumNum < num) { + if (secondMaximumNum < maximumNum) { + secondMaximumNum = maximumNum; + } + maximumNum = num; + } else if (secondMaximumNum < num && num < maximumNum) { + secondMaximumNum = num; + } + } + } + return secondMaximumNum; + } +} diff --git a/Easy/Second Minimum Node in a binary tree.java b/Easy/Second Minimum Node in a binary tree.java index fdcf16fc..8ddeb335 100644 --- a/Easy/Second Minimum Node in a binary tree.java +++ b/Easy/Second Minimum Node in a binary tree.java @@ -4,35 +4,31 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int findSecondMinimumValue(TreeNode root) { - if (root == null) { - return -1; - } - if (root.left == null && root.right == null) { - return -1; - } - - int left = root.left.val; - int right = root.right.val; - - // if value same as root value, need to find the next candidate - if (root.left.val == root.val) { - left = findSecondMinimumValue(root.left); - } - if (root.right.val == root.val) { - right = findSecondMinimumValue(root.right); - } - - if (left != -1 && right != -1) { - return Math.min(left, right); - } else if (left != -1) { - return left; - } else { - return right; - } + public int findSecondMinimumValue(TreeNode root) { + long[] topTwo = {root.val, Long.MAX_VALUE}; + helper(root, topTwo); + return topTwo[1] == Long.MAX_VALUE ? -1 : (int) topTwo[1]; + } + + private void helper(TreeNode root, long[] topTwo) { + if (root == null) { + return; } + if (topTwo[0] < root.val && root.val < topTwo[1]) { + topTwo[1] = root.val; + } else { + helper(root.left, topTwo); + helper(root.right, topTwo); + } + } } diff --git a/Easy/Self Dividing Number.java b/Easy/Self Dividing Number.java new file mode 100644 index 00000000..dd0c952a --- /dev/null +++ b/Easy/Self Dividing Number.java @@ -0,0 +1,23 @@ +class Solution { + public List selfDividingNumbers(int left, int right) { + List ans = new ArrayList<>(); + for (int i = left; i <= right; i++) { + if (isSelfDivisible(i)) { + ans.add(i); + } + } + return ans; + } + + private boolean isSelfDivisible(int num) { + int copy = num; + while (copy > 0) { + int rem = copy % 10; + copy /= 10; + if (rem == 0 || num % rem != 0) { + return false; + } + } + return true; + } +} diff --git a/Easy/Sentence Similarity.java b/Easy/Sentence Similarity.java index e2293433..38f62e43 100644 --- a/Easy/Sentence Similarity.java +++ b/Easy/Sentence Similarity.java @@ -1,23 +1,22 @@ class Solution { - public boolean areSentencesSimilar(String[] words1, String[] words2, String[][] pairs) { - if (words1.length != words2.length) return false; - - Map> map = new HashMap<>(); - - for (String[] p: pairs) { - if (!map.containsKey(p[0])) { - map.put(p[0], new HashSet<>()); - } - map.get(p[0]).add(p[1]); - } - - for (int i=0;i> similarPairs) { + if (sentence1.length != sentence2.length) { + return false; } + Map> similarWords = new HashMap<>(); + for (List pair : similarPairs) { + similarWords.computeIfAbsent(pair.get(0), k -> new HashSet<>()).add(pair.get(1)); + similarWords.computeIfAbsent(pair.get(1), k -> new HashSet<>()).add(pair.get(0)); + } + for (int i = 0; i < sentence1.length; i++) { + if (sentence1[i].equals(sentence2[i]) + || similarWords.getOrDefault(sentence1[i], new HashSet<>()).contains(sentence2[i]) + || similarWords.getOrDefault(sentence2[i], new HashSet<>()).contains(sentence1[1])) { + continue; + } + return false; + } + return sentence1.length != sentence2.length; + } } diff --git a/Easy/Separate the Digits in an Array.java b/Easy/Separate the Digits in an Array.java new file mode 100644 index 00000000..9bd6878f --- /dev/null +++ b/Easy/Separate the Digits in an Array.java @@ -0,0 +1,19 @@ +class Solution { + public int[] separateDigits(int[] nums) { + List result = new ArrayList<>(); + for (int num : nums) { + int startIdx = result.size(); + while (num > 0) { + result.add(num % 10); + num /= 10; + } + int endIdx = result.size() - 1; + while (startIdx < endIdx) { + int temp = result.get(startIdx); + result.set(startIdx++, result.get(endIdx)); + result.set(endIdx--, temp); + } + } + return result.stream().mapToInt(Integer::intValue).toArray(); + } +} diff --git a/Easy/Set Mismatch.java b/Easy/Set Mismatch.java index 49ba13f1..eac82238 100644 --- a/Easy/Set Mismatch.java +++ b/Easy/Set Mismatch.java @@ -1,26 +1,19 @@ class Solution { public int[] findErrorNums(int[] nums) { - int[] ans = {-1,1}; - Map map = new HashMap<>(); - - for(int i=0;i set = new HashSet<>(); + for (int i = 1; i <= n; i++) { + if (!set.add(nums[i - 1])) { + result[0] = nums[i - 1]; } } - - for (int i=1;i<=nums.length;i++) { - if (!map.containsKey(i)) { - ans[1] = i; - } - if (map.containsKey(i) && map.get(i) == 2) { - ans[0] = i; + for (int i = 1; i <= n; i++) { + if (!set.contains(i)) { + result[1] = i; + break; } } - - return ans; + return result; } } diff --git a/Easy/Shortest Completing Word.java b/Easy/Shortest Completing Word.java new file mode 100644 index 00000000..5e9c9cb3 --- /dev/null +++ b/Easy/Shortest Completing Word.java @@ -0,0 +1,34 @@ +class Solution { + public String shortestCompletingWord(String licensePlate, String[] words) { + int shortestWordIdx = -1; + Map licensePlateFrequency = getFrequencyMap(licensePlate); + for (int i = 0; i < words.length; i++) { + if (canComplete(licensePlateFrequency, words[i])) { + if (shortestWordIdx == -1 || words[i].length() < words[shortestWordIdx].length()) { + shortestWordIdx = i; + } + } + } + return words[shortestWordIdx]; + } + + private boolean canComplete(Map licensePlateFrequency, String word) { + Map wordFrequency = getFrequencyMap(word); + for (Character key : licensePlateFrequency.keySet()) { + if (wordFrequency.getOrDefault(key, 0) < licensePlateFrequency.get(key)) { + return false; + } + } + return true; + } + + private Map getFrequencyMap(String s) { + Map map = new HashMap<>(); + for (char c : s.toCharArray()) { + if (Character.isLetter(c)) { + map.put(Character.toLowerCase(c), map.getOrDefault(Character.toLowerCase(c), 0) + 1); + } + } + return map; + } +} diff --git a/Easy/Shortest Distance to Target String in a Circular Array.java b/Easy/Shortest Distance to Target String in a Circular Array.java new file mode 100644 index 00000000..9280c7b9 --- /dev/null +++ b/Easy/Shortest Distance to Target String in a Circular Array.java @@ -0,0 +1,24 @@ +class Solution { + public int closetTarget(String[] words, String target, int startIndex) { + int firstIdx = -1; + int lastIdx = -1; + int n = words.length; + int minDistance = Integer.MAX_VALUE; + for (int i = 0; i < n; i++) { + if (words[i].equals(target)) { + if (firstIdx == -1) { + firstIdx = i; + } + lastIdx = i; + minDistance = Math.min(minDistance, Math.abs(i - startIndex)); + } + } + if (minDistance == Integer.MAX_VALUE) { + return -1; + } + return Math.min(minDistance, Math.min( + n - startIndex + firstIdx, // Reach first instance by circulating from end of array + startIndex + n - lastIdx // Reach last instance by circulating from start of array + )); + } +} diff --git a/Easy/Shortest Distance to a Character.java b/Easy/Shortest Distance to a Character.java index 73ebfa5d..b053588f 100644 --- a/Easy/Shortest Distance to a Character.java +++ b/Easy/Shortest Distance to a Character.java @@ -1,36 +1,20 @@ class Solution { - public static int[] shortestToChar(String S, char C) { - int[] ans = new int[S.length()]; - - int count = (int) S.chars().filter(ch -> ch == C).count(); - - int[] Cindexes = new int[count]; - int[] indexes = new int[S.length()]; - - int i = 0; - - for (int j=0; j= 0; i--) { + if (S.charAt(i) == C) { + prev = i; + } + ans[i] = Math.min(ans[i], prev - i); + } + return ans; + } } diff --git a/Easy/Shortest Subarray With OR at Least K I.java b/Easy/Shortest Subarray With OR at Least K I.java new file mode 100644 index 00000000..0032852b --- /dev/null +++ b/Easy/Shortest Subarray With OR at Least K I.java @@ -0,0 +1,17 @@ +class Solution { + public int minimumSubarrayLength(int[] nums, int k) { + int n = nums.length; + int result = Integer.MAX_VALUE; + for (int i = 0; i < n; i++) { + int curr = 0; + for (int j = i; j < n; j++) { + curr |= nums[j]; + if (curr >= k) { + result = Math.min(result, j - i + 1); + break; + } + } + } + return result == Integer.MAX_VALUE ? -1 : result; + } +} diff --git a/Easy/Shortest Unsorted Continuous Subarray.java b/Easy/Shortest Unsorted Continuous Subarray.java deleted file mode 100644 index 2757ecbd..00000000 --- a/Easy/Shortest Unsorted Continuous Subarray.java +++ /dev/null @@ -1,33 +0,0 @@ -class Solution { - public int findUnsortedSubarray(int[] nums) { - - int[] copy = new int[nums.length]; - for (int i=0;i> map; - public WordDistance(String[] words) { - map = new HashMap<>(); - - for (int i=0; i indexes = new ArrayList<>(); - indexes.add(i); - - map.put(words[i], indexes); - } - } - } - - public int shortest(String word1, String word2) { - List index1 = map.get(word1); - List index2 = map.get(word2); - - int i = 0; - int j = 0; - int diff = Integer.MAX_VALUE; - - while (i < index1.size() && j < index2.size()) { - diff = Math.min(diff, Math.abs(index1.get(i) - index2.get(j))); - - if (index1.get(i) > index2.get(j)) { - j++; - } - else { - i++; - } - } - - return diff; - } -} - -/** - * Your WordDistance object will be instantiated and called as such: - * WordDistance obj = new WordDistance(words); - * int param_1 = obj.shortest(word1,word2); - */ diff --git a/Easy/Shortest Word Distance III.java b/Easy/Shortest Word Distance III.java deleted file mode 100644 index 3b05dcee..00000000 --- a/Easy/Shortest Word Distance III.java +++ /dev/null @@ -1,43 +0,0 @@ -class Solution { - public int shortestWordDistance(String[] words, String word1, String word2) { - int dist1 = -1; - int dist2 = -1; - int minDist = Integer.MAX_VALUE; - - boolean sameWord = word1.equals(word2); - - for (int i=0; i 0 ? 0 : 1; + } + return negCount % 2 == 0 ? 1 : -1; + } +} diff --git a/Easy/Similar RGB Color.java b/Easy/Similar RGB Color.java new file mode 100644 index 00000000..968464dc --- /dev/null +++ b/Easy/Similar RGB Color.java @@ -0,0 +1,16 @@ +class Solution { + public String similarRGB(String color) { + StringBuilder simlarColor = new StringBuilder(); + simlarColor.append("#"); + for (int i = 1; i < 6; i += 2) { + simlarColor.append(findClosestColor(color.substring(i, i + 2))); + } + return simlarColor.toString(); + } + + private String findClosestColor(String section) { + int num = Integer.parseInt(section, 16); + int roundedValue = Math.round((float) num / 17); + return Integer.toHexString(roundedValue).repeat(2); + } +} diff --git a/Easy/Single Number.java b/Easy/Single Number.java index 94568349..9c1601e9 100644 --- a/Easy/Single Number.java +++ b/Easy/Single Number.java @@ -1,24 +1,9 @@ -public class Solution { - public int singleNumber(int[] nums) { - if (nums.length == 1) return nums[0]; - Arrays.sort(nums); - if (nums[0] != nums[1]) { - return nums[0]; - } - boolean twice = true; - for (int i=0;i map = new HashMap<>(); + for (int i = 0; i < 26; i++) { + map.put(keyboard.charAt(i), i); + } + int position = 0; + int time = 0; + for (char c : word.toCharArray()) { + time += Math.abs(position - map.get(c)); + position = map.get(c); + } + return time; + } +} diff --git a/Easy/Slowest Key.java b/Easy/Slowest Key.java new file mode 100644 index 00000000..e1c7f29f --- /dev/null +++ b/Easy/Slowest Key.java @@ -0,0 +1,17 @@ +class Solution { + public char slowestKey(int[] releaseTimes, String keysPressed) { + int maxReleaseTime = 0; + int maxReleaseTimeIdx = 0; + for (int i = 0; i < releaseTimes.length; i++) { + int idx = keysPressed.charAt(i) - 'a'; + int currReleaseTime = i == 0 ? releaseTimes[i] : (releaseTimes[i] - releaseTimes[i - 1]); + if (currReleaseTime > maxReleaseTime) { + maxReleaseTimeIdx = idx; + maxReleaseTime = currReleaseTime; + } else if (maxReleaseTime == currReleaseTime && maxReleaseTimeIdx < idx) { + maxReleaseTimeIdx = idx; + } + } + return ((char) ('a' + maxReleaseTimeIdx)); + } +} diff --git a/Easy/Smallest Even Multiple.java b/Easy/Smallest Even Multiple.java new file mode 100644 index 00000000..24964eca --- /dev/null +++ b/Easy/Smallest Even Multiple.java @@ -0,0 +1,5 @@ +class Solution { + public int smallestEvenMultiple(int n) { + return n % 2 == 0 ? n : 2 * n; + } +} diff --git a/Easy/Smallest Index With Equal Value.java b/Easy/Smallest Index With Equal Value.java new file mode 100644 index 00000000..1c6d2ea3 --- /dev/null +++ b/Easy/Smallest Index With Equal Value.java @@ -0,0 +1,5 @@ +class Solution { + public int smallestEqual(int[] nums) { + return IntStream.range(0, nums.length).filter(i -> i % 10 == nums[i]).findFirst().orElse(-1); + } +} diff --git a/Easy/Smallest Range I.java b/Easy/Smallest Range I.java new file mode 100644 index 00000000..8ba8f821 --- /dev/null +++ b/Easy/Smallest Range I.java @@ -0,0 +1,11 @@ +class Solution { + public int smallestRangeI(int[] A, int K) { + int maximum = A[0]; + int minimum = A[0]; + for (int num : A) { + maximum = Math.max(num, maximum); + minimum = Math.min(num, minimum); + } + return Math.max(0, maximum - minimum - 2 * K); + } +} diff --git a/Easy/Snake in Matrix.java b/Easy/Snake in Matrix.java new file mode 100644 index 00000000..5dce2568 --- /dev/null +++ b/Easy/Snake in Matrix.java @@ -0,0 +1,22 @@ +class Solution { + + private static final Map COMMAND_TO_DIRECTION = Map.of( + "UP", new int[]{-1, 0}, + "DOWN", new int[]{1, 0}, + "LEFT", new int[]{0, -1}, + "RIGHT", new int[]{0, 1} + ); + + public int finalPositionOfSnake(int n, List commands) { + int position = 0; + int x = 0; + int y = 0; + for (String command : commands) { + int[] change = COMMAND_TO_DIRECTION.get(command); + x += change[0]; + y += change[1]; + position = x * n + y; + } + return position; + } +} diff --git a/Easy/Sort Array By Parity II.java b/Easy/Sort Array By Parity II.java new file mode 100644 index 00000000..c03d9709 --- /dev/null +++ b/Easy/Sort Array By Parity II.java @@ -0,0 +1,16 @@ +class Solution { + public int[] sortArrayByParityII(int[] A) { + int start = 1; + for (int i = 0; i < A.length; i += 2) { + if (A[i] % 2 == 1) { + while (A[start] % 2 != 0) { + start += 2; + } + int temp = A[i]; + A[i] = A[start]; + A[start] = temp; + } + } + return A; + } +} diff --git a/Easy/Sort Array By Parity.java b/Easy/Sort Array By Parity.java new file mode 100644 index 00000000..0b54ae53 --- /dev/null +++ b/Easy/Sort Array By Parity.java @@ -0,0 +1,16 @@ +class Solution { + public int[] sortArrayByParity(int[] nums) { + int start = 0; + int end = 0; + int n = nums.length; + while (end < n) { + if (nums[end] % 2 == 0) { + int temp = nums[start]; + nums[start++] = nums[end]; + nums[end] = temp; + } + end++; + } + return nums; + } +} diff --git a/Easy/Sort Array by Increasing Frequency.java b/Easy/Sort Array by Increasing Frequency.java new file mode 100644 index 00000000..0fa7b374 --- /dev/null +++ b/Easy/Sort Array by Increasing Frequency.java @@ -0,0 +1,24 @@ +class Solution { + public int[] frequencySort(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> { + int c = map.get(o1).compareTo(map.get(o2)); + if (c != 0) { + return c; + } + return o2.compareTo(o1); + }); + pq.addAll(map.keySet()); + int idx = 0; + while (!pq.isEmpty()) { + int removed = pq.remove(); + for (int i = 0; i < map.get(removed); i++) { + nums[idx++] = removed; + } + } + return nums; + } +} diff --git a/Easy/Sort Even and Odd Indices Independently.java b/Easy/Sort Even and Odd Indices Independently.java new file mode 100644 index 00000000..7b7e8203 --- /dev/null +++ b/Easy/Sort Even and Odd Indices Independently.java @@ -0,0 +1,22 @@ +class Solution { + public int[] sortEvenOdd(int[] nums) { + PriorityQueue oddIndices = new PriorityQueue<>((o1, o2) -> o2 - o1); + PriorityQueue evenIndices = new PriorityQueue<>(); + for (int i = 0; i < nums.length; i++) { + if (i % 2 == 0) { + evenIndices.add(nums[i]); + } else { + oddIndices.add(nums[i]); + } + } + int[] result = new int[nums.length]; + for (int i = 0; i < nums.length; i++) { + if (i % 2 == 0) { + result[i] = evenIndices.poll(); + } else { + result[i] = oddIndices.poll(); + } + } + return result; + } +} diff --git a/Easy/Sort Integers by The Number of 1 Bits.java b/Easy/Sort Integers by The Number of 1 Bits.java new file mode 100644 index 00000000..4b1e7c2c --- /dev/null +++ b/Easy/Sort Integers by The Number of 1 Bits.java @@ -0,0 +1,9 @@ +class Solution { + public int[] sortByBits(int[] arr) { + return Arrays.stream(arr) + .boxed() + .sorted(Comparator.comparingInt(Integer::bitCount).thenComparingInt(o -> o)) + .mapToInt(Integer::intValue) + .toArray(); + } +} diff --git a/Easy/Sort the People.java b/Easy/Sort the People.java new file mode 100644 index 00000000..03678ec2 --- /dev/null +++ b/Easy/Sort the People.java @@ -0,0 +1,10 @@ +class Solution { + public String[] sortPeople(String[] names, int[] heights) { + return IntStream.range(0, names.length) + .boxed() + .sorted((o1, o2) -> heights[o2] - heights[o1]) + .map(idx -> names[idx]) + .toList() + .toArray(new String[0]); + } +} diff --git a/Easy/Sorting the Sentence.java b/Easy/Sorting the Sentence.java new file mode 100644 index 00000000..6909055c --- /dev/null +++ b/Easy/Sorting the Sentence.java @@ -0,0 +1,18 @@ +class Solution { + public String sortSentence(String s) { + String[] positions = new String[9]; + String[] strs = s.split("\\s+"); + for (String str : strs) { + int digit = Character.getNumericValue(str.charAt(str.length() - 1)); + positions[digit - 1] = str.substring(0, str.length() - 1); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < positions.length; i++) { + if (positions[i] == null) { + break; + } + sb.append(positions[i]).append(" "); + } + return sb.toString().trim(); + } +} diff --git a/Easy/Special Array I.java b/Easy/Special Array I.java new file mode 100644 index 00000000..5057f626 --- /dev/null +++ b/Easy/Special Array I.java @@ -0,0 +1,10 @@ +class Solution { + public boolean isArraySpecial(int[] nums) { + for (int i = 1; i < nums.length; i++) { + if (nums[i] % 2 == nums[i - 1] % 2) { + return false; + } + } + return true; + } +} diff --git a/Easy/Special Array With X Elements Greater Than or Equal X.java b/Easy/Special Array With X Elements Greater Than or Equal X.java new file mode 100644 index 00000000..58ed1735 --- /dev/null +++ b/Easy/Special Array With X Elements Greater Than or Equal X.java @@ -0,0 +1,16 @@ +class Solution { + public int specialArray(int[] nums) { + int[] count = new int[1001]; + for (int num : nums) { + count[num]++; + } + int n = nums.length; + for (int i = 0; i < 1001; i++) { + if (n == i) { + return i; + } + n -= count[i]; + } + return -1; + } +} diff --git a/Easy/Special Positions in a Binary Matrix.java b/Easy/Special Positions in a Binary Matrix.java new file mode 100644 index 00000000..fa5c8e56 --- /dev/null +++ b/Easy/Special Positions in a Binary Matrix.java @@ -0,0 +1,23 @@ +class Solution { + public int numSpecial(int[][] mat) { + int[] rowCount = new int[mat.length]; + int[] colCount = new int[mat[0].length]; + for (int i = 0; i < mat.length; i++) { + for (int j = 0; j < mat[0].length; j++) { + if (mat[i][j] == 1) { + rowCount[i]++; + colCount[j]++; + } + } + } + int count = 0; + for (int i = 0; i < mat.length; i++) { + for (int j = 0; j < mat[0].length; j++) { + if (mat[i][j] == 1 && rowCount[i] == 1 && colCount[j] == 1) { + count++; + } + } + } + return count; + } +} diff --git a/Easy/Split Strings by Separator.java b/Easy/Split Strings by Separator.java new file mode 100644 index 00000000..2292a309 --- /dev/null +++ b/Easy/Split Strings by Separator.java @@ -0,0 +1,22 @@ +class Solution { + public List splitWordsBySeparator(List words, char separator) { + List result = new ArrayList<>(); + for (String word : words) { + int startIdx = 0; + int currIdx = 0; + while (currIdx < word.length()) { + if (word.charAt(currIdx) == separator) { + if (currIdx - startIdx > 0) { + result.add(word.substring(startIdx, currIdx)); + } + startIdx = currIdx + 1; + } + currIdx++; + } + if (currIdx - startIdx > 0) { + result.add(word.substring(startIdx, currIdx)); + } + } + return result; + } +} diff --git a/Easy/Split With Minimum Sum.java b/Easy/Split With Minimum Sum.java new file mode 100644 index 00000000..3f816605 --- /dev/null +++ b/Easy/Split With Minimum Sum.java @@ -0,0 +1,22 @@ +class Solution { + public int splitNum(int num) { + List digits = new ArrayList<>(); + while (num > 0) { + digits.add(num % 10); + num /= 10; + } + Collections.sort(digits); + int numOne = 0; + int numTwo = 0; + boolean flag = true; + for (int digit : digits) { + if (flag) { + numOne = numOne * 10 + digit; + } else { + numTwo = numTwo * 10 + digit; + } + flag = !flag; + } + return numOne + numTwo; + } +} diff --git a/Easy/Split a String in Balanced Strings.java b/Easy/Split a String in Balanced Strings.java new file mode 100644 index 00000000..2488bb79 --- /dev/null +++ b/Easy/Split a String in Balanced Strings.java @@ -0,0 +1,13 @@ +class Solution { + public int balancedStringSplit(String s) { + int count = 0; + int val = 0; + for (char c : s.toCharArray()) { + val += c == 'L' ? -1 : 1; + if (val == 0) { + count++; + } + } + return count; + } +} diff --git a/Easy/Split the Array.java b/Easy/Split the Array.java new file mode 100644 index 00000000..607a2de0 --- /dev/null +++ b/Easy/Split the Array.java @@ -0,0 +1,10 @@ +class Solution { + public boolean isPossibleToSplit(int[] nums) { + return Arrays.stream(nums) + .boxed() + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())) + .values() + .stream() + .allMatch(v -> v <= 2); + } +} diff --git a/Easy/SqrtX.java b/Easy/SqrtX.java index 0cd9c2c6..9c96e058 100644 --- a/Easy/SqrtX.java +++ b/Easy/SqrtX.java @@ -1,5 +1,21 @@ -public class Solution { - public int mySqrt(int x) { - return (int)Math.sqrt((double)x); +class Solution { + public int mySqrt(int x) { + if (x < 2) { + return x; } -} \ No newline at end of file + int left = 2; + int right = x / 2; + while (left <= right) { + int mid = (left + right) / 2; + long square = ((long) mid) * mid; + if (square > x) { + right = mid - 1; + } else if (square < x) { + left = mid + 1; + } else { + return mid; + } + } + return right; + } +} diff --git a/Easy/Squares of a Sorted Array.java b/Easy/Squares of a Sorted Array.java index 65f5c973..08f5faa6 100644 --- a/Easy/Squares of a Sorted Array.java +++ b/Easy/Squares of a Sorted Array.java @@ -1,21 +1,18 @@ class Solution { - public int[] sortedSquares(int[] A) { - int[] arr = new int[A.length]; + public int[] sortedSquares(int[] nums) { + int n = nums.length; int start = 0; - int end = A.length - 1; - int idx = A.length - 1; - - while (start <= end) { - if (Math.abs(A[start]) < Math.abs(A[end])) { - arr[idx--] = A[end] * A[end]; - end--; - } - else { - arr[idx--] = A[start] * A[start]; + int end = n - 1; + int[] result = new int[n]; + for (int i = n - 1; i >= 0; i--) { + if (Math.abs(nums[start]) >= Math.abs(nums[end])) { + result[i] = nums[start] * nums[start]; start++; + } else { + result[i] = nums[end] * nums[end]; + end--; } } - - return arr; + return result; } } diff --git a/Easy/String Compression.java b/Easy/String Compression.java deleted file mode 100644 index 6a13ffb1..00000000 --- a/Easy/String Compression.java +++ /dev/null @@ -1,27 +0,0 @@ -class Solution { - public int compress(char[] chars) { - - int ans = 0; - int ind = 0; - - while (ind < chars.length) { - char currChar = chars[ind]; - int count = 0; - - while(ind < chars.length && chars[ind] == currChar) { - ind++; - count++; - } - - chars[ans++] = currChar; - - if (count != 1) { - for (char c : Integer.toString(count).toCharArray()) { - chars[ans++] = c; - } - } - } - - return ans; - } -} diff --git a/Easy/String Matching in an Array.java b/Easy/String Matching in an Array.java new file mode 100644 index 00000000..463f98b1 --- /dev/null +++ b/Easy/String Matching in an Array.java @@ -0,0 +1,26 @@ +class Solution { + public List stringMatching(String[] words) { + List list = new ArrayList<>(); + for (int i = 0; i < words.length; i++) { + for (int j = 0; j < words.length; j++) { + if (i != j && isSubstring(words[i], words[j])) { + list.add(words[i]); + break; + } + } + } + return list; + } + + private boolean isSubstring(String s1, String s2) { + if (s1.length() > s2.length()) { + return false; + } + for (int i = 0; i < s2.length() - s1.length() + 1; i++) { + if (s2.substring(i, i + s1.length()).equals(s1)) { + return true; + } + } + return false; + } +} diff --git a/Easy/Strobogrammatic Number.java b/Easy/Strobogrammatic Number.java index 70e41872..76ceb310 100644 --- a/Easy/Strobogrammatic Number.java +++ b/Easy/Strobogrammatic Number.java @@ -1,18 +1,15 @@ class Solution { - public boolean isStrobogrammatic(String num) { - StringBuilder sb = new StringBuilder(); - for (char c : num.toCharArray()) { - if (c == '0' || c == '1' || c == '8') { - sb.append(c); - } - else if (c == '6' || c == '9') { - sb.append(c == '6' ? '9' : '6'); - } - else { - return false; - } - } - - return sb.reverse().toString().equals(num); + public boolean isStrobogrammatic(String num) { + StringBuilder sb = new StringBuilder(); + for (char c : num.toCharArray()) { + if (c == '6' || c == '9') { + sb.append(c == '6' ? '9' : '6'); + } else if (c == '0' || c == '8' || c == '1') { + sb.append(c); + } else { + return false; + } } + return sb.reverse().toString().equals(num); + } } diff --git a/Easy/Strong Password Checker II.java b/Easy/Strong Password Checker II.java new file mode 100644 index 00000000..56e82a98 --- /dev/null +++ b/Easy/Strong Password Checker II.java @@ -0,0 +1,25 @@ +class Solution { + public boolean strongPasswordCheckerII(String password) { + boolean lowerCaseFound = false; + boolean upperCaseFound = false; + boolean digitFound = false; + boolean specialCharFound = false; + String specialChars = "!@#$%^&*()-+"; + for (int i = 0; i < password.length(); i++) { + char c = password.charAt(i); + if (specialChars.indexOf(c) != -1) { + specialCharFound = true; + } else if (Character.isDigit(c)) { + digitFound = true; + } else if (Character.isUpperCase(c)) { + upperCaseFound = true; + } else if (Character.isLowerCase(c)) { + lowerCaseFound = true; + } + if (i > 0 && password.charAt(i - 1) == c) { + return false; + } + } + return password.length() >= 8 && lowerCaseFound && upperCaseFound && digitFound && specialCharFound; + } +} diff --git a/Easy/Student Attendance Record I.java b/Easy/Student Attendance Record I.java index 2cef111b..75021837 100644 --- a/Easy/Student Attendance Record I.java +++ b/Easy/Student Attendance Record I.java @@ -1,18 +1,16 @@ class Solution { - public boolean checkRecord(String s) { - int absCount = 0; - if (s.contains("LLL")) { - return false; + public boolean checkRecord(String s) { + int absentCount = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == 'A') { + absentCount++; + } else if (c == 'L') { + if (i > 1 && s.charAt(i - 1) == 'L' && s.charAt(i - 2) == 'L') { + return false; } - - for (int i=0;i1) { - return false; - } - } - return true; + } } + return absentCount < 2; + } } diff --git a/Easy/Subarrays Distinct Element Sum of Squares I.java b/Easy/Subarrays Distinct Element Sum of Squares I.java new file mode 100644 index 00000000..fa7cee6a --- /dev/null +++ b/Easy/Subarrays Distinct Element Sum of Squares I.java @@ -0,0 +1,15 @@ +class Solution { + public int sumCounts(List nums) { + int sum = 0; + int n = nums.size(); + for (int i = 0; i < n; i++) { + Set set = new HashSet<>(); + for (int j = i; j < n; j++) { + set.add(nums.get(j)); + int size = set.size(); + sum += size * size; + } + } + return sum; + } +} diff --git a/Easy/Subdomain Visit Count.java b/Easy/Subdomain Visit Count.java deleted file mode 100644 index f3e711ba..00000000 --- a/Easy/Subdomain Visit Count.java +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { - public List subdomainVisits(String[] cpdomains) { - Map map = new HashMap<>(); - - for (String s : cpdomains) { - String[] strs = s.split("\\s+"); - int count = Integer.parseInt(strs[0]); - String[] domains = strs[1].split("\\."); - - String temp = domains[domains.length-1]; - int domainLen = domains.length-1; - - while(domainLen >= 0) { - map.put(temp, map.getOrDefault(temp, 0) + count); - if (domainLen > 0) { - temp = domains[domainLen-1] + "." + temp; - } - domainLen--; - } - - } - - List ans = new ArrayList<>(); - for (Map.Entry entry : map.entrySet()) { - String str = String.valueOf(entry.getValue()) + " " + entry.getKey(); - ans.add(str); - } - - return ans; - } -} diff --git a/Easy/Substrings of Size Three with Distinct Characters.java b/Easy/Substrings of Size Three with Distinct Characters.java new file mode 100644 index 00000000..9e54553f --- /dev/null +++ b/Easy/Substrings of Size Three with Distinct Characters.java @@ -0,0 +1,20 @@ +class Solution { + public int countGoodSubstrings(String s) { + Map map = new HashMap<>(); + int count = 0; + for (int i = 0; i < Math.min(s.length(), 2); i++) { + map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); + } + for (int i = 2; i < s.length(); i++) { + map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); + if (map.size() == 3) { + count++; + } + map.put(s.charAt(i - 2), map.getOrDefault(s.charAt(i - 2), 0) - 1); + if (map.get(s.charAt(i - 2)) == 0) { + map.remove(s.charAt(i - 2)); + } + } + return count; + } +} diff --git a/Easy/Subtract the Product and Sum of Digits of an Integer.java b/Easy/Subtract the Product and Sum of Digits of an Integer.java new file mode 100644 index 00000000..d08e41f7 --- /dev/null +++ b/Easy/Subtract the Product and Sum of Digits of an Integer.java @@ -0,0 +1,12 @@ +class Solution { + public int subtractProductAndSum(int n) { + int sum = 0; + int product = 1; + while (n > 0) { + sum += n % 10; + product *= n % 10; + n /= 10; + } + return product - sum; + } +} diff --git a/Easy/Subtree of Another Tree.java b/Easy/Subtree of Another Tree.java index 7c565ce5..c0e307eb 100644 --- a/Easy/Subtree of Another Tree.java +++ b/Easy/Subtree of Another Tree.java @@ -4,29 +4,31 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public boolean isSubtree(TreeNode s, TreeNode t) { - return traverseAndString(s).contains(traverseAndString(t)); - } - - public String traverseAndString(TreeNode root) { - StringBuilder res = new StringBuilder(); - traverse(root, res); - return res.toString(); + public boolean isSubtree(TreeNode root, TreeNode subRoot) { + if (root == null) { + return false; + } + boolean result = root.val == subRoot.val && isSubtreeHelper(root, subRoot); + return result || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } - public void traverse(TreeNode root, StringBuilder res) { - - if (root == null) { - res.append("-"); - return; + private boolean isSubtreeHelper(TreeNode root, TreeNode subRoot) { + if (root == null && subRoot == null) { + return true; + } + if (root == null || subRoot == null) { + return false; } - - traverse(root.left, res); - traverse(root.right, res); - res.append(String.valueOf(root.val) + ","); + return root.val == subRoot.val && isSubtreeHelper(root.left, subRoot.left) && isSubtreeHelper(root.right, subRoot.right); } } diff --git a/Easy/Sum Of Two Integers.java b/Easy/Sum Of Two Integers.java new file mode 100644 index 00000000..c1a70d9a --- /dev/null +++ b/Easy/Sum Of Two Integers.java @@ -0,0 +1,8 @@ +public class Solution { + public int getSum(int x, int y) { + if (y == 0) + return x; + else + return getSum( x ^ y, (x & y) << 1); + } +} diff --git a/Easy/Sum of All Odd Length Subarrays.java b/Easy/Sum of All Odd Length Subarrays.java new file mode 100644 index 00000000..4127387b --- /dev/null +++ b/Easy/Sum of All Odd Length Subarrays.java @@ -0,0 +1,15 @@ +class Solution { + public int sumOddLengthSubarrays(int[] arr) { + int sum = 0; + for (int i = 0; i < arr.length; i++) { + int currSum = 0; + for (int j = i; j < arr.length; j++) { + currSum += arr[j]; + if ((j - i + 1) % 2 != 0) { + sum += currSum; + } + } + } + return sum; + } +} diff --git a/Easy/Sum of All Subset XOR Totals.java b/Easy/Sum of All Subset XOR Totals.java new file mode 100644 index 00000000..fe82567a --- /dev/null +++ b/Easy/Sum of All Subset XOR Totals.java @@ -0,0 +1,14 @@ +class Solution { + public int subsetXORSum(int[] nums) { + return recurse(nums, 0, 0); + } + + private int recurse(int[] nums, int idx, int currXor) { + if (idx == nums.length) { + return currXor; + } + int performXor = recurse(nums, idx + 1, currXor ^ nums[idx]); + int notPerformXor = recurse(nums, idx + 1, currXor); + return performXor + notPerformXor; + } +} diff --git a/Easy/Sum of Digits in Base K.java b/Easy/Sum of Digits in Base K.java new file mode 100644 index 00000000..9775701b --- /dev/null +++ b/Easy/Sum of Digits in Base K.java @@ -0,0 +1,10 @@ +class Solution { + public int sumBase(int n, int k) { + int digitSum = 0; + while (n > 0) { + digitSum += n % k; + n /= k; + } + return digitSum; + } +} diff --git a/Easy/Sum of Digits of String After Convert.java b/Easy/Sum of Digits of String After Convert.java new file mode 100644 index 00000000..3b78aaae --- /dev/null +++ b/Easy/Sum of Digits of String After Convert.java @@ -0,0 +1,18 @@ +class Solution { + public int getLucky(String s, int k) { + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + sb.append(c - 'a' + 1); + } + while (k-- > 0) { + String temp = sb.toString(); + sb.setLength(0); + int val = 0; + for (char c : temp.toCharArray()) { + val += Character.getNumericValue(c); + } + sb.append(val); + } + return Integer.parseInt(sb.toString()); + } +} diff --git a/Easy/Sum of Even Numbers After Queries.java b/Easy/Sum of Even Numbers After Queries.java deleted file mode 100644 index a7e1e9f8..00000000 --- a/Easy/Sum of Even Numbers After Queries.java +++ /dev/null @@ -1,28 +0,0 @@ -class Solution { - public int[] sumEvenAfterQueries(int[] A, int[][] queries) { - int[] evenQuerySum = new int[queries.length]; - - int currEvenSum = 0; - for (int num : A) { - currEvenSum += num % 2 == 0 ? num : 0; - } - - for (int i=0; i queue = new LinkedList<>(); + queue.add(new TreeNode[]{root, null}); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeNode[] removed = queue.remove(); + TreeNode node = removed[0]; + TreeNode parent = removed[1]; + if (node.left == null && node.right == null) { + if (parent != null && parent.left == node) { + sum += node.val; + } + } else { + if (node.left != null) { + queue.add(new TreeNode[]{node.left, node}); + } + if (node.right != null) { + queue.add(new TreeNode[]{node.right, node}); + } + } + } + } + return sum; + } +} diff --git a/Easy/Sum of Root To Leaf Binary Numbers.java b/Easy/Sum of Root To Leaf Binary Numbers.java new file mode 100644 index 00000000..d49907f2 --- /dev/null +++ b/Easy/Sum of Root To Leaf Binary Numbers.java @@ -0,0 +1,60 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int sumRootToLeaf(TreeNode root) { + Queue queue = new LinkedList<>(); + queue.add(new NodeToBinaryRepresentation(root, new StringBuilder())); + int sum = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + NodeToBinaryRepresentation removed = queue.remove(); + StringBuilder sb = new StringBuilder().append(removed.sb.toString()).append(removed.node.val); + if (removed.node.left == null && removed.node.right == null) { + sum += getIntegerValue(sb.toString()); + } else { + if (removed.node.left != null) { + queue.add(new NodeToBinaryRepresentation(removed.node.left, sb)); + } + if (removed.node.right != null) { + queue.add(new NodeToBinaryRepresentation(removed.node.right, sb)); + } + } + } + } + return sum; + } + + private int getIntegerValue(String s) { + int value = 0; + int multiplier = 1; + for (int i = s.length() - 1; i >= 0; i--) { + value += Character.getNumericValue(s.charAt(i)) * multiplier; + multiplier *= 2; + } + return value; + } + + private static class NodeToBinaryRepresentation { + TreeNode node; + StringBuilder sb; + + public NodeToBinaryRepresentation(TreeNode node, StringBuilder sb) { + this.node = node; + this.sb = sb; + } + } +} diff --git a/Easy/Sum of Squares of Special Elements.java b/Easy/Sum of Squares of Special Elements.java new file mode 100644 index 00000000..2072eee5 --- /dev/null +++ b/Easy/Sum of Squares of Special Elements.java @@ -0,0 +1,8 @@ +class Solution { + public int sumOfSquares(int[] nums) { + return IntStream.range(0, nums.length) + .filter(i -> nums.length % (i + 1) == 0) + .map(i -> nums[i] * nums[i]) + .sum(); + } +} diff --git a/Easy/Sum of Unique Elements.java b/Easy/Sum of Unique Elements.java new file mode 100644 index 00000000..50782e0c --- /dev/null +++ b/Easy/Sum of Unique Elements.java @@ -0,0 +1,10 @@ +import java.util.Map.Entry; + +class Solution { + public int sumOfUnique(int[] nums) { + return Arrays.stream(nums).boxed() + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())) + .entrySet().stream().filter(e -> e.getValue().equals(1L)).map( + Entry::getKey).reduce(0, Integer::sum); + } +} diff --git a/Easy/Sum of Values at Indices With K Set Bits.java b/Easy/Sum of Values at Indices With K Set Bits.java new file mode 100644 index 00000000..598f65c1 --- /dev/null +++ b/Easy/Sum of Values at Indices With K Set Bits.java @@ -0,0 +1,8 @@ +class Solution { + public int sumIndicesWithKSetBits(List nums, int k) { + return IntStream.range(0, nums.size()) + .filter(idx -> Integer.bitCount(idx) == k) + .map(idx -> nums.get(idx)) + .sum(); + } +} diff --git a/Easy/Sum of Variable Length Subarrays.java b/Easy/Sum of Variable Length Subarrays.java new file mode 100644 index 00000000..5dc7d585 --- /dev/null +++ b/Easy/Sum of Variable Length Subarrays.java @@ -0,0 +1,19 @@ +class Solution { + public int subarraySum(int[] nums) { + int n = nums.length; + int[] prefixSum = new int[n]; + int sum = 0; + int result = 0; + for (int i = 0; i < n; i++) { + sum += nums[i]; + prefixSum[i] = sum; + int start = Math.max(0, i - nums[i]); + int subarraySum = prefixSum[i]; + if (start > 0) { + subarraySum -= prefixSum[start - 1]; + } + result += subarraySum; + } + return result; + } +} diff --git a/Easy/Sum of left leaves.java b/Easy/Sum of left leaves.java deleted file mode 100644 index d0f6e832..00000000 --- a/Easy/Sum of left leaves.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public int sumOfLeftLeaves(TreeNode root) { - if (root == null) return 0; - int ans = 0; - if(root.left != null) { - if(root.left.left == null && root.left.right == null) { - ans += root.left.val; - } - else { - ans += sumOfLeftLeaves(root.left); - } - } - ans += sumOfLeftLeaves(root.right); - - return ans; - } -} diff --git a/Easy/Sum of square numbers.java b/Easy/Sum of square numbers.java deleted file mode 100644 index cd8e6598..00000000 --- a/Easy/Sum of square numbers.java +++ /dev/null @@ -1,20 +0,0 @@ -class Solution { - public boolean judgeSquareSum(int c) { - int a = 0; - int b = (int)Math.sqrt(c); - - while (a <= b) { - int temp = a*a + b*b; - if (temp < c) { - a++; - } - else if (temp > c) { - b--; - } - else { - return true; - } - } - return false; - } -} diff --git a/Easy/Summary Ranges.java b/Easy/Summary Ranges.java new file mode 100644 index 00000000..0de1dc7b --- /dev/null +++ b/Easy/Summary Ranges.java @@ -0,0 +1,16 @@ +class Solution { + public List summaryRanges(int[] nums) { + List result = new ArrayList<>(); + int idx = 0; + while (idx < nums.length) { + int startIdx = idx; + int endIdx = idx; + idx++; + while (idx < nums.length && nums[idx] - nums[idx - 1] == 1) { + endIdx = idx++; + } + result.add(startIdx == endIdx ? String.valueOf(nums[startIdx]) : nums[startIdx] + "->" + nums[endIdx]); + } + return result; + } +} diff --git a/Easy/Symmetric Tree.java b/Easy/Symmetric Tree.java index bfc8e3eb..929d6ade 100644 --- a/Easy/Symmetric Tree.java +++ b/Easy/Symmetric Tree.java @@ -4,31 +4,38 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public boolean isSymmetric(TreeNode root) { - if (root == null) return true; - return isSymmetric(root.left, root.right); - } - - public boolean isSymmetric(TreeNode left, TreeNode right) { - if (left == null && right == null) { - return true; - } - else if (left == null && right != null) { - return false; - } - else if (left != null && right == null) { - return false; - } - else if (left != null && right != null) { - if (left.val != right.val) { - return false; + Queue queue = new LinkedList<>(); + queue.add(new TreeNode[]{root.left, root.right}); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeNode[] removed = queue.remove(); + TreeNode nodeOne = removed[0]; + TreeNode nodeTwo = removed[1]; + if (nodeOne == null && nodeTwo == null) { + continue; + } + if (nodeOne == null || nodeTwo == null) { + return false; + } + if (nodeOne.val != nodeTwo.val) { + return false; + } + queue.add(new TreeNode[]{nodeOne.left, nodeTwo.right}); + queue.add(new TreeNode[]{nodeOne.right, nodeTwo.left}); } } - - return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left); + return true; } } diff --git a/Easy/Take Gifts From the Richest Pile.java b/Easy/Take Gifts From the Richest Pile.java new file mode 100644 index 00000000..ea754818 --- /dev/null +++ b/Easy/Take Gifts From the Richest Pile.java @@ -0,0 +1,17 @@ +class Solution { + public long pickGifts(int[] gifts, int k) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + long totalGifts = 0; + for (int gift : gifts) { + pq.add(gift); + totalGifts += gift; + } + while (k-- > 0) { + int removedGift = pq.poll(); + int remainingGift = (int) Math.sqrt(removedGift); + totalGifts -= removedGift - remainingGift; + pq.add(remainingGift); + } + return totalGifts; + } +} diff --git a/Easy/Teemo Attacking.java b/Easy/Teemo Attacking.java new file mode 100644 index 00000000..45e33622 --- /dev/null +++ b/Easy/Teemo Attacking.java @@ -0,0 +1,11 @@ +class Solution { + public int findPoisonedDuration(int[] timeSeries, int duration) { + int totalDuration = 0; + int prevTime = timeSeries[0]; + for (int i = 1; i < timeSeries.length; i++) { + totalDuration += Math.min(duration, timeSeries[i] - prevTime); + prevTime = timeSeries[i]; + } + return totalDuration + duration; + } +} diff --git a/Easy/Teoplitz Matrix.java b/Easy/Teoplitz Matrix.java new file mode 100644 index 00000000..97bbc287 --- /dev/null +++ b/Easy/Teoplitz Matrix.java @@ -0,0 +1,12 @@ +class Solution { + public boolean isToeplitzMatrix(int[][] matrix) { + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length; j++) { + if (i > 0 && j > 0 && matrix[i][j] != matrix[i - 1][j - 1]) { + return false; + } + } + } + return true; + } +} diff --git a/Easy/The Employee That Worked on the Longest Task.java b/Easy/The Employee That Worked on the Longest Task.java new file mode 100644 index 00000000..e4d30e69 --- /dev/null +++ b/Easy/The Employee That Worked on the Longest Task.java @@ -0,0 +1,20 @@ +class Solution { + public int hardestWorker(int n, int[][] logs) { + int maxTime = 0; + int startTime = 0; + int hardestWorkerId = 0; + for (int[] log : logs) { + int taskTime = log[1] - startTime; + startTime = log[1]; + if (taskTime > maxTime) { + maxTime = taskTime; + hardestWorkerId = log[0]; + } else if (taskTime == maxTime) { + if (hardestWorkerId > log[0]) { + hardestWorkerId = log[0]; + } + } + } + return hardestWorkerId; + } +} diff --git a/Easy/The K Weakest Rows in a Matrix.java b/Easy/The K Weakest Rows in a Matrix.java new file mode 100644 index 00000000..a4a52ad7 --- /dev/null +++ b/Easy/The K Weakest Rows in a Matrix.java @@ -0,0 +1,28 @@ +class Solution { + public int[] kWeakestRows(int[][] mat, int k) { + PriorityQueue pq = + new PriorityQueue<>(Comparator.comparingInt((int[] o) -> o[1]).thenComparingInt(o -> o[0])); + for (int i = 0; i < mat.length; i++) { + pq.add(new int[]{i, findNumberOfSoldiers(mat[i])}); + } + int[] result = new int[k]; + for (int i = 0; i < k && !pq.isEmpty(); i++){ + result[i] = pq.poll()[0]; + } + return result; + } + + private int findNumberOfSoldiers(int[] row) { + int left = 0; + int right = row.length - 1; + while (left <= right) { + int mid = (left + right) / 2; + if (row[mid] == 0) { + right = mid - 1; + } else { + left = mid + 1; + } + } + return right < 0 ? 0 : left; + } +} diff --git a/Easy/Third Maximum Number.java b/Easy/Third Maximum Number.java index f4cced58..7fcce2df 100644 --- a/Easy/Third Maximum Number.java +++ b/Easy/Third Maximum Number.java @@ -1,17 +1,23 @@ -public class Solution { - public int thirdMax(int[] nums) { - Arrays.sort(nums); - ArrayList arr = new ArrayList(); - for (int i=0;i= 3) { - return arr.get(arr.size()-3); - } - else { - return arr.get(arr.size()-1); - } +class Solution { + public int thirdMax(int[] nums) { + final double BASE_VALUE = ((double) Integer.MIN_VALUE) - 1; + double firstMax = BASE_VALUE; + double secMax = BASE_VALUE; + double thirdMax = BASE_VALUE; + for (int num : nums) { + if (num > firstMax) { + thirdMax = secMax; + secMax = firstMax; + firstMax = num; + } + else if (num > secMax && num < firstMax) { + thirdMax = secMax; + secMax = num; + } + else if (num > thirdMax && num < firstMax && num < secMax) { + thirdMax = num; + } } -} \ No newline at end of file + return thirdMax == BASE_VALUE ? (int) firstMax : (int) thirdMax; + } +} diff --git a/Easy/Thousand Separator.java b/Easy/Thousand Separator.java new file mode 100644 index 00000000..a156c77e --- /dev/null +++ b/Easy/Thousand Separator.java @@ -0,0 +1,20 @@ +class Solution { + public String thousandSeparator(int n) { + if (n == 0) { + return "0"; + } + StringBuilder sb = new StringBuilder(); + int count = 0; + while (n > 0) { + int rem = n % 10; + sb.append(rem); + count++; + n /= 10; + if (count == 3 && n > 0) { + sb.append('.'); + count = 0; + } + } + return sb.reverse().toString(); + } +} diff --git a/Easy/Three Consecutive Odds.java b/Easy/Three Consecutive Odds.java new file mode 100644 index 00000000..7f2a0064 --- /dev/null +++ b/Easy/Three Consecutive Odds.java @@ -0,0 +1,10 @@ +class Solution { + public boolean threeConsecutiveOdds(int[] arr) { + for (int i = 2; i < arr.length; i++) { + if (arr[i] % 2 != 0 && arr[i - 1] % 2 != 0 && arr[i - 2] % 2 != 0) { + return true; + } + } + return false; + } +} diff --git a/Easy/Three Divisors.java b/Easy/Three Divisors.java new file mode 100644 index 00000000..7b755498 --- /dev/null +++ b/Easy/Three Divisors.java @@ -0,0 +1,14 @@ +class Solution { + public boolean isThree(int n) { + int numOfDivisors = 0; + for (int i = 1; i <= n; i++) { + if (n % i == 0) { + numOfDivisors++; + } + if (numOfDivisors > 3) { + return false; + } + } + return numOfDivisors == 3; + } +} diff --git a/Easy/Time Needed to Buy Tickets.java b/Easy/Time Needed to Buy Tickets.java new file mode 100644 index 00000000..8f7e1a57 --- /dev/null +++ b/Easy/Time Needed to Buy Tickets.java @@ -0,0 +1,13 @@ +class Solution { + public int timeRequiredToBuy(int[] tickets, int k) { + int timeRequired = 0; + for(int i = 0;i < tickets.length; i++){ + if(i <= k){ + timeRequired += Math.min(tickets[k], tickets[i]); + } else { + timeRequired += Math.min(tickets[k] - 1, tickets[i]); + } + } + return timeRequired; + } +} diff --git a/Easy/To Lower Case.java b/Easy/To Lower Case.java index a65387c9..0640e6f0 100644 --- a/Easy/To Lower Case.java +++ b/Easy/To Lower Case.java @@ -1,14 +1,6 @@ class Solution { - public String toLowerCase(String str) { - char[] chars = str.toCharArray(); - for (int i=0; i= 65 && ascii <= 90) { - ascii = 97 + (ascii - 65); - chars[i] = (char) ascii; - } - } - - return String.valueOf(chars); - } + public String toLowerCase(String s) { + return s.chars().mapToObj(c -> (char) c).map(Character::toLowerCase).map(String::valueOf) + .collect(Collectors.joining()); + } } diff --git a/Easy/Toeplitz Matrix.java b/Easy/Toeplitz Matrix.java index c5422a95..bccbd515 100644 --- a/Easy/Toeplitz Matrix.java +++ b/Easy/Toeplitz Matrix.java @@ -1,11 +1,12 @@ class Solution { - public boolean isToeplitzMatrix(int[][] matrix) { - for (int i=0;i R) return trimBST(root.left, L, R); - - root.left = trimBST(root.left, L, R); - root.right = trimBST(root.right, L, R); - - return root; - } -} diff --git a/Easy/Truncate Sentence.java b/Easy/Truncate Sentence.java new file mode 100644 index 00000000..3b910dac --- /dev/null +++ b/Easy/Truncate Sentence.java @@ -0,0 +1,12 @@ +class Solution { + public String truncateSentence(String s, int k) { + int idx = 0; + while (idx < s.length() && k > 0) { + if (s.charAt(idx) == ' ') { + k--; + } + idx++; + } + return s.substring(0, (idx == s.length() ? idx : idx - 1)); + } +} diff --git a/Easy/Two City Scheduling.java b/Easy/Two City Scheduling.java deleted file mode 100644 index 8d7a6255..00000000 --- a/Easy/Two City Scheduling.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public int twoCitySchedCost(int[][] costs) { - Arrays.sort(costs, new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - return o1[0] - o1[1] - (o2[0] - o2[1]); - } - }); - - int total = 0; - for (int i = 0; i < costs.length; i++) { - if (i < costs.length / 2) { - total += costs[i][0]; - } - else { - total += costs[i][1]; - } - } - - return total; - } -} diff --git a/Easy/Two Furthest Houses With Different Colors.java b/Easy/Two Furthest Houses With Different Colors.java new file mode 100644 index 00000000..af52bca8 --- /dev/null +++ b/Easy/Two Furthest Houses With Different Colors.java @@ -0,0 +1,13 @@ +class Solution { + public int maxDistance(int[] colors) { + int startIdx = 0; + int endIdx = colors.length - 1; + while (colors[0] == colors[endIdx]) { + endIdx--; + } + while (colors[colors.length - 1] == colors[startIdx]) { + startIdx++; + } + return Math.max(colors.length - 1 - startIdx, endIdx); + } +} diff --git a/Easy/Two Out of Three.java b/Easy/Two Out of Three.java new file mode 100644 index 00000000..7deb6a0b --- /dev/null +++ b/Easy/Two Out of Three.java @@ -0,0 +1,19 @@ +class Solution { + public List twoOutOfThree(int[] nums1, int[] nums2, int[] nums3) { + Map> map = new HashMap<>(); + updateMap(map, nums1, "1"); + updateMap(map, nums2, "2"); + updateMap(map, nums3, "3"); + return map.entrySet() + .stream() + .filter(entry -> entry.getValue().size() > 1) + .map(entry -> entry.getKey()) + .collect(Collectors.toList()); + } + + private void updateMap(Map> map, int[] nums, String key) { + for (int num : nums) { + map.computeIfAbsent(num, k -> new HashSet<>()).add(key); + } + } +} diff --git a/Easy/Two Sum II.java b/Easy/Two Sum II.java deleted file mode 100644 index 6d313038..00000000 --- a/Easy/Two Sum II.java +++ /dev/null @@ -1,19 +0,0 @@ -class Solution { - public int[] twoSum(int[] numbers, int target) { - int[] ans = new int[2]; - int i = 0; - int j = numbers.length-1; - while (numbers[i] + numbers[j] != target) { - if (numbers[i] + numbers[j] > target) { - j--; - } - else { - i++; - } - } - ans[0] = i+1; - ans[1] = j+1; - - return ans; - } -} diff --git a/Easy/Two Sum III - Data Structure Design.java b/Easy/Two Sum III - Data Structure Design.java index bafbfa64..84a33905 100644 --- a/Easy/Two Sum III - Data Structure Design.java +++ b/Easy/Two Sum III - Data Structure Design.java @@ -1,39 +1,27 @@ class TwoSum { - /** Initialize your data structure here. */ - List list; - Map map; - public TwoSum() { - list = new ArrayList<>(); - map = new HashMap<>(); - } - - /** Add the number to an internal data structure.. */ - public void add(int number) { - if (map.containsKey(number)) { - map.put(number, map.get(number) + 1); - } - else { - map.put(number, 1); - list.add(number); - } - } - - /** Find if there exists any pair of numbers which sum is equal to the value. */ - public boolean find(int value) { - for (int num : list) { - int diff = value - num; - if (diff != num && map.containsKey(diff)) { - return true; - } - - if (diff == num && map.get(diff) > 1) { - return true; - } + /** Initialize your data structure here. */ + Map map; + public TwoSum() { + map = new HashMap<>(); + } + + /** Add the number to an internal data structure.. */ + public void add(int number) { + map.put(number, map.getOrDefault(number, 0) + 1); + } + + /** Find if there exists any pair of numbers which sum is equal to the value. */ + public boolean find(int value) { + for (Integer key : map.keySet()) { + if (map.containsKey(value - key)) { + if (value - key != key || (value - key == key && map.get(key) > 1)) { + return true; } - - return false; + } } + return false; + } } /** diff --git a/Easy/Two Sum IV - Input is a BST.java b/Easy/Two Sum IV - Input is a BST.java index 84f1f8cd..c55e4b47 100644 --- a/Easy/Two Sum IV - Input is a BST.java +++ b/Easy/Two Sum IV - Input is a BST.java @@ -4,46 +4,42 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public boolean findTarget(TreeNode root, int k) { - Stack stack = new Stack<>(); - while (root != null) { - stack.push(root); - root = root.left; - } - - Set set = new HashSet<>(); - int min = popStack(stack); - set.add(min); - - while (!stack.isEmpty()) { - int num = popStack(stack); - if (set.contains(k-num)) { - return true; - } - - if (min + num > k) { - return false; - } - - set.add(num); - } - - return false; + public boolean findTarget(TreeNode root, int k) { + if (root == null) { + return false; + } + Stack stack = new Stack<>(); + Set set = new HashSet<>(); + while (root != null) { + if (set.contains(k - root.val)) { + return true; + } + stack.push(root); + set.add(root.val); + root = root.left; } - - private int popStack(Stack stack) { - TreeNode n = stack.pop(); - TreeNode right = n.right; - - while (right != null) { - stack.push(right); - right = right.left; + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + TreeNode rightNode = removed.right; + while (rightNode != null) { + if (set.contains(k - rightNode.val)) { + return true; } - - return n.val; + stack.push(rightNode); + set.add(rightNode.val); + rightNode = rightNode.left; + } } + return false; + } } diff --git a/Easy/Two Sum Less Than K.java b/Easy/Two Sum Less Than K.java index c8376739..5acfd8dc 100644 --- a/Easy/Two Sum Less Than K.java +++ b/Easy/Two Sum Less Than K.java @@ -1,20 +1,22 @@ class Solution { - public int twoSumLessThanK(int[] A, int K) { - TreeSet set = new TreeSet<>(); - int maxSum = -1; - - for (int i = 0; i < A.length; i++) { - int diff = K - A[i]; - if (diff > 0) { - Integer second = set.lower(diff); - if (second != null) { - maxSum = Math.max(maxSum, A[i] + second); - } - } - - set.add(A[i]); + public int twoSumLessThanK(int[] nums, int k) { + int[] counter = new int[1001]; + for (int num : nums) { + counter[num]++; + } + int result = -1; + int left = 1; + int right = 1000; + while (left <= right) { + if (left + right >= k || counter[right] == 0) { + right--; + } else { + if (counter[left] > (left == right ? 1 : 0)) { + result = Math.max(result, left + right); } - - return maxSum; + left++; + } } + return result; + } } diff --git a/Easy/Type of Triangle II.java b/Easy/Type of Triangle II.java new file mode 100644 index 00000000..09f0cb88 --- /dev/null +++ b/Easy/Type of Triangle II.java @@ -0,0 +1,15 @@ +class Solution { + public String triangleType(int[] nums) { + Arrays.sort(nums); + if (nums[0] + nums[1] <= nums[2]) { + return "none"; + } + if (nums[0] == nums[1] && nums[1] == nums[2]) { + return "equilateral"; + } + if (nums[0] == nums[1] || nums[1] == nums[2] || nums[0] == nums[2]) { + return "isosceles"; + } + return "scalene"; + } +} diff --git a/Easy/Ugly Number.java b/Easy/Ugly Number.java new file mode 100644 index 00000000..345df6c7 --- /dev/null +++ b/Easy/Ugly Number.java @@ -0,0 +1,11 @@ +class Solution { + public boolean isUgly(int n) { + int[] primes = {2, 3, 5}; + for (int i = 0; i < primes.length; i++) { + while (n > 1 && n % primes[i] == 0) { + n /= primes[i]; + } + } + return n == 1; + } +} diff --git a/Easy/Uncommon Words from Two Sentences.java b/Easy/Uncommon Words from Two Sentences.java index 4693b5c9..3b7eab9e 100644 --- a/Easy/Uncommon Words from Two Sentences.java +++ b/Easy/Uncommon Words from Two Sentences.java @@ -1,19 +1,20 @@ class Solution { - public static String[] uncommonFromSentences(String A, String B) { - Map map = Arrays. - stream((A + " " + B). - split("\\s+")). - collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - - List uncommon = map. - entrySet(). - stream(). - filter(e -> e.getValue() == 1). - map(e -> e.getKey()). - collect(Collectors.toList()); - - String[] ans = new String[uncommon.size()]; - - return uncommon.toArray(ans); + public String[] uncommonFromSentences(String s1, String s2) { + Map map = new HashMap<>(); + String[] wordsOne = s1.split("\\s+"); + for (String word : wordsOne) { + map.put(word, map.getOrDefault(word, 0) + 1); } + String[] wordsTwo = s2.split("\\s+"); + for (String word : wordsTwo) { + map.put(word, map.getOrDefault(word, 0) + 1); + } + List result = new ArrayList<>(); + for (String key : map.keySet()) { + if (map.get(key) == 1) { + result.add(key); + } + } + return result.toArray(new String[]{}); + } } diff --git a/Easy/Unique Email Addresses.java b/Easy/Unique Email Addresses.java index ea794493..eb3da5d5 100644 --- a/Easy/Unique Email Addresses.java +++ b/Easy/Unique Email Addresses.java @@ -1,30 +1,13 @@ class Solution { - public int numUniqueEmails(String[] emails) { - return Arrays.stream(emails) - .map(e -> getFormattedEmail(e)) - .collect(Collectors.toSet()) - .size(); - } - - private String getFormattedEmail(String email) { - StringBuilder sb = new StringBuilder(); - int idx = 0; - - while (idx < email.length()) { - if (email.charAt(idx) == '@' || email.charAt(idx) == '+') { - break; - } - if (email.charAt(idx) != '.') { - sb.append(email.charAt(idx)); - } - - idx++; - } - - while (email.charAt(idx) != '@') { - idx++; - } - - return sb.append('@').append(email.substring(idx + 1)).toString(); - } + public int numUniqueEmails(String[] emails) { + return Arrays.stream(emails).map(Solution::getFormattedEmail).collect(Collectors.toSet()).size(); + } + + private static String getFormattedEmail(String email) { + String[] strs = email.split("@"); + int plusIdx = strs[0].indexOf('+'); + String formattedLocalName = strs[0].substring(0, (plusIdx == -1 ? strs[0].length() : plusIdx)) + .replaceAll("\\.", ""); + return formattedLocalName + "@" + strs[1]; + } } diff --git a/Easy/Unique Morse Code Words.java b/Easy/Unique Morse Code Words.java index b6206351..891a02b0 100644 --- a/Easy/Unique Morse Code Words.java +++ b/Easy/Unique Morse Code Words.java @@ -1,18 +1,14 @@ class Solution { - public static int uniqueMorseRepresentations(String[] words) { - String[] codes = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."}; - Set set = new HashSet<>(); - - for (String word : words) { - StringBuilder sb = new StringBuilder(); - - for (char c : word.toCharArray()) { - sb.append(codes[c-'a']); - } - - set.add(sb.toString()); - } - - return set.size(); + private final String[] CODE = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."}; + public int uniqueMorseRepresentations(String[] words) { + return Arrays.stream(words).map(e -> getEncoding(e)).collect(Collectors.toSet()).size(); + } + + private String getEncoding(String s) { + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + sb.append(CODE[c - 'a']); } + return sb.toString(); + } } diff --git a/Easy/Unique Number of Occurrences.java b/Easy/Unique Number of Occurrences.java new file mode 100644 index 00000000..b442d51c --- /dev/null +++ b/Easy/Unique Number of Occurrences.java @@ -0,0 +1,9 @@ +class Solution { + public boolean uniqueOccurrences(int[] arr) { + Map map = new HashMap<>(); + for (int num : arr) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + return map.size() == new HashSet<>(map.values()).size(); + } +} diff --git a/Easy/Univalued Binary Tree.java b/Easy/Univalued Binary Tree.java index 2ac4196d..cba6d177 100644 --- a/Easy/Univalued Binary Tree.java +++ b/Easy/Univalued Binary Tree.java @@ -8,24 +8,20 @@ * } */ class Solution { - int currVal; - public boolean isUnivalTree(TreeNode root) { - currVal = Integer.MAX_VALUE; - return isUnivalTreeHelper(root); + public boolean isUnivalTree(TreeNode root) { + if (root == null) { + return true; } - - private boolean isUnivalTreeHelper(TreeNode root) { - if (root == null) { - return true; - } - - if (currVal == Integer.MAX_VALUE) { - currVal = root.val; - } - else if (currVal != root.val) { - return false; - } - - return isUnivalTreeHelper(root.left) && isUnivalTreeHelper(root.right); + return helper(root, root.val); + } + + private boolean helper(TreeNode root, int val) { + if (root == null) { + return true; } + if (root.val != val) { + return false; + } + return helper(root.left, val) && helper(root.right, val); + } } diff --git a/Easy/Valid Anagram.java b/Easy/Valid Anagram.java new file mode 100644 index 00000000..5bf5d251 --- /dev/null +++ b/Easy/Valid Anagram.java @@ -0,0 +1,17 @@ +class Solution { + public boolean isAnagram(String s, String t) { + int[] counter = new int[26]; + for (char c : s.toCharArray()) { + counter[c - 'a']++; + } + for (char c : t.toCharArray()) { + counter[c - 'a']--; + } + for (int i = 0; i < 26; i++) { + if (counter[i] != 0) { + return false; + } + } + return true; + } +} diff --git a/Easy/Valid Mountain Array.java b/Easy/Valid Mountain Array.java new file mode 100644 index 00000000..e8750107 --- /dev/null +++ b/Easy/Valid Mountain Array.java @@ -0,0 +1,19 @@ +class Solution { + public boolean validMountainArray(int[] A) { + if (A.length < 3) { + return false; + } + int idx = 0; + int n = A.length; + while (idx + 1 < n && A[idx] < A[idx + 1]) { + idx++; + } + if (idx == 0 || idx == n - 1) { + return false; + } + while (idx + 1 < n && A[idx] > A[idx + 1]) { + idx++; + } + return idx == n - 1; + } +} diff --git a/Easy/Valid Palindrome II.java b/Easy/Valid Palindrome II.java index 24ac1c5c..04a163a0 100644 --- a/Easy/Valid Palindrome II.java +++ b/Easy/Valid Palindrome II.java @@ -1,29 +1,22 @@ class Solution { - public boolean validPalindrome(String s) { - if (isPalindrome(s)) return true; - - int i=0; - int j = s.length()-1; - - while (i=j) { - return true; - } - - if (isPalindrome(s.substring(i+1,j+1)) || isPalindrome(s.substring(i,j))) { - return true; - } - - return false; - } - - public boolean isPalindrome(String s) { - StringBuilder sb = new StringBuilder(""); - sb.append(s); - return s.equals(sb.reverse().toString()); + return validPalindromeHelper(s.substring(0, startIdx) + s.substring(startIdx + 1), true) || + validPalindromeHelper(s.substring(0, endIdx) + s.substring(endIdx + 1), true); + } + startIdx++; + endIdx--; } + return true; + } } diff --git a/Easy/Valid Palindrome.java b/Easy/Valid Palindrome.java index 50c1efd3..efc7bd93 100644 --- a/Easy/Valid Palindrome.java +++ b/Easy/Valid Palindrome.java @@ -1,21 +1,34 @@ class Solution { - public boolean isPalindrome(String s) { - StringBuilder sb = new StringBuilder(""); - - for (char c : s.toCharArray()) { - if (Character.isLetterOrDigit(c)) { - sb.append(c); - } + public boolean isPalindrome(String s) { + int startIdx = 0; + int endIdx = s.length() - 1; + while (startIdx < endIdx) { + if (!isAlphanumeric(s.charAt(startIdx))) { + startIdx++; + } else if (!isAlphanumeric(s.charAt(endIdx))) { + endIdx--; + } else { + if (!areSame(s.charAt(startIdx), s.charAt(endIdx))) { + return false; } - - String S = sb.toString().toLowerCase(); - - return isPalindromeImpl(S); + startIdx++; + endIdx--; + } } - - public boolean isPalindromeImpl(String s) { - if (s.length() <= 1) return true; - - return s.charAt(0) == s.charAt(s.length()-1) && isPalindromeImpl(s.substring(1, s.length()-1)); + return true; + } + + private boolean areSame(char c1, char c2) { + if (Character.isAlphabetic(c1) && Character.isAlphabetic(c2)) { + return Character.toLowerCase(c1) == Character.toLowerCase(c2); + } else if (Character.isDigit(c1) && Character.isDigit(c2)) { + return c1 == c2; + } else { + return false; } + } + + private boolean isAlphanumeric(char c) { + return Character.isAlphabetic(c) || Character.isDigit(c); + } } diff --git a/Easy/Valid Parantheses.java b/Easy/Valid Parantheses.java deleted file mode 100644 index c33858a1..00000000 --- a/Easy/Valid Parantheses.java +++ /dev/null @@ -1,24 +0,0 @@ -class Solution { - public boolean isValid(String s) { - Stack stack = new Stack<>(); - String open = "{(["; - String close = "})]"; - for (int i=0;i stack = new ArrayDeque<>(); + for (char c : s.toCharArray()) { + if (c == '(' || c == '[' || c == '{') { + stack.add(c); + } else { + if (stack.isEmpty()) { + return false; + } + char popped = stack.removeLast(); + if (!((c == ')' && popped == '(') || (c == ']' && popped == '[') || (c == '}' && popped == '{'))) { + return false; + } + } + } + return stack.isEmpty(); + } +} diff --git a/Easy/Valid Perfect Square.java b/Easy/Valid Perfect Square.java index fd931dc8..16c1a509 100644 --- a/Easy/Valid Perfect Square.java +++ b/Easy/Valid Perfect Square.java @@ -1,11 +1,22 @@ class Solution { - public boolean isPerfectSquare(int num) { - int i = 1; - while(num > 0) { - num -= i; - i += 2; - } - - return num == 0; + public boolean isPerfectSquare(int num) { + if (num == 1) { + return true; } + long start = 2; + long end = num / 2; + while (start <= end) { + long mid = start + (end - start) / 2; + long currSquare = mid * mid; + if (currSquare == num) { + return true; + } + if (currSquare > num) { + end = mid - 1; + } else { + start = mid + 1; + } + } + return false; + } } diff --git a/Easy/Valid Word Abbrevation.java b/Easy/Valid Word Abbrevation.java deleted file mode 100644 index b067c570..00000000 --- a/Easy/Valid Word Abbrevation.java +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { - public static boolean validWordAbbreviation(String word, String abbr) { - char[] wordChar = word.toCharArray(); - char[] abbrChar = abbr.toCharArray(); - - int i = 0; - int j = 0; - - while (j < abbrChar.length && i < wordChar.length) { - if (abbrChar[j] == wordChar[i]) { - i++; - j++; - continue; - } - - if (abbrChar[j] <= '0' || abbrChar[j] > '9') { - return false; - } - - int start = j; - while (j= '0' && abbrChar[j] <= '9') { - ++j; - } - - int num = Integer.valueOf(abbr.substring(start, j)); - i += num; - } - - return i == wordChar.length && j == abbrChar.length; - } -} diff --git a/Easy/Valid Word Abbreviation.java b/Easy/Valid Word Abbreviation.java new file mode 100644 index 00000000..688b39fe --- /dev/null +++ b/Easy/Valid Word Abbreviation.java @@ -0,0 +1,28 @@ +class Solution { + public boolean validWordAbbreviation(String word, String abbr) { + int wordIdx = 0; + int abbrIdx = 0; + while (wordIdx < word.length() && abbrIdx < abbr.length()) { + if (Character.isDigit(abbr.charAt(abbrIdx))) { + if (abbr.charAt(abbrIdx) == '0') { + return false; + } + int count = 0; + while (abbrIdx < abbr.length() && Character.isDigit(abbr.charAt(abbrIdx))) { + count = count * 10 + Character.getNumericValue(abbr.charAt(abbrIdx++)); + } + wordIdx += count; + if (wordIdx > word.length()) { + return false; + } + } else { + if (word.charAt(wordIdx) != abbr.charAt(abbrIdx)) { + return false; + } + wordIdx++; + abbrIdx++; + } + } + return wordIdx == word.length() && abbrIdx == abbr.length(); + } +} diff --git a/Easy/Valid Word Square.java b/Easy/Valid Word Square.java new file mode 100644 index 00000000..0226d4d5 --- /dev/null +++ b/Easy/Valid Word Square.java @@ -0,0 +1,23 @@ +class Solution { + public boolean validWordSquare(List words) { + int column = 0; + for (String rowWord : words) { + String columnWord = getColumnWord(words, column++); + if (!rowWord.equals(columnWord)) { + return false; + } + } + return true; + } + + private String getColumnWord(List words, int column) { + StringBuilder sb = new StringBuilder(); + for (String word : words) { + if (column >= word.length()) { + break; + } + sb.append(word.charAt(column)); + } + return sb.toString(); + } +} diff --git a/Easy/Valid Word.java b/Easy/Valid Word.java new file mode 100644 index 00000000..c9611bbd --- /dev/null +++ b/Easy/Valid Word.java @@ -0,0 +1,21 @@ +class Solution { + + private static final Set VOWELS = Set.of('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'); + + public boolean isValid(String word) { + boolean vowelFound = false; + boolean consonantFound = false; + for (char c : word.toCharArray()) { + if (Character.isLetter(c)) { + if (VOWELS.contains(c)) { + vowelFound = true; + } else { + consonantFound = true; + } + } else if (!Character.isDigit(c)) { + return false; + } + } + return word.length() >= 3 && vowelFound && consonantFound; + } +} diff --git a/Easy/Verifying an Alien Dictionary.java b/Easy/Verifying an Alien Dictionary.java index d9445ba0..08bf111e 100644 --- a/Easy/Verifying an Alien Dictionary.java +++ b/Easy/Verifying an Alien Dictionary.java @@ -1,33 +1,27 @@ class Solution { public boolean isAlienSorted(String[] words, String order) { - Map orderMap = new HashMap<>(); - for (int i=0; i map = new HashMap<>(); + for (int i = 0; i < order.length(); i++) { + map.put(order.charAt(i), i); } - - String prev = null; - - for (String word : words) { - if (prev == null) { - prev = word; - continue; + for (int i = 0; i < words.length - 1; i++) { + if (!inOrder(words[i], words[i + 1], map)) { + return false; } - - for (int i=0; i orderMap.get(prev.charAt(i))) { - break; - } - else if (orderMap.get(word.charAt(i)) < orderMap.get(prev.charAt(i))) { - return false; - } - else if (word.length() != prev.length() && i == word.length() - 1) { - return false; - } - } - - prev = word; } - return true; } + + private static boolean inOrder(String wordOne, String wordTwo, Map map) { + for (int i = 0; i < Math.min(wordOne.length(), wordTwo.length()); i++) { + int diff = map.get(wordOne.charAt(i)) - map.get(wordTwo.charAt(i)); + if (diff < 0) { + return true; + } + if (diff > 0) { + return false; + } + } + return wordOne.length() <= wordTwo.length(); + } } diff --git a/Easy/Water Bottles.java b/Easy/Water Bottles.java new file mode 100644 index 00000000..5ef90a4f --- /dev/null +++ b/Easy/Water Bottles.java @@ -0,0 +1,13 @@ +class Solution { + public int numWaterBottles(int numBottles, int numExchange) { + int bottleCount = 0; + int emptyBottles = 0; + while (numBottles > 0) { + bottleCount += numBottles; + emptyBottles += numBottles; + numBottles = emptyBottles / numExchange; + emptyBottles %= numExchange; + } + return bottleCount; + } +} diff --git a/Easy/Winner of the Linked List Game.java b/Easy/Winner of the Linked List Game.java new file mode 100644 index 00000000..198fdd75 --- /dev/null +++ b/Easy/Winner of the Linked List Game.java @@ -0,0 +1,23 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public String gameResult(ListNode head) { + ListNode curr = head; + int count = 0; + while (curr != null) { + int even = curr.val; + int odd = curr.next.val; + count += even == odd ? 0 : (even > odd ? 1 : -1); + curr = curr.next.next; + } + return count == 0 ? "Tie" : (count > 0 ? "Even" : "Odd"); + } +} diff --git a/Easy/Word Pattern.java b/Easy/Word Pattern.java index 2617c650..5f62cf62 100644 --- a/Easy/Word Pattern.java +++ b/Easy/Word Pattern.java @@ -1,33 +1,23 @@ class Solution { - public boolean wordPattern(String pattern, String str) { - Map patternMap = new HashMap<>(); - StringBuilder patternCode = new StringBuilder(); - int maxVal = 1; - - for (char c : pattern.toCharArray()) { - if (patternMap.containsKey(c)) { - patternCode.append(patternMap.get(c)); - } - else { - patternMap.put(c, maxVal++); - patternCode.append(patternMap.get(c)); - } - } - - Map strMap = new HashMap<>(); - StringBuilder strCode = new StringBuilder(); - maxVal = 1; - - for (String s : str.trim().split("\\s+")) { - if (strMap.containsKey(s)) { - strCode.append(strMap.get(s)); - } - else { - strMap.put(s, maxVal++); - strCode.append(strMap.get(s)); - } - } - - return patternCode.toString().equals(strCode.toString()); + public boolean wordPattern(String pattern, String str) { + StringBuilder patternSb = new StringBuilder(); + Map patternMap = new HashMap<>(); + int count = 0; + for (char c : pattern.toCharArray()) { + if (!patternMap.containsKey(c)) { + patternMap.put(c, count++); + } + patternSb.append(patternMap.get(c)); } + StringBuilder strSb = new StringBuilder(); + Map strMap = new HashMap<>(); + count = 0; + for (String s : str.split("\\s+")) { + if (!strMap.containsKey(s)) { + strMap.put(s, count++); + } + strSb.append(strMap.get(s)); + } + return patternSb.toString().equals(strSb.toString()); + } } diff --git a/Easy/X of a Kind in a Deck of Cards.java b/Easy/X of a Kind in a Deck of Cards.java new file mode 100644 index 00000000..a11d0044 --- /dev/null +++ b/Easy/X of a Kind in a Deck of Cards.java @@ -0,0 +1,31 @@ +class Solution { + public boolean hasGroupsSizeX(int[] deck) { + Map map = new HashMap<>(); + int maxGroupCount = Integer.MIN_VALUE; + for (int card : deck) { + map.put(card, map.getOrDefault(card, 0) + 1); + maxGroupCount = Math.max(maxGroupCount, map.get(card)); + } + for (Integer key : map.keySet()) { + if (map.get(key) < 2) { + return false; + } + } + for (int i = 2; i <= maxGroupCount; i++) { + boolean allPaired = true; + for (Integer key : map.keySet()) { + if (map.get(key) < i) { + return false; + } + if (map.get(key) % i != 0) { + allPaired = false; + break; + } + } + if (allPaired) { + return true; + } + } + return false; + } +} diff --git a/Easy/XOR Operation in an Array.java b/Easy/XOR Operation in an Array.java new file mode 100644 index 00000000..17908959 --- /dev/null +++ b/Easy/XOR Operation in an Array.java @@ -0,0 +1,10 @@ +class Solution { + public int xorOperation(int n, int start) { + int xor = start; + for (int i = 1; i < n; i++) { + int nextNum = start + 2 * i; + xor = xor ^ nextNum; + } + return xor; + } +} diff --git a/Easy/add_digit.java b/Easy/add_digit.java deleted file mode 100644 index ee4c9f53..00000000 --- a/Easy/add_digit.java +++ /dev/null @@ -1,21 +0,0 @@ -//Solution with running time O(1) - -public class Solution { - public int addDigits(int num) { - if(num!=0) - { - if(num%9!=0) - { - return num%9; - } - else - { - return 9; - } - } - else - { - return 0; - } - } -} diff --git a/Easy/contains_duplicates.java b/Easy/contains_duplicates.java deleted file mode 100644 index e779009b..00000000 --- a/Easy/contains_duplicates.java +++ /dev/null @@ -1,35 +0,0 @@ -import java.util.Arrays; -public class Solution { - public boolean containsDuplicate(int[] nums) { - int n = nums.length; - Arrays.sort(nums); - int c=1; - for(int i=0;i al=new ArrayList(); - for (int i=0;i integers) { - int[] ret = new int[integers.size()]; - for (int i=0; i < ret.length; i++) { - ret[i] = integers.get(i).intValue(); - } - return ret; - } -} \ No newline at end of file diff --git a/Easy/majority_element.java b/Easy/majority_element.java deleted file mode 100644 index 20e4362a..00000000 --- a/Easy/majority_element.java +++ /dev/null @@ -1,21 +0,0 @@ -import java.util.ArrayList; -public class Solution { - public int majorityElement(int[] num) - { - int major = num[0]; - int appears = 1; - - for (int i = 1, count = num.length; i < count; ++i){ - if (num[i] == major) { - appears ++; - } else if (appears == 0) { - appears ++; - major = num[i]; - } else { - appears --; - } - } - - return major; - } -} \ No newline at end of file diff --git a/Easy/move_zeroes.java b/Easy/move_zeroes.java deleted file mode 100644 index 25a35ecd..00000000 --- a/Easy/move_zeroes.java +++ /dev/null @@ -1,29 +0,0 @@ -public class Main { - static void moveZeroes(int[] nums) - { - int n =nums.length; - int[] ans=new int[n]; - int count=0; - int k=0; - for(int i=0;in) - { - break; - } - i++; - } - - if(c==1) - { - return true; - } - else - { - return false; - } - } -} \ No newline at end of file diff --git a/Easy/remove_duplicates_sorted.java b/Easy/remove_duplicates_sorted.java deleted file mode 100644 index 2b157cbb..00000000 --- a/Easy/remove_duplicates_sorted.java +++ /dev/null @@ -1,21 +0,0 @@ -public class Solution { - public static int removeDuplicates(int[] A) { - if (A.length < 2) - return A.length; - - int j = 0; - int i = 1; - - while (i < A.length) { - if (A[i] == A[j]) { - i++; - } else { - j++; - A[j] = A[i]; - i++; - } - } - - return j + 1; - } -} \ No newline at end of file diff --git a/Easy/remove_element.java b/Easy/remove_element.java deleted file mode 100644 index a01de9eb..00000000 --- a/Easy/remove_element.java +++ /dev/null @@ -1,17 +0,0 @@ -public class Solution { - public int removeElement(int[] A, int elem) { - int i=0; - int j=0; - - while(j < A.length){ - if(A[j] != elem){ - A[i] = A[j]; - i++; - } - - j++; - } - - return i; -} -} \ No newline at end of file diff --git a/Easy/sum_of_two_integers.java b/Easy/sum_of_two_integers.java deleted file mode 100644 index 65f75c56..00000000 --- a/Easy/sum_of_two_integers.java +++ /dev/null @@ -1,8 +0,0 @@ -public class Solution { - public int getSum(int x, int y) { - if (y == 0) - return x; - else - return getSum( x ^ y, (x & y) << 1); - } -} \ No newline at end of file diff --git a/Easy/ugly_number.java b/Easy/ugly_number.java deleted file mode 100644 index e286ed9a..00000000 --- a/Easy/ugly_number.java +++ /dev/null @@ -1,24 +0,0 @@ -public class Solution { - public boolean isUgly(int num) { - if(num<=0) - { - return false; - } - else - { - while(num%2==0) - { - num/=2; - } - while(num%3==0) - { - num/=3; - } - while(num%5==0) - { - num/=5; - } - return num==1; - } - } -} \ No newline at end of file diff --git a/Easy/valid_anagrams.java b/Easy/valid_anagrams.java deleted file mode 100644 index c27826e8..00000000 --- a/Easy/valid_anagrams.java +++ /dev/null @@ -1,12 +0,0 @@ -import java.util.Arrays; -public class Solution { - public boolean isAnagram(String s, String t) { - char[] schar = s.toCharArray(); - char[] tchar = t.toCharArray(); - Arrays.sort(schar); - Arrays.sort(tchar); - s = new String(schar); - t = new String(tchar); - return s.equals(t); - } - } diff --git a/Explore/Easy/Arrays/Best Time to Buy and Sell Stock II.java b/Explore/Easy/Arrays/Best Time to Buy and Sell Stock II.java deleted file mode 100644 index b8ac504e..00000000 --- a/Explore/Easy/Arrays/Best Time to Buy and Sell Stock II.java +++ /dev/null @@ -1,15 +0,0 @@ -class Solution { - public int maxProfit(int[] prices) { - int profit = 0; - - for (int i=1;i 0) { - profit += diff; - } - } - - return profit; - } -} diff --git a/Explore/Easy/Arrays/Contains Duplicate.java b/Explore/Easy/Arrays/Contains Duplicate.java deleted file mode 100644 index 4268a04d..00000000 --- a/Explore/Easy/Arrays/Contains Duplicate.java +++ /dev/null @@ -1,11 +0,0 @@ -class Solution { - public boolean containsDuplicate(int[] nums) { - Set arr = new HashSet<>(); - - for (int i=0;i map1 = new HashMap<>(); - Map map2 = new HashMap<>(); - - for (int i=0;i list = new ArrayList<>(); - - for(Map.Entry entry : map1.entrySet()) { - if (map2.containsKey(entry.getKey())) { - int count = Math.min(entry.getValue(), map2.get(entry.getKey())); - while (count > 0) { - list.add(entry.getKey()); - count--; - } - } - } - - int[] ans = new int[list.size()]; - - for (int i=0;i=0;i--) { - if (digits[i] < 9) { - digits[i]++; - return digits; - } - - digits[i] = 0; - } - - int[] newDigits = new int[digits.length+1]; - newDigits[0] = 1; - - return newDigits; - } -} diff --git a/Explore/Easy/Arrays/Remove Duplicates from Sorted Array.java b/Explore/Easy/Arrays/Remove Duplicates from Sorted Array.java deleted file mode 100644 index 7f1b92d8..00000000 --- a/Explore/Easy/Arrays/Remove Duplicates from Sorted Array.java +++ /dev/null @@ -1,19 +0,0 @@ -class Solution { - public int removeDuplicates(int[] nums) { - int n = nums.length; - - if (n == 0 || n == 1) return n; - - int j = 0; - - for (int i=0;i map = new HashMap<>(); - int[] ans = new int[2]; - - for (int i=0;i rows = new HashSet(); - Set columns = new HashSet(); - Set cube = new HashSet(); - - for (int j = 0; j < 9;j++) { - - if(board[i][j]!='.' && !rows.add(board[i][j])) - return false; - - if(board[j][i]!='.' && !columns.add(board[j][i])) - return false; - - int RowIndex = 3*(i/3); - int ColIndex = 3*(i%3); - - if(board[RowIndex + j/3][ColIndex + j%3]!='.' && !cube.add(board[RowIndex + j/3][ColIndex + j%3])) - return false; - } - - } - - return true; - } -} diff --git a/Explore/Easy/Design/Min Stack.java b/Explore/Easy/Design/Min Stack.java deleted file mode 100644 index 41c7c6ed..00000000 --- a/Explore/Easy/Design/Min Stack.java +++ /dev/null @@ -1,42 +0,0 @@ -class MinStack { - private Stack stack = new Stack(); - private Stack minStack = new Stack(); - - public void push(int x) { - stack.push(x); - if (minStack.size() != 0) { - int min = minStack.peek(); - if (x <= min) { - minStack.push(x); - } - } else { - minStack.push(x); - } - } - - public void pop() { - int x = stack.pop(); - if (minStack.size() != 0) { - if (x == minStack.peek()) { - minStack.pop(); - } - } - } - - public int top() { - return stack.peek(); - } - - public int getMin() { - return minStack.peek(); - } -} - -/** - * Your MinStack object will be instantiated and called as such: - * MinStack obj = new MinStack(); - * obj.push(x); - * obj.pop(); - * int param_3 = obj.top(); - * int param_4 = obj.getMin(); - */ diff --git a/Explore/Easy/Design/Shuffle an Array.java b/Explore/Easy/Design/Shuffle an Array.java deleted file mode 100644 index 05fc1174..00000000 --- a/Explore/Easy/Design/Shuffle an Array.java +++ /dev/null @@ -1,40 +0,0 @@ -class Solution { - - private int[] nums; - private Random random; - - public Solution(int[] nums) { - this.nums = nums; - random = new Random(); - } - - /** Resets the array to its original configuration and return it. */ - public int[] reset() { - return nums; - } - - /** Returns a random shuffling of the array. */ - public int[] shuffle() { - if (nums == null) return null; - int[] shuf = nums.clone(); - for (int i=1;i n) return 0; - if (i == n) return 1; - - if (memo[i] > 0) return memo[i]; - - memo[i] = climbStairs(memo, i+1, n) + climbStairs(memo, i+2, n); - - return memo[i]; - } -} diff --git a/Explore/Easy/Dynamic Programming/House Robber.java b/Explore/Easy/Dynamic Programming/House Robber.java deleted file mode 100644 index 4f5b502c..00000000 --- a/Explore/Easy/Dynamic Programming/House Robber.java +++ /dev/null @@ -1,12 +0,0 @@ -class Solution { - public int rob(int[] nums) { - int[][] dp = new int[nums.length+1][2]; - - for (int i=1;i<=nums.length;i++) { - dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]); - dp[i][1] = nums[i-1] + dp[i-1][0]; - } - - return Math.max(dp[nums.length][0], dp[nums.length][1]); - } -} diff --git a/Explore/Easy/Dynamic Programming/Maximum Subarray.java b/Explore/Easy/Dynamic Programming/Maximum Subarray.java deleted file mode 100644 index 70fa9505..00000000 --- a/Explore/Easy/Dynamic Programming/Maximum Subarray.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public int maxSubArray(int[] nums) { - - int sum = 0; - int max = Integer.MIN_VALUE; - int i = 0; - - while (i l2.val) { - temp.next = new ListNode(l2.val); - temp = temp.next; - l2 = l2.next; - } - else { - temp.next = new ListNode(l1.val); - temp = temp.next; - l1 = l1.next; - } - } - else if (l1 != null) { - temp.next = new ListNode(l1.val); - temp = temp.next; - l1 = l1.next; - } - else if (l2 != null) { - temp.next = new ListNode(l2.val); - temp = temp.next; - l2 = l2.next; - } - } - - return ans.next; - } -} diff --git a/Explore/Easy/Linked Lists/Palindrome Linked List.java b/Explore/Easy/Linked Lists/Palindrome Linked List.java deleted file mode 100644 index 2b7a5c25..00000000 --- a/Explore/Easy/Linked Lists/Palindrome Linked List.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public boolean isPalindrome(ListNode head) { - if (head == null || head.next == null) return true; - int l = 0; - ListNode curr = head; - - while (curr != null) { - l++; - curr = curr.next; - } - - int i = 1; - curr = head; - - while (i < l/2) { - curr = curr.next; - i++; - } - - ListNode mid = reverse(curr.next); - - curr = head; - - while(mid != null) { - if (curr.val != mid.val) return false; - curr = curr.next; - mid = mid.next; - } - - return true; - } - - public ListNode reverse(ListNode head) { - ListNode curr = head; - ListNode prev = null; - ListNode next = null; - - while(curr != null) { - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - - return prev; - } -} diff --git a/Explore/Easy/Linked Lists/Remove Nth Node From End of List.java b/Explore/Easy/Linked Lists/Remove Nth Node From End of List.java deleted file mode 100644 index a319e3ec..00000000 --- a/Explore/Easy/Linked Lists/Remove Nth Node From End of List.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public ListNode removeNthFromEnd(ListNode head, int n) { - int l = 0; - ListNode curr = head; - - while (curr != null) { - l++; - curr = curr.next; - } - - if (l -n == 0) { - ListNode tmp = head.next; - head = null; - return tmp; - } - - curr = head; - int c = 1; - l = l-n; - - while(c != l) { - c++; - curr = curr.next; - } - - curr.next = curr.next.next; - - return head; - } -} diff --git a/Explore/Easy/Linked Lists/Reverse Linked List.java b/Explore/Easy/Linked Lists/Reverse Linked List.java deleted file mode 100644 index 8aeaa6ae..00000000 --- a/Explore/Easy/Linked Lists/Reverse Linked List.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public ListNode reverseList(ListNode head) { - ListNode curr = head; - ListNode prev = null; - ListNode next = null; - - while (curr != null) { - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - - return prev; - } -} diff --git a/Explore/Easy/Math/Count Primes.java b/Explore/Easy/Math/Count Primes.java deleted file mode 100644 index cce1c733..00000000 --- a/Explore/Easy/Math/Count Primes.java +++ /dev/null @@ -1,21 +0,0 @@ -class Solution { - public int countPrimes(int n) { - int[] arr = new int[n]; - - for (int i=2;i fizzBuzz(int n) { - List ans = new ArrayList<>(); - for (int i=1;i<=n;i++) { - if (i%3 != 0 && i%5 != 0) { - ans.add(String.valueOf(i)); - } - else if (i%3 == 0 && i%5 == 0) { - ans.add("FizzBuzz"); - } - else if(i%3 == 0) { - ans.add("Fizz"); - } - else { - ans.add("Buzz"); - } - } - - return ans; - } -} diff --git a/Explore/Easy/Math/Power of Three.java b/Explore/Easy/Math/Power of Three.java deleted file mode 100644 index ed03bb74..00000000 --- a/Explore/Easy/Math/Power of Three.java +++ /dev/null @@ -1,11 +0,0 @@ -class Solution { - public boolean isPowerOfThree(int n) { - if (n < 1) return false; - - while (n%3 == 0) { - n /= 3; - } - - return n == 1; - } -} diff --git a/Explore/Easy/Math/Roman to Integer.java b/Explore/Easy/Math/Roman to Integer.java deleted file mode 100644 index 2078e1d5..00000000 --- a/Explore/Easy/Math/Roman to Integer.java +++ /dev/null @@ -1,39 +0,0 @@ -class Solution { - public int romanToInt(String s) { - String symbol = "IVXLCDM"; - int[] val = {1, 5, 10, 50, 100, 500, 1000}; - - char[] s_char = s.toCharArray(); - - int[] s_val = new int[s_char.length]; - - for (int i=0;i= s2) { - total += s1; - k++; - } - else{ - total += s2-s1; - k += 2; - } - } - else { - total += s1; - k++; - } - } - - return total; - } -} diff --git a/Explore/Easy/Others/Hamming Distance.java b/Explore/Easy/Others/Hamming Distance.java deleted file mode 100644 index 057a1b25..00000000 --- a/Explore/Easy/Others/Hamming Distance.java +++ /dev/null @@ -1,5 +0,0 @@ -class Solution { - public int hammingDistance(int x, int y) { - return Integer.bitCount(x^y); - } -} diff --git a/Explore/Easy/Others/Missing Number.java b/Explore/Easy/Others/Missing Number.java deleted file mode 100644 index c9886640..00000000 --- a/Explore/Easy/Others/Missing Number.java +++ /dev/null @@ -1,11 +0,0 @@ -class Solution { - public int missingNumber(int[] nums) { - int xor = 0; - int i = 0; - for (i=0;i map = new HashMap<>(); - public List> generate(int numRows) { - List> ans = new ArrayList<>(); - - for (int i=0;i temp = new ArrayList<>(); - for(int j = 0;j<=i;j++) { - if (i == j || j == 0) { - temp.add(1); - } - else { - temp.add(ans.get(i-1).get(j-1) + ans.get(i-1).get(j)); - } - } - - ans.add(temp); - } - - return ans; - } -} diff --git a/Explore/Easy/Others/Reverse Bits.java b/Explore/Easy/Others/Reverse Bits.java deleted file mode 100644 index 36ec5763..00000000 --- a/Explore/Easy/Others/Reverse Bits.java +++ /dev/null @@ -1,13 +0,0 @@ -public class Solution { - // you need treat n as an unsigned value - public int reverseBits(int n) { - int result = 0; - for (int i = 0; i < 32; i++) { - result += n & 1; - n >>>= 1; - if (i < 31) - result <<= 1; - } - return result; - } -} diff --git a/Explore/Easy/Others/Valid Parantheses.java b/Explore/Easy/Others/Valid Parantheses.java deleted file mode 100644 index 10033b6a..00000000 --- a/Explore/Easy/Others/Valid Parantheses.java +++ /dev/null @@ -1,23 +0,0 @@ -class Solution { - public boolean isValid(String s) { - String start = "({["; - String end = ")}]"; - - Stack stack = new Stack<>(); - - for (int i=0;i=0 && j>=0) { - if (nums1[i] > nums2[j]) { - nums1[k--] = nums1[i--]; - } - else { - nums1[k--] = nums2[j--]; - } - } - - while(j >= 0) { - nums1[k--] = nums2[j--]; - } - } -} diff --git a/Explore/Easy/Strings/Count and Say.java b/Explore/Easy/Strings/Count and Say.java deleted file mode 100644 index 8fd83c74..00000000 --- a/Explore/Easy/Strings/Count and Say.java +++ /dev/null @@ -1,32 +0,0 @@ -class Solution { - public String countAndSay(int n) { - String first = "1"; - String str = "11"; - - if (n == 1) return first; - if (n == 2) return str; - - for (int i = 3; i<=n; i++) { - str += "$"; - int len = str.length(); - - int cnt = 1; - String tmp = ""; - - for (int j = 1; j < len; j++) { - if (str.charAt(j) != str.charAt(j-1)) { - tmp += String.valueOf(cnt); - tmp += str.charAt(j-1); - - cnt = 1; - } - - else cnt++; - } - - str = tmp; - } - - return str; - } -} diff --git a/Explore/Easy/Strings/First Unique Character in a String.java b/Explore/Easy/Strings/First Unique Character in a String.java deleted file mode 100644 index 5c20c16d..00000000 --- a/Explore/Easy/Strings/First Unique Character in a String.java +++ /dev/null @@ -1,17 +0,0 @@ -class Solution { - public int firstUniqChar(String s) { - int[] ascii = new int[26]; - - for (int i=0;i= '0' && c[i] <= '9') { - int digit = c[i] - '0'; - if (num > bound || (num == bound && digit > 7)) { - return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; - } - - num = num * 10 + digit; - i++; - } - return sign * num; - } -} diff --git a/Explore/Easy/Strings/Valid Anagram.java b/Explore/Easy/Strings/Valid Anagram.java deleted file mode 100644 index aaa0953a..00000000 --- a/Explore/Easy/Strings/Valid Anagram.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public boolean isAnagram(String s, String t) { - - if (s.length() != t.length()) return false; - - int[] ascii = new int[26]; - - for (int i=0;i= 97 && (int) s.charAt(i) <= 122) || Character.isDigit(s.charAt(i))) { - sb.append(String.valueOf(s.charAt(i))); - } - } - - return sb.toString().toLowerCase().equals(sb.reverse().toString().toLowerCase()); - } -} diff --git a/Explore/Easy/Trees/Binary Tree Level Order Traversal.java b/Explore/Easy/Trees/Binary Tree Level Order Traversal.java deleted file mode 100644 index c1323496..00000000 --- a/Explore/Easy/Trees/Binary Tree Level Order Traversal.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public List> levelOrder(TreeNode root) { - Queue queue = new LinkedList<>(); - List> ans = new ArrayList<>(); - - if (root == null) return ans; - - queue.add(root); - - while(!queue.isEmpty()) { - List temp = new ArrayList<>(); - while (!queue.isEmpty()) { - temp.add(queue.remove()); - } - - List lst = new ArrayList<>(); - - for (TreeNode t : temp) { - lst.add(t.val); - - if (t.left != null) queue.add(t.left); - if (t.right != null) queue.add(t.right); - } - - ans.add(lst); - } - - return ans; - } -} diff --git a/Explore/Easy/Trees/Convert Sorted Array to Binary Search Tree.java b/Explore/Easy/Trees/Convert Sorted Array to Binary Search Tree.java deleted file mode 100644 index 92393eda..00000000 --- a/Explore/Easy/Trees/Convert Sorted Array to Binary Search Tree.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public TreeNode sortedArrayToBST(int[] nums) { - return sortedArrayToBST(nums, 0, nums.length-1); - } - - public TreeNode sortedArrayToBST(int arr[], int start, int end) { - - if (start > end) { - return null; - } - - int mid = (start + end) / 2; - - TreeNode node = new TreeNode(arr[mid]); - node.left = sortedArrayToBST(arr, start, mid - 1); - node.right = sortedArrayToBST(arr, mid + 1, end); - - return node; - } -} diff --git a/Explore/Easy/Trees/Maximum Depth of Binary Tree.java b/Explore/Easy/Trees/Maximum Depth of Binary Tree.java deleted file mode 100644 index 8dc92307..00000000 --- a/Explore/Easy/Trees/Maximum Depth of Binary Tree.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public int maxDepth(TreeNode root) { - if (root == null) return 0; - - return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); - } -} diff --git a/Explore/Easy/Trees/Symmetric Tree.java b/Explore/Easy/Trees/Symmetric Tree.java deleted file mode 100644 index 65a6d838..00000000 --- a/Explore/Easy/Trees/Symmetric Tree.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public boolean isSymmetric(TreeNode root) { - if (root == null) return true; - - return isSymmetric(root.left, root.right); - } - - public boolean isSymmetric(TreeNode rLeft, TreeNode rRight) { - if (rLeft == null && rRight == null) { - return true; - } - if ((rLeft == null && rRight != null) || (rLeft != null && rRight == null)) { - return false; - } - - if (rLeft != null && rRight != null) { - if (rLeft.val != rRight.val) return false; - } - - return isSymmetric(rLeft.left, rRight.right) && isSymmetric(rLeft.right, rRight.left); - } -} diff --git a/Explore/Easy/Trees/Validate Binary Search Tree.java b/Explore/Easy/Trees/Validate Binary Search Tree.java deleted file mode 100644 index ad07834a..00000000 --- a/Explore/Easy/Trees/Validate Binary Search Tree.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public boolean isValidBST(TreeNode root) { - Stack stack = new Stack<>(); - TreeNode prev = null; - - while (root != null || !stack.empty()) { - while(root != null) { - stack.push(root); - root = root.left; - } - - if (prev != null && prev.val >= stack.peek().val) { - return false; - } - - root = stack.pop(); - prev = root; - root = root.right; - } - - return true; - } -} diff --git a/Explore/Medium/Arrays and Strings/3Sum.java b/Explore/Medium/Arrays and Strings/3Sum.java deleted file mode 100644 index fa68d8bb..00000000 --- a/Explore/Medium/Arrays and Strings/3Sum.java +++ /dev/null @@ -1,34 +0,0 @@ -class Solution { - public List> threeSum(int[] nums) { - - Arrays.sort(nums); - - List> ans = new ArrayList<>(); - - for (int i=0;i 0 && nums[i] == nums[i-1]) continue; - - int j = i+1; - int k = nums.length-1; - - int target = -nums[i]; - - while (j target) k--; - else { - j++; - } - } - } - - return ans; - } -} diff --git a/Explore/Medium/Arrays and Strings/Group Anagrams.java b/Explore/Medium/Arrays and Strings/Group Anagrams.java deleted file mode 100644 index 758782ae..00000000 --- a/Explore/Medium/Arrays and Strings/Group Anagrams.java +++ /dev/null @@ -1,30 +0,0 @@ -class Solution { - public List> groupAnagrams(String[] strs) { - Map> map = new HashMap<>(); - - for (String s : strs) { - char[] ar = s.toCharArray(); - Arrays.sort(ar); - String s_sorted = String.valueOf(ar); - - if (map.containsKey(s_sorted)) { - List temp = map.get(s_sorted); - temp.add(s); - map.put(s_sorted, temp); - } - else { - List temp = new ArrayList<>(); - temp.add(s); - map.put(s_sorted, temp); - } - } - - List> ans = new ArrayList<>(); - - for (Map.Entry> entry : map.entrySet()) { - ans.add(entry.getValue()); - } - - return ans; - } -} diff --git a/Explore/Medium/Arrays and Strings/Increasing Triplet Subsequence.java b/Explore/Medium/Arrays and Strings/Increasing Triplet Subsequence.java deleted file mode 100644 index b90490c6..00000000 --- a/Explore/Medium/Arrays and Strings/Increasing Triplet Subsequence.java +++ /dev/null @@ -1,21 +0,0 @@ -class Solution { - public boolean increasingTriplet(int[] nums) { - if (nums.length < 3) return false; - - int x = Integer.MAX_VALUE; - int y = Integer.MAX_VALUE; - - for (int i=0;i= z) { - x = z; - } - else if (y >= z) { - y = z; - } - else return true; - } - - return false; - } -} diff --git a/Explore/Medium/Arrays and Strings/Longest Palindromic Substring.java b/Explore/Medium/Arrays and Strings/Longest Palindromic Substring.java deleted file mode 100644 index 569508e3..00000000 --- a/Explore/Medium/Arrays and Strings/Longest Palindromic Substring.java +++ /dev/null @@ -1,28 +0,0 @@ -class Solution { - public String longestPalindrome(String s) { - int start = 0; - int end = 0; - - for (int i=0;i end - start) { - start = i - (len - 1)/2; - end = i + len/2; - } - } - - return s.substring(start, end+1); - } - - public int expandCenter(String s, int left, int right) { - while (left >=0 && right < s.length() && s.charAt(left) == s.charAt(right)) { - left--; - right++; - } - - return right - left - 1; - } -} diff --git a/Explore/Medium/Arrays and Strings/Longest Substring Without Repeating Characters.java b/Explore/Medium/Arrays and Strings/Longest Substring Without Repeating Characters.java deleted file mode 100644 index bde380e6..00000000 --- a/Explore/Medium/Arrays and Strings/Longest Substring Without Repeating Characters.java +++ /dev/null @@ -1,22 +0,0 @@ -class Solution { - public int lengthOfLongestSubstring(String s) { - - Set set = new HashSet<>(); - int maxLen = Integer.MIN_VALUE; - - int i=0, j=0; - int n = s.length(); - - while(i findMissingRanges(int[] nums, int lower, int upper) { - List list = new ArrayList<>(); - - if (nums.length == 0) { - list.add(getString(lower, upper)); - return list; - } - - List range = getRange(nums); - int i = 0; - - while (lower <= upper && i < range.size()) { - String s = range.get(i); - if (s.indexOf('>') != -1) { - int start = Integer.parseInt(s.split("->")[0]); - int end = Integer.parseInt(s.split("->")[1]); - - if (lower != start) { - list.add(getString(lower, start-1)); - } - - lower = end + 1; - } - else { - int num = Integer.parseInt(s); - if (lower != num) { - list.add(getString(lower, num-1)); - } - - lower = num + 1; - } - - i++; - } - - String s = range.get(range.size()-1); - if (s.indexOf('>') != -1) { - int start = Integer.parseInt(s.split("->")[0]); - int end = Integer.parseInt(s.split("->")[1]); - - if (end != upper) { - list.add(getString(end+1, upper)); - } - } - else { - int num = Integer.parseInt(s); - if (upper != num) { - list.add(getString(num+1, upper)); - } - } - - return list; - } - - private static List getRange(int[] num) { - - List list = new ArrayList<>(); - if (num.length == 0) { - return list; - } - - int i = 1; - StringBuilder sb = new StringBuilder(); - sb.append(num[0]); - int count = 1; - - while (i 1) { - sb.append("->").append(num[i-1]); - list.add(sb.toString()); - } - else { - list.add(sb.toString()); - } - - sb = new StringBuilder(); - sb.append(num[i]); - count = 1; - } - - i++; - } - - if (count > 1) { - sb.append("->").append(num[num.length-1]); - } - - list.add(sb.toString()); - - return list; - } - - private static String getString(int start, int end) { - StringBuilder sb = new StringBuilder(); - if (start == end) { - sb.append(start); - } - else { - sb.append(start).append("->").append(end); - } - - return sb.toString(); - } -} diff --git a/Explore/Medium/Arrays and Strings/Set Matrix Zeroes.java b/Explore/Medium/Arrays and Strings/Set Matrix Zeroes.java deleted file mode 100644 index 6c043646..00000000 --- a/Explore/Medium/Arrays and Strings/Set Matrix Zeroes.java +++ /dev/null @@ -1,64 +0,0 @@ -class Solution { - public void setZeroes(int[][] arr) { - if (arr.length == 0 || arr[0].length == 0) { - return; - } - - - int numOfRows = arr.length; - int numOfCols = arr[0].length; - boolean firstRowZero = false; - boolean firstColZero = false; - - for (int i = 0; i < numOfCols; i++) { - if (arr[0][i] == 0) { - firstRowZero = true; - break; - } - } - - for (int i = 0; i < numOfRows; i++) { - if (arr[i][0] == 0) { - firstColZero = true; - break; - } - } - - for (int i = 1; i < numOfRows; i++) { - for (int j = 0; j < numOfCols; j++) { - if (arr[i][j] == 0) { - arr[0][j] = 0; - arr[i][0] = 0; - } - } - } - - for (int i = 1; i < numOfRows; i++) { - if (arr[i][0] == 0) { - for (int j = 1; j < numOfCols; j++) { - arr[i][j] = 0; - } - } - } - - for (int i = 0; i < numOfCols; i++) { - if (arr[0][i] == 0) { - for (int j = 1; j < numOfRows; j++) { - arr[j][i] = 0; - } - } - } - - if (firstRowZero) { - for (int i = 0; i < numOfCols; i++) { - arr[0][i] = 0; - } - } - - if (firstColZero) { - for (int i = 0; i < numOfRows; i++) { - arr[i][0] = 0; - } - } - } -} diff --git a/Explore/Medium/Linked Lists/Add Two Numbers.java b/Explore/Medium/Linked Lists/Add Two Numbers.java deleted file mode 100644 index 5ec675ce..00000000 --- a/Explore/Medium/Linked Lists/Add Two Numbers.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - ListNode ans = new ListNode(0); - ListNode curr = ans; - - int carry = 0; - - while (l1 != null || l2 != null) { - - int temp = 0; - - if (l1 != null && l2 != null) { - temp = l1.val + l2.val + carry; - l1 = l1.next; - l2 = l2.next; - } - else if (l1 != null && l2 == null) { - temp = l1.val + carry; - l1 = l1.next; - } - else if (l1 == null && l2 != null) { - temp = l2.val + carry; - l2 = l2.next; - } - - carry = temp > 9 ? temp/10 : 0; - temp = temp > 9 ? temp%10 : temp; - - curr.next = new ListNode(temp); - curr = curr.next; - } - - if (carry != 0) { - curr.next = new ListNode(carry); - curr = curr.next; - } - - return ans.next; - } -} diff --git a/Explore/Medium/Linked Lists/Intersection of Two Linked Lists.java b/Explore/Medium/Linked Lists/Intersection of Two Linked Lists.java deleted file mode 100644 index 316eefbe..00000000 --- a/Explore/Medium/Linked Lists/Intersection of Two Linked Lists.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { - * val = x; - * next = null; - * } - * } - */ -public class Solution { - public ListNode getIntersectionNode(ListNode headA, ListNode headB) { - - if (headA == null || headB == null) return null; - - int lenA = getLength(headA); - int lenB = getLength(headB); - - ListNode currA = headA; - ListNode currB = headB; - - if (lenB > lenA) { - int diff = lenB - lenA; - - while (diff != 0) { - currB = currB.next; - diff--; - } - } - else { - int diff = lenA - lenB; - - while (diff != 0) { - currA = currA.next; - diff--; - } - } - - while(currB != null) { - if (currA == currB) return currA; - currA = currA.next; - currB = currB.next; - } - - return null; - } - - public int getLength(ListNode head) { - int l = 0; - while (head != null) { - head = head.next; - l++; - } - - return l; - } -} diff --git a/Explore/Medium/Linked Lists/Odd Even Linked List.java b/Explore/Medium/Linked Lists/Odd Even Linked List.java deleted file mode 100644 index 92b55544..00000000 --- a/Explore/Medium/Linked Lists/Odd Even Linked List.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public ListNode oddEvenList(ListNode head) { - - if (head == null || head.next == null) return head; - - ListNode odd = head; - ListNode even = head.next; - ListNode evenHead = even; - - while(even != null && even.next != null) { - odd.next = odd.next.next; - even.next = even.next.next; - - odd = odd.next; - even = even.next; - } - - odd.next = evenHead; - - return head; - } -} diff --git a/Explore/Medium/Sorting & Searching/Sort Colors.java b/Explore/Medium/Sorting & Searching/Sort Colors.java deleted file mode 100644 index 4a8fdd4e..00000000 --- a/Explore/Medium/Sorting & Searching/Sort Colors.java +++ /dev/null @@ -1,23 +0,0 @@ -class Solution { - public void sortColors(int[] nums) { - - int n0 = -1; - int n1 = -1; - int n2 = -1; - - for (int i=0;i topKFrequent(int[] nums, int k) { - List[] bucket = new List[nums.length+1]; - Map frequencyMap = new HashMap<>(); - for (int n : nums) { - frequencyMap.put(n, frequencyMap.getOrDefault(n, 0) + 1); - } - - for (int key : frequencyMap.keySet()) { - int frequency = frequencyMap.get(key); - - if (bucket[frequency] == null) { - bucket[frequency] = new ArrayList<>(); - } - - bucket[frequency].add(key); - } - - List res = new ArrayList<>(); - - for (int pos = bucket.length - 1; pos >= 0 && res.size() < k; pos--) { - if (bucket[pos] != null) { - res.addAll(bucket[pos]); - } - } - - return res; - } -} diff --git a/Explore/Medium/Trees and Graphs/Binary Tree Inorder Traversal.java b/Explore/Medium/Trees and Graphs/Binary Tree Inorder Traversal.java deleted file mode 100644 index 811b92e6..00000000 --- a/Explore/Medium/Trees and Graphs/Binary Tree Inorder Traversal.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public List inorderTraversal(TreeNode root) { - List list = new ArrayList<>(); - - Stack stack = new Stack<>(); - - while (root != null || !stack.empty()) { - - while(root != null) { - stack.push(root); - root = root.left; - } - - root = stack.pop(); - - list.add(root.val); - root = root.right; - } - - return list; - } -} diff --git a/Explore/Medium/Trees and Graphs/Binary Tree Zigzag Level Order Traversal.java b/Explore/Medium/Trees and Graphs/Binary Tree Zigzag Level Order Traversal.java deleted file mode 100644 index a87e311c..00000000 --- a/Explore/Medium/Trees and Graphs/Binary Tree Zigzag Level Order Traversal.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public List> zigzagLevelOrder(TreeNode root) { - - Stack s1 = new Stack<>(); - Stack s2 = new Stack<>(); - - List> ans = new ArrayList<>(); - - if (root == null) return ans; - - s1.push(root); - - while (!s1.empty() || !s2.empty()) { - - List list = new ArrayList<>(); - - while (!s1.empty()) { - TreeNode temp = s1.pop(); - - list.add(temp.val); - - if (temp.left != null) { - s2.add(temp.left); - } - - if (temp.right != null) { - s2.add(temp.right); - } - } - - if (list.size() > 0) { - ans.add(list); - continue; - } - - while (!s2.empty()) { - TreeNode temp = s2.pop(); - list.add(temp.val); - - if (temp.right != null) { - s1.add(temp.right); - } - - if (temp.left != null) { - s1.add(temp.left); - } - - } - - ans.add(list); - } - - return ans; - } -} diff --git a/Explore/Medium/Trees and Graphs/Construct Binary Tree from Preorder and Inorder Traversal.java b/Explore/Medium/Trees and Graphs/Construct Binary Tree from Preorder and Inorder Traversal.java deleted file mode 100644 index ddfa9f42..00000000 --- a/Explore/Medium/Trees and Graphs/Construct Binary Tree from Preorder and Inorder Traversal.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public TreeNode buildTree(int[] preorder, int[] inorder) { - return buildTreeHelper(0, 0, inorder.length-1, preorder, inorder); - } - - public TreeNode buildTreeHelper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) { - if (preStart > preorder.length-1 || inStart > inEnd) { - return null; - } - - TreeNode root = new TreeNode(preorder[preStart]); - int inIndex = -1; - - for (int i = inStart; i <= inEnd; i++) { - if (inorder[i] == root.val) { - inIndex = i; - break; - } - } - - root.left = buildTreeHelper(preStart+1, inStart, inIndex-1, preorder, inorder); - root.right = buildTreeHelper(preStart + inIndex - inStart + 1, inIndex + 1, inEnd, preorder, inorder); - - return root; - } -} \ No newline at end of file diff --git a/Explore/Medium/Trees and Graphs/Kth Smallest Element in a BST.java b/Explore/Medium/Trees and Graphs/Kth Smallest Element in a BST.java deleted file mode 100644 index 6b46a29f..00000000 --- a/Explore/Medium/Trees and Graphs/Kth Smallest Element in a BST.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public int kthSmallest(TreeNode root, int k) { - Stack stack = new Stack<>(); - List list = new ArrayList<>(); - - while(root != null || !stack.empty()) { - while (root != null) { - stack.push(root); - root = root.left; - } - - root = stack.pop(); - list.add(root.val); - root = root.right; - } - - return list.get(k-1); - } -} diff --git a/Explore/Medium/Trees and Graphs/Populating Next Right Pointers in Each Node.java b/Explore/Medium/Trees and Graphs/Populating Next Right Pointers in Each Node.java deleted file mode 100644 index b012ec6b..00000000 --- a/Explore/Medium/Trees and Graphs/Populating Next Right Pointers in Each Node.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Definition for binary tree with next pointer. - * public class TreeLinkNode { - * int val; - * TreeLinkNode left, right, next; - * TreeLinkNode(int x) { val = x; } - * } - */ -public class Solution { - public void connect(TreeLinkNode root) { - - TreeLinkNode start=root; - - while(start!=null){ - - TreeLinkNode cur=start; - - while(cur!=null){ - if(cur.left!=null) cur.left.next=cur.right; - if(cur.right!=null && cur.next!=null) cur.right.next=cur.next.left; - - cur=cur.next; - } - - start=start.left; - } - } -} diff --git a/Hard/Add Edges to Make Degrees of All Nodes Even.java b/Hard/Add Edges to Make Degrees of All Nodes Even.java new file mode 100644 index 00000000..2258af63 --- /dev/null +++ b/Hard/Add Edges to Make Degrees of All Nodes Even.java @@ -0,0 +1,48 @@ +class Solution { + public boolean isPossible(int n, List> edges) { + Map> graph = new HashMap<>(); + for (List edge : edges) { + graph.computeIfAbsent(edge.get(0), k -> new HashSet<>()).add(edge.get(1)); + graph.computeIfAbsent(edge.get(1), k -> new HashSet<>()).add(edge.get(0)); + } + List nodeWithOddEdges = graph.entrySet() + .stream() + .filter(e -> e.getValue().size() % 2 != 0) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + if (nodeWithOddEdges.size() == 0) { + return true; + } + if (nodeWithOddEdges.size() == 2) { + Integer nodeOne = nodeWithOddEdges.get(0); + Integer nodeTwo = nodeWithOddEdges.get(1); + if (!hasEdge(graph, nodeOne, nodeTwo)) { + return true; + } + for (int i = 1; i <= n; i++) { + if (i == nodeOne || i == nodeTwo) { + continue; + } + if (!hasEdge(graph, i, nodeOne) && !hasEdge(graph, i, nodeTwo)) { + return true; + } + } + } + if (nodeWithOddEdges.size() == 4) { + Integer nodeOne = nodeWithOddEdges.get(0); + Integer nodeTwo = nodeWithOddEdges.get(1); + Integer nodeThree = nodeWithOddEdges.get(2); + Integer nodeFour = nodeWithOddEdges.get(3); + if ((!hasEdge(graph, nodeOne, nodeTwo) && !hasEdge(graph, nodeThree, nodeFour)) || + (!hasEdge(graph, nodeOne, nodeThree) && !hasEdge(graph, nodeTwo, nodeFour)) || + (!hasEdge(graph, nodeOne, nodeFour) && !hasEdge(graph, nodeTwo, nodeThree))) { + return true; + } + } + return false; + } + + private static boolean hasEdge(Map> graph, int nodeOne, int nodeTwo) { + return graph.getOrDefault(nodeOne, new HashSet<>()).contains(nodeTwo); + } +} diff --git a/Hard/Alien Dictionary.java b/Hard/Alien Dictionary.java new file mode 100644 index 00000000..939de634 --- /dev/null +++ b/Hard/Alien Dictionary.java @@ -0,0 +1,48 @@ +class Solution { + public String alienOrder(String[] words) { + Map> graph = new HashMap<>(); + for (String word : words) { + for (char c : word.toCharArray()) { + graph.computeIfAbsent(c, k -> new HashSet<>()); + } + } + for (int i = 0; i < words.length - 1; i++) { + String word1 = words[i]; + String word2 = words[i + 1]; + int minLength = Math.min(word1.length(), word2.length()); + if (word1.length() > word2.length() && word1.startsWith(word2)) { + return ""; + } + for (int j = 0; j < minLength; j++) { + if (word1.charAt(j) != word2.charAt(j)) { + graph.get(word1.charAt(j)).add(word2.charAt(j)); + break; + } + } + } + StringBuilder sb = new StringBuilder(); + Map visited = new HashMap<>(); + for (Character c : graph.keySet()) { + if (dfs(c, graph, sb, visited)) { + return ""; + } + } + return sb.reverse().toString(); + } + + private boolean dfs(Character c, Map> graph, + StringBuilder sb, Map visited) { + if (visited.containsKey(c)) { + return visited.get(c); + } + visited.put(c, true); + for (Character neighbor : graph.getOrDefault(c, new HashSet<>())) { + if (dfs(neighbor, graph, sb, visited)) { + return true; + } + } + visited.put(c, false); + sb.append(c); + return false; + } +} diff --git a/Hard/All O`one Data Structure.java b/Hard/All O`one Data Structure.java new file mode 100644 index 00000000..211e4f01 --- /dev/null +++ b/Hard/All O`one Data Structure.java @@ -0,0 +1,108 @@ +class AllOne { + private final NodeList head; + private final NodeList tail; + private final Map countToNodeMapping; + private final Map keyToCountMapping; + + public AllOne() { + head = new NodeList(Integer.MIN_VALUE); + tail = new NodeList(Integer.MAX_VALUE); + head.next = tail; + tail.prev = head; + countToNodeMapping = new HashMap<>(); + keyToCountMapping = new HashMap<>(); + } + + public void inc(String key) { + if (keyToCountMapping.containsKey(key)) { + updateKey(key, 1); + } else { + keyToCountMapping.put(key, 1); + if (head.next.count != 1) { + addNodeAfter(new NodeList(1), head); + } + head.next.keys.add(key); + countToNodeMapping.put(1, head.next); + } + } + + public void dec(String key) { + if (keyToCountMapping.containsKey(key)) { + int count = keyToCountMapping.get(key); + if (count == 1) { + keyToCountMapping.remove(key); + removeKey(countToNodeMapping.get(count), key); + } else { + updateKey(key, -1); + } + } + } + + public String getMaxKey() { + return tail.prev == head ? "" : tail.prev.keys.iterator().next(); + } + + public String getMinKey() { + return head.next == tail ? "" : head.next.keys.iterator().next(); + } + + private void updateKey(String key, int diff) { + int count = keyToCountMapping.get(key); + keyToCountMapping.put(key, count + diff); + NodeList currNode = countToNodeMapping.get(count); + NodeList newNode; + if (countToNodeMapping.containsKey(count + diff)) { + newNode = countToNodeMapping.get(count + diff); + } else { + newNode = new NodeList(count + diff); + countToNodeMapping.put(count + diff, newNode); + // If diff == 1 then new node will have count greater than currNode else it will have count less than currNode + addNodeAfter(newNode, diff == 1 ? currNode : currNode.prev); + } + newNode.keys.add(key); + removeKey(currNode, key); + } + + private void removeKey(NodeList nodeList, String key) { + nodeList.keys.remove(key); + if (nodeList.keys.isEmpty()) { + removeNodeList(nodeList); + countToNodeMapping.remove(nodeList.count); + } + } + + private void removeNodeList(NodeList nodeList) { + nodeList.prev.next = nodeList.next; + nodeList.next.prev = nodeList.prev; + nodeList.next = null; + nodeList.prev = null; + } + + private void addNodeAfter(NodeList node, NodeList prevNode) { + node.prev = prevNode; + node.next = prevNode.next; + prevNode.next.prev = node; + prevNode.next = node; + } + + private static class NodeList { + int count; + Set keys; + NodeList next; + NodeList prev; + + public NodeList(int count) { + this.count = count; + keys = new HashSet<>(); + } + } +} + +/** + * Your AllOne object will be instantiated and called as such: + * AllOne obj = new AllOne(); + * obj.inc(key); + * obj.dec(key); + * String param_3 = obj.getMaxKey(); + * String param_4 = obj.getMinKey(); + */ diff --git a/Hard/Arithmetic Slices II - Subsequence.java b/Hard/Arithmetic Slices II - Subsequence.java new file mode 100644 index 00000000..f193579f --- /dev/null +++ b/Hard/Arithmetic Slices II - Subsequence.java @@ -0,0 +1,22 @@ +class Solution { + public int numberOfArithmeticSlices(int[] nums) { + int n = nums.length; + Map[] count = new Map[n]; + int result = 0; + for (int i = 0; i < n; i++) { + count[i] = new HashMap<>(); + for (int j = 0; j < i; j++) { + long delta = ((long) nums[i]) - ((long) nums[j]); + if (delta < Integer.MIN_VALUE || delta > Integer.MAX_VALUE) { + continue; + } + int diff = (int) delta; + int sum = count[j].getOrDefault(diff, 0); + int current = count[i].getOrDefault(diff, 0); + count[i].put(diff, current + sum + 1); + result += sum; + } + } + return result; + } +} diff --git a/Hard/Basic Calculator III.java b/Hard/Basic Calculator III.java index ab8af16e..dd97e966 100644 --- a/Hard/Basic Calculator III.java +++ b/Hard/Basic Calculator III.java @@ -1,74 +1,28 @@ class Solution { - public int calculate(String s) { - if (s.length() == 0) { - return 0; + public int calculate(String s) { + int currNum = 0; + int prevNum = 0; + int result = 0; + char operation = '+'; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (Character.isDigit(c)) { + currNum = currNum * 10 + Character.getNumericValue(c); + } + if ((!Character.isDigit(c) && !Character.isWhitespace(c)) || i == s.length() - 1) { + if (operation == '-' || operation == '+') { + result += prevNum; + prevNum = operation == '+' ? currNum : -currNum; + } else if (operation == '*') { + prevNum = prevNum * currNum; + } else { + prevNum = prevNum / currNum; } - - Stack nums = new Stack<>(); - Stack ops = new Stack<>(); - int num = 0; - - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == ' ') { - continue; - } - - if (Character.isDigit(c)) { - num = c - '0'; - while (i < s.length() - 1 && Character.isDigit(s.charAt(i + 1))) { - num = num * 10 + (s.charAt(i + 1) - '0'); - i++; - } - - nums.push(num); - num = 0; - } - else if (c == '(') { - ops.push(c); - } - else if (c == ')') { - while (ops.peek() != '(') { - nums.push(performOperation(ops.pop(), nums.pop(), nums.pop())); - } - ops.pop(); - } - else if (c == '+' || c == '-' || c == '*' || c == '/') { - while (!ops.isEmpty() && precedence(c, ops.peek())) { - nums.push(performOperation(ops.pop(), nums.pop(), nums.pop())); - } - - ops.push(c); - } - } - - while (!ops.isEmpty()) { - nums.push(performOperation(ops.pop(), nums.pop(), nums.pop())); - } - - return nums.pop(); - } - - private int performOperation(char op, int b, int a) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } - - return 0; - } - - private boolean precedence(char op1, char op2) { - if (op2 == '(' || op2 == ')') { - return false; - } - - if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) { - return false; - } - - return true; + operation = c; + currNum = 0; + } } + result += prevNum; + return result; + } } diff --git a/Hard/Basic Calculator.java b/Hard/Basic Calculator.java index edd9467f..1a1813d0 100644 --- a/Hard/Basic Calculator.java +++ b/Hard/Basic Calculator.java @@ -1,55 +1,29 @@ class Solution { - public static int calculate(String s) { - Stack stack = new Stack<>(); - int res = 0; - int num = 0; - int sign = 1; - boolean hasNumberStarted = false; - - for (int i=0; i stack = new Stack<>(); + int result = 0; + int number = 0; + int sign = 1; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (Character.isDigit(c)) { + number = number * 10 + Character.getNumericValue(c); + } else if (c == '+' || c == '-') { + result += sign * number; + sign = c == '+' ? 1 : -1; + number = 0; + } else if (c == '(') { + stack.push(result); + stack.push(sign); + sign = 1; + result = 0; + } else if (c == ')') { + result += sign * number; + result *= stack.pop(); + result += stack.pop(); + number = 0; + } } + return result + (sign * number); + } } diff --git a/Hard/Best Time to Buy and Sell Stock IV.java b/Hard/Best Time to Buy and Sell Stock IV.java new file mode 100644 index 00000000..8aecbd84 --- /dev/null +++ b/Hard/Best Time to Buy and Sell Stock IV.java @@ -0,0 +1,18 @@ +class Solution { + public int maxProfit(int k, int[] prices) { + if (k == 0) { + return 0; + } + int[][] dp = new int[k + 1][2]; + for (int i = 0; i <= k; i++) { + dp[i][0] = 1000; + } + for (int i = 0; i < prices.length; i++) { + for (int j = 1; j <= k; j++) { + dp[j][0] = Math.min(dp[j][0], prices[i] - dp[j - 1][1]); + dp[j][1] = Math.max(dp[j][1], prices[i] - dp[j][0]); + } + } + return dp[k][1]; + } +} diff --git a/Hard/Binary Tree Cameras.java b/Hard/Binary Tree Cameras.java new file mode 100644 index 00000000..f87825e6 --- /dev/null +++ b/Hard/Binary Tree Cameras.java @@ -0,0 +1,45 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + private final int NOT_MONITORED = 0; + private final int MONITORED_NOCAM = 1; + private final int MONITORED_WITHCAM = 2; + + public int minCameraCover(TreeNode root) { + if (root == null) { + return 0; + } + int[] cameras = {0}; + int top = dfs(root, cameras); + return cameras[0] + (top == NOT_MONITORED ? 1 : 0); + } + + private int dfs(TreeNode root, int[] cameras) { + if (root == null) { + return MONITORED_NOCAM; + } + int left = dfs(root.left, cameras); + int right = dfs(root.right, cameras); + if (left == MONITORED_NOCAM && right == MONITORED_NOCAM) { + return NOT_MONITORED; + } else if (left == NOT_MONITORED || right == NOT_MONITORED) { + cameras[0]++; + return MONITORED_WITHCAM; + } else { + return MONITORED_NOCAM; + } + } +} diff --git a/Hard/Binary Tree Maximum Path Sum.java b/Hard/Binary Tree Maximum Path Sum.java index c53cb7d0..3e143413 100644 --- a/Hard/Binary Tree Maximum Path Sum.java +++ b/Hard/Binary Tree Maximum Path Sum.java @@ -4,27 +4,31 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - int maxDownVal; - public int maxPathSum(TreeNode root) { - maxDownVal = Integer.MIN_VALUE; - updateVal(root); - return maxDownVal; - } - - private int updateVal(TreeNode root) { - if (root == null) { - return 0; - } - - int left = Math.max(0, updateVal(root.left)); - int right = Math.max(0, updateVal(root.right)); - - maxDownVal = Math.max(maxDownVal, left+right+root.val); - - return Math.max(left, right) + root.val; + int maxVal; + public int maxPathSum(TreeNode root) { + maxVal = Integer.MIN_VALUE; + helper(root); + return maxVal; + } + + private int helper(TreeNode root) { + if (root == null) { + return 0; } + int left = Math.max(helper(root.left), 0); + int right = Math.max(helper(root.right), 0); + int sum = root.val + left + right; + maxVal = Math.max(maxVal, sum); + return root.val + Math.max(left, right); + } } diff --git a/Hard/Binary Tree PostOrder Traversal.java b/Hard/Binary Tree PostOrder Traversal.java deleted file mode 100644 index 53983b32..00000000 --- a/Hard/Binary Tree PostOrder Traversal.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public List postorderTraversal(TreeNode root) { - List values = new ArrayList<>(); - if (root == null) { - return values; - } - - Stack stack1 = new Stack<>(); - Stack stack2 = new Stack<>(); - - stack1.push(root); - - while (!stack1.empty()) { - TreeNode temp = stack1.pop(); - stack2.push(temp); - - if (temp.left != null) { - stack1.push(temp.left); - } - - if (temp.right != null) { - stack1.push(temp.right); - } - } - - while (!stack2.empty()) { - values.add(stack2.pop().val); - } - - return values; - } -} diff --git a/Hard/Build Array Where You Can Find The Maximum Exactly K Comparisons.java b/Hard/Build Array Where You Can Find The Maximum Exactly K Comparisons.java new file mode 100644 index 00000000..c7ede11f --- /dev/null +++ b/Hard/Build Array Where You Can Find The Maximum Exactly K Comparisons.java @@ -0,0 +1,28 @@ +class Solution { + + private static final int MOD = (int) 1000_000_007; + + public int numOfArrays(int n, int m, int k) { + int[][][] dp = new int[n + 1][m + 1][k + 1]; + for (int i = 0; i < dp[0].length; i++) { + dp[n][i][0] = 1; + } + for (int i = n - 1; i >= 0; i--) { + for (int j = m; j >= 0; j--) { + for (int l = 0; l <= k; l++) { + int result = 0; + for (int num = 1; num <= j; num++) { + result = (result + dp[i + 1][j][l]) % MOD; + } + if (l > 0) { + for (int num = j + 1; num <= m; num++) { + result = (result + dp[i + 1][num][l - 1]) % MOD; + } + } + dp[i][j][l] = result; + } + } + } + return dp[0][0][k]; + } +} diff --git a/Hard/Bus Routes.java b/Hard/Bus Routes.java new file mode 100644 index 00000000..54c2762a --- /dev/null +++ b/Hard/Bus Routes.java @@ -0,0 +1,39 @@ +class Solution { + public int numBusesToDestination(int[][] routes, int source, int target) { + if (source == target) { + return 0; + } + Map> stopToBusMapping = new HashMap<>(); + for (int i = 0; i < routes.length; i++) { + for (int stop : routes[i]) { + stopToBusMapping.computeIfAbsent(stop, k -> new HashSet<>()).add(i); + } + } + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); + for (int route : stopToBusMapping.get(source)) { + queue.add(route); + visited.add(route); + } + int buses = 1; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int removed = queue.remove(); + for (int stop : routes[removed]) { + if (stop == target) { + return buses; + } + for (int nextBus : stopToBusMapping.getOrDefault(stop, new HashSet<>())) { + if (!visited.contains(nextBus)) { + visited.add(nextBus); + queue.add(nextBus); + } + } + } + } + buses++; + } + return -1; + } +} diff --git a/Hard/Candy.java b/Hard/Candy.java index afb4ecda..269d4d6a 100644 --- a/Hard/Candy.java +++ b/Hard/Candy.java @@ -1,31 +1,22 @@ class Solution { public int candy(int[] ratings) { - if (ratings.length <= 1) { - return ratings.length; - } - - int[] candies = new int[ratings.length]; - for (int i = 0; i < ratings.length; i++) { - candies[i] = 1; - } - - for (int i = 1; i < ratings.length; i++) { + int n = ratings.length; + int[] candies = new int[n]; + Arrays.fill(candies, 1); + for (int i = 1; i < n; i++) { if (ratings[i] > ratings[i - 1]) { candies[i] = candies[i - 1] + 1; } } - - for (int i = ratings.length - 1; i > 0; i--) { - if (ratings[i - 1] > ratings[i]) { - candies[i - 1] = Math.max(candies[i] + 1, candies[i - 1]); + for (int i = n - 2; i >= 0; i--) { + if (ratings[i] > ratings[i + 1]) { + candies[i] = Math.max(candies[i], candies[i + 1] + 1); } } - - int candyCount = 0; - for (int candy : candies) { - candyCount += candy; + int totalCandies = 0; + for (int i = 0; i < n; i++) { + totalCandies += candies[i]; } - - return candyCount; + return totalCandies; } } diff --git a/Hard/Checking Existence of Edge Length Limited Paths.java b/Hard/Checking Existence of Edge Length Limited Paths.java new file mode 100644 index 00000000..d03848ef --- /dev/null +++ b/Hard/Checking Existence of Edge Length Limited Paths.java @@ -0,0 +1,41 @@ +class Solution { + public boolean[] distanceLimitedPathsExist(int n, int[][] edgeList, int[][] queries) { + UnionFind unionFind = new UnionFind(n); + for (int i = 0; i < queries.length; i++) { + queries[i] = new int[]{queries[i][0], queries[i][1], queries[i][2], i}; + } + Arrays.sort(queries, Comparator.comparingInt(a -> a[2])); + Arrays.sort(edgeList, Comparator.comparingInt(a -> a[2])); + boolean[] result = new boolean[queries.length]; + for (int i = 0, j = 0; i < queries.length; i++) { + int[] query = queries[i]; + while (j < edgeList.length && edgeList[j][2] < query[2]) { + unionFind.union(edgeList[j][0], edgeList[j++][1]); + } + result[query[3]] = unionFind.find(query[0]) == unionFind.find(query[1]); + } + return result; + } + + private static class UnionFind { + private final int[] parent; + + public UnionFind(int n) { + this.parent = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + } + } + + public int find(int node) { + if (parent[node] != node) { + parent[node] = find(parent[node]); + } + return parent[node]; + } + + public void union(int x, int y) { + parent[find(x)] = parent[find(y)]; + } + } +} diff --git a/Hard/Cherry Pickup II.java b/Hard/Cherry Pickup II.java new file mode 100644 index 00000000..1786e8cc --- /dev/null +++ b/Hard/Cherry Pickup II.java @@ -0,0 +1,32 @@ +class Solution { + public int cherryPickup(int[][] grid) { + int m = grid.length; + int n = grid[0].length; + Integer[][][] cache = new Integer[m][n][n]; + return recurse(0, 0, n - 1, grid, cache); + } + + private int recurse(int row, int colOne, int colTwo, int[][] grid, Integer[][][] cache) { + if (colOne < 0 || colOne >= grid[0].length || colTwo < 0 || colTwo >= grid[0].length) { + return 0; + } + if (cache[row][colOne][colTwo] != null) { + return cache[row][colOne][colTwo]; + } + int result = 0; + result += grid[row][colOne]; + if (colOne != colTwo) { + result += grid[row][colTwo]; + } + if (row != grid.length - 1) { + int max = 0; + for (int c1 = colOne - 1; c1 <= colOne + 1; c1++) { + for (int c2 = colTwo - 1; c2 <= colTwo + 1; c2++) { + max = Math.max(max, recurse(row + 1, c1, c2, grid, cache)); + } + } + result += max; + } + return cache[row][colOne][colTwo] = result; + } +} diff --git a/Hard/Concatenated Words.java b/Hard/Concatenated Words.java new file mode 100644 index 00000000..470c05d6 --- /dev/null +++ b/Hard/Concatenated Words.java @@ -0,0 +1,58 @@ +class Solution { + public List findAllConcatenatedWordsInADict(String[] words) { + TrieNode root = new TrieNode('-'); + for (String word : words) { + addWord(word, root); + } + List concatenations = new ArrayList<>(); + for (String word : words) { + if (isConcatentation(word, root, 0, 0)) { + concatenations.add(word); + } + } + return concatenations; + } + + private void addWord(String s, TrieNode root) { + TrieNode curr = root; + for (int i = 0; i < s.length(); i++) { + if (!curr.map.containsKey(s.charAt(i))) { + curr.map.put(s.charAt(i), new TrieNode(s.charAt(i))); + } + curr = curr.map.get(s.charAt(i)); + } + curr.isWord = true; + } + + private boolean isConcatentation(String s, TrieNode root, int idx, int count) { + TrieNode curr = root; + for (int i = idx; i < s.length(); i++) { + if (!curr.map.containsKey(s.charAt(i))) { + return false; + } + if (curr.map.get(s.charAt(i)).isWord) { + if (i == s.length() - 1) { + return count >= 1; + } + if (isConcatentation(s, root, i + 1, count + 1)) { + return true; + } + } + curr = curr.map.get(s.charAt(i)); + } + return false; + } +} + + +class TrieNode { + char c; + Map map; + boolean isWord; + + public TrieNode(char c) { + this.c = c; + map = new HashMap<>(); + isWord = false; + } +} diff --git a/Hard/Constrained Subsequence Sum.java b/Hard/Constrained Subsequence Sum.java new file mode 100644 index 00000000..9dabd1d4 --- /dev/null +++ b/Hard/Constrained Subsequence Sum.java @@ -0,0 +1,16 @@ +class Solution { + public int constrainedSubsetSum(int[] nums, int k) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> b[0] - a[0]); + pq.add(new int[]{nums[0], 0}); + int result = nums[0]; + for (int i = 1; i < nums.length; i++) { + while (i - pq.peek()[1] > k) { + pq.remove(); + } + int curr = Math.max(0, pq.peek()[0]) + nums[i]; + result = Math.max(result, curr); + pq.add(new int[]{curr, i}); + } + return result; + } +} diff --git a/Hard/Construct Target Array With Multiple Sums.java b/Hard/Construct Target Array With Multiple Sums.java new file mode 100644 index 00000000..a8a71438 --- /dev/null +++ b/Hard/Construct Target Array With Multiple Sums.java @@ -0,0 +1,28 @@ +class Solution { + public boolean isPossible(int[] target) { + if (target.length == 1) { + return target[0] == 1; + } + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + int sum = 0; + for (int num : target) { + sum += num; + pq.add(num); + } + int n = target.length; + while (pq.peek() > 1) { + int largest = pq.poll(); + int remaining = sum - largest; + if (remaining == 1) { + return true; + } + int delta = largest % remaining; + if (delta == 0 || delta == largest) { + return false; + } + pq.add(delta); + sum = sum - largest + delta; + } + return true; + } +} diff --git a/Hard/Count Subarrays With Fixed Bounds.java b/Hard/Count Subarrays With Fixed Bounds.java new file mode 100644 index 00000000..2846d647 --- /dev/null +++ b/Hard/Count Subarrays With Fixed Bounds.java @@ -0,0 +1,21 @@ +class Solution { + public long countSubarrays(int[] nums, int minK, int maxK) { + long result = 0; + int minPosition = -1; + int maxPosition = -1; + int leftIdx = -1; + for (int i = 0; i < nums.length; i++) { + if (nums[i] < minK || nums[i] > maxK) { + leftIdx = i; + } + if (nums[i] == minK) { + minPosition = i; + } + if (nums[i] == maxK) { + maxPosition = i; + } + result += Math.max(0, Math.min(maxPosition, minPosition) - leftIdx); + } + return result; + } +} diff --git a/Hard/Count Vowels Permutation.java b/Hard/Count Vowels Permutation.java new file mode 100644 index 00000000..a0a2c36c --- /dev/null +++ b/Hard/Count Vowels Permutation.java @@ -0,0 +1,24 @@ +class Solution { + public int countVowelPermutation(int n) { + long aCount = 1; + long eCount = 1; + long iCount = 1; + long oCount = 1; + long uCount = 1; + final int MOD = 1000000007; + for (int i = 1; i < n; i++) { + long aCountNew = (eCount + iCount + uCount) % MOD; + long eCountNew = (aCount + iCount) % MOD; + long iCountNew = (eCount + oCount) % MOD; + long oCountNew = (iCount) % MOD; + long uCountNew = (iCount + oCount) % MOD; + aCount = aCountNew; + eCount = eCountNew; + iCount = iCountNew; + oCount = oCountNew; + uCount = uCountNew; + } + long result = (aCount + eCount + iCount + oCount + uCount) % MOD; + return (int) result; + } +} diff --git a/Hard/Count of Smaller Numbers After Self.java b/Hard/Count of Smaller Numbers After Self.java new file mode 100644 index 00000000..30f10d48 --- /dev/null +++ b/Hard/Count of Smaller Numbers After Self.java @@ -0,0 +1,50 @@ +class Solution { + public List countSmaller(int[] nums) { + int n = nums.length; + int[] result = new int[n]; + int[] indices = new int[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + mergesort(indices, 0, n, result, nums); + return Arrays.stream(result).boxed().collect(Collectors.toList()); + } + + private void mergesort(int[] indices, int left, int right, int[] result, int[] nums) { + if (right - left <= 1) { + return; + } + int mid = (left + right) / 2; + mergesort(indices, left, mid, result, nums); + mergesort(indices, mid, right, result, nums); + merge(indices, left, right, mid, result, nums); + } + + private void merge(int[] indices, int left, int right, int mid, int[] result, int[] nums) { + int i = left; + int j = mid; + List temp = new ArrayList<>(); + while (i < mid && j < right) { + if (nums[indices[i]] <= nums[indices[j]]) { + result[indices[i]] += j - mid; + temp.add(indices[i]); + i++; + } else { + temp.add(indices[j]); + j++; + } + } + while (i < mid) { + result[indices[i]] += j - mid; + temp.add(indices[i]); + i++; + } + while (j < right) { + temp.add(indices[j]); + j++; + } + for (int k = left; k < right; k++) { + indices[k] = temp.get(k - left); + } + } +} diff --git a/Hard/Course Schedule III.java b/Hard/Course Schedule III.java new file mode 100644 index 00000000..ceea807c --- /dev/null +++ b/Hard/Course Schedule III.java @@ -0,0 +1,17 @@ +class Solution { + public int scheduleCourse(int[][] courses) { + Arrays.sort(courses, (a, b) -> a[1] - b[1]); + PriorityQueue queue = new PriorityQueue<>((a, b) -> b - a); + int time = 0; + for (int[] course : courses) { + if (time + course[0] <= course[1]) { + queue.add(course[0]); + time += course[0]; + } else if (!queue.isEmpty() && queue.peek() > course[0]) { + time += course[0] - queue.poll(); + queue.add(course[0]); + } + } + return queue.size(); + } +} diff --git a/Hard/Critical Connections in a Network.java b/Hard/Critical Connections in a Network.java new file mode 100644 index 00000000..92d73cb4 --- /dev/null +++ b/Hard/Critical Connections in a Network.java @@ -0,0 +1,49 @@ +class Solution { + public List> criticalConnections(int n, List> connections) { + Map> graph = new HashMap<>(); + Map rank = new HashMap<>(); + Set connectionSet = new HashSet<>(); + buildGraph(n, connections, graph, rank, connectionSet); + dfs(0, 0, graph, rank, connectionSet); + List> result = new ArrayList<>(); + for (String conn : connectionSet) { + int nodeOne = Integer.parseInt(conn.split("-")[0]); + int nodeTwo = Integer.parseInt(conn.split("-")[1]); + result.add(Arrays.asList(nodeOne, nodeTwo)); + } + return result; + } + + private void buildGraph(int n, List> connections, Map> graph, Map rank, Set connectionSet) { + for (int i = 0; i < n; i++) { + graph.put(i, new ArrayList<>()); + rank.put(i, null); + } + for (List edge : connections) { + graph.get(edge.get(0)).add(edge.get(1)); + graph.get(edge.get(1)).add(edge.get(0)); + connectionSet.add( + Math.min(edge.get(0), edge.get(1)) + "-" + Math.max(edge.get(0), edge.get(1))); + } + } + + private int dfs(int node, int discoveryRank, Map> graph, Map rank, Set connectionSet) { + if (rank.get(node) != null) { + return rank.get(node); + } + rank.put(node, discoveryRank); + int minimumRank = discoveryRank + 1; + for (Integer neighbor : graph.get(node)) { + Integer neighborRank = rank.get(neighbor); + if (neighborRank != null && neighborRank == discoveryRank - 1) { + continue; + } + int recursiveRank = dfs(neighbor, discoveryRank + 1, graph, rank, connectionSet); + if (recursiveRank <= discoveryRank) { + connectionSet.remove(Math.min(node, neighbor) + "-" + Math.max(node, neighbor)); + } + minimumRank = Math.min(minimumRank, recursiveRank); + } + return minimumRank; + } +} diff --git a/Hard/Design Graph With Shortest Path Calculator.java b/Hard/Design Graph With Shortest Path Calculator.java new file mode 100644 index 00000000..0b7fddf1 --- /dev/null +++ b/Hard/Design Graph With Shortest Path Calculator.java @@ -0,0 +1,43 @@ +class Graph { + + private final Map> graph; + + public Graph(int n, int[][] edges) { + this.graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(new Connection(edge[1], edge[2])); + } + } + + public void addEdge(int[] edge) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(new Connection(edge[1], edge[2])); + } + + public int shortestPath(int node1, int node2) { + PriorityQueue queue = new PriorityQueue<>(Comparator.comparingInt(a -> a[1])); + queue.add(new int[]{node1, 0}); + Set seen = new HashSet<>(); + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int node = removed[0]; + if (node == node2) { + return removed[1]; + } + if (graph.containsKey(node) && seen.add(node)) { + for (Connection connection : graph.getOrDefault(removed[0], new ArrayList<>())) { + queue.add(new int[]{connection.node, removed[1] + connection.cost}); + } + } + } + return -1; + } + + private record Connection(int node, int cost) { } +} + +/** + * Your Graph object will be instantiated and called as such: + * Graph obj = new Graph(n, edges); + * obj.addEdge(edge); + * int param_2 = obj.shortestPath(node1,node2); + */ diff --git a/Hard/Design In-Memory File System.java b/Hard/Design In-Memory File System.java new file mode 100644 index 00000000..9002c758 --- /dev/null +++ b/Hard/Design In-Memory File System.java @@ -0,0 +1,155 @@ +import java.util.Optional; + +class FileSystem { + + private final Node root; + + public FileSystem() { + this.root = new DirectoryNode("/"); + } + + public List ls(String path) { + String[] splits = path.split("/"); + if (splits.length == 0) { + return buildlsResult((DirectoryNode) root); + } + Node curr = root; + for (int i = 1; i < splits.length - 1; i++) { + curr = ((DirectoryNode) curr).getNode(splits[i]).get(); + } + Node lastNode = ((DirectoryNode) curr).getNode(splits[splits.length - 1]).get(); + if (lastNode.isFile()) { + return Collections.singletonList(lastNode.getName()); + } + return buildlsResult((DirectoryNode) lastNode); + } + + public void mkdir(String path) { + String[] splits = path.split("/"); + createIfNotExists(splits); + } + + public void addContentToFile(String filePath, String content) { + String[] splits = filePath.split("/"); + DirectoryNode directoryNode = createIfNotExists(Arrays.copyOfRange(splits, 0, splits.length)); + String fileName = splits[splits.length - 1]; + if (directoryNode.getNode(fileName).isEmpty()) { + FileNode fileNode = new FileNode(fileName); + directoryNode.addContent(fileName, fileNode); + } + FileNode fileNode = (FileNode) directoryNode.getNode(fileName).get(); + fileNode.addContent(content); + } + + public String readContentFromFile(String filePath) { + String[] splits = filePath.split("/"); + DirectoryNode directoryNode = createIfNotExists(Arrays.copyOfRange(splits, 0, splits.length)); + String fileName = splits[splits.length - 1]; + FileNode fileNode = (FileNode) directoryNode.getNode(fileName).get(); + return fileNode.getContents(); + } + + private static List buildlsResult(DirectoryNode curr) { + return curr + .getContents() + .stream() + .map(Node::getName) + .sorted() + .collect(Collectors.toList()); + } + + private DirectoryNode createIfNotExists(String[] splits) { + DirectoryNode curr = (DirectoryNode) root; + for (int i = 1; i < splits.length; i++) { + Optional nextDirectory = curr.getNode(splits[i]); + if (nextDirectory.isEmpty()) { + DirectoryNode node = new DirectoryNode(splits[i]); + curr.addContent(splits[i], node); + curr = node; + } else { + curr = (DirectoryNode) nextDirectory.get(); + } + } + return curr; + } + + private static class FileNode implements Node { + + private final String name; + + private final StringBuilder contents; + + public FileNode(String name) { + this.name = name; + this.contents = new StringBuilder(); + } + + public void addContent(String content) { + this.contents.append(content); + } + + public String getContents() { + return contents.toString(); + } + + @Override + public String getName() { + return this.name; + } + + @Override + public boolean isFile() { + return true; + } + } + + private static class DirectoryNode implements Node { + + private String name; + + private final Map contents; + + public DirectoryNode(String name) { + this.name = name; + this.contents = new HashMap<>(); + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isFile() { + return false; + } + + public void addContent(String key, Node node) { + contents.put(key, node); + } + + public List getContents() { + return contents.values().stream().toList(); + } + + public Optional getNode(String nodeName) { + return Optional.ofNullable(contents.getOrDefault(nodeName, null)); + } + } + + private interface Node { + + String getName(); + + boolean isFile(); + } +} + +/** + * Your FileSystem object will be instantiated and called as such: + * FileSystem obj = new FileSystem(); + * List param_1 = obj.ls(path); + * obj.mkdir(path); + * obj.addContentToFile(filePath,content); + * String param_4 = obj.readContentFromFile(filePath); + */ diff --git a/Hard/Design Movie Rental System.java b/Hard/Design Movie Rental System.java new file mode 100644 index 00000000..0aaeb6c8 --- /dev/null +++ b/Hard/Design Movie Rental System.java @@ -0,0 +1,102 @@ +class MovieRentingSystem { + + Comparator comparator = + (o1, o2) -> { + if (o1.price != o2.price) { + return o1.price - o2.price; + } + if (o1.shopId != o2.shopId) { + return o1.shopId - o2.shopId; + } + return o1.movieId - o2.movieId; + }; + Map> movieToUnrentedShopMapping; + Map shopMoviePairToPriceMapping; + TreeSet rentedMovies; + + public MovieRentingSystem(int n, int[][] entries) { + movieToUnrentedShopMapping = new HashMap<>(); + shopMoviePairToPriceMapping = new HashMap<>(); + rentedMovies = new TreeSet<>(comparator); + for (int[] entry : entries) { + movieToUnrentedShopMapping + .computeIfAbsent(entry[1], k -> new TreeSet<>(comparator)) + .add(new MovieEntry(entry[1], entry[2], entry[0])); + shopMoviePairToPriceMapping.put(new ShopMoviePair(entry[0], entry[1]), entry[2]); + } + } + + public List search(int movie) { + return movieToUnrentedShopMapping.getOrDefault(movie, Collections.emptySet()).stream() + .limit(5) + .map(e -> e.shopId) + .collect(Collectors.toList()); + } + + public void rent(int shop, int movie) { + int price = shopMoviePairToPriceMapping.get(new ShopMoviePair(shop, movie)); + movieToUnrentedShopMapping.get(movie).remove(new MovieEntry(movie, price, shop)); + rentedMovies.add(new MovieEntry(movie, price, shop)); + } + + public void drop(int shop, int movie) { + int price = shopMoviePairToPriceMapping.get(new ShopMoviePair(shop, movie)); + movieToUnrentedShopMapping.get(movie).add(new MovieEntry(movie, price, shop)); + rentedMovies.remove(new MovieEntry(movie, price, shop)); + } + + public List> report() { + return rentedMovies.stream() + .limit(5) + .map(e -> List.of(e.shopId, e.movieId)) + .collect(Collectors.toList()); + } + + class ShopMoviePair { + int shopId; + int movieId; + + public ShopMoviePair(int shopId, int movieId) { + this.shopId = shopId; + this.movieId = movieId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ShopMoviePair that = (ShopMoviePair) o; + return shopId == that.shopId && movieId == that.movieId; + } + + @Override + public int hashCode() { + return Objects.hash(shopId, movieId); + } + } + + class MovieEntry { + int movieId; + int price; + int shopId; + + public MovieEntry(int movieId, int price, int shopId) { + this.movieId = movieId; + this.price = price; + this.shopId = shopId; + } + } +} + +/** + * Your MovieRentingSystem object will be instantiated and called as such: + * MovieRentingSystem obj = new MovieRentingSystem(n, entries); + * List param_1 = obj.search(movie); + * obj.rent(shop,movie); + * obj.drop(shop,movie); + * List> param_4 = obj.report(); + */ diff --git a/Hard/Design Search Autocomplete System.java b/Hard/Design Search Autocomplete System.java index 161bf92e..c4c15c9e 100644 --- a/Hard/Design Search Autocomplete System.java +++ b/Hard/Design Search Autocomplete System.java @@ -1,107 +1,79 @@ class AutocompleteSystem { - Node root; - Map wordWeight; - int i; - StringBuilder sb; - - public AutocompleteSystem(String[] sentences, int[] times) { - root = new Node(""); - wordWeight = new HashMap<>(); - i = 0; - sb = new StringBuilder(); - - for (String sentence : sentences) { - insertWord(sentence); - wordWeight.put(sentence, times[i++]); - } + private final TrieNode root; + private TrieNode queryNode; + private final Map popularityMap; + StringBuilder sb; + boolean invalidQuery; + + public AutocompleteSystem(String[] sentences, int[] times) { + root = new TrieNode(); + this.popularityMap = new HashMap<>(); + for (int i = 0; i < sentences.length; i++) { + indexSentence(sentences[i], root); + this.popularityMap.put( + sentences[i], this.popularityMap.getOrDefault(sentences[i], 0) + times[i]); } - - private void insertWord(String sentence) { - Node curr = root; - for (int i=0; i input(char c) { - if (c == '#') { - wordWeight.put(sb.toString(), wordWeight.getOrDefault(sb.toString(), 0) + 1); - insertWord(sb.toString()); - sb = new StringBuilder(); - return new ArrayList<>(); - } - - sb.append(c); - - PriorityQueue pq = new PriorityQueue<>(new Comparator() { - @Override - public int compare(String o1, String o2) { - if (wordWeight.get(o1) - wordWeight.get(o2) == 0) { - return o2.compareTo(o1); - } - else { - return wordWeight.get(o1) - wordWeight.get(o2); - } - } - }); - - String prefix = sb.toString(); - Node curr = root; - - for (char ch : prefix.toCharArray()) { - if (curr.childrens.containsKey(ch)) { - curr = curr.childrens.get(ch); - } - else { - return new ArrayList<>(); - } - } - - findAllChildWorlds(curr, pq); - - List ans = new ArrayList<>(); - while (!pq.isEmpty()) { - ans.add(pq.poll()); - } - - Collections.reverse(ans); - - return ans; + public List input(char c) { + if (c == '#') { + cleanUp(); + return new ArrayList<>(); } - - private void findAllChildWorlds(Node curr, PriorityQueue pq) { - if (curr.isWord) { - pq.add(curr.prefix); - if (pq.size() > 3) { - pq.poll(); - } - } - - for (char c : curr.childrens.keySet()) { - findAllChildWorlds(curr.childrens.get(c), pq); - } + this.sb.append(c); + if (!this.queryNode.children.containsKey(c) || invalidQuery) { + this.invalidQuery = true; + return new ArrayList<>(); } -} - -class Node { - String prefix; - Map childrens; - boolean isWord; - - public Node(String prefix) { - this.prefix = prefix; - this.childrens = new HashMap<>(); + this.queryNode = this.queryNode.children.get(c); + return this.queryNode.sentences.stream() + .sorted( + (o1, o2) -> { + int c1 = popularityMap.get(o2).compareTo(popularityMap.get(o1)); + if (c1 != 0) { + return c1; + } + return o1.compareTo(o2); + }) + .limit(3) + .collect(Collectors.toList()); + } + + private void cleanUp() { + this.queryNode = root; + String inputString = this.sb.toString(); + this.sb.setLength(0); + this.popularityMap.put(inputString, this.popularityMap.getOrDefault(inputString, 0) + 1); + this.invalidQuery = false; + indexSentence(inputString, root); + } + + private static class TrieNode { + + private final Map children; + private final Set sentences; + + public TrieNode() { + this.children = new HashMap<>(); + this.sentences = new HashSet<>(); } + } } + /** * Your AutocompleteSystem object will be instantiated and called as such: * AutocompleteSystem obj = new AutocompleteSystem(sentences, times); diff --git a/Hard/Design Skiplist.java b/Hard/Design Skiplist.java new file mode 100644 index 00000000..8554fcb7 --- /dev/null +++ b/Hard/Design Skiplist.java @@ -0,0 +1,86 @@ +class Skiplist { + + private Node head; + private Random random; + + public Skiplist() { + this.head = new Node(-1); + this.random = new Random(); + } + + public boolean search(int target) { + Node curr = head; + while (curr != null) { + while (curr.next != null && curr.next.val < target) { + curr = curr.next; + } + if (curr.next != null && curr.next.val == target) { + return true; + } + curr = curr.down; + } + return false; + } + + public void add(int num) { + Stack stack = new Stack<>(); + Node curr = head; + while (curr != null) { + while (curr.next != null && curr.next.val < num) { + curr = curr.next; + } + stack.push(curr); + curr = curr.down; + } + boolean newLevel = true; + Node downNode = null; + while (newLevel && !stack.isEmpty()) { + curr = stack.pop(); + Node newNode = new Node(num); + newNode.next = curr.next; + newNode.down = downNode; + curr.next = newNode; + downNode = curr.next; + newLevel = random.nextDouble() < 0.5; + } + if (newLevel) { + Node prevHead = head; + head = new Node(-1); + head.down = prevHead; + } + } + + public boolean erase(int num) { + Node curr = head; + boolean found = false; + while (curr != null) { + while (curr.next != null && curr.next.val < num) { + curr = curr.next; + } + if (curr.next != null && curr.next.val == num) { + found = true; + curr.next = curr.next.next; + } + curr = curr.down; + } + return found; + } + + private static class Node { + int val; + Node next; + Node down; + + public Node(int val) { + this.val = val; + } + } +} + +/** + * Your Skiplist object will be instantiated and called as such: + * Skiplist obj = new Skiplist(); + * boolean param_1 = obj.search(target); + * obj.add(num); + * boolean param_3 = obj.erase(num); + */ diff --git a/Hard/Dice Roll Simulation.java b/Hard/Dice Roll Simulation.java new file mode 100644 index 00000000..47ba0ce5 --- /dev/null +++ b/Hard/Dice Roll Simulation.java @@ -0,0 +1,29 @@ +class Solution { + private final long MOD = (long) Math.pow(10, 9) + 7; + + public int dieSimulator(int n, int[] rollMax) { + long[][] dp = new long[n][7]; + for(int i = 0; i < 6; i++) { + dp[0][i] = 1; + } + dp[0][6] = 6; + for(int i = 1; i < n; i++) { + long sum = 0; + for(int j = 0; j < 6; j++) { + dp[i][j] = dp[i - 1][6]; + if (i - rollMax[j] < 0) { + sum = (sum + dp[i][j]) % MOD; + } else { + if (i - rollMax[j] - 1 >= 0) { + dp[i][j] = (dp[i][j] - (dp[i - rollMax[j] - 1][6] - dp[i - rollMax[j] - 1][j])) % MOD + MOD; + } else { + dp[i][j] = (dp[i][j] - 1) % MOD; + } + sum = (sum + dp[i][j]) % MOD; + } + } + dp[i][6] = sum; + } + return (int) (dp[n - 1][6]); + } +} diff --git a/Hard/Divide Array Into Increasing Sequences.java b/Hard/Divide Array Into Increasing Sequences.java new file mode 100644 index 00000000..5e93803c --- /dev/null +++ b/Hard/Divide Array Into Increasing Sequences.java @@ -0,0 +1,23 @@ +class Solution { + public boolean canDivideIntoSubsequences(int[] nums, int K) { + int maxCount = 1; + int count = 1; + int idx = 1; + int n = nums.length; + while (idx < n) { + if (nums[idx] == nums[idx - 1]) { + count++; + } + else { + maxCount = Math.max(maxCount, count); + count = 1; + } + + idx++; + } + + maxCount = Math.max(maxCount, count); + + return nums.length >= maxCount * K; + } +} diff --git a/Hard/Edit Distance.java b/Hard/Edit Distance.java index e3428cdc..b7ae5930 100644 --- a/Hard/Edit Distance.java +++ b/Hard/Edit Distance.java @@ -1,32 +1,34 @@ class Solution { - public int minDistance(String s1, String s2) { - return minDistanceHelperDP(s1, s2, s1.length(), s2.length()); + public int minDistance(String word1, String word2) { + return minDistanceHelper( + word1, + word2, + word1.length(), + word2.length(), + new Integer[word1.length() + 1][word2.length() + 1]); } - - private int minDistanceHelperDP(String s1, String s2, int m, int n) { - int[][] dp = new int[m+1][n+1]; - for (int i=0;i<=m;i++) { - for (int j=0;j<=n;j++) { - // First substring is empty - if (i == 0) { - dp[i][j] = j; - } - // Second substring is empty - else if (j == 0) { - dp[i][j] = i; - } - // If character are same, value is same as the previous dp array - else if (s1.charAt(i-1) == s2.charAt(j-1)) { - dp[i][j] = dp[i-1][j-1]; - } - // If different, then 1 + min - else { - dp[i][j] = 1 + Math.min(dp[i-1][j-1], Math.min(dp[i][j-1], dp[i-1][j])); - } - } + private int minDistanceHelper(String word1, String word2, int word1Index, int word2Index, Integer[][] memo) { + if (word1Index == 0) { + return word2Index; } - - return dp[m][n]; + if (word2Index == 0) { + return word1Index; + } + if (memo[word1Index][word2Index] != null) { + return memo[word1Index][word2Index]; + } + int minEditDistance = 0; + if (word1.charAt(word1Index - 1) == word2.charAt(word2Index - 1)) { + minEditDistance = minDistanceHelper(word1, word2, word1Index - 1, word2Index - 1, memo); + } else { + int distanceWithInsertion = minDistanceHelper(word1, word2, word1Index, word2Index - 1, memo); + int distanceWithDeletion = minDistanceHelper(word1, word2, word1Index - 1, word2Index, memo); + int distanceWithReplace = minDistanceHelper(word1, word2, word1Index - 1, word2Index - 1, memo); + minEditDistance = Math.min(distanceWithInsertion, + Math.min(distanceWithDeletion, distanceWithReplace)) + 1; + } + memo[word1Index][word2Index] = minEditDistance; + return minEditDistance; } } diff --git a/Hard/Employee Free Time.java b/Hard/Employee Free Time.java new file mode 100644 index 00000000..a5a33b13 --- /dev/null +++ b/Hard/Employee Free Time.java @@ -0,0 +1,32 @@ +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ +/* +*/ +class Solution { + public List employeeFreeTime(List> schedule) { + List ans = new ArrayList<>(); + PriorityQueue pq = new PriorityQueue<>((a,b) -> a.start - b.start); + schedule.forEach(e -> pq.addAll(e)); + + Interval temp = pq.poll(); + while (!pq.isEmpty()) { + if (temp.end < pq.peek().start) { + ans.add(new Interval(temp.end, pq.peek().start)); + temp = pq.poll(); + } + else { + temp = temp.end < pq.peek().end ? pq.peek() : temp; + pq.poll(); + } + } + + return ans; + } +} diff --git a/Hard/Expression Add Operators.java b/Hard/Expression Add Operators.java new file mode 100644 index 00000000..57e56235 --- /dev/null +++ b/Hard/Expression Add Operators.java @@ -0,0 +1,29 @@ +class Solution { + public List addOperators(String num, int target) { + List result = new ArrayList<>(); + helper(num, target, "", result, 0, 0, 0); + return result; + } + + private void helper(String s, long target, String path, List result, int pos, long calculatedResult, long multed) { + if (pos == s.length()) { + if (calculatedResult == target) { + result.add(new String(path)); + } + return; + } + for (int i = pos; i < s.length(); i++) { + if (i != pos && s.charAt(pos) == '0') { + break; + } + long curr = Long.parseLong(s.substring(pos, i + 1)); + if (pos == 0) { + helper(s, target, path + curr, result, i + 1, curr, curr); + } else { + helper(s, target, path + "+" + curr, result, i + 1, calculatedResult + curr, curr); + helper(s, target, path + "-" + curr, result, i + 1, calculatedResult - curr, -curr); + helper(s, target, path + "*" + curr, result, i + 1, calculatedResult - multed + multed * curr, multed * curr); + } + } + } +} diff --git a/Hard/Find All People With Secret.java b/Hard/Find All People With Secret.java new file mode 100644 index 00000000..b18f289a --- /dev/null +++ b/Hard/Find All People With Secret.java @@ -0,0 +1,39 @@ +class Solution { + public List findAllPeople(int n, int[][] meetings, int firstPerson) { + Map> graph = new HashMap<>(); + for (int[] meeting : meetings) { + int x = meeting[0]; + int y = meeting[1]; + int time = meeting[2]; + graph.computeIfAbsent(x, k -> new ArrayList<>()).add(new int[]{time, y}); + graph.computeIfAbsent(y, k -> new ArrayList<>()).add(new int[]{time, x}); + } + int[] earliestTime = new int[n]; + Arrays.fill(earliestTime, Integer.MAX_VALUE); + earliestTime[0] = 0; + earliestTime[firstPerson] = 0; + Queue queue = new LinkedList<>(); + queue.add(new int[]{0, 0}); + queue.add(new int[]{firstPerson, 0}); + while (!queue.isEmpty()) { + int[] removed = queue.poll(); + int person = removed[0]; + int time = removed[1]; + for (int[] conn : graph.getOrDefault(person, new ArrayList<>())) { + int t = conn[0]; + int p = conn[1]; + if (t >= time && earliestTime[p] > t) { + earliestTime[p] = t; + queue.add(new int[]{p, t}); + } + } + } + List result = new ArrayList<>(); + for (int i = 0; i < n; i++) { + if (earliestTime[i] != Integer.MAX_VALUE) { + result.add(i); + } + } + return result; + } +} diff --git a/Hard/Find K-th Smallest Pair Distance.java b/Hard/Find K-th Smallest Pair Distance.java new file mode 100644 index 00000000..6d84cfa8 --- /dev/null +++ b/Hard/Find K-th Smallest Pair Distance.java @@ -0,0 +1,31 @@ +class Solution { + public int smallestDistancePair(int[] nums, int k) { + Arrays.sort(nums); + int n = nums.length; + int left = 0; + int right = nums[n - 1] - nums[0]; + while (left < right) { + int mid = (left + right) / 2; + int count = countPairs(nums, mid); + if (count < k) { + left = mid + 1; + } else { + right = mid; + } + } + return left; + } + + private int countPairs(int[] nums, int distance) { + int count = 0; + int n = nums.length; + int left = 0; + for (int i = 0; i < n; i++) { + while (nums[i] - nums[left] > distance) { + left++; + } + count += i - left; + } + return count; + } +} diff --git a/Hard/Find Median From Data Stream.java b/Hard/Find Median From Data Stream.java deleted file mode 100644 index 85ef83f0..00000000 --- a/Hard/Find Median From Data Stream.java +++ /dev/null @@ -1,47 +0,0 @@ -lass MedianFinder { - - /** initialize your data structure here. */ - PriorityQueue maxHeap; - PriorityQueue minHeap; - - public MedianFinder() { - maxHeap = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o1 - o2; - } - }); - - minHeap = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o2 - o1; - } - }); - } - - public void addNum(int num) { - maxHeap.offer(num); - minHeap.offer(maxHeap.poll()); - - if (maxHeap.size() < minHeap.size()) { - maxHeap.offer(minHeap.poll()); - } - } - - public double findMedian() { - if (maxHeap.size() == minHeap.size()) { - return (double) (maxHeap.peek() + minHeap.peek())/2; - } - else { - return maxHeap.peek(); - } - } -} - -/** - * Your MedianFinder object will be instantiated and called as such: - * MedianFinder obj = new MedianFinder(); - * obj.addNum(num); - * double param_2 = obj.findMedian(); - */ diff --git a/Hard/Find Median from Data Stream.java b/Hard/Find Median from Data Stream.java new file mode 100644 index 00000000..89269294 --- /dev/null +++ b/Hard/Find Median from Data Stream.java @@ -0,0 +1,31 @@ +class MedianFinder { + + private final PriorityQueue minQueue; + private final PriorityQueue maxQueue; + + public MedianFinder() { + this.minQueue = new PriorityQueue<>(); + this.maxQueue = new PriorityQueue<>((a, b) -> b - a); + } + + public void addNum(int num) { + maxQueue.add(num); + minQueue.add(maxQueue.poll()); + if (maxQueue.size() < minQueue.size()) { + maxQueue.add(minQueue.poll()); + } + } + + public double findMedian() { + return maxQueue.size() > minQueue.size() ? + ((double) maxQueue.peek()) : + ((maxQueue.peek() + minQueue.peek()) / (2.0)); + } +} + +/** + * Your MedianFinder object will be instantiated and called as such: + * MedianFinder obj = new MedianFinder(); + * obj.addNum(num); + * double param_2 = obj.findMedian(); + */ diff --git a/Hard/Find Minimum in Rotated Sorted Array II.java b/Hard/Find Minimum in Rotated Sorted Array II.java index 3f383eef..524fa9a3 100644 --- a/Hard/Find Minimum in Rotated Sorted Array II.java +++ b/Hard/Find Minimum in Rotated Sorted Array II.java @@ -1,27 +1,19 @@ class Solution { - public int findMin(int[] nums) { - int start = 0; - int end = nums.length-1; - int minVal = Integer.MAX_VALUE; - - while (start <= end) { - int mid = (start + end)/2; - if (((mid > 0 ? nums[mid] < nums[mid-1] : true) && (mid < nums.length-1 ? nums[mid] < nums[mid+1] : true))) { - return nums[mid]; - } - else if (nums[mid] < nums[end]) { - end = mid; - } - else if (nums[mid] > nums[end]){ - start = mid+1; - } - else { - end--; - } - - minVal = Math.min(nums[mid], minVal); - } - - return minVal; + public int findMin(int[] nums) { + int start = 0; + int end = nums.length - 1; + while (start <= end) { + int mid = start + (end - start) / 2; + if (nums[mid] < nums[end]) { + end = mid; + } + else if (nums[mid] > nums[end]) { + start = mid + 1; + } + else { + end--; + } } + return nums[start]; + } } diff --git a/Hard/Find in Mountain Array.java b/Hard/Find in Mountain Array.java new file mode 100644 index 00000000..d030c247 --- /dev/null +++ b/Hard/Find in Mountain Array.java @@ -0,0 +1,49 @@ +/** + * // This is MountainArray's API interface. + * // You should not implement it, or speculate about its implementation + * interface MountainArray { + * public int get(int index) {} + * public int length() {} + * } + */ + +class Solution { + public int findInMountainArray(int target, MountainArray mountainArr) { + int n = mountainArr.length(); + int start = 1; + int end = n - 2; + while (start != end) { + int mid = (start + end) / 2; + if (mountainArr.get(mid) < mountainArr.get(mid + 1)) { + start = mid + 1; + } else { + end = mid; + } + } + int peakIndex = start; + start = 0; + end = peakIndex; + while (start != end) { + int mid = (start + end) / 2; + if (mountainArr.get(mid) < target) { + start = mid + 1; + } else { + end = mid; + } + } + if (mountainArr.get(start) == target) { + return start; + } + start = peakIndex + 1; + end = n - 1; + while (start != end) { + int mid = (start + end) / 2; + if (mountainArr.get(mid) > target) { + start = mid + 1; + } else { + end = mid; + } + } + return mountainArr.get(start) == target ? start : -1; + } +} diff --git a/Hard/Find the Kth Smallest Sum of a Matrix With Sorted Rows.java b/Hard/Find the Kth Smallest Sum of a Matrix With Sorted Rows.java new file mode 100644 index 00000000..e5800be2 --- /dev/null +++ b/Hard/Find the Kth Smallest Sum of a Matrix With Sorted Rows.java @@ -0,0 +1,19 @@ +class Solution { + public int kthSmallest(int[][] mat, int k) { + PriorityQueue prevSum = new PriorityQueue<>(Collections.reverseOrder()); + prevSum.add(0); + for (int[] row : mat) { + PriorityQueue nextSum = new PriorityQueue<>(Collections.reverseOrder()); + for (int sum : prevSum) { + for (int c = 0; c < mat[0].length; c++) { + nextSum.add(sum + row[c]); + if (nextSum.size() > k) { + nextSum.poll(); + } + } + } + prevSum = nextSum; + } + return prevSum.poll(); + } +} diff --git a/Hard/Find the Longest Valid Obstacle Course at Each Position.java b/Hard/Find the Longest Valid Obstacle Course at Each Position.java new file mode 100644 index 00000000..fcd272fb --- /dev/null +++ b/Hard/Find the Longest Valid Obstacle Course at Each Position.java @@ -0,0 +1,34 @@ +class Solution { + public int[] longestObstacleCourseAtEachPosition(int[] obstacles) { + int n = obstacles.length; + int lisLength = 0; + int[] result = new int[n]; + int[] lis = new int[n]; + for (int i = 0; i < n; i++) { + int height = obstacles[i]; + int idx = bisect(lis, height, lisLength); + if (idx == lisLength) { + lisLength++; + } + lis[idx] = height; + result[i] = idx + 1; + } + return result; + } + + private int bisect(int[] lis, int target, int right) { + if (right == 0) { + return 0; + } + int left = 0; + while (left < right) { + int mid = left + (right - left) / 2; + if (lis[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + return left; + } +} diff --git a/Hard/First Missing Positive.java b/Hard/First Missing Positive.java index 8cdc4f6e..3b501319 100644 --- a/Hard/First Missing Positive.java +++ b/Hard/First Missing Positive.java @@ -1,19 +1,27 @@ class Solution { public int firstMissingPositive(int[] nums) { - Set set = new HashSet<>(); - int max = 0; - - for (int num : nums) { - set.add(num); - max = Math.max(max, num); + int n = nums.length; + for (int i = 0; i < n; i++) { + if (nums[i] < 0) { + nums[i] = 0; + } + } + for (int i = 0; i < n; i++) { + int val = Math.abs(nums[i]); + if (val >= 1 && val <= n) { + int idx = val - 1; + if (nums[idx] > 0) { + nums[idx] *= -1; + } else if (nums[idx] == 0) { + nums[idx] = -1 * (n + 1); + } + } } - - for (int i = 1; i <= max; i++) { - if (!set.contains(i)) { + for (int i = 1; i <= n; i++) { + if (nums[i - 1] >= 0) { return i; } - } - - return max + 1; + } + return n + 1; } } diff --git a/Hard/Frog Jump.java b/Hard/Frog Jump.java new file mode 100644 index 00000000..4885064e --- /dev/null +++ b/Hard/Frog Jump.java @@ -0,0 +1,26 @@ +class Solution { + public boolean canCross(int[] stones) { + int[][] memo = new int[stones.length][stones.length]; + for (int[] row : memo) { + Arrays.fill(row, -1); + } + return helper(stones, 0, 0, memo) == 1; + } + + private int helper(int[] stones, int idx, int jumpSize, int[][] memo) { + if (memo[idx][jumpSize] >= 0) { + return memo[idx][jumpSize]; + } + for (int i = idx + 1; i < stones.length; i++) { + int gap = stones[i] - stones[idx]; + if (gap >= jumpSize - 1 && gap <= jumpSize + 1) { + if (helper(stones, i, gap, memo) == 1) { + memo[idx][gap] = 1; + return 1; + } + } + } + memo[idx][jumpSize] = (idx == stones.length - 1) ? 1 : 0; + return memo[idx][jumpSize]; + } +} diff --git a/Hard/Greatest Common Divisor Traversal.java b/Hard/Greatest Common Divisor Traversal.java new file mode 100644 index 00000000..81ab07de --- /dev/null +++ b/Hard/Greatest Common Divisor Traversal.java @@ -0,0 +1,80 @@ +class Solution { + + private static final int MAX = 100_000; + + public boolean canTraverseAllPairs(int[] nums) { + int n = nums.length; + if (n == 1) { + return true; + } + boolean[] exists = new boolean[MAX + 1]; + for (int num : nums) { + exists[num] = true; + } + if (exists[1]) { + return false; + } + int[] sieve = new int[MAX + 1]; + for (int i = 2; i <= MAX; i++) { + if (sieve[i] == 0) { + for (int j = i; j <= MAX; j += i) { + sieve[j] = i; + } + } + } + Union union = new Union(2 * MAX + 1); + for (int num : nums) { + int curr = num; + while (curr > 1) { + int prime = sieve[curr]; + int root = prime + MAX; + if (union.find(root) != union.find(num)) { + union.merge(root, num); + } + while (curr % prime == 0) { + curr /= prime; + } + } + } + int count = 0; + for (int i = 2; i <= MAX; i++) { + if (exists[i] && union.find(i) == i) { + count++; + } + } + return count == 1; + } + + private class Union { + private final int[] union; + private final int[] size; + + public Union(int n) { + this.union = new int[n + 1]; + this.size = new int[n + 1]; + for (int i = 0; i <= n; i++) { + union[i] = i; + size[i] = 1; + } + } + + public int find(int num) { + return union[num] == num ? num : (union[num] = find(union[num])); + } + + public void merge(int x, int y) { + int findX = find(x); + int findY = find(y); + if (findX == findY) { + return; + } + if (size[findX] > size[findY]) { + int temp = findX; + findX = findY; + findY = temp; + } + union[findX] = findY; + size[findY] += size[findX]; + } + } +} diff --git a/Hard/Hard.md b/Hard/Hard.md new file mode 100644 index 00000000..c612b7b3 --- /dev/null +++ b/Hard/Hard.md @@ -0,0 +1,56 @@ +# Hard LeetCode-Java-Solutions +S.no | Coding Problem +--- | --- +1|[Merge K Sorted Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardMerge K Sorted Lists.java) +2|[Serialize and Deserialize a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardSerialize and Deserialize a Binary Tree.java) +3|[Palindrome Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardPalindrome Pairs.java) +4|[Binary Tree PostOrder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardBinary Tree PostOrder Traversal.java) +5|[Largest Rectangle in Histogram](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLargest Rectangle in Histogram.java) +6|[Trapping Rain Water](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardTrapping Rain Water.java) +7|[Parallel Courses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardParallel Courses.java) +8|[LFU Cache](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLFU Cache.java) +9|[Unique Paths III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardUnique Paths III.java) +10|[Integer to English Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardInteger to English Words.java) +11|[Number of Valid Subarrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardNumber of Valid Subarrays.java) +12|[Candy](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardCandy.java) +13|[Odd Even Jump](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardOdd Even Jump.java) +14|[Longest Consecutive Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLongest Consecutive Sequence.java) +15|[Substring with Concatenation of All Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardSubstring with Concatenation of All Words.java) +16|[Median of Two Sorted Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardMedian of Two Sorted Arrays.java) +17|[Longest Substring with At Most K Distinct Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLongest Substring with At Most K Distinct Characters.java) +18|[Closest Binary Search Tree Values II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardClosest Binary Search Tree Values II.java) +19|[Edit Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardEdit Distance.java) +20|[Longest Palindrome Product](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLongest Palindrome Product.java) +21|[K Empty Slots](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardK Empty Slots.java) +22|[Cut Off Trees for Golf Event](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardCut Off Trees for Golf Event.java) +23|[Word Break II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardWord Break II.java) +24|[LRU Cache](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLRU Cache.java) +25|[Parsing A Boolean Expression](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardParsing A Boolean Expression.java) +26|[Maximum Frequency Stack](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardMaximum Frequency Stack.java) +27|[N-Queens](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardN-Queens.java) +28|[Sliding Window Maximum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardSliding Window Maximum.java) +29|[Optimal Account Balancing](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardOptimal Account Balancing.java) +30|[Divide Array Into Increasing Sequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardDivide Array Into Increasing Sequences.java) +31|[Serialize and Deserialize N-ary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardSerialize and Deserialize N-ary Tree.java) +32|[Word Search II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardWord Search II.java) +33|[Insert Delete GetRandom O(1) - Duplicates Allowed](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardInsert Delete GetRandom O(1) - Duplicates Allowed.java) +34|[Recover a Tree From Preorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardRecover a Tree From Preorder Traversal.java) +35|[Text Justification](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardText Justification.java) +36|[Find Median From Data Stream](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardFind Median From Data Stream.java) +37|[Number of Submatrices That Sum to Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardNumber of Submatrices That Sum to Target.java) +38|[First Missing Positive](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardFirst Missing Positive.java) +39|[Minimum Window Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardMinimum Window Substring.java) +40|[Stream of Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardStream of Characters.java) +41|[Prefix and Suffix Search](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardPrefix and Suffix Search.java) +42|[Longest Substring with At Most Two Distinct Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLongest Substring with At Most Two Distinct Characters.java) +43|[Find Minimum in Rotated Sorted Array II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardFind Minimum in Rotated Sorted Array II.java) +44|[Sliding Window Median](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardSliding Window Median.java) +45|[Basic Calculator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardBasic Calculator.java) +46|[Binary Tree Maximum Path Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardBinary Tree Maximum Path Sum.java) +47|[Interleaving String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardInterleaving String.java) +48|[Valid Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardValid Number.java) +49|[Robot Room Cleaner](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardRobot Room Cleaner.java) +50|[Employee Free Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardEmployee Free Time.java) +51|[Design Search Autocomplete System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardDesign Search Autocomplete System.java) +52|[Basic Calculator III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardBasic Calculator III.java) +53|[Longest Increasing Path in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/HardLongest Increasing Path in a Matrix.java) diff --git a/Hard/Height of Binary Tree After Subtree Removal Queries.java b/Hard/Height of Binary Tree After Subtree Removal Queries.java new file mode 100644 index 00000000..ebd9acbe --- /dev/null +++ b/Hard/Height of Binary Tree After Subtree Removal Queries.java @@ -0,0 +1,48 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int[] treeQueries(TreeNode root, int[] queries) { + Map result = new HashMap<>(); + Map heightCache = new HashMap<>(); + dfs(root, 0, 0, result, heightCache); + int[] answer = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + answer[i] = result.get(queries[i]); + } + return answer; + } + + private void dfs(TreeNode node, int depth, int maxDepth, Map result, Map heightCache) { + if (node == null) { + return; + } + result.put(node.val, maxDepth); + dfs(node.left, depth + 1, Math.max(maxDepth, depth + 1 + height(node.right, heightCache)), result, heightCache); + dfs(node.right, depth + 1, Math.max(maxDepth, depth + 1 + height(node.left, heightCache)), result, heightCache); + } + + private int height(TreeNode node, Map heightCache) { + if (node == null) { + return -1; + } + if (heightCache.containsKey(node)) { + return heightCache.get(node); + } + int currHeight = 1 + Math.max(height(node.left, heightCache), height(node.right, heightCache)); + heightCache.put(node, currHeight); + return currHeight; + } +} diff --git a/Hard/IPO.java b/Hard/IPO.java new file mode 100644 index 00000000..26cfaac8 --- /dev/null +++ b/Hard/IPO.java @@ -0,0 +1,31 @@ +class Solution { + public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) { + int n = profits.length; + Project[] projects = new Project[n]; + int maximumCapital = w; + for (int i = 0; i < n; i++) { + projects[i] = new Project(capital[i], profits[i]); + } + Arrays.sort(projects); + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + int idx = 0; + for (int i = 0; i < k; i++) { + while (idx < n && projects[idx].capital <= maximumCapital) { + pq.add(projects[idx++].profit); + } + if (pq.isEmpty()) { + break; + } + maximumCapital += pq.poll(); + } + return maximumCapital; + } + + private record Project(int capital, int profit) implements Comparable { + + @Override + public int compareTo(Project o) { + return capital - o.capital; + } + } +} diff --git a/Hard/Interleaving String.java b/Hard/Interleaving String.java deleted file mode 100644 index 3fd73eb2..00000000 --- a/Hard/Interleaving String.java +++ /dev/null @@ -1,33 +0,0 @@ -class Solution { - public boolean isInterleave(String s1, String s2, String s3) { - if (s1.length()+s2.length() != s3.length()) { - return false; - } - - boolean[][] dp = new boolean[s1.length()+1][s2.length()+1]; - - dp[0][0] = true; - - for (int i = 0; i <= s1.length(); i++){ - for (int j = 0; j <= s2.length(); j++){ - boolean s1Check = false; - boolean s2Check = false; - - if (i > 0) { - s1Check = dp[i-1][j] && s3.charAt(i+j-1) == s1.charAt(i-1); - } - - if (j > 0) { - s2Check = dp[i][j-1] && s3.charAt(i+j-1) == s2.charAt(j-1); - } - - if (i>0 || j>0) { - dp[i][j] = s1Check || s2Check; - } - } - } - - - return dp[s1.length()][s2.length()]; - } -} diff --git a/Hard/Jump Game IV.java b/Hard/Jump Game IV.java new file mode 100644 index 00000000..960ce4b7 --- /dev/null +++ b/Hard/Jump Game IV.java @@ -0,0 +1,39 @@ +class Solution { + public int minJumps(int[] arr) { + int n = arr.length; + Map> graph = new HashMap<>(); + for (int i = 0; i < n; i++) { + graph.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i); + } + Queue path = new LinkedList<>(); + Set visited = new HashSet<>(); + path.add(0); + int steps = 0; + while (!path.isEmpty()) { + int size = path.size(); + while (size-- > 0) { + int removed = path.remove(); + if (removed == n - 1) { + return steps; + } + for (Integer child : graph.get(arr[removed])) { + if (!visited.contains(child)) { + visited.add(child); + path.add(child); + } + } + graph.get(arr[removed]).clear(); + if (removed + 1 < n && !visited.contains(removed + 1)) { + visited.add(removed + 1); + path.add(removed + 1); + } + if (removed - 1 >= 0 && !visited.contains(removed - 1)) { + visited.add(removed - 1); + path.add(removed - 1); + } + } + steps++; + } + return -1; + } +} diff --git a/Hard/K Empty Slots.java b/Hard/K Empty Slots.java index 6b004bf0..bb499351 100644 --- a/Hard/K Empty Slots.java +++ b/Hard/K Empty Slots.java @@ -1,19 +1,23 @@ class Solution { - public int kEmptySlots(int[] flowers, int k) { - TreeSet set = new TreeSet<>(); - int day = 0; - - for (int flower : flowers) { - day++; - set.add(flower); - Integer lower = set.lower(flower); - Integer higher = set.higher(flower); - - if ((lower != null && flower - lower - 1 == k) || (higher != null && higher - flower - 1 == k)) { - return day; - } - } - - return -1; + public int kEmptySlots(int[] bulbs, int k) { + int n = bulbs.length; + int[] position = new int[n + 1]; + for (int i = 0; i < n; i++) { + position[bulbs[i]] = i; } + int result = Integer.MAX_VALUE; + int start = 1; + int end = k + 2; + for (int i = 1; end <= n; i++) { + if (position[i] > position[start] && position[i] > position[end]) { + continue; + } + if (i == end) { + result = Math.min(result, Math.max(position[start], position[end]) + 1); + } + start = i; + end = k + 1 + i; + } + return result == Integer.MAX_VALUE ? -1 : result; + } } diff --git a/Hard/K Inverse Pairs Array.java b/Hard/K Inverse Pairs Array.java new file mode 100644 index 00000000..0b6e0d8f --- /dev/null +++ b/Hard/K Inverse Pairs Array.java @@ -0,0 +1,17 @@ +class Solution { + public int kInversePairs(int n, int k) { + int[][] dp = new int[n + 1][k + 1]; + int mod = 1000000007; + for (int i = 1; i <= n; i++) { + for (int j = 0; j <= k; j++) { + if (j == 0) { + dp[i][j] = 1; + } else { + int curr = (dp[i - 1][j] + mod - ((j - i) >= 0 ? dp[i - 1][j - i] : 0)) % mod; + dp[i][j] = (dp[i][j - 1] + curr) % mod; + } + } + } + return ((dp[n][k] + mod - (k > 0 ? dp[n][k - 1] : 0)) % mod); + } +} diff --git a/Hard/K-th Smallest in Lexicographical Order.java b/Hard/K-th Smallest in Lexicographical Order.java new file mode 100644 index 00000000..9063cd56 --- /dev/null +++ b/Hard/K-th Smallest in Lexicographical Order.java @@ -0,0 +1,27 @@ +class Solution { + public int findKthNumber(int n, int k) { + int curr = 1; + k--; + while (k > 0) { + int count = countNumsWithPrefix(n, curr, curr + 1); + if (count <= k) { + curr++; + k -= count; + } else { + curr *= 10; + k--; + } + } + return curr; + } + + private int countNumsWithPrefix(int n, long start, long end) { + int count = 0; + while (start <= n) { + count += Math.min(n + 1, end) - start; + start *= 10; + end *= 10; + } + return count; + } +} diff --git a/Hard/Kth Smallest Number in Multiplication Table.java b/Hard/Kth Smallest Number in Multiplication Table.java new file mode 100644 index 00000000..84d55bf2 --- /dev/null +++ b/Hard/Kth Smallest Number in Multiplication Table.java @@ -0,0 +1,19 @@ +class Solution { + public int findKthNumber(int m, int n, int k) { + int low = 0; + int high = m * n; + while (low < high) { + int mid = (low + high) / 2; + int count = 0; + for (int i = 1; i <= m; i++) { + count += Math.min(n, mid / i); + } + if (count >= k) { + high = mid; + } else { + low = mid + 1; + } + } + return low; + } +} diff --git a/Hard/LFU Cache.java b/Hard/LFU Cache.java index 588f7a60..d4caef70 100644 --- a/Hard/LFU Cache.java +++ b/Hard/LFU Cache.java @@ -1,75 +1,122 @@ class LFUCache { - private Map valMap; - private Map freqMap; - private Map> freqCountMap; - private int capacity; - private int minValue; + private final TreeMap frequencyToNodeMap; + private final Map keyToNodeMap; + private final int capacity; public LFUCache(int capacity) { - valMap = new HashMap<>(); - freqMap = new HashMap<>(); - freqCountMap = new HashMap<>(); + this.frequencyToNodeMap = new TreeMap<>(); + this.keyToNodeMap = new HashMap<>(); this.capacity = capacity; - minValue = 0; } public int get(int key) { - if (!valMap.containsKey(key)) { + if (!keyToNodeMap.containsKey(key)) { return -1; } + Node node = keyToNodeMap.get(key); + updateNodeForFrequencyChange(node); + return node.value; + } - // Updating frequency - int oldFreq = freqMap.get(key); - freqMap.put(key, oldFreq + 1); - int newFreq = freqMap.get(key); - - // Removing from old frequency set - LinkedHashSet set = freqCountMap.get(oldFreq); - set.remove(key); - if (set.isEmpty()) { - // As this was the only key with min freq so minimum frequency should be updated - if (minValue == oldFreq) { - minValue = oldFreq + 1; - } - freqCountMap.remove(oldFreq); - } - else { - freqCountMap.put(oldFreq, set); + public void put(int key, int value) { + if (this.keyToNodeMap.containsKey(key)) { + updateNode(key, value); + } else { + addNewNode(key, value); } + } - // Updating new frequency set - freqCountMap.computeIfAbsent(newFreq, k -> new LinkedHashSet<>()).add(key); - - return valMap.get(key); + private void updateNode(int key, int value) { + Node node = keyToNodeMap.get(key); + node.value = value; + updateNodeForFrequencyChange(node); } - public void put(int key, int value) { + private void addNewNode(int key, int value) { if (capacity == 0) { return; } - - if (get(key) != -1) { - valMap.put(key, value); - return; + if (capacity == keyToNodeMap.size()) { + evictCache(); + } + Node node = new Node(key, value); + addToFrequencyMap(node); + keyToNodeMap.put(key, node); + } + + private void evictCache() { + int firstKey = frequencyToNodeMap.firstKey(); + Node nodeToEvict = frequencyToNodeMap.get(firstKey).getFirstNode(); + removeNode(nodeToEvict); + keyToNodeMap.remove(nodeToEvict.key); + if (frequencyToNodeMap.get(firstKey).getFirstNode().value == -1) { + frequencyToNodeMap.remove(firstKey); + } + } + + private void updateNodeForFrequencyChange(Node node) { + int prevFrequency = node.frequency; + node.frequency = node.frequency + 1; + removeNode(node); + if (frequencyToNodeMap.get(prevFrequency).getFirstNode().value == -1) { + frequencyToNodeMap.remove(prevFrequency); } + addToFrequencyMap(node); + } - if (valMap.size() == capacity) { - LinkedHashSet set = freqCountMap.get(minValue); - int keyToBeDeleted = set.iterator().next(); - valMap.remove(keyToBeDeleted); - freqMap.remove(keyToBeDeleted); - set.remove(keyToBeDeleted); + private void removeNode(Node node) { + Node prevToNode = node.prev; + Node nextToNode = node.next; + prevToNode.next = nextToNode; + nextToNode.prev = prevToNode; + } - if (set.isEmpty()) { - freqCountMap.remove(minValue); - } + private void addToFrequencyMap(Node node) { + if (!frequencyToNodeMap.containsKey(node.frequency)) { + frequencyToNodeMap.put(node.frequency, new NodeLinkedList()); } + frequencyToNodeMap.get(node.frequency).addNode(node); + } + + private static class NodeLinkedList { + private final Node head; + private final Node tail; - valMap.put(key, value); - freqMap.put(key, 1); - freqCountMap.computeIfAbsent(1, k -> new LinkedHashSet<>()).add(key); - minValue = 1; + public NodeLinkedList() { + this.head = new Node(-1, -1); + this.tail = new Node(-1, -1); + head.next = tail; + tail.prev = head; + } + + public Node getFirstNode() { + return head.next; + } + + public void addNode(Node node) { + Node prevToTail = tail.prev; + node.prev = prevToTail; + prevToTail.next = node; + node.next = tail; + tail.prev = node; + } + } + + private static class Node { + private final int key; + private int value; + private int frequency; + private Node next; + private Node prev; + + public Node(int key, int value) { + this.key = key; + this.value = value; + this.frequency = 1; + this.next = null; + this.prev = null; + } } } diff --git a/Hard/LRU Cache.java b/Hard/LRU Cache.java deleted file mode 100644 index 34c92558..00000000 --- a/Hard/LRU Cache.java +++ /dev/null @@ -1,96 +0,0 @@ -class LRUCache { - - Map map; - Node head, tail; - int capacity; - int count; - - public LRUCache(int capacity) { - map = new HashMap<>(); - this.capacity = capacity; - - head = new Node(); - head.previous = null; - - tail = new Node(); - tail.next = null; - - head.next = tail; - tail.previous = head; - - this.count = 0; - } - - public int get(int key) { - Node node = map.get(key); - - if (node == null) { - return -1; - } - - moveToHead(node); - - return node.val; - } - - private void moveToHead(Node node) { - removeNode(node); - addNode(node); - } - - private void addNode(Node node) { - node.previous = head; - node.next = head.next; - - head.next.previous = node; - head.next = node; - } - - private Node popTail() { - Node res = tail.previous; - removeNode(res); - - return res; - } - - private void removeNode(Node node) { - Node pre = node.previous; - Node post = node.next; - - pre.next = post; - post.previous = pre; - } - - public void put(int key, int value) { - Node node = map.get(key); - - if (node == null) { - Node newNode = new Node(); - newNode.key = key; - newNode.val = value; - - map.put(key, newNode); - addNode(newNode); - - count++; - - if (count > capacity) { - Node tail = popTail(); - map.remove(tail.key); - count--; - } - } - else { - node.val = value; - moveToHead(node); - } - } - - private class Node { - Node previous; - Node next; - int key; - int val; - } -} - diff --git a/Hard/Largest Color Value in a Directed Graph.java b/Hard/Largest Color Value in a Directed Graph.java new file mode 100644 index 00000000..2d2fe6d5 --- /dev/null +++ b/Hard/Largest Color Value in a Directed Graph.java @@ -0,0 +1,39 @@ +class Solution { + public int largestPathValue(String colors, int[][] edges) { + int n = colors.length(); + Map> graph = new HashMap<>(); + int[] indegree = new int[n]; + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()) + .add(edge[1]); + indegree[edge[1]]++; + } + int[][] count = new int[n][26]; + Queue queue = new LinkedList<>(); + for (int i = 0; i < n; i++) { + if (indegree[i] == 0) { + queue.add(i); + } + } + int result = 1; + int seen = 0; + while (!queue.isEmpty()) { + int node = queue.remove(); + result = Math.max(result, ++count[node][colors.charAt(node) - 'a']); + seen++; + if (!graph.containsKey(node)) { + continue; + } + for (int neighbor : graph.get(node)) { + for (int i = 0; i < 26; i++) { + count[neighbor][i] = Math.max(count[neighbor][i], count[node][i]); + } + indegree[neighbor]--; + if (indegree[neighbor] == 0) { + queue.add(neighbor); + } + } + } + return seen < n ? -1 : result; + } +} diff --git a/Hard/Largest Rectangle in Histogram.java b/Hard/Largest Rectangle in Histogram.java index a8dde610..837baf32 100644 --- a/Hard/Largest Rectangle in Histogram.java +++ b/Hard/Largest Rectangle in Histogram.java @@ -1,20 +1,17 @@ class Solution { - public int largestRectangleArea(int[] heights) { - Stack stack = new Stack<>(); - int maxArea = 0; - - for (int i = 0; i < heights.length; i++) { - while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) { - maxArea = Math.max(maxArea, heights[stack.pop()] * (i - (stack.isEmpty() ? 0 : stack.peek() + 1))); - } - - stack.push(i); - } - - while (!stack.isEmpty()) { - maxArea = Math.max(maxArea, heights[stack.pop()] * (heights.length - (stack.isEmpty() ? 0 : stack.peek() + 1))); - } - - return maxArea; + public int largestRectangleArea(int[] heights) { + Stack stack = new Stack<>(); + int maxArea = 0; + stack.push(-1); + for (int i = 0; i < heights.length; i++) { + while (stack.peek() != -1 && heights[stack.peek()] >= heights[i]) { + maxArea = Math.max(maxArea, heights[stack.pop()] * (i - stack.peek() - 1)); + } + stack.push(i); } + while (stack.peek() != -1) { + maxArea = Math.max(maxArea, heights[stack.pop()] * (heights.length - stack.peek() - 1)); + } + return maxArea; + } } diff --git a/Hard/Longest Consecutive Sequence.java b/Hard/Longest Consecutive Sequence.java deleted file mode 100644 index 9ba20263..00000000 --- a/Hard/Longest Consecutive Sequence.java +++ /dev/null @@ -1,27 +0,0 @@ -class Solution { - public int longestConsecutive(int[] nums) { - Set set = new HashSet<>(); - for (int num : nums) { - set.add(num); - } - - int maxLen = 0; - Iterator iterator = set.iterator(); - while (iterator.hasNext()) { - int num = iterator.next(); - if (!set.contains(num - 1)) { - int current = num; - int currLen = 1; - - while (set.contains(current + 1)) { - current += 1; - currLen++; - } - - maxLen = Math.max(maxLen, currLen); - } - } - - return maxLen; - } -} diff --git a/Hard/Longest Cycle in a Graph.java b/Hard/Longest Cycle in a Graph.java new file mode 100644 index 00000000..6405e016 --- /dev/null +++ b/Hard/Longest Cycle in a Graph.java @@ -0,0 +1,26 @@ +class Solution { + public int longestCycle(int[] edges) { + int n = edges.length; + boolean[] visited = new boolean[n]; + int[] result = {-1}; + for (int i = 0; i < n; i++) { + if (!visited[i]) { + Map map = new HashMap<>(); + map.put(i, 1); + dfs(i, edges, map, visited, result); + } + } + return result[0]; + } + + private void dfs(int node, int[] edges, Map map, boolean[] visited, int[] result) { + visited[node] = true; + int neighbor = edges[node]; + if (neighbor != -1 && !visited[neighbor]) { + map.put(neighbor, map.get(node) + 1); + dfs(neighbor, edges, map, visited, result); + } else if (neighbor != -1 && map.containsKey(neighbor)) { + result[0] = Math.max(result[0], map.get(node) - map.get(neighbor) + 1); + } + } +} diff --git a/Hard/Longest Increasing Path in a Matrix.java b/Hard/Longest Increasing Path in a Matrix.java index 33c4d437..e7c7f819 100644 --- a/Hard/Longest Increasing Path in a Matrix.java +++ b/Hard/Longest Increasing Path in a Matrix.java @@ -1,42 +1,30 @@ class Solution { - int[][] dp; - public int longestIncreasingPath(int[][] matrix) { - if (matrix.length == 0 || matrix[0].length == 0) { - return 0; - } - - int max = 0; - dp = new int[matrix.length][matrix[0].length]; - - for (int i = 0; i < matrix.length; i++) { - for (int j = 0; j < matrix[0].length; j++) { - max = Math.max(max, getIncreasingPathLength(matrix, i, j, Integer.MIN_VALUE)); - } - } - - return max; + private final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int longestIncreasingPath(int[][] matrix) { + int numRows = matrix.length; + int numCols = matrix[0].length; + int maxPathLength = 0; + int[][] cache = new int[numRows][numCols]; + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + maxPathLength = Math.max(maxPathLength, helper(matrix, numRows, numCols, i, j, cache)); + } } - - private int getIncreasingPathLength(int[][] matrix, int row, int col, int prev) { - if (row < 0 || - col < 0 || - row >= matrix.length || - col >= matrix[0].length || - matrix[row][col] <= prev) { - return 0; - } - - if (dp[row][col] != 0) { - return dp[row][col]; - } - - int up = getIncreasingPathLength(matrix, row - 1, col, matrix[row][col]); - int down = getIncreasingPathLength(matrix, row + 1, col, matrix[row][col]); - int right = getIncreasingPathLength(matrix, row, col + 1, matrix[row][col]); - int left = getIncreasingPathLength(matrix, row, col - 1, matrix[row][col]); - - dp[row][col] = 1 + Math.max(Math.max(up, down), Math.max(right, left)); - - return dp[row][col]; + return maxPathLength; + } + + private int helper(int[][] matrix, int numRows, int numCols, int i, int j, int[][] cache) { + if (cache[i][j] != 0) { + return cache[i][j]; } + for (int[] dir : DIRS) { + int x = i + dir[0]; + int y = j + dir[1]; + if (x >= 0 && y >= 0 && x < numRows && y < numCols && matrix[x][y] > matrix[i][j]) { + cache[i][j] = Math.max(cache[i][j], helper(matrix, numRows, numCols, x, y, cache)); + } + } + return ++cache[i][j]; + } } diff --git a/Hard/Longest Substring with At Most K Distinct Characters.java b/Hard/Longest Substring with At Most K Distinct Characters.java deleted file mode 100644 index 4e524cfd..00000000 --- a/Hard/Longest Substring with At Most K Distinct Characters.java +++ /dev/null @@ -1,24 +0,0 @@ -class Solution { - public int lengthOfLongestSubstringKDistinct(String s, int k) { - int maxLen = 0; - int start = 0; - - Map map = new HashMap<>(); - for (int i = 0; i < s.length(); i++) { - map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); - - while (map.size() > k) { - map.put(s.charAt(start), map.get(s.charAt(start)) - 1); - if (map.get(s.charAt(start)) == 0) { - map.remove(s.charAt(start)); - } - - start++; - } - - maxLen = Math.max(maxLen, i - start + 1); - } - - return maxLen; - } -} diff --git a/Hard/Longest Substring with At Most Two Distinct Characters.java b/Hard/Longest Substring with At Most Two Distinct Characters.java deleted file mode 100644 index deb1b3d7..00000000 --- a/Hard/Longest Substring with At Most Two Distinct Characters.java +++ /dev/null @@ -1,27 +0,0 @@ -class Solution { - public int lengthOfLongestSubstringTwoDistinct(String s) { - Map map = new HashMap<>(); - int slow = 0; - int fast = 0; - int maxLen = 0; - int n = s.length(); - - while (fast < n) { - map.put(s.charAt(fast), map.getOrDefault(s.charAt(fast), 0) + 1); - - while (map.size() > 2) { - map.put(s.charAt(slow), map.getOrDefault(s.charAt(slow), 0) - 1); - if (map.get(s.charAt(slow)) <= 0) { - map.remove(s.charAt(slow)); - } - - slow++; - } - - fast++; - maxLen = Math.max(maxLen, fast - slow); - } - - return maxLen; - } -} diff --git a/Hard/Longest Valid Parentheses.java b/Hard/Longest Valid Parentheses.java new file mode 100644 index 00000000..5f0d934c --- /dev/null +++ b/Hard/Longest Valid Parentheses.java @@ -0,0 +1,34 @@ +class Solution { + public int longestValidParentheses(String s) { + int maxLength = 0; + int leftIdx = 0; + int rightIdx = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '(') { + leftIdx++; + } else { + rightIdx++; + } + if (leftIdx == rightIdx) { + maxLength = Math.max(maxLength, 2 * rightIdx); + } else if (rightIdx > leftIdx) { + leftIdx = rightIdx = 0; + } + } + leftIdx = 0; + rightIdx = 0; + for (int i = s.length() - 1; i >= 0; i--) { + if (s.charAt(i) == '(') { + leftIdx++; + } else { + rightIdx++; + } + if (leftIdx == rightIdx) { + maxLength = Math.max(maxLength, 2 * rightIdx); + } else if (leftIdx > rightIdx) { + leftIdx = rightIdx = 0; + } + } + return maxLength; + } +} diff --git a/Hard/Make Array Strictly Increasing.java b/Hard/Make Array Strictly Increasing.java new file mode 100644 index 00000000..77bed2a8 --- /dev/null +++ b/Hard/Make Array Strictly Increasing.java @@ -0,0 +1,41 @@ +class Solution { + public int makeArrayIncreasing(int[] arr1, int[] arr2) { + Arrays.sort(arr2); + Map, Integer> dp = new HashMap<>(); + int result = dfs(0, -1, arr1, arr2, dp); + return result < 2001 ? result : -1; + } + + private int dfs(int idx, int prev, int[] arr1, int[] arr2, Map, Integer> dp) { + if (idx == arr1.length) { + return 0; + } + if (dp.containsKey(new Pair<>(idx, prev))) { + return dp.get(new Pair<>(idx, prev)); + } + int cost = 2001; + if (arr1[idx] > prev) { + cost = dfs(idx + 1, arr1[idx], arr1, arr2, dp); + } + int replaceIdx = binarySearch(arr2, prev); + if (replaceIdx < arr2.length) { + cost = Math.min(cost, 1 + dfs(idx + 1, arr2[replaceIdx], arr1, arr2, dp)); + } + dp.put(new Pair<>(idx, prev), cost); + return cost; + } + + private static int binarySearch(int[] arr, int value) { + int left = 0; + int right = arr.length; + while (left < right) { + int mid = (left + right) / 2; + if (arr[mid] <= value) { + left = mid + 1; + } else { + right = mid; + } + } + return left; + } +} diff --git a/Hard/Making A Large Island.java b/Hard/Making A Large Island.java new file mode 100644 index 00000000..d1026bd7 --- /dev/null +++ b/Hard/Making A Large Island.java @@ -0,0 +1,68 @@ +class Solution { + + private static final int[][] DIRS = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; + + public int largestIsland(int[][] grid) { + int n = grid.length; + int tag = 2; + int result = 0; + Map tagToAreaMapping = new HashMap<>(); + // Calculate area without changing 0 to 1 & tag each island for future reference + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1) { + tagToAreaMapping.put(tag, dfs(grid, i, j, tag)); + result = Math.max(result, tagToAreaMapping.get(tag)); + tag++; + } + } + } + // Now start changing each 0 to 1 & add the area of all connected islands by referencing their tags + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 0) { + Set visited = new HashSet<>(); + int currArea = 1; + List moves = getMoves(i, j, n); + for (int[] move : moves) { + int x = move[0]; + int y = move[1]; + int currTag = grid[x][y]; + if (currTag > 1 && visited.add(currTag)) { + currArea += tagToAreaMapping.get(currTag); + } + } + result = Math.max(result, currArea); + } + } + } + return result; + } + + private int dfs(int[][] grid, int x, int y, int tag) { + int area = 1; + int n = grid.length; + grid[x][y] = tag; + List moves = getMoves(x, y, n); + for (int[] move : moves) { + int i = move[0]; + int j = move[1]; + if (grid[i][j] == 1) { + area += dfs(grid, i, j, tag); + } + } + return area; + } + + private List getMoves(int x, int y, int n) { + List moves = new ArrayList<>(); + for (int[] dir : DIRS) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newX < n && newY >= 0 && newY < n) { + moves.add(new int[]{newX, newY}); + } + } + return moves; + } +} diff --git a/Hard/Max Dot Product of Two Subsequences.java b/Hard/Max Dot Product of Two Subsequences.java new file mode 100644 index 00000000..c2eca127 --- /dev/null +++ b/Hard/Max Dot Product of Two Subsequences.java @@ -0,0 +1,30 @@ +class Solution { + public int maxDotProduct(int[] nums1, int[] nums2) { + int maxOne = Integer.MIN_VALUE; + int maxTwo = Integer.MIN_VALUE; + int minOne = Integer.MAX_VALUE; + int minTwo = Integer.MAX_VALUE; + for (int num : nums1) { + maxOne = Math.max(maxOne, num); + minOne = Math.min(minOne, num); + } + for (int num : nums2) { + maxTwo = Math.max(maxTwo, num); + minTwo = Math.min(minTwo, num); + } + if (maxOne < 0 && minTwo > 0) { + return maxOne * minTwo; + } + if (minOne > 0 && maxTwo < 0) { + return minOne * maxTwo; + } + int[][] dp = new int[nums1.length + 1][nums2.length + 1]; + for (int i = nums1.length - 1; i >= 0; i--) { + for (int j = nums2.length - 1; j >= 0; j--) { + int curr = nums1[i] * nums2[j] + dp[i + 1][j + 1]; + dp[i][j] = Math.max(curr, Math.max(dp[i + 1][j], dp[i][j + 1])); + } + } + return dp[0][0]; + } +} diff --git a/Hard/Max Points on a Line.java b/Hard/Max Points on a Line.java new file mode 100644 index 00000000..7368488e --- /dev/null +++ b/Hard/Max Points on a Line.java @@ -0,0 +1,26 @@ +class Solution { + public int maxPoints(int[][] points) { + int max = 0; + for (int i = 0; i < points.length - 1; i++) { + Map map = new HashMap<>(); + for (int j = i + 1; j < points.length; j++) { + double slope = calculateSlope(points[i], points[j]); + map.put(slope, map.getOrDefault(slope, 0) + 1); + max = Math.max(max, map.get(slope)); + } + } + return max + 1; + } + + private double calculateSlope(int[] p1, int[] p2) { + double y = (p2[1] - p1[1]) * 1.0; + double x = (p2[0] - p1[0]) * 1.0; + if (x == 0) { + return Double.NaN; + } + if(y == 0) { + return 0.0; + } + return ((double) y * 1.0) / x; + } +} diff --git a/Hard/Max Stack.java b/Hard/Max Stack.java new file mode 100644 index 00000000..918b74b5 --- /dev/null +++ b/Hard/Max Stack.java @@ -0,0 +1,85 @@ +class MaxStack { + + private TreeMap> map; + private Node head; + private Node tail; + + public MaxStack() { + this.map = new TreeMap<>(); + this.head = new Node(-1); + this.tail = new Node(-1); + this.head.next = this.tail; + this.tail.prev = this.head; + } + + public void push(int x) { + Node node = createNode(x); + map.computeIfAbsent(x, k -> new Stack<>()).push(node); + } + + private Node createNode(int x) { + Node node = new Node(x); + Node prevToTail = tail.prev; + node.next = tail; + tail.prev = node; + prevToTail.next = node; + node.prev = prevToTail; + return node; + } + + public int pop() { + Node toRemove = tail.prev; + int val = toRemove.val; + map.get(val).pop(); + if (map.get(val).isEmpty()) { + map.remove(val); + } + removeNode(toRemove); + return toRemove.val; + } + + public int top() { + return tail.prev.val; + } + + public int peekMax() { + return map.lastKey(); + } + + public int popMax() { + int val = map.lastKey(); + Node node = map.get(val).pop(); + if (map.get(val).isEmpty()) { + map.remove(val); + } + removeNode(node); + return val; + } + + private void removeNode(Node node) { + Node prevNode = node.prev; + Node nextNode = node.next; + prevNode.next = nextNode; + nextNode.prev = prevNode; + } + + private static class Node { + Node next; + Node prev; + int val; + + public Node(int val) { + this.val = val; + } + } +} + +/** + * Your MaxStack object will be instantiated and called as such: + * MaxStack obj = new MaxStack(); + * obj.push(x); + * int param_2 = obj.pop(); + * int param_3 = obj.top(); + * int param_4 = obj.peekMax(); + * int param_5 = obj.popMax(); + */ diff --git a/Hard/Maximize Score After N Operations.java b/Hard/Maximize Score After N Operations.java new file mode 100644 index 00000000..2ed4f892 --- /dev/null +++ b/Hard/Maximize Score After N Operations.java @@ -0,0 +1,37 @@ +class Solution { + public int maxScore(int[] nums) { + int dpSize = 1 << nums.length; + int[] dp = new int[dpSize]; + Arrays.fill(dp, -1); + return backtrack(nums, 0, 0, dp); + } + + private int backtrack(int[] nums, int mask, int pickCount, int[] dp) { + if (2 * pickCount == nums.length) { + return 0; + } + if (dp[mask] != -1) { + return dp[mask]; + } + int maxScore = 0; + for (int i = 0; i < nums.length; i++) { + for (int j = i + 1; j < nums.length; j++) { + if (((mask >> i) & 1) == 1 || ((mask >> j) & 1) == 1) { + continue; + } + int newMask = mask | (1 << i) | (1 << j); + int curr = (pickCount + 1) * gcd(nums[i], nums[j]); + int remaining = backtrack(nums, newMask, pickCount + 1, dp); + maxScore = Math.max(maxScore, curr + remaining); + } + } + return dp[mask] = maxScore; + } + + private int gcd(int a, int b) { + if (b == 0) { + return a; + } + return gcd(b, a % b); + } +} diff --git a/Hard/Maximum Frequency Stack.java b/Hard/Maximum Frequency Stack.java index 726b5651..a638cede 100644 --- a/Hard/Maximum Frequency Stack.java +++ b/Hard/Maximum Frequency Stack.java @@ -1,26 +1,35 @@ class FreqStack { - Map map; - Map> freqMap; - int maxFreq; - public FreqStack() { - freqMap = new HashMap<>(); - map = new HashMap<>(); - maxFreq = Integer.MIN_VALUE; - } - - public void push(int x) { - map.put(x, map.getOrDefault(x, 0) + 1); - maxFreq = Math.max(maxFreq, map.get(x)); - freqMap.computeIfAbsent(map.get(x), k -> new Stack<>()).push(x); - } + + private Map frequencyMap; + private Map> frequencyGroup; + private int maxFrequency; + + public FreqStack() { + this.frequencyMap = new HashMap<>(); + this.frequencyGroup = new HashMap<>(); + this.maxFrequency = 0; + } - public int pop() { - int popped = freqMap.get(maxFreq).pop(); - map.put(popped, map.get(popped) - 1); - if (freqMap.get(maxFreq).size() == 0) { - maxFreq--; - } + public void push(int val) { + int newFrequency = this.frequencyMap.getOrDefault(val, 0) + 1; + this.frequencyMap.put(val, newFrequency); + this.maxFrequency = Math.max(this.maxFrequency, newFrequency); + this.frequencyGroup.computeIfAbsent(newFrequency, k -> new Stack<>()).push(val); + } - return popped; + public int pop() { + int val = this.frequencyGroup.get(this.maxFrequency).pop(); + this.frequencyMap.put(val, this.frequencyMap.get(val) - 1); + if (this.frequencyGroup.get(this.maxFrequency).isEmpty()) { + this.maxFrequency--; } + return val; + } } + +/** + * Your FreqStack object will be instantiated and called as such: + * FreqStack obj = new FreqStack(); + * obj.push(val); + * int param_2 = obj.pop(); + */ diff --git a/Hard/Maximum Number of Non-Overlapping Substrings.java b/Hard/Maximum Number of Non-Overlapping Substrings.java new file mode 100644 index 00000000..419ec9ce --- /dev/null +++ b/Hard/Maximum Number of Non-Overlapping Substrings.java @@ -0,0 +1,38 @@ +class Solution { + public List maxNumOfSubstrings(String s) { + int[] leftIdx = new int[26]; + int[] rightIdx = new int[26]; + Arrays.fill(leftIdx, s.length()); + List ans = new ArrayList<>(); + for (int i = 0; i < s.length(); i++) { + int c = s.charAt(i) - 'a'; + leftIdx[c] = Math.min(i, leftIdx[c]); + rightIdx[c] = i; + } + int right = -1; + for (int i = 0; i < s.length(); i++) { + if (i == leftIdx[s.charAt(i) - 'a']) { + int newRight = helper(s, i, leftIdx, rightIdx); + if (newRight != -1) { + if (i > right) { + ans.add(""); + } + right = newRight; + ans.set(ans.size() - 1, s.substring(i, right + 1)); + } + } + } + return ans; + } + + private int helper(String s, int idx, int[] leftIdx, int[] rightIdx) { + int right = rightIdx[s.charAt(idx) - 'a']; + for (int i = idx; i <= right; i++) { + if (leftIdx[s.charAt(i) - 'a'] < idx) { + return -1; + } + right = Math.max(right, rightIdx[s.charAt(i) - 'a']); + } + return right; + } +} diff --git a/Hard/Maximum Performance of a Team.java b/Hard/Maximum Performance of a Team.java new file mode 100644 index 00000000..11a444da --- /dev/null +++ b/Hard/Maximum Performance of a Team.java @@ -0,0 +1,26 @@ +class Solution { + + private final static int MOD = (int) Math.pow(10, 9) + 7; + + public int maxPerformance(int n, int[] speed, int[] efficiency, int k) { + List pairs = new ArrayList<>(); + for (int i = 0; i < n; ++i) { + pairs.add(new int[]{efficiency[i], speed[i]}); + } + Collections.sort(pairs, (o1, o2) -> o2[0] - o1[0]); + PriorityQueue speedMinHeap = new PriorityQueue<>(); + long speedSum = 0; + long performance = 0; + for (int[] pair : pairs) { + Integer currEfficiency = pair[0]; + Integer currSpeed = pair[1]; + if (speedMinHeap.size() > k - 1) { + speedSum -= speedMinHeap.remove(); + } + speedMinHeap.add(currSpeed); + speedSum += currSpeed; + performance = Math.max(performance, speedSum * currEfficiency); + } + return (int) (performance % MOD); + } +} diff --git a/Hard/Maximum Profit in Job Scheduling.java b/Hard/Maximum Profit in Job Scheduling.java new file mode 100644 index 00000000..8a785d43 --- /dev/null +++ b/Hard/Maximum Profit in Job Scheduling.java @@ -0,0 +1,46 @@ +class Solution { + public int jobScheduling(int[] startTime, int[] endTime, int[] profit) { + int n = profit.length; + int[][] jobs = new int[n][3]; + for (int i = 0; i < n; i++) { + jobs[i] = new int[]{startTime[i], endTime[i], profit[i]}; + } + Arrays.sort(jobs, (a, b) -> a[0] - b[0]); + for (int i = 0; i < n; i++) { + startTime[i] = jobs[i][0]; + } + int[] dp = new int[n + 1]; + Arrays.fill(dp, -1); + return findMaxProfit(jobs, startTime, 0, n, dp); + } + + private int findMaxProfit(int[][] jobs, int[] startTime, int position, int n, int[] dp) { + if (position == n) { + return 0; + } + if (dp[position] != -1) { + return dp[position]; + } + int nextPosition = binarySearch(startTime, jobs[position][1]); + return dp[position] = Math.max( + findMaxProfit(jobs, startTime, position + 1, n, dp), // skip executing current job + jobs[position][2] + findMaxProfit(jobs, startTime, nextPosition, n, dp) // execute current job & move to next position + ); + } + + private static int binarySearch(int[] startTime, int endTime) { + int left = 0; + int right = startTime.length - 1; + int nextPosition = startTime.length; + while (left <= right) { + int mid = (left + right) / 2; + if (startTime[mid] >= endTime) { + nextPosition = mid; + right = mid - 1; + } else { + left = mid + 1; + } + } + return nextPosition; + } +} diff --git a/Hard/Maximum Sum BST in Binary Tree.java b/Hard/Maximum Sum BST in Binary Tree.java new file mode 100644 index 00000000..eff81a2a --- /dev/null +++ b/Hard/Maximum Sum BST in Binary Tree.java @@ -0,0 +1,39 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int maxSumBST(TreeNode root) { + int[] ans = {0}; + helper(root, ans); + return ans[0]; + } + + private int[] helper(TreeNode root, int[] ans) { + if (root == null) { + // new int[]{min, max, sum} + return new int[]{Integer.MAX_VALUE, Integer.MIN_VALUE, 0}; + } + int[] left = helper(root.left, ans); + int[] right = helper(root.right, ans); + if (!(left != null && right != null && root.val > left[1] && root.val < right[0])) { + return null; + } + int sum = root.val + left[2] + right[2]; + ans[0] = Math.max(ans[0], sum); + int min = Math.min(root.val, left[0]); + int max = Math.max(root.val, right[1]); + return new int[]{min, max, sum}; + } +} diff --git a/Hard/Maximum Value of K Coins From Piles.java b/Hard/Maximum Value of K Coins From Piles.java new file mode 100644 index 00000000..08fbc802 --- /dev/null +++ b/Hard/Maximum Value of K Coins From Piles.java @@ -0,0 +1,20 @@ +class Solution { + public int maxValueOfCoins(List> piles, int k) { + int n = piles.size(); + int[][] dp = new int[n + 1][k + 1]; + for (int i = 1; i <= n; i++) { + for (int coins = 0; coins <= k; coins++) { + int currSum = 0; + for (int currCoins = 0; + currCoins <= Math.min((int) piles.get(i - 1).size(), coins); + currCoins++) { + if (currCoins > 0) { + currSum += piles.get(i - 1).get(currCoins - 1); + } + dp[i][coins] = Math.max(dp[i][coins], dp[i - 1][coins - currCoins] + currSum); + } + } + } + return dp[n][k]; + } +} diff --git a/Hard/Median of Two Sorted Arrays.java b/Hard/Median of Two Sorted Arrays.java index 375c07fa..33ec700b 100644 --- a/Hard/Median of Two Sorted Arrays.java +++ b/Hard/Median of Two Sorted Arrays.java @@ -1,42 +1,25 @@ class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { - int n = nums1.length + nums2.length; - ArrayList arr = new ArrayList<>(); - - int i = 0; - int j = 0; - int k = 0; - int limit = (n)/2 + 1; - - while (i < nums1.length && j < nums2.length && k < limit) { - if (nums1[i] < nums2[j]) { - arr.add(nums1[i]); - i++; - } - else { - arr.add(nums2[j]); - j++; - } - k++; - } - - if (i < nums1.length) { - while (i < nums1.length && k < limit) { - arr.add(nums1[i]); - i++; - k++; - } + if (nums1.length < nums2.length) { + return findMedianSortedArrays(nums2, nums1); } - else { - while (j < nums2.length && k < limit) { - arr.add (nums2[j]); - j++; - k++; + int low = 0; + int high = nums2.length * 2; + while (low <= high) { + int midTwo = (low + high) / 2; + int midOne = nums1.length + nums2.length - midTwo; + double leftOne = (midOne == 0) ? Integer.MIN_VALUE : nums1[(midOne - 1) / 2]; + double leftTwo = (midTwo == 0) ? Integer.MIN_VALUE : nums2[(midTwo - 1) / 2]; + double rightOne = (midOne == nums1.length * 2) ? Integer.MAX_VALUE : nums1[(midOne) / 2]; + double rightTwo = (midTwo == nums2.length * 2) ? Integer.MAX_VALUE : nums2[(midTwo) / 2]; + if (leftOne > rightTwo) { + low = midTwo + 1; + } else if (leftTwo > rightOne) { + high = midTwo - 1; + } else { + return (Math.max(leftOne, leftTwo) + Math.min(rightOne, rightTwo)) / 2; } } - - k--; - - return n%2 == 0 ? (double) (arr.get(k - 1) + arr.get(k)) / 2.0 : (double) arr.get(k); + return -1; } } diff --git a/Hard/Meeting Rooms III.java b/Hard/Meeting Rooms III.java new file mode 100644 index 00000000..48167f8c --- /dev/null +++ b/Hard/Meeting Rooms III.java @@ -0,0 +1,31 @@ +class Solution { + public int mostBooked(int n, int[][] meetings) { + Arrays.sort(meetings, Comparator.comparingInt(o -> o[0])); + PriorityQueue ongoingMeetings = new PriorityQueue<>(Comparator.comparingInt(a -> a[0])); + int[] frequency = new int[n]; + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> o1[0] == o2[0] ? (int) (o1[1] - o2[1]) : (int) (o1[0] - o2[0])); + for (int i = 0; i < n; i++) { + pq.add(new long[]{0, i}); + } + for (int[] meeting : meetings) { + int startTime = meeting[0]; + while (pq.peek()[0] < startTime) { + pq.add(new long[]{startTime, pq.poll()[1]}); + } + long[] finishedMeeting = pq.poll(); + int room = (int) finishedMeeting[1]; + long endTime = finishedMeeting[0] + (meeting[1] - meeting[0]); + frequency[room]++; + pq.add(new long[]{endTime, room}); + } + int maxCount = 0; + int roomWithMaxCount = 0; + for (int i = 0; i < n; i++) { + if (frequency[i] > maxCount) { + maxCount = frequency[i]; + roomWithMaxCount = i; + } + } + return roomWithMaxCount; + } +} diff --git a/Hard/Merge K Sorted Lists.java b/Hard/Merge K Sorted Lists.java index 7f225ffc..df8ddc91 100644 --- a/Hard/Merge K Sorted Lists.java +++ b/Hard/Merge K Sorted Lists.java @@ -3,41 +3,29 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode mergeKLists(ListNode[] lists) { - if (lists.length == 0) { - return null; - } - - PriorityQueue queue = new PriorityQueue<>(lists.length, new Comparator() { - @Override - public int compare(ListNode o1, ListNode o2) { - return o1.val - o2.val; - } - }); - - for (int i = 0; i < lists.length; i++) { - if (lists[i] != null) { - queue.add(lists[i]); - } - } - - ListNode head = new ListNode(0); - ListNode p = head; - - while (!queue.isEmpty()) { - ListNode node = queue.poll(); - p.next = node; - if (node.next != null) { - queue.add(node.next); - } - - p = p.next; - } - - return head.next; + public ListNode mergeKLists(ListNode[] lists) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> a.val - b.val); + for (ListNode listNode : lists) { + if (listNode != null) { + pq.add(listNode); + } } + ListNode dummy = new ListNode(0); + ListNode curr = dummy; + while (!pq.isEmpty()) { + ListNode removed = pq.remove(); + curr.next = new ListNode(removed.val); + curr = curr.next; + if (removed.next != null) { + pq.add(removed.next); + } + } + return dummy.next; + } } diff --git a/Hard/Minimize Deviation in Array.java b/Hard/Minimize Deviation in Array.java new file mode 100644 index 00000000..905621e6 --- /dev/null +++ b/Hard/Minimize Deviation in Array.java @@ -0,0 +1,21 @@ +class Solution { + public int minimumDeviation(int[] nums) { + int currMinimum = Integer.MAX_VALUE; + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + for (int num : nums) { + if (num % 2 != 0) { + num *= 2; + } + currMinimum = Math.min(currMinimum, num); + pq.add(num); + } + int deviation = Integer.MAX_VALUE; + while (pq.peek() % 2 == 0) { + int removed = pq.poll() / 2; + currMinimum = Math.min(currMinimum, removed); + pq.add(removed); + deviation = Math.min(deviation, pq.peek() - currMinimum); + } + return deviation; + } +} diff --git a/Hard/Minimum Cost to Hire K Workers.java b/Hard/Minimum Cost to Hire K Workers.java new file mode 100644 index 00000000..753c5673 --- /dev/null +++ b/Hard/Minimum Cost to Hire K Workers.java @@ -0,0 +1,43 @@ +class Solution { + public double mincostToHireWorkers(int[] quality, int[] wage, int K) { + int n = quality.length; + Worker[] workers = new Worker[n]; + for (int i = 0; i < n; i++) { + workers[i] = new Worker(quality[i], wage[i]); + } + Arrays.sort(workers); + double ans = 1e9; + int sum = 0; + PriorityQueue pool = new PriorityQueue<>(); + for (Worker worker : workers) { + pool.offer(-worker.quality); + sum += worker.quality; + if (pool.size() > K) { + sum += pool.poll(); + } + if (pool.size() == K) { + ans = Math.min(ans, sum * worker.ratio()); + } + } + return ans; + } +} + + +class Worker implements Comparable { + int quality; + int wage; + + public Worker(int quality, int wage) { + this.quality = quality; + this.wage = wage; + } + + public double ratio() { + return (double) wage / quality; + } + + public int compareTo(Worker other) { + return Double.compare(ratio(), other.ratio()); + } +} diff --git a/Hard/Minimum Cost to Make Array Equal.java b/Hard/Minimum Cost to Make Array Equal.java new file mode 100644 index 00000000..9fe9b8f9 --- /dev/null +++ b/Hard/Minimum Cost to Make Array Equal.java @@ -0,0 +1,27 @@ +class Solution { + public long minCost(int[] nums, int[] cost) { + int n = nums.length; + int[][] numWithCost = new int[n][2]; + for (int i = 0; i < n; i++) { + numWithCost[i] = new int[]{nums[i], cost[i]}; + } + Arrays.sort(numWithCost, (a, b) -> a[0] - b[0]); + long[] prefixCost = new long[n]; + prefixCost[0] = numWithCost[0][1]; + for (int i = 1; i < n; i++) { + prefixCost[i] = numWithCost[i][1] + prefixCost[i - 1]; + } + long totalCost = 0; + for (int i = 1; i < n; i++) { + totalCost += 1L * numWithCost[i][1] * (numWithCost[i][0] - numWithCost[0][0]); + } + long result = totalCost; + for (int i = 1; i < n; ++i) { + int gap = numWithCost[i][0] - numWithCost[i - 1][0]; + totalCost += 1L * prefixCost[i - 1] * gap; + totalCost -= 1L * (prefixCost[n - 1] - prefixCost[i - 1]) * gap; + result = Math.min(result, totalCost); + } + return result; + } +} diff --git a/Hard/Minimum Difficulty of a Job Schedule.java b/Hard/Minimum Difficulty of a Job Schedule.java new file mode 100644 index 00000000..ebc94cc7 --- /dev/null +++ b/Hard/Minimum Difficulty of a Job Schedule.java @@ -0,0 +1,30 @@ +class Solution { + + private static final int INVALID_VALUE = 300_001; + + public int minDifficulty(int[] jobDifficulty, int d) { + if (jobDifficulty.length < d) { + return -1; + } + Integer[][][] dp = new Integer[jobDifficulty.length][d + 1][1001]; + return dfs(jobDifficulty, 0, d, 0, dp); + } + + private int dfs(int[] jobDifficulty, int idx, int d, int currMax, Integer[][][] dp) { + if (idx == jobDifficulty.length) { + return d == 0 ? 0 : INVALID_VALUE; + } + if (d == 0) { + return INVALID_VALUE; + } + if (dp[idx][d][currMax] != null) { + return dp[idx][d][currMax]; + } + currMax = Math.max(currMax, jobDifficulty[idx]); + int result = Math.min(dfs( + jobDifficulty, idx + 1, d, currMax, dp), // continue same sequence + currMax + dfs(jobDifficulty, idx + 1, d - 1, 0, dp) // break sequence + ); + return dp[idx][d][currMax] = result; + } +} diff --git a/Hard/Minimum Insertion Steps to Make a String Palindrome.java b/Hard/Minimum Insertion Steps to Make a String Palindrome.java new file mode 100644 index 00000000..3ffd2f07 --- /dev/null +++ b/Hard/Minimum Insertion Steps to Make a String Palindrome.java @@ -0,0 +1,22 @@ +class Solution { + public int minInsertions(String s) { + int n = s.length(); + return n - lcs(s, new StringBuilder(s).reverse().toString(), n, n); + } + + private int lcs(String s1, String s2, int m, int n) { + int[][] dp = new int[m + 1][n + 1]; + for (int i = 0; i <= m; i++) { + for (int j = 0; j <= n; j++) { + if (i == 0 || j == 0) { + dp[i][j] = 0; + } else if (s1.charAt(i - 1) == s2.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + return dp[m][n]; + } +} diff --git a/Hard/Minimum Number of Operations to Make Array Continuous.java b/Hard/Minimum Number of Operations to Make Array Continuous.java new file mode 100644 index 00000000..f6f07059 --- /dev/null +++ b/Hard/Minimum Number of Operations to Make Array Continuous.java @@ -0,0 +1,25 @@ +class Solution { + public int minOperations(int[] nums) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + int[] arr = new int[set.size()]; + int idx = 0; + for (Integer num : set) { + arr[idx++] = num; + } + Arrays.sort(arr); + int n = nums.length; + int result = n; + int j = 0; + for (int i = 0; i < arr.length; i++) { + while (j < arr.length && arr[j] < arr[i] + n) { + j++; + } + int count = j - i; + result = Math.min(result, n - count); + } + return result; + } +} diff --git a/Hard/Minimum Number of Refueling Stops.java b/Hard/Minimum Number of Refueling Stops.java new file mode 100644 index 00000000..217cbe08 --- /dev/null +++ b/Hard/Minimum Number of Refueling Stops.java @@ -0,0 +1,27 @@ +class Solution { + public int minRefuelStops(int target, int startFuel, int[][] stations) { + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + int result = 0; + int prev = 0; + for (int[] station : stations) { + int location = station[0]; + int capacity = station[1]; + startFuel -= location - prev; + while (!pq.isEmpty() && startFuel < 0) { + startFuel += pq.poll(); + result++; + } + if (startFuel < 0) { + return -1; + } + pq.add(capacity); + prev = location; + } + startFuel -= target - prev; + while (!pq.isEmpty() && startFuel < 0) { + startFuel += pq.poll(); + result++; + } + return startFuel < 0 ? -1 : result; + } +} diff --git a/Hard/Minimum Number of Removals to Make Mountain Array.java b/Hard/Minimum Number of Removals to Make Mountain Array.java new file mode 100644 index 00000000..b74f6feb --- /dev/null +++ b/Hard/Minimum Number of Removals to Make Mountain Array.java @@ -0,0 +1,30 @@ +class Solution { + public int minimumMountainRemovals(int[] nums) { + int n = nums.length; + int[] leftIncreasingLength = new int[n]; + int[] rightDecreasingLength = new int[n]; + Arrays.fill(leftIncreasingLength, 1); + Arrays.fill(rightDecreasingLength, 1); + for (int i = 0; i < n; i++) { + for (int j = i - 1; j >= 0; j--) { + if (nums[i] > nums[j]) { + leftIncreasingLength[i] = Math.max(leftIncreasingLength[i], leftIncreasingLength[j] + 1); + } + } + } + for (int i = n - 1; i >= 0; i--) { + for (int j = i + 1; j < n; j++) { + if (nums[i] > nums[j]) { + rightDecreasingLength[i] = Math.max(rightDecreasingLength[i], rightDecreasingLength[j] + 1); + } + } + } + int minRemovals = Integer.MAX_VALUE; + for (int i = 0; i < n; i++) { + if (leftIncreasingLength[i] > 1 && rightDecreasingLength[i] > 1) { + minRemovals = Math.min(minRemovals, n - leftIncreasingLength[i] - rightDecreasingLength[i] + 1); + } + } + return minRemovals; + } +} diff --git a/Hard/Minimum Replacements to Sort the Array.java b/Hard/Minimum Replacements to Sort the Array.java new file mode 100644 index 00000000..1c3cfc4f --- /dev/null +++ b/Hard/Minimum Replacements to Sort the Array.java @@ -0,0 +1,14 @@ +class Solution { + public long minimumReplacement(int[] nums) { + int n = nums.length; + long numOfOperations = 0; + for (int i = n - 2; i >= 0; i--) { + if (nums[i] > nums[i + 1]) { + long numElements = (long)(nums[i] + nums[i + 1] - 1) / (long)nums[i + 1]; + numOfOperations += numElements - 1; + nums[i] = nums[i] / (int)numElements; + } + } + return numOfOperations; + } +} diff --git a/Hard/Minimum Window Subsequence.java b/Hard/Minimum Window Subsequence.java new file mode 100644 index 00000000..d1a9b971 --- /dev/null +++ b/Hard/Minimum Window Subsequence.java @@ -0,0 +1,39 @@ +class Solution { + public String minWindow(String s1, String s2) { + int right = 0; + int minWindowLength = Integer.MAX_VALUE; + String result = ""; + while (right < s1.length()) { + int s2Idx = 0; + while (right < s1.length()) { + if (s1.charAt(right) == s2.charAt(s2Idx)) { + s2Idx++; + } + if (s2Idx == s2.length()) { + break; + } + right++; + } + if (right == s1.length()) { + break; + } + int s1EndIdx = right; + int s2EndIdx = s2.length() - 1; + while (s1EndIdx >= 0) { + if (s1.charAt(s1EndIdx) == s2.charAt(s2EndIdx)) { + s2EndIdx--; + } + if (s2EndIdx < 0) { + break; + } + s1EndIdx--; + } + if (right - s1EndIdx + 1 < minWindowLength) { + minWindowLength = right - s1EndIdx + 1; + result = s1.substring(s1EndIdx, right + 1); + } + right = s1EndIdx + 1; + } + return result; + } +} diff --git a/Hard/Minimum Window Substring.java b/Hard/Minimum Window Substring.java index b5d6ae76..40cfa2ce 100644 --- a/Hard/Minimum Window Substring.java +++ b/Hard/Minimum Window Substring.java @@ -2,42 +2,37 @@ class Solution { public String minWindow(String s, String t) { Map map = new HashMap<>(); for (char c : t.toCharArray()) { - map.put(c, (map.getOrDefault(c, 0) + 1)); + map.put(c, map.getOrDefault(c, 0) + 1); } - + int targetSize = map.size(); int start = 0; - int end = 0; - int count = map.size(); - int minLen = Integer.MAX_VALUE; - String ans = ""; - - while (end < s.length()) { - if (map.containsKey(s.charAt(end))) { - map.put(s.charAt(end), map.get(s.charAt(end)) - 1); - if (map.get(s.charAt(end)) == 0) { - count--; + int minLength = Integer.MAX_VALUE; + int minStart = -1; + int minEnd = -1; + int n = s.length(); + for (int i = 0; i < n; i++) { + if (map.containsKey(s.charAt(i))) { + map.put(s.charAt(i), map.get(s.charAt(i)) - 1); + if (map.get(s.charAt(i)) == 0) { + targetSize--; } } - - end++; - - while (count == 0) { - if (end - start < minLen) { - minLen = end - start; - ans = s.substring(start, end); - } - + while (start <= i && targetSize == 0) { + int currLength = i - start; + if (minLength > currLength) { + minLength = currLength; + minStart = start; + minEnd = i + 1; + } if (map.containsKey(s.charAt(start))) { map.put(s.charAt(start), map.get(s.charAt(start)) + 1); - if (map.get(s.charAt(start)) > 0) { - count++; + if (map.get(s.charAt(start)) == 1) { + targetSize++; } } - start++; } } - - return ans; + return minLength == Integer.MAX_VALUE ? "" : s.substring(minStart, minEnd); } } diff --git a/Hard/My Calendar III.java b/Hard/My Calendar III.java new file mode 100644 index 00000000..47a51702 --- /dev/null +++ b/Hard/My Calendar III.java @@ -0,0 +1,26 @@ +class MyCalendarThree { + + private TreeMap delta; + + public MyCalendarThree() { + this.delta = new TreeMap<>(); + } + + public int book(int start, int end) { + delta.put(start, delta.getOrDefault(start, 0) + 1); + delta.put(end, delta.getOrDefault(end, 0) - 1); + int activeEvents = 0; + int maxEvents = 0; + for (int d : delta.values()) { + activeEvents += d; + maxEvents = Math.max(maxEvents, activeEvents); + } + return maxEvents; + } +} + +/** + * Your MyCalendarThree object will be instantiated and called as such: + * MyCalendarThree obj = new MyCalendarThree(); + * int param_1 = obj.book(start,end); + */ diff --git a/Hard/N-Queens II.java b/Hard/N-Queens II.java new file mode 100644 index 00000000..0cc14059 --- /dev/null +++ b/Hard/N-Queens II.java @@ -0,0 +1,29 @@ +class Solution { + public int totalNQueens(int n) { + return backtrack(0, new HashSet<>(), new HashSet<>(), new HashSet<>(), n); + } + + private int backtrack(int row, Set diagonals, Set antiDiagonals, Set columns, int n) { + if (row == n) { + return 1; + } + int possibleSolutions = 0; + for (int col = 0; col < n; col++) { + int currDiagonal = row - col; + int currAntiDiagonal = row + col; + if (columns.contains(col) || diagonals.contains(currDiagonal) || antiDiagonals.contains(currAntiDiagonal)) { + continue; + } + columns.add(col); + diagonals.add(currDiagonal); + antiDiagonals.add(currAntiDiagonal); + + possibleSolutions += backtrack(row + 1, diagonals, antiDiagonals, columns, n); + + columns.remove(col); + diagonals.remove(currDiagonal); + antiDiagonals.remove(currAntiDiagonal); + } + return possibleSolutions; + } +} diff --git a/Hard/N-Queens.java b/Hard/N-Queens.java new file mode 100644 index 00000000..0551c884 --- /dev/null +++ b/Hard/N-Queens.java @@ -0,0 +1,45 @@ +class Solution { + public List> solveNQueens(int n) { + List> result = new ArrayList<>(); + char[][] board = new char[n][n]; + for (char[] row : board) { + Arrays.fill(row, '.'); + } + backtrack(0, new HashSet<>(), new HashSet<>(), new HashSet<>(), board, result, n); + return result; + } + + private void backtrack(int row, Set diagonals, Set antiDiagonals, Set columns, char[][] board, List> result, int n) { + if (row == n) { + result.add(buildBoard(board, n)); + return; + } + for (int col = 0; col < n; col++) { + int currDiagonal = row - col; + int currAntiDiagonal = row + col; + if (columns.contains(col) || diagonals.contains(currDiagonal) || antiDiagonals.contains(currAntiDiagonal)) { + continue; + } + columns.add(col); + diagonals.add(currDiagonal); + antiDiagonals.add(currAntiDiagonal); + board[row][col] = 'Q'; + + backtrack(row + 1, diagonals, antiDiagonals, columns, board, result, n); + + columns.remove(col); + diagonals.remove(currDiagonal); + antiDiagonals.remove(currAntiDiagonal); + board[row][col] = '.'; + } + } + + private List buildBoard(char[][] board, int n) { + List resultBoard = new ArrayList<>(); + for (int row = 0; row < n; row++) { + String currentRow = new String(board[row]); + resultBoard.add(currentRow); + } + return resultBoard; + } +} diff --git a/Hard/Naming a Company.java b/Hard/Naming a Company.java new file mode 100644 index 00000000..c24f78fe --- /dev/null +++ b/Hard/Naming a Company.java @@ -0,0 +1,26 @@ +class Solution { + public long distinctNames(String[] ideas) { + Map> map = new HashMap<>(); + for (String idea : ideas) { + map.computeIfAbsent(idea.charAt(0), k -> new HashSet<>()).add(idea.substring(1, idea.length())); + } + long result = 0; + for (Character key1 : map.keySet()) { + for (Character key2 : map.keySet()) { + if (key1 == key2) { + continue; + } + int intersection = 0; + for (String word : map.get(key1)) { + if (map.get(key2).contains(word)) { + intersection++; + } + } + int distinctOne = map.get(key1).size() - intersection; + int distinctTwo = map.get(key2).size() - intersection; + result += distinctOne * distinctTwo; + } + } + return result; + } +} diff --git a/Hard/Number of Flowers in Full Bloom.java b/Hard/Number of Flowers in Full Bloom.java new file mode 100644 index 00000000..37bb43e7 --- /dev/null +++ b/Hard/Number of Flowers in Full Bloom.java @@ -0,0 +1,25 @@ +class Solution { + public int[] fullBloomFlowers(int[][] flowers, int[] people) { + int[] peopleCopy = Arrays.copyOf(people, people.length); + Arrays.sort(peopleCopy); + Arrays.sort(flowers, (a, b) -> Arrays.compare(a, b)); + Map map = new HashMap<>(); + PriorityQueue pq = new PriorityQueue<>(); + int idx = 0; + for (int person : peopleCopy) { + while (idx < flowers.length && flowers[idx][0] <= person) { + pq.add(flowers[idx][1]); + idx++; + } + while (!pq.isEmpty() && pq.peek() < person) { + pq.poll(); + } + map.put(person, pq.size()); + } + int[] result = new int[people.length]; + for (int i = 0; i < people.length; i++) { + result[i] = map.get(people[i]); + } + return result; + } +} diff --git a/Hard/Number of Paths with Max Score.java b/Hard/Number of Paths with Max Score.java new file mode 100644 index 00000000..576a6942 --- /dev/null +++ b/Hard/Number of Paths with Max Score.java @@ -0,0 +1,42 @@ +class Solution { + int[][] dirs = {{-1, 0}, {0, -1}, {-1, -1}}; + final int MOD = 1000000007; + int[][] dpSum; + int[][] dpCount; + public int[] pathsWithMaxScore(List board) { + int numRows = board.size(); + int numCols = board.get(0).length(); + dpSum = new int[numRows][numCols]; + dpCount = new int[numRows][numCols]; + dpCount[numRows - 1][numCols - 1] = 1; + helper(board, numRows, numCols); + return new int[]{dpSum[0][0], dpCount[0][0]}; + } + + private void helper(List board, int numRows, int numCols) { + for (int x = numRows - 1; x >= 0; x--) { + for (int y = numCols - 1; y >= 0; y--) { + if (dpCount[x][y] == 0) { + continue; + } + for (int[] dir : dirs) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newY >= 0 && board.get(newX).charAt(newY) != 'X') { + int tempSum = dpSum[x][y]; + if (board.get(newX).charAt(newY) != 'E') { + tempSum += Character.getNumericValue(board.get(newX).charAt(newY)); + } + if (tempSum > dpSum[newX][newY]) { + dpCount[newX][newY] = dpCount[x][y]; + dpSum[newX][newY] = tempSum; + } + else if (tempSum == dpSum[newX][newY]) { + dpCount[newX][newY] = (dpCount[newX][newY] + dpCount[x][y]) % MOD; + } + } + } + } + } + } +} diff --git a/Hard/Number of Squareful Arrays.java b/Hard/Number of Squareful Arrays.java new file mode 100644 index 00000000..b21f3889 --- /dev/null +++ b/Hard/Number of Squareful Arrays.java @@ -0,0 +1,35 @@ +class Solution { + public int numSquarefulPerms(int[] nums) { + Arrays.sort(nums); + int[] count = {0}; + backtrack(new ArrayList<>(), nums, new boolean[nums.length], -1, count); + return count[0]; + } + + private void backtrack(List temp, int[] nums, boolean[] used, int lastNumber, int[] count) { + if (temp.size() == nums.length){ + count[0]++; + return; + } + for (int i = 0; i < nums.length; i++){ + if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])){ + continue; + } + if (lastNumber != -1) { + if (!isSquare(nums[i] + lastNumber)) { + continue; + } + } + used[i] = true; + temp.add(nums[i]); + backtrack(temp, nums, used, nums[i], count); + temp.remove(temp.size() - 1); + used[i] = false; + } + } + + private boolean isSquare(int num) { + int squareRoot = (int) Math.sqrt(num); + return squareRoot * squareRoot == num; + } +} diff --git a/Hard/Number of Submatrices That Sum to Target.java b/Hard/Number of Submatrices That Sum to Target.java new file mode 100644 index 00000000..d8f9dfc5 --- /dev/null +++ b/Hard/Number of Submatrices That Sum to Target.java @@ -0,0 +1,26 @@ +class Solution { + public int numSubmatrixSumTarget(int[][] matrix, int target) { + int rows = matrix.length; + int cols = matrix[0].length; + int[][] prefixSum = new int[rows + 1][cols + 1]; + for (int i = 1; i <= rows; i++) { + for (int j = 1; j <= cols; j++) { + prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1] + matrix[i - 1][j - 1]; + } + } + int count = 0; + int currSum = 0; + for (int i = 1; i <= rows; i++) { + for (int j = i; j <= rows; j++) { + Map map = new HashMap<>(); + map.put(0, 1); + for (int k = 1; k <= cols; k++) { + currSum = prefixSum[j][k] - prefixSum[i - 1][k]; + count += map.getOrDefault(currSum - target, 0); + map.put(currSum, map.getOrDefault(currSum, 0) + 1); + } + } + } + return count; + } +} diff --git a/Hard/Number of Ways of Cutting a Pizza.java b/Hard/Number of Ways of Cutting a Pizza.java new file mode 100644 index 00000000..a96b2064 --- /dev/null +++ b/Hard/Number of Ways of Cutting a Pizza.java @@ -0,0 +1,37 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int ways(String[] pizza, int k) { + int rows = pizza.length; + int cols = pizza[0].length(); + int[][] apples = new int[rows + 1][cols + 1]; + int[][][] dp = new int[k][rows][cols]; + for (int row = rows - 1; row >= 0; row--) { + for (int col = cols - 1; col >= 0; col--) { + apples[row][col] = (pizza[row].charAt(col) == 'A' ? 1 : 0) + apples[row + 1][col] + apples[row][col + 1] - apples[row + 1][col + 1]; + dp[0][row][col] = apples[row][col] > 0 ? 1 : 0; + } + } + + for (int i = 1; i < k; i++) { + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + for (int nextRow = row + 1; nextRow < rows; nextRow++) { + if (apples[row][col] - apples[nextRow][col] > 0) { + dp[i][row][col] += dp[i - 1][nextRow][col]; + dp[i][row][col] %= MOD; + } + } + for (int nextCol = col + 1; nextCol < cols; nextCol++) { + if (apples[row][col] - apples[row][nextCol] > 0) { + dp[i][row][col] += dp[i - 1][row][nextCol]; + dp[i][row][col] %= MOD; + } + } + } + } + } + return dp[k - 1][0][0]; + } +} diff --git a/Hard/Number of Ways to Form a Target String Given a Dictionary.java b/Hard/Number of Ways to Form a Target String Given a Dictionary.java new file mode 100644 index 00000000..a6354f1f --- /dev/null +++ b/Hard/Number of Ways to Form a Target String Given a Dictionary.java @@ -0,0 +1,28 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int numWays(String[] words, String target) { + int m = target.length(); + int k = words[0].length(); + int[][] count = new int[26][k]; + for (int i = 0; i < k; i++) { + for (String word : words) { + count[word.charAt(i) - 'a'][i]++; + } + } + long[][] dp = new long[m + 1][k + 1]; + dp[0][0] = 1l; + for (int i = 0; i <= m; i++) { + for (int j = 0; j < k; j++) { + if (i < m) { + dp[i + 1][j + 1] += count[target.charAt(i) - 'a'][j] * dp[i][j]; + dp[i + 1][j + 1] %= MOD; + } + dp[i][j + 1] += dp[i][j]; + dp[i][j + 1] %= MOD; + } + } + return (int) dp[m][k]; + } +} diff --git a/Hard/Number of Ways to Reorder Array to Get Same BST.java b/Hard/Number of Ways to Reorder Array to Get Same BST.java new file mode 100644 index 00000000..a47c1f1d --- /dev/null +++ b/Hard/Number of Ways to Reorder Array to Get Same BST.java @@ -0,0 +1,38 @@ +class Solution { + + private static final long MOD = 1000_000_007; + + public int numOfWays(int[] nums) { + int n = nums.length; + long[][] dp = new long[n][n]; + for (int i = 0; i < n; i++) { + dp[i][0] = dp[i][i] = 1; + } + for (int i = 2; i < n; i++) { + for (int j = 1; j < i; j++) { + dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % MOD; + } + } + List list = Arrays.stream(nums).boxed().collect(Collectors.toList()); + return (int) ((dfs(list, dp) - 1) % MOD); + } + + private long dfs(List nums, long[][] dp) { + int n = nums.size(); + if (n < 3) { + return 1; + } + List leftNodes = new ArrayList<>(); + List rightNodes = new ArrayList<>(); + for (int i = 1; i < n; i++) { + if (nums.get(i) < nums.get(0)) { + leftNodes.add(nums.get(i)); + } else { + rightNodes.add(nums.get(i)); + } + } + long leftCount = dfs(leftNodes, dp) % MOD; + long rightCount = dfs(rightNodes, dp) % MOD; + return (((leftCount * rightCount) % MOD) * dp[n - 1][leftNodes.size()]) % MOD; + } +} diff --git a/Hard/Number of Ways to Stay in the Same Place After Some Steps.java b/Hard/Number of Ways to Stay in the Same Place After Some Steps.java new file mode 100644 index 00000000..a9ce7edf --- /dev/null +++ b/Hard/Number of Ways to Stay in the Same Place After Some Steps.java @@ -0,0 +1,23 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int numWays(int steps, int arrLen) { + arrLen = Math.min(arrLen, steps); + int[][] dp = new int[arrLen][steps + 1]; + dp[0][0] = 1; + for (int i = 1; i <= steps; i++) { + for (int j = arrLen - 1; j >= 0; j--) { + int result = dp[j][i - 1]; + if (j > 0) { + result = (result + dp[j - 1][i - 1]) % MOD; + } + if (j < arrLen - 1) { + result = (result + dp[j + 1][i - 1]) % MOD; + } + dp[j][i] = result; + } + } + return dp[0][steps]; + } +} diff --git a/Hard/Odd Even Jump.java b/Hard/Odd Even Jump.java new file mode 100644 index 00000000..b5290dee --- /dev/null +++ b/Hard/Odd Even Jump.java @@ -0,0 +1,36 @@ +class Solution { + public int oddEvenJumps(int[] A) { + int n = A.length; + if (n <= 1) { + return n; + } + boolean[] odd = new boolean[n]; + boolean[] even = new boolean[n]; + odd[n - 1] = even[n - 1] = true; + TreeMap map = new TreeMap<>(); + map.put(A[n - 1], n - 1); + int count = 0; + for (int i = n - 2; i >= 0; i--) { + int val = A[i]; + if (map.containsKey(val)) { + odd[i] = even[map.get(val)]; + even[i] = odd[map.get(val)]; + } + else { + Integer lower = map.lowerKey(val); + Integer higher = map.higherKey(val); + if (lower != null) { + even[i] = odd[map.get(lower)]; + } + if (higher != null) { + odd[i] = even[map.get(higher)]; + } + } + map.put(val, i); + } + for (boolean b : odd) { + count += b ? 1 : 0; + } + return count; + } +} diff --git a/Hard/Paint House II.java b/Hard/Paint House II.java new file mode 100644 index 00000000..23ac7a3d --- /dev/null +++ b/Hard/Paint House II.java @@ -0,0 +1,28 @@ +class Solution { + public int minCostII(int[][] costs) { + int n = costs.length; + int k = costs[0].length; + int[][] dp = new int[n][k]; + for (int i = 0; i < k; i++) { + dp[0][i] = costs[0][i]; + } + for (int i = 1; i < n; i++) { + for (int j = 0; j < k; j++) { + dp[i][j] = minCost(dp[i - 1], j) + costs[i][j]; + } + } + return minCost(dp[n - 1], -1); + } + + private int minCost(int[] dp, int currPaintIdx) { + int cost = Integer.MAX_VALUE; + int idx = 0; + while (idx < dp.length) { + if (!(currPaintIdx != -1 && idx == currPaintIdx)) { + cost = Math.min(cost, dp[idx]); + } + idx++; + } + return cost; + } +} diff --git a/Hard/Paint House III.java b/Hard/Paint House III.java new file mode 100644 index 00000000..461973f0 --- /dev/null +++ b/Hard/Paint House III.java @@ -0,0 +1,37 @@ +class Solution { + private static final int MAXIMUM_POSSIBLE_COST = 1000001; + + public int minCost(int[] houses, int[][] cost, int m, int n, int target) { + Integer[][][] dp = new Integer[m + 1][target + 1][n + 1]; // [Current House][Neighborhood Count][Previous Color] + int result = helper(houses, cost, target, 0, 0, dp); + return result == MAXIMUM_POSSIBLE_COST ? -1 : result; + } + + public int helper(int[] houses, int[][] cost, int target, int idx, int numOfNeighbourhood, Integer[][][] dp) { + if (idx == houses.length) { + return numOfNeighbourhood != target ? MAXIMUM_POSSIBLE_COST : 0; + } + if (numOfNeighbourhood > target) { + return MAXIMUM_POSSIBLE_COST; + } + int prevHouseColor = idx == 0 ? 0 : houses[idx - 1]; + if (dp[idx][numOfNeighbourhood][prevHouseColor] != null) { + return dp[idx][numOfNeighbourhood][prevHouseColor]; + } + int minimumCost = MAXIMUM_POSSIBLE_COST; + if (houses[idx] != 0) { + int currColor = houses[idx]; + int updatedNumOfNeighbourhood = currColor != prevHouseColor ? numOfNeighbourhood + 1 : numOfNeighbourhood; + minimumCost = helper(houses, cost, target, idx + 1, updatedNumOfNeighbourhood, dp); + } else { + for (int currentColor = 1; currentColor <= cost[idx].length; currentColor++) { + houses[idx] = currentColor; // Color the house with currentColor + int updatedNumOfNeighbourhood = currentColor != prevHouseColor ? numOfNeighbourhood + 1 : numOfNeighbourhood; + int currCost = cost[idx][currentColor - 1] + helper(houses, cost, target, idx + 1, updatedNumOfNeighbourhood, dp); + minimumCost = Math.min(minimumCost, currCost); + houses[idx] = 0; // Remove the currentColor for recursion + } + } + return dp[idx][numOfNeighbourhood][prevHouseColor] = minimumCost; + } +} diff --git a/Hard/Painting the Walls.java b/Hard/Painting the Walls.java new file mode 100644 index 00000000..ceeb36f2 --- /dev/null +++ b/Hard/Painting the Walls.java @@ -0,0 +1,26 @@ +class Solution { + + private static final int INVALID_VALUE = 1000_000_000; + + public int paintWalls(int[] cost, int[] time) { + int n = cost.length; + Integer[][] dp = new Integer[n][n + 1]; + return compute(0, n, cost, time, dp, n); + } + + private int compute(int idx, int remain, int[] cost, int[] time, Integer[][] dp, int n) { + if (remain <= 0) { + return 0; + } + if (idx == n) { + return INVALID_VALUE; + } + if (dp[idx][remain] != null) { + return dp[idx][remain]; + } + int paint = cost[idx] + compute(idx + 1, remain - 1 - time[idx], cost, time, dp, n); + int noPaint = compute(idx + 1, remain, cost, time, dp, n); + dp[idx][remain] = Math.min(paint, noPaint); + return dp[idx][remain]; + } +} diff --git a/Hard/Palindrome Pairs.java b/Hard/Palindrome Pairs.java index a9ad8490..004bc645 100644 --- a/Hard/Palindrome Pairs.java +++ b/Hard/Palindrome Pairs.java @@ -1,54 +1,68 @@ class Solution { - public List> palindromePairs(String[] words) { - List> lists = new ArrayList<>(); - Map map = new HashMap<>(); - for (int i=0; i> palindromePairs(String[] words) { + TrieNode root = new TrieNode(); + for (int i = 0; i < words.length; i++) { + String reversed = new StringBuilder(words[i]).reverse().toString(); + TrieNode curr = root; + for (int j = 0; j < reversed.length(); j++) { + if (isPalindrome(reversed, j)) { + curr.palindromePrefixRemainingIds.add(i); } - - if (map.containsKey("")) { - for (int i = 0; i < words.length; i++) { - if (i == map.get("")) { - continue; - } - - if (palindromeCheck(words[i])) { - lists.add(Arrays.asList(map.get(""), i)); - } - } + if (!curr.children.containsKey(reversed.charAt(j))) { + curr.children.put(reversed.charAt(j), new TrieNode()); } - - for (int i=0; i> result = new ArrayList<>(); + for (int i = 0; i < words.length; i++) { + String word = words[i]; + TrieNode curr = root; + for (int j = 0; j < word.length(); j++) { + if (curr.wordEndingId != -1 && isPalindrome(word, j)) { + result.add(Arrays.asList(i, curr.wordEndingId)); + } + char c = word.charAt(j); + curr = curr.children.get(c); + if (curr == null) { + break; } - - return lists; + } + if (curr == null) { + continue; + } + if (curr.wordEndingId != -1 && curr.wordEndingId != i) { + result.add(Arrays.asList(i, curr.wordEndingId)); + } + for (int idx : curr.palindromePrefixRemainingIds) { + result.add(Arrays.asList(i, idx)); + } } + return result; + } + + private static boolean isPalindrome(String s, int start) { + int end = s.length() - 1; + while (start < end) { + if (s.charAt(start) != s.charAt(end)) { + return false; + } + start++; + end--; + } + return true; + } + + private static class TrieNode { + private int wordEndingId; + private Map children; + private List palindromePrefixRemainingIds; - private boolean palindromeCheck(String word) { - int i = 0; - int j = word.length() - 1; - - while (i < j) { - if (word.charAt(i) != word.charAt(j)) { - return false; - } - - i++; - j--; - } - - return true; + public TrieNode() { + this.wordEndingId = -1; + this.children = new HashMap<>(); + this.palindromePrefixRemainingIds = new ArrayList<>(); } + } } diff --git a/Hard/Parallel Courses III.java b/Hard/Parallel Courses III.java new file mode 100644 index 00000000..f557c244 --- /dev/null +++ b/Hard/Parallel Courses III.java @@ -0,0 +1,35 @@ +class Solution { + public int minimumTime(int n, int[][] relations, int[] time) { + Map> map = new HashMap<>(); + int[] indegree = new int[n + 1]; + for (int[] relation : relations) { + int course = relation[0]; + int prereq = relation[1]; + indegree[course]++; + map.computeIfAbsent(prereq, k -> new ArrayList<>()).add(course); + } + Queue queue = new LinkedList<>(); + int[] maxTime = new int[n + 1]; + for (int i = 1; i <= n; i++) { + if (indegree[i] == 0) { + queue.add(i); + maxTime[i] = time[i - 1]; + } + } + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer dependent : map.getOrDefault(removed, new ArrayList<>())) { + maxTime[dependent] = Math.max(maxTime[dependent], maxTime[removed] + time[dependent - 1]); + indegree[dependent]--; + if (indegree[dependent] == 0) { + queue.add(dependent); + } + } + } + int result = 0; + for (int i = 1; i <= n; i++) { + result = Math.max(result, maxTime[i]); + } + return result; + } +} diff --git a/Hard/Parsing A Boolean Expression.java b/Hard/Parsing A Boolean Expression.java index 2c419aa8..97a56130 100644 --- a/Hard/Parsing A Boolean Expression.java +++ b/Hard/Parsing A Boolean Expression.java @@ -1,72 +1,43 @@ class Solution { public boolean parseBoolExpr(String expression) { - char[] chars = expression.toCharArray(); - Stack operations = new Stack<>(); - Stack boolValues = new Stack<>(); - - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; - if (c == '!' || c == '&' || c == '|') { - operations.push(c); - } - else if (c == '(') { - boolValues.push('#'); - } - else if (c == 't' || c == 'f') { - boolValues.push(chars[i]); - } - else if (c == ',') { - continue; - } - else { - List list = new ArrayList<>(); - while (!boolValues.isEmpty()) { - char temp = boolValues.pop(); - if (temp == '#') { - break; - } - - list.add(temp); + Stack stack = new Stack<>(); + for (char c : expression.toCharArray()) { + if (c == ')') { + List values = new ArrayList<>(); + while (stack.peek() != '(') { + values.add(stack.pop()); } - - boolValues.push(performOperation(list, operations.pop())); + stack.pop(); + char operation = stack.pop(); + char result = evaluate(operation, values); + stack.push(result); + } else if (c != ',') { + stack.push(c); } } - - return boolValues.peek() == 't' ? true : false; + return stack.peek() == 't'; } - private Character performOperation(List list, Character operation) { - if (operation == '|') { - return performOr(list); - } - else if (operation == '&') { - return performAnd(list); + private static char evaluate(char operation, List values) { + if (operation == '!') { + return values.get(0) == 't' ? 'f' : 't'; } - else { - return list.get(0) == 't' ? 'f' : 't'; - } - } - - private Character performAnd(List list) { - boolean val = getBooleanValue(list.get(0)); - for (int i = 1; i < list.size(); i++) { - val &= getBooleanValue(list.get(i)); + if (operation == '&') { + for (char value : values) { + if (value == 'f') { + return 'f'; + } + } + return 't'; } - - return val ? 't' : 'f'; - } - - private Character performOr(List list) { - boolean val = getBooleanValue(list.get(0)); - for (int i = 1; i < list.size(); i++) { - val |= getBooleanValue(list.get(i)); + if (operation == '|') { + for (char value : values) { + if (value == 't') { + return 't'; + } + } + return 'f'; } - - return val ? 't' : 'f'; - } - - private boolean getBooleanValue(Character character) { - return character == 't' ? true : false; + return 'f'; } } diff --git a/Hard/Patching Array.java b/Hard/Patching Array.java new file mode 100644 index 00000000..6bf2a8ed --- /dev/null +++ b/Hard/Patching Array.java @@ -0,0 +1,16 @@ +class Solution { + public int minPatches(int[] nums, int n) { + int patches = 0; + long miss = 1; + int idx = 0; + while (miss <= n) { + if (idx < nums.length && nums[idx] <= miss) { + miss += nums[idx++]; + } else { + miss += miss; + patches++; + } + } + return patches; + } +} diff --git a/Hard/Perfect Rectangle.java b/Hard/Perfect Rectangle.java new file mode 100644 index 00000000..fb79a5e3 --- /dev/null +++ b/Hard/Perfect Rectangle.java @@ -0,0 +1,41 @@ +class Solution { + public boolean isRectangleCover(int[][] rectangles) { + int x1 = Integer.MAX_VALUE; + int x2 = Integer.MIN_VALUE; + int y1 = Integer.MAX_VALUE; + int y2 = Integer.MIN_VALUE; + Set set = new HashSet(); + int totalArea = 0; + for (int[] rectangle : rectangles) { + x1 = Math.min(rectangle[0], x1); + y1 = Math.min(rectangle[1], y1); + x2 = Math.max(rectangle[2], x2); + y2 = Math.max(rectangle[3], y2); + totalArea += (rectangle[2] - rectangle[0]) * (rectangle[3] - rectangle[1]); + String s1 = rectangle[0] + " " + rectangle[1]; + String s2 = rectangle[0] + " " + rectangle[3]; + String s3 = rectangle[2] + " " + rectangle[3]; + String s4 = rectangle[2] + " " + rectangle[1]; + if (!set.add(s1)) { + set.remove(s1); + } + if (!set.add(s2)) { + set.remove(s2); + } + if (!set.add(s3)) { + set.remove(s3); + } + if (!set.add(s4)) { + set.remove(s4); + } + } + if (!set.contains(x1 + " " + y1) || + !set.contains(x1 + " " + y2) || + !set.contains(x2 + " " + y1) || + !set.contains(x2 + " " + y2) || + set.size() != 4) { + return false; + } + return totalArea == (x2 - x1) * (y2 - y1); + } +} diff --git a/Hard/Poor Pigs.java b/Hard/Poor Pigs.java new file mode 100644 index 00000000..275fb45a --- /dev/null +++ b/Hard/Poor Pigs.java @@ -0,0 +1,6 @@ +class Solution { + public int poorPigs(int buckets, int minutesToDie, int minutesToTest) { + int states = minutesToTest / minutesToDie + 1; + return (int) Math.ceil(Math.log(buckets) / Math.log(states)); + } +} diff --git a/Hard/Prefix and Suffix Search.java b/Hard/Prefix and Suffix Search.java index 81822d71..e7778aff 100644 --- a/Hard/Prefix and Suffix Search.java +++ b/Hard/Prefix and Suffix Search.java @@ -1,86 +1,48 @@ class WordFilter { - Map wordWeight; - Node root; - public WordFilter(String[] words) { - wordWeight = new HashMap<>(); - root = new Node(""); - for (int i=0; i words = getWords(prefix); - int idx = -1; - int maxWeight = Integer.MIN_VALUE; - - for (String word : words) { - if (word.endsWith(suffix)) { - if (wordWeight.get(word) > maxWeight) { - maxWeight = wordWeight.get(word); - idx = wordWeight.get(word); - } - } + return curr.maxIdx; + } + + private void indexWord(String word, int idx) { + for (int i = word.length() - 1; i >= 0; i--) { + String suffixAndPrefix = word.substring(i, word.length()) + "{" + word; + TrieNode curr = root; + for (char c : suffixAndPrefix.toCharArray()) { + if (curr.children[c - 'a'] == null) { + curr.children[c - 'a'] = new TrieNode(); } - - return idx; + curr = curr.children[c - 'a']; + curr.maxIdx = idx; + } } - - private List getWords(String prefix) { - List words = new ArrayList<>(); - Node curr = root; - for (int i=0; i words, Node curr) { - if (curr.isWord) { - words.add(curr.prefix); - } - - for (char c : curr.childrens.keySet()) { - findAllChildWords(words, curr.childrens.get(c)); - } - } - - class Node { - String prefix; - Map childrens; - boolean isWord = false; - - public Node(String prefix) { - this.prefix = prefix; - childrens = new HashMap<>(); - } + } + + + private class TrieNode { + TrieNode[] children; + int maxIdx; + public TrieNode() { + this.children = new TrieNode[27]; + this.maxIdx = 0; } + } } /** diff --git a/Hard/Profitable Schemes.java b/Hard/Profitable Schemes.java new file mode 100644 index 00000000..7a1cabc4 --- /dev/null +++ b/Hard/Profitable Schemes.java @@ -0,0 +1,23 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) { + Integer[][][] dp = new Integer[101][101][101]; + return helper(0, 0, 0, n, minProfit, group, profit, dp); + } + + private int helper(int pos, int count, int profit, int n, int minProfit, int[] group, int[] profits, Integer[][][] dp) { + if (pos == group.length) { + return profit >= minProfit ? 1 : 0; + } + if (dp[pos][count][profit] != null) { + return dp[pos][count][profit]; + } + int totalWays = helper(pos + 1, count, profit, n, minProfit, group, profits, dp); + if (count + group[pos] <= n) { + totalWays += helper(pos + 1, count + group[pos], Math.min(minProfit, profit + profits[pos]), n, minProfit, group, profits, dp); + } + return dp[pos][count][profit] = totalWays % MOD; + } +} diff --git a/Hard/README.md b/Hard/README.md new file mode 100644 index 00000000..0e44bb8b --- /dev/null +++ b/Hard/README.md @@ -0,0 +1,127 @@ +# Hard LeetCode-Java-Solutions +S.no | Coding Problem +--- | --- +1|[Concatenated Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Concatenated%20Words.java) +2|[Minimum Cost to Make Array Equal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Cost%20to%20Make%20Array%20Equal.java) +3|[Max Stack](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Max%20Stack.java) +4|[Course Schedule III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Course%20Schedule%20III.java) +5|[Binary Tree Cameras](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Binary%20Tree%20Cameras.java) +6|[Remove Invalid Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Remove%20Invalid%20Parentheses.java) +7|[First Missing Positive](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/First%20Missing%20Positive.java) +8|[Reconstruct Itinerary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Reconstruct%20Itinerary.java) +9|[Frog Jump](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Frog%20Jump.java) +10|[Sort Items by Groups Respecting Dependencies](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Sort%20Items%20by%20Groups%20Respecting%20Dependencies.java) +11|[Shortest Path Visiting All Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Shortest%20Path%20Visiting%20All%20Nodes.java) +12|[Critical Connections in a Network](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Critical%20Connections%20in%20a%20Network.java) +13|[Sliding Window Median](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Sliding%20Window%20Median.java) +14|[Edit Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Edit%20Distance.java) +15|[Checking Existence of Edge Length Limited Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Checking%20Existence%20of%20Edge%20Length%20Limited%20Paths.java) +16|[Perfect Rectangle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Perfect%20Rectangle.java) +17|[Minimum Window Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Window%20Subsequence.java) +18|[Remove Max Number of Edges to Keep Graph Fully Traversable](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Remove%20Max%20Number%20of%20Edges%20to%20Keep%20Graph%20Fully%20Traversable.java) +19|[K Inverse Pairs Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/K%20Inverse%20Pairs%20Array.java) +20|[Merge K Sorted Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Merge%20K%20Sorted%20Lists.java) +21|[Minimum Replacements to Sort the Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Replacements%20to%20Sort%20the%20Array.java) +22|[Design Movie Rental System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Design%20Movie%20Rental%20System.java) +23|[Sliding Window Maximum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Sliding%20Window%20Maximum.java) +24|[My Calendar III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/My%20Calendar%20III.java) +25|[Longest Cycle in a Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Longest%20Cycle%20in%20a%20Graph.java) +26|[Text Justification](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Text%20Justification.java) +27|[Design In-Memory File System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Design%20In-Memory%20File%20System.java) +28|[Basic Calculator III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Basic%20Calculator%20III.java) +29|[Integer to English Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Integer%20to%20English%20Words.java) +30|[Naming a Company](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Naming%20a%20Company.java) +31|[Minimum Number of Refueling Stops](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Number%20of%20Refueling%20Stops.java) +32|[Rearrange String k Distance Apart](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Rearrange%20String%20k%20Distance%20Apart.java) +33|[Make Array Strictly Increasing](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Make%20Array%20Strictly%20Increasing.java) +34|[Median of Two Sorted Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Median%20of%20Two%20Sorted%20Arrays.java) +35|[Vertical Order Traversal Of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Vertical%20Order%20Traversal%20Of%20a%20Binary%20Tree.java) +36|[Divide Array Into Increasing Sequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Divide%20Array%20Into%20Increasing%20Sequences.java) +37|[Word Break II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Word%20Break%20II.java) +38|[Maximum Number of Non-Overlapping Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximum%20Number%20of%20Non-Overlapping%20Substrings.java) +39|[Paint House II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Paint%20House%20II.java) +40|[Subarrays with K Different Integers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Subarrays%20with%20K%20Different%20Integers.java) +41|[Maximum Performance of a Team](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximum%20Performance%20of%20a%20Team.java) +42|[Jump Game IV](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Jump%20Game%20IV.java) +43|[Paint House III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Paint%20House%20III.java) +44|[LFU Cache](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/LFU%20Cache.java) +45|[Scramble String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Scramble%20String.java) +46|[Word Search II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Word%20Search%20II.java) +47|[K Empty Slots](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/K%20Empty%20Slots.java) +48|[Employee Free Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Employee%20Free%20Time.java) +49|[Maximize Score After N Operations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximize%20Score%20After%20N%20Operations.java) +50|[Max Points on a Line](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Max%20Points%20on%20a%20Line.java) +51|[The Skyline Problem](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/The%20Skyline%20Problem.java) +52|[N-Queens](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/N-Queens.java) +53|[Longest Palindrome Product](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Longest%20Palindrome%20Product.java) +54|[Odd Even Jump](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Odd%20Even%20Jump.java) +55|[Palindrome Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Palindrome%20Pairs.java) +56|[Stream of Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Stream%20of%20Characters.java) +57|[Cut Off Trees for Golf Event](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Cut%20Off%20Trees%20for%20Golf%20Event.java) +58|[Kth Smallest Number in Multiplication Table](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Kth%20Smallest%20Number%20in%20Multiplication%20Table.java) +59|[String Compression II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/String%20Compression%20II.java) +60|[Minimize Deviation in Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimize%20Deviation%20in%20Array.java) +61|[Minimum Cost to Hire K Workers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Cost%20to%20Hire%20K%20Workers.java) +62|[Find the Longest Valid Obstacle Course at Each Position](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Find%20the%20Longest%20Valid%20Obstacle%20Course%20at%20Each%20Position.java) +63|[Number of Valid Subarrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Valid%20Subarrays.java) +64|[Maximum Value of K Coins From Piles](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximum%20Value%20of%20K%20Coins%20From%20Piles.java) +65|[Substring with Concatenation of All Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Substring%20with%20Concatenation%20of%20All%20Words.java) +66|[Number of Paths with Max Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Paths%20with%20Max%20Score.java) +67|[Profitable Schemes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Profitable%20Schemes.java) +68|[Design Search Autocomplete System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Design%20Search%20Autocomplete%20System.java) +69|[Number of Squareful Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Squareful%20Arrays.java) +70|[N-Queens II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/N-Queens%20II.java) +71|[Robot Room Cleaner](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Robot%20Room%20Cleaner.java) +72|[Poor Pigs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Poor%20Pigs.java) +73|[Minimum Window Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Window%20Substring.java) +74|[Number of Ways of Cutting a Pizza](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Ways%20of%20Cutting%20a%20Pizza.java) +75|[Hard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Hard.md) +76|[Parsing A Boolean Expression](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Parsing%20A%20Boolean%20Expression.java) +77|[Trapping Rain Water](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Trapping%20Rain%20Water.java) +78|[Similar String Groups](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Similar%20String%20Groups.java) +79|[Number of Ways to Form a Target String Given a Dictionary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Ways%20to%20Form%20a%20Target%20String%20Given%20a%20Dictionary.java) +80|[Find the Kth Smallest Sum of a Matrix With Sorted Rows](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Find%20the%20Kth%20Smallest%20Sum%20of%20a%20Matrix%20With%20Sorted%20Rows.java) +81|[Optimal Account Balancing](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Optimal%20Account%20Balancing.java) +82|[Design Skiplist](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Design%20Skiplist.java) +83|[Wildcard Matching](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Wildcard%20Matching.java) +84|[Expression Add Operators](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Expression%20Add%20Operators.java) +85|[Count of Smaller Numbers After Self](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Count%20of%20Smaller%20Numbers%20After%20Self.java) +86|[Number of Ways to Reorder Array to Get Same BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Ways%20to%20Reorder%20Array%20to%20Get%20Same%20BST.java) +87|[Find Median from Data Stream](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Find%20Median%20from%20Data%20Stream.java) +88|[Best Time to Buy and Sell Stock IV](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20IV.java) +89|[Find Minimum in Rotated Sorted Array II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Find%20Minimum%20in%20Rotated%20Sorted%20Array%20II.java) +90|[Longest Valid Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Longest%20Valid%20Parentheses.java) +91|[Stone Game III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Stone%20Game%20III.java) +92|[Reducing Dishes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Reducing%20Dishes.java) +93|[Count Subarrays With Fixed Bounds](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Count%20Subarrays%20With%20Fixed%20Bounds.java) +94|[Stamping The Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Stamping%20The%20Sequence.java) +95|[Number of Submatrices That Sum to Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Number%20of%20Submatrices%20That%20Sum%20to%20Target.java) +96|[Candy](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Candy.java) +97|[Minimum Insertion Steps to Make a String Palindrome](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Insertion%20Steps%20to%20Make%20a%20String%20Palindrome.java) +98|[Shortest Distance from All Buildings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Shortest%20Distance%20from%20All%20Buildings.java) +99|[Recover a Tree From Preorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Recover%20a%20Tree%20From%20Preorder%20Traversal.java) +100|[Count Vowels Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Count%20Vowels%20Permutation.java) +101|[Longest Increasing Path in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Longest%20Increasing%20Path%20in%20a%20Matrix.java) +102|[Maximum Profit in Job Scheduling](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximum%20Profit%20in%20Job%20Scheduling.java) +103|[Closest Binary Search Tree Values II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Closest%20Binary%20Search%20Tree%20Values%20II.java) +104|[Basic Calculator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Basic%20Calculator.java) +105|[Alien Dictionary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Alien%20Dictionary.java) +106|[Prefix and Suffix Search](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Prefix%20and%20Suffix%20Search.java) +107|[Construct Target Array With Multiple Sums](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Construct%20Target%20Array%20With%20Multiple%20Sums.java) +108|[Tallest Billboard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Tallest%20Billboard.java) +109|[Largest Color Value in a Directed Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Largest%20Color%20Value%20in%20a%20Directed%20Graph.java) +110|[Valid Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Valid%20Number.java) +111|[Dice Roll Simulation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Dice%20Roll%20Simulation.java) +112|[Maximum Frequency Stack](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximum%20Frequency%20Stack.java) +113|[Reverse Nodes in k-Group](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Reverse%20Nodes%20in%20k-Group.java) +114|[Serialize and Deserialize N-ary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Serialize%20and%20Deserialize%20N-ary%20Tree.java) +115|[Serialize and Deserialize a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Serialize%20and%20Deserialize%20a%20Binary%20Tree.java) +116|[Minimum Difficulty of a Job Schedule](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Minimum%20Difficulty%20of%20a%20Job%20Schedule.java) +117|[Unique Paths III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Unique%20Paths%20III.java) +118|[Restore The Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Restore%20The%20Array.java) +119|[IPO](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/IPO.java) +120|[Insert Delete GetRandom O(1) - Duplicates Allowed](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Insert%20Delete%20GetRandom%20O(1)%20-%20Duplicates%20Allowed.java) +121|[Add Edges to Make Degrees of All Nodes Even](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Add%20Edges%20to%20Make%20Degrees%20of%20All%20Nodes%20Even.java) +122|[Maximum Sum BST in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Maximum%20Sum%20BST%20in%20Binary%20Tree.java) +123|[Binary Tree Maximum Path Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Binary%20Tree%20Maximum%20Path%20Sum.java) +124|[Largest Rectangle in Histogram](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Hard/Largest%20Rectangle%20in%20Histogram.java) diff --git a/Hard/Rearrange String k Distance Apart.java b/Hard/Rearrange String k Distance Apart.java new file mode 100644 index 00000000..da212877 --- /dev/null +++ b/Hard/Rearrange String k Distance Apart.java @@ -0,0 +1,26 @@ +class Solution { + public String rearrangeString(String s, int k) { + Map map = new HashMap<>(); + for (char c : s.toCharArray()) { + map.put(c, map.getOrDefault(c, 0) + 1); + } + PriorityQueue pq = new PriorityQueue<>((a, b) -> map.get(b).compareTo(map.get(a))); + Queue busy = new LinkedList<>(); + StringBuilder sb = new StringBuilder(); + pq.addAll(map.keySet()); + while (!pq.isEmpty()) { + Character removed = pq.poll(); + sb.append(removed); + map.put(removed, map.get(removed) - 1); + busy.add(removed); + if (busy.size() < k) { + continue; + } + Character busyRemoved = busy.remove(); + if (map.get(busyRemoved) > 0) { + pq.add(busyRemoved); + } + } + return sb.length() == s.length() ? sb.toString() : ""; + } +} diff --git a/Medium/Reconstruct Itinerary.java b/Hard/Reconstruct Itinerary.java similarity index 79% rename from Medium/Reconstruct Itinerary.java rename to Hard/Reconstruct Itinerary.java index c98913d2..e5616f94 100644 --- a/Medium/Reconstruct Itinerary.java +++ b/Hard/Reconstruct Itinerary.java @@ -4,22 +4,16 @@ public List findItinerary(List> tickets) { for (List ticket : tickets) { map.computeIfAbsent(ticket.get(0), k -> new PriorityQueue<>()).add(ticket.get(1)); } - - List route = new ArrayList<>(); Stack stack = new Stack<>(); - stack.push("JFK"); - + List result = new ArrayList<>(); while (!stack.isEmpty()) { while (map.containsKey(stack.peek()) && !map.get(stack.peek()).isEmpty()) { stack.push(map.get(stack.peek()).poll()); } - - route.add(stack.pop()); + result.add(stack.pop()); } - - Collections.reverse(route); - - return route; + Collections.reverse(result); + return result; } } diff --git a/Hard/Recover a Tree From Preorder Traversal.java b/Hard/Recover a Tree From Preorder Traversal.java index 69f3fe55..b851ca44 100644 --- a/Hard/Recover a Tree From Preorder Traversal.java +++ b/Hard/Recover a Tree From Preorder Traversal.java @@ -4,41 +4,45 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode recoverFromPreorder(String S) { - Map map = new HashMap<>(); + public TreeNode recoverFromPreorder(String traversal) { + Stack stack = new Stack<>(); int idx = 0; - int n = S.length(); - - while (idx < n) { - int level = 0; - StringBuilder sb = new StringBuilder(); - - while (idx < n && S.charAt(idx) == '-') { - level++; + while (idx < traversal.length()) { + int depth = 0; + while (idx < traversal.length() && traversal.charAt(idx) == '-') { + depth++; idx++; } - - while (idx < n && Character.isDigit(S.charAt(idx))) { - sb.append(S.charAt(idx++)); + int value = 0; + while (idx < traversal.length() && Character.isDigit(traversal.charAt(idx))) { + value = value * 10 + Character.getNumericValue(traversal.charAt(idx++)); } - - TreeNode currNode = new TreeNode(Integer.parseInt(sb.toString())); - map.put(level, currNode); - if (level > 0) { - TreeNode parent = map.get(level - 1); - if (parent.left == null) { - parent.left = currNode; - } - else { - parent.right = currNode; + TreeNode node = new TreeNode(value); + while (stack.size() > depth) { + stack.pop(); + } + if (!stack.isEmpty()) { + if (stack.peek().left == null) { + stack.peek().left = node; + } else { + stack.peek().right = node; } } + stack.push(node); + } + while (stack.size() > 1) { + stack.pop(); } - - return map.get(0); + return stack.peek(); } } diff --git a/Hard/Reducing Dishes.java b/Hard/Reducing Dishes.java new file mode 100644 index 00000000..2a69540e --- /dev/null +++ b/Hard/Reducing Dishes.java @@ -0,0 +1,20 @@ +class Solution { + public int maxSatisfaction(int[] satisfaction) { + Arrays.sort(satisfaction); + int n = satisfaction.length; + Integer[][] dp = new Integer[n + 1][n + 1]; + return helper(satisfaction, 0, 1, dp); + } + + private int helper(int[] satisfaction, int idx, int time, Integer[][] dp) { + if (idx == satisfaction.length) { + return 0; + } + if (dp[idx][time] != null) { + return dp[idx][time]; + } + dp[idx][time] = Math.max(satisfaction[idx] * time + helper(satisfaction, idx + 1, time + 1, dp), + helper(satisfaction, idx + 1, time, dp)); + return dp[idx][time]; + } +} diff --git a/Hard/Remove Invalid Parentheses.java b/Hard/Remove Invalid Parentheses.java new file mode 100644 index 00000000..843bf157 --- /dev/null +++ b/Hard/Remove Invalid Parentheses.java @@ -0,0 +1,44 @@ +class Solution { + Set validStrings; + int minimumRemoved; + public List removeInvalidParentheses(String s) { + validStrings = new HashSet<>(); + minimumRemoved = Integer.MAX_VALUE; + backtrack(s, 0, 0, 0, new StringBuilder(), 0); + return new ArrayList<>(validStrings); + } + + private void backtrack(String s, int idx, int leftCount, int rightCount, StringBuilder sb, int removedCount) { + if (idx == s.length()) { + if (leftCount == rightCount) { + if (removedCount <= minimumRemoved) { + String possibleAns = sb.toString(); + if (removedCount < minimumRemoved) { + validStrings.clear(); + minimumRemoved = removedCount; + } + validStrings.add(possibleAns); + } + } + } + else { + char c = s.charAt(idx); + if (c != '(' && c != ')') { + sb.append(c); + backtrack(s, idx + 1, leftCount, rightCount, sb, removedCount); + sb.deleteCharAt(sb.length() - 1); + } + else { + backtrack(s, idx + 1, leftCount, rightCount, sb, removedCount + 1); + sb.append(c); + if (c == '(') { + backtrack(s, idx + 1, leftCount + 1, rightCount, sb, removedCount); + } + else if (rightCount < leftCount) { + backtrack(s, idx + 1, leftCount, rightCount + 1, sb, removedCount); + } + sb.deleteCharAt(sb.length() - 1); + } + } + } +} diff --git a/Hard/Remove Max Number of Edges to Keep Graph Fully Traversable.java b/Hard/Remove Max Number of Edges to Keep Graph Fully Traversable.java new file mode 100644 index 00000000..152ab81b --- /dev/null +++ b/Hard/Remove Max Number of Edges to Keep Graph Fully Traversable.java @@ -0,0 +1,67 @@ +class Solution { + public int maxNumEdgesToRemove(int n, int[][] edges) { + UnionFind alice = new UnionFind(n); + UnionFind bob = new UnionFind(n); + int requiredEdges = 0; + for (int[] edge : edges) { + if (edge[0] == 3) { + requiredEdges += (alice.union(edge[1], edge[2]) | bob.union(edge[1], edge[2])); + } + } + for (int[] edge : edges) { + if (edge[0] == 1) { + requiredEdges += alice.union(edge[1], edge[2]); + } else if (edge[0] == 2) { + requiredEdges += bob.union(edge[1], edge[2]); + } + } + if (alice.isConnected() && bob.isConnected()) { + return edges.length - requiredEdges; + } + return -1; + } + + private class UnionFind { + private final int[] representatives; + private final int[] componentSize; + private int components; + + public UnionFind(int n) { + this.representatives = new int[n + 1]; + this.componentSize = new int[n + 1]; + this.components = n; + for (int i = 0; i <= n; i++) { + componentSize[i] = 1; + representatives[i] = i; + } + } + + public int find(int x) { + if (representatives[x] == x) { + return x; + } + return representatives[x] = find(representatives[x]); + } + + public int union(int x, int y) { + x = find(x); + y = find(y); + if (x == y) { + return 0; + } + if (componentSize[x] > componentSize[y]) { + componentSize[x] += componentSize[y]; + representatives[y] = x; + } else { + componentSize[y] += componentSize[x]; + representatives[x] = y; + } + components--; + return 1; + } + + public boolean isConnected() { + return components == 1; + } + } +} diff --git a/Hard/Restore The Array.java b/Hard/Restore The Array.java new file mode 100644 index 00000000..9b6ffc76 --- /dev/null +++ b/Hard/Restore The Array.java @@ -0,0 +1,31 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int numberOfArrays(String s, int k) { + int n = s.length(); + int[] dp = new int[n + 1]; + return dfs(dp, 0, s, k); + } + + private int dfs(int[] dp, int start, String s, int k) { + if (dp[start] != 0) { + return dp[start]; + } + if (start == s.length()) { + return 1; + } + if (s.charAt(start) == '0') { + return 0; + } + int count = 0; + for (int end = start; end < s.length(); end++) { + String currNum = s.substring(start, end + 1); + if (Long.parseLong(currNum) > k) { + break; + } + count = (count + dfs(dp, end + 1, s, k)) % MOD; + } + return dp[start] = count; + } +} diff --git a/Hard/Reverse Nodes in k-Group.java b/Hard/Reverse Nodes in k-Group.java new file mode 100644 index 00000000..f28071ac --- /dev/null +++ b/Hard/Reverse Nodes in k-Group.java @@ -0,0 +1,53 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode reverseKGroup(ListNode head, int k) { + ListNode newHead = null; + ListNode prev = null; + ListNode curr = head; + while (curr != null) { + ListNode start = curr; + int idx = 1; + for (idx = 1; idx < k && curr.next != null; idx++) { + curr = curr.next; + } + if (idx != k) { + curr = null; + continue; + } + ListNode next = curr.next; + curr.next = null; + ListNode reversedNode = reverse(start); + if (newHead == null) { + newHead = reversedNode; + } + if (prev != null) { + prev.next = reversedNode; + } + prev = start; + start.next = next; + curr = next; + } + return newHead; + } + + private ListNode reverse(ListNode node) { + ListNode curr = node; + ListNode prev = null; + while (curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } +} diff --git a/Hard/Robot Collisions.java b/Hard/Robot Collisions.java new file mode 100644 index 00000000..4202122c --- /dev/null +++ b/Hard/Robot Collisions.java @@ -0,0 +1,38 @@ +class Solution { + public List survivedRobotsHealths(int[] positions, int[] healths, String directions) { + int n = positions.length; + Integer[] indices = new Integer[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + Arrays.sort(indices, (a, b) -> Integer.compare(positions[a], positions[b])); + Stack stack = new Stack<>(); + for (Integer index : indices) { + if (directions.charAt(index) == 'R') { + stack.push(index); + } else { + while (!stack.isEmpty() && healths[index] > 0) { + int poppedIndex = stack.pop(); + if (healths[poppedIndex] > healths[index]) { + healths[poppedIndex]--; + healths[index] = 0; + stack.push(poppedIndex); + } else if (healths[poppedIndex] < healths[index]) { + healths[index]--; + healths[poppedIndex] = 0; + } else { + healths[poppedIndex] = 0; + healths[index] = 0; + } + } + } + } + List result = new ArrayList<>(); + for (int i = 0; i < n; i++) { + if (healths[i] > 0) { + result.add(healths[i]); + } + } + return result; + } +} diff --git a/Hard/Robot Room Cleaner.java b/Hard/Robot Room Cleaner.java new file mode 100644 index 00000000..ece02018 --- /dev/null +++ b/Hard/Robot Room Cleaner.java @@ -0,0 +1,48 @@ +/** + * // This is the robot's control interface. + * // You should not implement it, or speculate about its implementation + * interface Robot { + * // Returns true if the cell in front is open and robot moves into the cell. + * // Returns false if the cell in front is blocked and robot stays in the current cell. + * public boolean move(); + * + * // Robot will stay in the same cell after calling turnLeft/turnRight. + * // Each turn will be 90 degrees. + * public void turnLeft(); + * public void turnRight(); + * + * // Clean the current cell. + * public void clean(); + * } + */ +class Solution { + int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + public void cleanRoom(Robot robot) { + Set set = new HashSet<>(); + int currX = 0; + int currY = 0; + helper(robot, currX, currY, 0, set); + } + + private void helper(Robot robot, int x, int y, int dir, Set set) { + if (set.contains(x + "|" + y)) { + return; + } + set.add(x + "|" + y); + robot.clean(); + for (int i = 0; i < 4; i++) { + if (robot.move()) { + int newX = x + dirs[dir][0]; + int newY = y + dirs[dir][1]; + helper(robot, newX, newY, dir, set); + robot.turnLeft(); + robot.turnLeft(); + robot.move(); + robot.turnRight(); + robot.turnRight(); + } + robot.turnRight(); + dir = (dir + 1) % 4; + } + } +} diff --git a/Hard/Scramble String.java b/Hard/Scramble String.java new file mode 100644 index 00000000..ac35d39c --- /dev/null +++ b/Hard/Scramble String.java @@ -0,0 +1,25 @@ +class Solution { + public boolean isScramble(String s1, String s2) { + int n = s1.length(); + Boolean[][][] dp = new Boolean[n][n][n + 1]; + return helper(s1, s2, 0, 0, n, dp); + } + + private boolean helper(String s1, String s2, int idxOne, int idxTwo, int n, Boolean[][][] dp) { + if (dp[idxOne][idxTwo][n] != null) { + return dp[idxOne][idxTwo][n]; + } + if (n == 1) { + return dp[idxOne][idxTwo][n] = s1.charAt(idxOne) == s2.charAt(idxTwo); + } + for (int l = 1; l < n; l++) { + if (helper(s1, s2, idxOne, idxTwo, l, dp) && helper(s1, s2, idxOne + l, idxTwo + l, n - l, dp)) { + return dp[idxOne][idxTwo][n] = true; + } + if (helper(s1, s2, idxOne, idxTwo + n - l, l, dp) && helper(s1, s2, idxOne + l, idxTwo, n - l, dp)) { + return dp[idxOne][idxTwo][n] = true; + } + } + return dp[idxOne][idxTwo][n] = false; + } +} diff --git a/Hard/Serialize and Deserialize N-ary Tree.java b/Hard/Serialize and Deserialize N-ary Tree.java index af8a394e..d9df1fa3 100644 --- a/Hard/Serialize and Deserialize N-ary Tree.java +++ b/Hard/Serialize and Deserialize N-ary Tree.java @@ -6,63 +6,73 @@ class Node { public Node() {} - public Node(int _val,List _children) { + public Node(int _val) { + val = _val; + } + + public Node(int _val, List _children) { val = _val; children = _children; } }; */ -class Codec { - // Encodes a tree to a single string. - StringBuilder sb; - public String serialize(Node root) { - if (root == null) { - return ""; - } - - sb = new StringBuilder(); - serializeHelper(root); - - return sb.toString().substring(0, sb.length() - 1); +class Codec { + // Encodes a tree to a single string. + + private static final String SEPARATOR = ","; + private static final String NULL_NODE = "X"; + + public String serialize(Node root) { + if (root == null) { + return NULL_NODE; } - - private void serializeHelper(Node root) { - if (root == null) { - return; + StringBuilder sb = new StringBuilder(); + Queue queue = new LinkedList<>(); + queue.add(root); + queue.add(null); + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + Node removed = queue.remove(); + if (removed == null) { + sb.append(NULL_NODE).append(SEPARATOR); + break; } - - sb.append(root.val).append(",").append(root.children.size()).append(","); - for (Node child : root.children) { - serializeHelper(child); + for (Node child : removed.children) { + queue.add(child); } + queue.add(null); + sb.append(removed.val).append(SEPARATOR); + } } + sb.deleteCharAt(sb.length() - 1); + return sb.toString(); + } - // Decodes your encoded data to tree. - public Node deserialize(String data) { - if (data == null || data.length() == 0) { - return null; - } - - Queue queue = new LinkedList<>(); - queue.addAll(Arrays.asList(data.split(","))); - - return deserializeHelper(queue); + // Decodes your encoded data to tree. + public Node deserialize(String data) { + String[] splits = data.split(SEPARATOR); + if (splits[0].equals(NULL_NODE)) { + return null; } - - private Node deserializeHelper(Queue queue) { - Node root = new Node(); - root.val = Integer.parseInt(queue.remove()); - int size = Integer.parseInt(queue.remove()); - - root.children = new ArrayList<>(size); - - for (int i = 0; i < size; i++) { - root.children.add(deserializeHelper(queue)); - } - - return root; + Node root = new Node(Integer.parseInt(splits[0])); + Queue queue = new LinkedList<>(); + queue.add(root); + int idx = 2; + while (idx < splits.length) { + Node node = queue.remove(); + List children = new ArrayList<>(); + while (!splits[idx].equals(NULL_NODE)) { + Node child = new Node(Integer.parseInt(splits[idx++])); + children.add(child); + queue.add(child); + } + idx++; + node.children = children; } + return root; + } } // Your Codec object will be instantiated and called as such: diff --git a/Hard/Serialize and Deserialize a Binary Tree.java b/Hard/Serialize and Deserialize a Binary Tree.java index d8b992b7..7639f07a 100644 --- a/Hard/Serialize and Deserialize a Binary Tree.java +++ b/Hard/Serialize and Deserialize a Binary Tree.java @@ -9,48 +9,50 @@ */ public class Codec { - // Encodes a tree to a single string. - public String serialize(TreeNode root) { - StringBuilder sb = new StringBuilder(); - serializeHelper(root, sb); - return sb.toString().substring(0, sb.length() - 1); + private static final String NULL_VALUE = "-"; + private static final String DELIMETER = " "; + + // Encodes a tree to a single string. + public String serialize(TreeNode root) { + if (root == null) { + return NULL_VALUE; } - - private void serializeHelper(TreeNode root, StringBuilder sb) { - if (root == null) { - sb.append("#").append(","); - return; - } - - sb.append(root.val).append(","); - serializeHelper(root.left, sb); - serializeHelper(root.right, sb); + StringBuilder sb = new StringBuilder(); + Stack stack = new Stack<>(); + stack.add(root); + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + if (removed == null) { + sb.append(NULL_VALUE).append(DELIMETER); + continue; + } + sb.append(removed.val).append(DELIMETER); + stack.push(removed.right); + stack.push(removed.left); } + return sb.toString().trim(); + } - // Decodes your encoded data to tree. - public TreeNode deserialize(String data) { - Queue values = new LinkedList<>(Arrays.asList(data.split(","))); - return deserializeHelper(values); - } - - private TreeNode deserializeHelper(Queue values) { - if (values.isEmpty()) { - return null; - } - - String val = values.remove(); - if (val.equals("#")) { - return null; - } - - TreeNode root = new TreeNode(Integer.parseInt(val)); - root.left = deserializeHelper(values); - root.right = deserializeHelper(values); - - return root; + // Decodes your encoded data to tree. + public TreeNode deserialize(String data) { + Queue queue = new LinkedList<>(Arrays.asList(data.split("\\s+"))); + return helper(queue); + } + + private TreeNode helper(Queue queue) { + if (queue.peek().equals(NULL_VALUE)) { + queue.remove(); + return null; } + TreeNode root = new TreeNode(Integer.parseInt(queue.peek())); + queue.remove(); + root.left = helper(queue); + root.right = helper(queue); + return root; + } } // Your Codec object will be instantiated and called as such: -// Codec codec = new Codec(); -// codec.deserialize(codec.serialize(root)); +// Codec ser = new Codec(); +// Codec deser = new Codec(); +// TreeNode ans = deser.deserialize(ser.serialize(root)); diff --git a/Hard/Shortest Distance from All Buildings.java b/Hard/Shortest Distance from All Buildings.java new file mode 100644 index 00000000..3d8a0127 --- /dev/null +++ b/Hard/Shortest Distance from All Buildings.java @@ -0,0 +1,56 @@ +class Solution { + int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + public int shortestDistance(int[][] grid) { + int numOfHouses = 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + numOfHouses += grid[i][j] == 1 ? 1 : 0; + } + } + int[] distance = {Integer.MAX_VALUE}; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 0) { + bfs(grid, i, j, numOfHouses, distance); + } + } + } + return distance[0] == Integer.MAX_VALUE ? -1 : distance[0]; + } + + private void bfs(int[][] grid, int i, int j, int numOfHouses, int[] distance) { + int currDistance = 0; + int numRows = grid.length; + int numCols = grid[0].length; + int houses = 0; + boolean[][] visited = new boolean[numRows][numCols]; + Queue queue = new LinkedList<>(); + queue.add(new int[]{i, j, 0}); + visited[i][j] = true; + while (!queue.isEmpty() && houses != numOfHouses) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + if (grid[x][y] == 1) { + houses++; + currDistance += removed[2]; + } + else if (grid[x][y] == 0) { + for (int[] dir : dirs) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newX < numRows && newY >= 0 && newY < numCols && !visited[newX][newY]) { + queue.add(new int[]{newX, newY, removed[2] + 1}); + visited[newX][newY] = true; + } + } + } + } + } + if (houses == numOfHouses) { + distance[0] = Math.min(distance[0], currDistance); + } + } +} diff --git a/Hard/Shortest Palindrome.java b/Hard/Shortest Palindrome.java new file mode 100644 index 00000000..3ff38e40 --- /dev/null +++ b/Hard/Shortest Palindrome.java @@ -0,0 +1,23 @@ +class Solution { + public String shortestPalindrome(String s) { + int n = s.length(); + if (n == 0) { + return s; + } + int left = 0; + for (int right = n - 1; right >= 0; right--) { + if (s.charAt(right) == s.charAt(left)) { + left++; + } + } + if (left == n) { + return s; + } + String nonPalindromeSuffix = s.substring(left); + StringBuilder reverseSuffix = new StringBuilder(nonPalindromeSuffix).reverse(); + return reverseSuffix + .append(shortestPalindrome(s.substring(0, left))) + .append(nonPalindromeSuffix) + .toString(); + } +} diff --git a/Hard/Shortest Path Visiting All Nodes.java b/Hard/Shortest Path Visiting All Nodes.java new file mode 100644 index 00000000..8d08ecfa --- /dev/null +++ b/Hard/Shortest Path Visiting All Nodes.java @@ -0,0 +1,33 @@ +class Solution { + public int shortestPathLength(int[][] graph) { + int n = graph.length; + Map>> map = new HashMap<>(); + Queue queue = new LinkedList<>(); + for (int i = 0; i < n; i++) { + Set visited = new HashSet<>(); + visited.add(i); + map.put(i, new HashSet<>(List.of(visited))); + queue.add(new State(i, 0, visited)); + } + while (!queue.isEmpty()) { + State removed = queue.remove(); + int node = removed.node(); + int steps = removed.steps(); + Set visited = removed.visited(); + if (visited.size() == n) { + return steps; + } + for (int conn : graph[node]) { + Set connVisited = new HashSet<>(visited); + connVisited.add(conn); + if (!map.get(conn).contains(connVisited)) { + queue.add(new State(conn, steps + 1, connVisited)); + map.computeIfAbsent(conn, k -> new HashSet<>()).add(connVisited); + } + } + } + return -1; + } + + private static record State(int node, int steps, Set visited) {} +} diff --git a/Hard/Similar String Groups.java b/Hard/Similar String Groups.java new file mode 100644 index 00000000..50eb13d2 --- /dev/null +++ b/Hard/Similar String Groups.java @@ -0,0 +1,51 @@ +class Solution { + public int numSimilarGroups(String[] strs) { + int n = strs.length; + Map> graph = new HashMap<>(); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (isSimilar(strs[i], strs[j])) { + graph.computeIfAbsent(i, k -> new ArrayList<>()).add(j); + graph.computeIfAbsent(j, k -> new ArrayList<>()).add(i); + } + } + } + boolean[] visited = new boolean[n]; + int count = 0; + for (int i = 0; i < n; i++) { + if (!visited[i]) { + bfs(i, graph, visited); + count++; + } + } + return count; + } + + private boolean isSimilar(String s1, String s2) { + int diff = 0; + for (int i = 0; i < s1.length(); i++) { + if (s1.charAt(i) != s2.charAt(i)) { + diff++; + } + } + return diff == 0 || diff == 2; + } + + private void bfs(int node, Map> graph, boolean[] visited) { + Queue queue = new LinkedList<>(); + queue.add(node); + visited[node] = true; + while (!queue.isEmpty()) { + node = queue.poll(); + if (!graph.containsKey(node)) { + continue; + } + for (int neighbor : graph.get(node)) { + if (!visited[neighbor]) { + visited[neighbor] = true; + queue.add(neighbor); + } + } + } + } +} diff --git a/Hard/Sliding Window Maximum.java b/Hard/Sliding Window Maximum.java index 1735cafb..635720b8 100644 --- a/Hard/Sliding Window Maximum.java +++ b/Hard/Sliding Window Maximum.java @@ -1,58 +1,19 @@ class Solution { - public static int[] maxSlidingWindowDynamic(int[] nums, int k) { - if (nums.length == 0 || nums.length < k) { - return new int[]{}; - } - - int[] maxLeft = new int[nums.length]; - int[] maxRight = new int[nums.length]; - - maxLeft[0] = nums[0]; - maxRight[nums.length-1] = nums[nums.length-1]; - - for (int i=1; i priorityQueue = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o2 - o1; + public int[] maxSlidingWindow(int[] nums, int k) { + Deque dequeue = new ArrayDeque<>(); + int[] result = new int[nums.length - k + 1]; + for (int i = 0; i < nums.length; i++) { + if (!dequeue.isEmpty() && dequeue.getFirst() == i - k) { + dequeue.removeFirst(); + } + while (!dequeue.isEmpty() && nums[i] > nums[dequeue.getLast()]) { + dequeue.removeLast(); + } + dequeue.addLast(i); + if (i >= k - 1) { + result[i - k + 1] = nums[dequeue.getFirst()]; } - }); - - for (int i=0; i list; - double[] ans; - boolean isEven; - - public double[] medianSlidingWindow(int[] nums, int k) { - list = new ArrayList<>(); - ans = new double[nums.length - k + 1]; - isEven = k % 2 == 0; - - for (int i=0; i list.get(list.size() - 1)) { - return list.size(); - } - - int start = 0; - int end = list.size(); - - while (start < end) { - int mid = (start + end) / 2; - - if (list.get(mid) < num) { - start = mid + 1; - } - else { - end = mid; + public double[] medianSlidingWindow(int[] nums, int windowSize) { + double[] medians = new double[nums.length - windowSize + 1]; + Map delayedRemovals = new HashMap<>(); + PriorityQueue maxHeap = new PriorityQueue<>(Collections.reverseOrder()); + PriorityQueue minHeap = new PriorityQueue<>(); + int currentIndex = 0; + while (currentIndex < windowSize) { + maxHeap.add(nums[currentIndex++]); + } + for (int j = 0; j < windowSize / 2; j++) { + minHeap.add(maxHeap.poll()); + } + int medianIndex = 0; + while (true) { + if (windowSize % 2 == 1) { + medians[medianIndex++] = maxHeap.peek(); + } else { + medians[medianIndex++] = ((double) maxHeap.peek() + (double) minHeap.peek()) / 2.0; } - } - - return end; - } - - private void removeElement(int num) { - for (int i=0; i= nums.length) { break; } + int outNum = nums[currentIndex - windowSize]; + int inNum = nums[currentIndex++]; + int balance = 0; + // Handle outgoing number + balance += (outNum <= maxHeap.peek() ? -1 : 1); + delayedRemovals.put(outNum, delayedRemovals.getOrDefault(outNum, 0) + 1); + // Handle incoming number + if (!maxHeap.isEmpty() && inNum <= maxHeap.peek()) { + balance++; + maxHeap.add(inNum); + } else { + balance--; + minHeap.add(inNum); + } + // Rebalance heaps + if (balance < 0) { + maxHeap.add(minHeap.poll()); + balance++; + } + if (balance > 0) { + minHeap.add(maxHeap.poll()); + balance--; + } + // Remove invalid numbers from the top of the heaps + while (delayedRemovals.getOrDefault(maxHeap.peek(), 0) > 0) { + delayedRemovals.put(maxHeap.peek(), delayedRemovals.get(maxHeap.peek()) - 1); + maxHeap.poll(); + } + while (!minHeap.isEmpty() && delayedRemovals.getOrDefault(minHeap.peek(), 0) > 0) { + delayedRemovals.put(minHeap.peek(), delayedRemovals.get(minHeap.peek()) - 1); + minHeap.poll(); + } } - } - - private double getMedian() { - if (isEven) { - return (double) (list.get(list.size()/2) + list.get(list.size()/2 - 1)) / 2; - } - else { - return (double) list.get(list.size()/2); - } + return medians; } } diff --git a/Hard/Smallest Range Covering Elements from K Lists.java b/Hard/Smallest Range Covering Elements from K Lists.java new file mode 100644 index 00000000..4e814027 --- /dev/null +++ b/Hard/Smallest Range Covering Elements from K Lists.java @@ -0,0 +1,29 @@ +class Solution { + public int[] smallestRange(List> nums) { + PriorityQueue pq = new PriorityQueue<>( + Comparator.comparingInt(a -> a[0])); + int max = Integer.MIN_VALUE; + int start = 0; + int end = Integer.MAX_VALUE; + for (int i = 0; i < nums.size(); i++) { + pq.add(new int[]{nums.get(i).get(0), i, 0}); + max = Math.max(max, nums.get(i).get(0)); + } + while (pq.size() == nums.size()) { + int[] removed = pq.poll(); + int min = removed[0]; + int row = removed[1]; + int col = removed[2]; + if (max - min < end - start) { + start = min; + end = max; + } + if (col + 1 < nums.get(row).size()) { + int next = nums.get(row).get(col + 1); + pq.add(new int[]{next, row, col + 1}); + max = Math.max(max, next); + } + } + return new int[]{start, end}; + } +} diff --git a/Hard/Sort Items by Groups Respecting Dependencies.java b/Hard/Sort Items by Groups Respecting Dependencies.java new file mode 100644 index 00000000..38c531a3 --- /dev/null +++ b/Hard/Sort Items by Groups Respecting Dependencies.java @@ -0,0 +1,62 @@ +class Solution { + public int[] sortItems(int n, int m, int[] group, List> beforeItems) { + int groupId = m; + for (int i = 0; i < group.length; i++) { + if (group[i] == -1) { + group[i] = groupId++; + } + } + Map> nodeToDependentNodes = new HashMap<>(); + Map> groupToDependentGroups = new HashMap<>(); + int[] itemIndegree = new int[n]; + int[] groupIndegree = new int[groupId]; + for (int i = 0; i < beforeItems.size(); i++) { + for (Integer prev : beforeItems.get(i)) { + nodeToDependentNodes.computeIfAbsent(prev, k -> new ArrayList<>()).add(i); + itemIndegree[i]++; + if (group[i] != group[prev]) { + groupToDependentGroups.computeIfAbsent(group[prev], k -> new ArrayList<>()).add(group[i]); + groupIndegree[group[i]]++; + } + } + } + List itemOrdering = topologicalSort(nodeToDependentNodes, itemIndegree); + List groupOrdering = topologicalSort(groupToDependentGroups, groupIndegree); + if (itemOrdering.isEmpty() || groupOrdering.isEmpty()) { + return new int[]{}; + } + Map> orderedGroups = new HashMap<>(); + for (Integer item : itemOrdering) { + orderedGroups.computeIfAbsent(group[item], k -> new ArrayList<>()).add(item); + } + int[] result = new int[n]; + int idx = 0; + for (Integer groupNo : groupOrdering) { + for (Integer item : orderedGroups.getOrDefault(groupNo, new ArrayList<>())) { + result[idx++] = item; + } + } + return result; + } + + private static List topologicalSort(Map> graph, int[] indegree) { + List visited = new ArrayList<>(); + Queue queue = new LinkedList<>(); + for (int i = 0; i < indegree.length; i++) { + if (indegree[i] == 0) { + queue.add(i); + } + } + while (!queue.isEmpty()) { + int removed = queue.remove(); + visited.add(removed); + for (Integer conn : graph.getOrDefault(removed, new ArrayList<>())) { + indegree[conn]--; + if (indegree[conn] == 0) { + queue.add(conn); + } + } + } + return visited.size() == indegree.length ? visited : new ArrayList<>(); + } +} diff --git a/Hard/Stamping The Sequence.java b/Hard/Stamping The Sequence.java new file mode 100644 index 00000000..1d472157 --- /dev/null +++ b/Hard/Stamping The Sequence.java @@ -0,0 +1,50 @@ +class Solution { + public int[] movesToStamp(String stamp, String target) { + char[] stampLetters = stamp.toCharArray(); + char[] targetLetters = target.toCharArray(); + List result = new ArrayList<>(); + boolean[] visited = new boolean[target.length()]; + int count = 0; + while (count < target.length()) { + boolean replace = false; + for (int i = 0; i <= target.length() - stamp.length(); i++) { + if (!visited[i] && isReplacePossible(stampLetters, targetLetters, i)) { + count = performStamping(targetLetters, i, stamp.length(), count); + replace = true; + visited[i] = true; + result.add(i); + if (count == targetLetters.length) { + break; + } + } + } + if (!replace) { + return new int[0]; + } + } + int[] resArray = new int[result.size()]; + for (int i = 0; i < result.size(); i++) { + resArray[i] = result.get(result.size() - i - 1); + } + return resArray; + } + + private boolean isReplacePossible(char[] stampLetters, char[] targetLetters, int idx) { + for (int i = 0; i < stampLetters.length; i++) { + if (targetLetters[i + idx] != '*' && targetLetters[i + idx] != stampLetters[i]) { + return false; + } + } + return true; + } + + private int performStamping(char[] targetLetters, int idx, int stampLength, int count) { + for (int i = 0; i < stampLength; i++) { + if (targetLetters[i + idx] != '*') { + targetLetters[i + idx] = '*'; + count++; + } + } + return count; + } +} diff --git a/Hard/Stone Game III.java b/Hard/Stone Game III.java new file mode 100644 index 00000000..0ee4e539 --- /dev/null +++ b/Hard/Stone Game III.java @@ -0,0 +1,16 @@ +class Solution { + public String stoneGameIII(int[] stoneValue) { + int n = stoneValue.length; + int[] dp = new int[n + 1]; + for (int i = n - 1; i >= 0; i--) { + dp[i] = stoneValue[i] - dp[i + 1]; + if (i + 2 <= n) { + dp[i] = Math.max(dp[i], stoneValue[i] + stoneValue[i + 1] - dp[i + 2]); + } + if (i + 3 <= n) { + dp[i] = Math.max(dp[i], stoneValue[i] + stoneValue[i + 1] + stoneValue[i + 2] - dp[i + 3]); + } + } + return dp[0] == 0 ? "Tie" : (dp[0] > 0 ? "Alice" : "Bob"); + } +} diff --git a/Hard/Stream of Characters.java b/Hard/Stream of Characters.java index 6cbd64e8..2f3fbed7 100644 --- a/Hard/Stream of Characters.java +++ b/Hard/Stream of Characters.java @@ -1,61 +1,51 @@ class StreamChecker { - String[] words; - TrieNode root; - StringBuilder sb = new StringBuilder(); - public StreamChecker(String[] words) { - this.words = words; - root = new TrieNode('#'); - treeify(words); + + Deque stream; + TrieNode root; + public StreamChecker(String[] words) { + root = new TrieNode('-'); + stream = new ArrayDeque<>(); + Arrays.stream(words).forEach(word -> addWord(word)); + } + + public void addWord(String word) { + TrieNode curr = root; + for (int i = word.length() - 1; i >= 0; i--) { + char c = word.charAt(i); + if (curr.children[c - 'a'] == null) { + curr.children[c - 'a'] = new TrieNode(c); + } + curr = curr.children[c - 'a']; } - - private void treeify (String[] words) { - for (String word : words) { - TrieNode curr = root; - for (int i = word.length() - 1; i >= 0; i--) { - char c = word.charAt(i); - if (curr.childrens[c - 'a'] == null) { - curr.childrens[c - 'a'] = new TrieNode(c); - } - - curr = curr.childrens[c - 'a']; - - if (i == 0) { - curr.isWord = true; - } - } - } - } - - public boolean query(char letter) { - sb.append(letter); - TrieNode curr = root; - for (int i = sb.length() - 1; i >= 0; i--) { - if (curr.childrens[sb.charAt(i) - 'a'] != null) { - curr = curr.childrens[sb.charAt(i) - 'a']; - } - else { - break; - } - - if (curr.isWord) { - return true; - } - } - + curr.isWord = true; + } + + public boolean query(char letter) { + stream.addFirst(letter); + TrieNode curr = root; + for (char c : stream) { + if (curr.isWord) { + return true; + } + if (curr.children[c - 'a'] == null) { return false; + } + curr = curr.children[c - 'a']; } - - class TrieNode { - char key; - TrieNode[] childrens; - boolean isWord; - - public TrieNode (char key) { - this.key = key; - this.childrens = new TrieNode[26]; - isWord = false; - } + return curr.isWord; + } + + + class TrieNode { + char c; + TrieNode[] children; + boolean isWord; + + public TrieNode(char c) { + this.c = c; + children = new TrieNode[26]; } + } } /** diff --git a/Hard/String Compression II.java b/Hard/String Compression II.java new file mode 100644 index 00000000..ac420adf --- /dev/null +++ b/Hard/String Compression II.java @@ -0,0 +1,58 @@ +class Solution { + + private static int[][][][] dp = new int[100][101][100][26]; + + public int getLengthOfOptimalCompression(String s, int k) { + int n = s.length(); + for (int i = 0; i < n; i++) { + for (int j = 0; j <= k; j++) { + for (int x = 0; x < n; x++) { + for (int y = 0; y < 26; y++) { + dp[i][j][x][y] = -1; + } + } + } + } + return solver(s.toCharArray(), 0, k, 0, s.charAt(0)); + } + + private int solver(char[] letters, int idx, int k, int currFrequency, char prevChar) { + if (idx == letters.length) { + return getLetterCount(currFrequency); + } + if (dp[idx][k][currFrequency][prevChar - 'a'] != -1) { + return dp[idx][k][currFrequency][prevChar - 'a']; + } + int result = 0; + if (letters[idx] == prevChar) { + result = k == 0 ? + solver(letters, idx + 1, k, currFrequency + 1, prevChar) : + Math.min( + solver(letters, idx + 1, k , currFrequency + 1, prevChar), // don't delete + solver(letters, idx + 1, k - 1 , currFrequency, prevChar) // delete + ); + } else { + result = k == 0 ? + getLetterCount(currFrequency) + solver(letters, idx + 1, k, 1, letters[idx]) : + Math.min( + getLetterCount(currFrequency) + solver(letters, idx + 1, k, 1, letters[idx]), // don't delete + solver(letters, idx + 1, k - 1, currFrequency, prevChar) // delete + ); + } + return dp[idx][k][currFrequency][prevChar - 'a'] = result; + } + + private static int getLetterCount(int frequency) { + if (frequency == 0) { + return 0; + } + int digits = 1; + if (frequency > 9) { + digits = 2; + } + if (frequency > 99) { + digits = 3; + } + return frequency == 1 ? 1 : (digits + 1); + } +} diff --git a/Hard/Subarrays with K Different Integers.java b/Hard/Subarrays with K Different Integers.java new file mode 100644 index 00000000..0a1d5559 --- /dev/null +++ b/Hard/Subarrays with K Different Integers.java @@ -0,0 +1,23 @@ +class Solution { + public int subarraysWithKDistinct(int[] nums, int k) { + return slidingWindowAtMost(nums, k) - slidingWindowAtMost(nums, k - 1); + } + + private int slidingWindowAtMost(int[] nums, int k) { + Map map = new HashMap<>(); + int left = 0; + int count = 0; + for (int right = 0; right < nums.length; right++) { + map.put(nums[right], map.getOrDefault(nums[right], 0) + 1); + while (map.size() > k) { + map.put(nums[left], map.get(nums[left]) - 1); + if (map.get(nums[left]) == 0) { + map.remove(nums[left]); + } + left++; + } + count += right - left + 1; + } + return count; + } +} diff --git a/Hard/Substring with Concatenation of All Words.java b/Hard/Substring with Concatenation of All Words.java index 95cf6132..5dcfd8bc 100644 --- a/Hard/Substring with Concatenation of All Words.java +++ b/Hard/Substring with Concatenation of All Words.java @@ -1,41 +1,53 @@ class Solution { - public List findSubstring(String s, String[] words) { - List indexes = new ArrayList<>(); - if (words.length == 0) { - return indexes; + public List findSubstring(String s, String[] words) { + int numberOfWords = words.length; + int singleWordLength = words[0].length(); + int totalSubstringLength = singleWordLength * numberOfWords; + Map wordCount = new HashMap<>(); + for (String word : words) { + wordCount.put(word, wordCount.getOrDefault(word, 0) + 1); + } + List result = new ArrayList<>(); + for (int i = 0; i < singleWordLength; i++) { + slidingWindow(i, s, result, singleWordLength, totalSubstringLength, wordCount, numberOfWords); + } + return result; + } + + private void slidingWindow(int left, String s, List answer, int singleWordLength, + int totalSubstringLength, Map wordCount, int numberOfWords) { + Map wordsFound = new HashMap<>(); + int wordsUsed = 0; + boolean excessWord = false; + int n = s.length(); + for (int right = left; right <= n - singleWordLength; right += singleWordLength) { + String currSubstring = s.substring(right, right + singleWordLength); + if (!wordCount.containsKey(currSubstring)) { + wordsFound.clear(); + wordsUsed = 0; + excessWord = false; + left = right + singleWordLength; + } else { + while (right - left == totalSubstringLength || excessWord) { + String leftmostWord = s.substring(left, left + singleWordLength); + left += singleWordLength; + wordsFound.put(leftmostWord, wordsFound.get(leftmostWord) - 1); + if (wordsFound.get(leftmostWord) >= wordCount.get(leftmostWord)) { + excessWord = false; + } else { + wordsUsed--; + } } - - Map freqMap = new HashMap<>(); - for (String word : words) { - freqMap.put(word, freqMap.getOrDefault(word, 0) + 1); + wordsFound.put(currSubstring, wordsFound.getOrDefault(currSubstring, 0) + 1); + if (wordsFound.get(currSubstring) <= wordCount.get(currSubstring)) { + wordsUsed++; + } else { + excessWord = true; } - - int start = 0; - int oneWordLen = words[0].length(); - int totalLen = oneWordLen * words.length; - - while ((s.length() - start) >= totalLen) { - String subStr = s.substring(start, start + totalLen); - int i = 0; - Map map = new HashMap<>(freqMap); - while (i < subStr.length()) { - String wordStr = subStr.substring(i, i + oneWordLen); - - if (!map.containsKey(wordStr) || map.get(wordStr) < 1) { - break; - } - - map.put(wordStr, map.get(wordStr) - 1); - i += oneWordLen; - } - - if (i >= subStr.length()) { - indexes.add(start); - } - - start++; + if (wordsUsed == numberOfWords && !excessWord) { + answer.add(left); } - - return indexes; + } } + } } diff --git a/Hard/Tallest Billboard.java b/Hard/Tallest Billboard.java new file mode 100644 index 00000000..04f81763 --- /dev/null +++ b/Hard/Tallest Billboard.java @@ -0,0 +1,35 @@ +class Solution { + public int tallestBillboard(int[] rods) { + int n = rods.length; + Map firstHalf = helper(rods, 0, n / 2); + Map secondHalf = helper(rods, n / 2, n); + int result = 0; + for (Integer difference : firstHalf.keySet()) { + if (secondHalf.containsKey(-1 * difference)) { + result = Math.max(result, firstHalf.get(difference) + secondHalf.get(-1 * difference)); + } + } + return result; + } + + private Map helper(int[] rods, int leftIdx, int rightIdx) { + Set> states = new HashSet<>(); + states.add(new Pair(0, 0)); + for (int i = leftIdx; i < rightIdx; i++) { + int rod = rods[i]; + Set> newStates = new HashSet<>(); + for (Pair state : states) { + newStates.add(new Pair(state.getKey() + rod, state.getValue())); + newStates.add(new Pair(state.getKey(), state.getValue() + rod)); + } + states.addAll(newStates); + } + Map dp = new HashMap<>(); + for (Pair pair : states) { + Integer left = pair.getKey(); + Integer right = pair.getValue(); + dp.put(left - right, Math.max(dp.getOrDefault(left - right, 0), left)); + } + return dp; + } +} diff --git a/Hard/The Skyline Problem.java b/Hard/The Skyline Problem.java new file mode 100644 index 00000000..92c9e516 --- /dev/null +++ b/Hard/The Skyline Problem.java @@ -0,0 +1,27 @@ +class Solution { + public List> getSkyline(int[][] buildings) { + List> result = new ArrayList<>(); + List heights = new ArrayList<>(); + for (int[] building : buildings) { + heights.add(new int[]{building[0], -1 * building[2]}); + heights.add(new int[]{building[1], 1 * building[2]}); + } + Collections.sort(heights, (a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]); + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + pq.add(0); + int previousMax = 0; + for (int[] height : heights) { + if (height[1] < 0) { + pq.add(-1 * height[1]); + } else { + pq.remove(height[1]); + } + int currentMax = pq.peek(); + if (currentMax != previousMax) { + result.add(Arrays.asList(height[0], currentMax)); + previousMax = currentMax; + } + } + return result; + } +} diff --git a/Hard/Trapping Rain Water.java b/Hard/Trapping Rain Water.java index 6abc9416..263ab08a 100644 --- a/Hard/Trapping Rain Water.java +++ b/Hard/Trapping Rain Water.java @@ -1,20 +1,23 @@ class Solution { - public int trap(int[] A) { - Stack stack = new Stack(); - int i = 0; - int maxWater = 0; - - while (i < A.length){ - if (stack.isEmpty() || A[i] <= A[stack.peek()]){ - stack.push(i++); - } - else { - int bot = stack.pop(); - maxWater += stack.isEmpty() ? 0 : - (Math.min(A[stack.peek()], A[i]) - A[bot]) * (i - stack.peek() - 1); - } + public int trap(int[] height) { + if (height.length == 0) { + return 0; } - - return maxWater; + int n = height.length; + int[] leftMax = new int[n]; + leftMax[0] = height[0]; + for (int i = 1; i < n; i++) { + leftMax[i] = Math.max(height[i], leftMax[i - 1]); + } + int[] rightMax = new int[n]; + rightMax[n - 1] = height[n - 1]; + for (int i = n - 2; i >= 0; i--) { + rightMax[i] = Math.max(rightMax[i + 1], height[i]); + } + int result = 0; + for (int i = 1; i < n - 1; i++) { + result += Math.min(leftMax[i], rightMax[i]) - height[i]; + } + return result; } } diff --git a/Hard/Unique Paths III.java b/Hard/Unique Paths III.java index d1af98f1..415cbc9c 100644 --- a/Hard/Unique Paths III.java +++ b/Hard/Unique Paths III.java @@ -1,66 +1,48 @@ class Solution { - int numOfPaths; - - public int uniquePathsIII(int[][] grid) { - numOfPaths = 0; - if (grid.length == 0 || grid[0].length == 0) { - return numOfPaths; - } - - int startX = -1; - int startY = -1; - int emptyObstacleCount = 0; - - for (int i = 0; i < grid.length; i++) { - for (int j = 0; j < grid[i].length; j++) { - if (grid[i][j] == 1) { - startX = i; - startY = j; - } else if (grid[i][j] == 0) { - emptyObstacleCount++; - } - } - } - - dfsHelper(grid, startX, startY, emptyObstacleCount, 0, new boolean[grid.length][grid[0].length]); - - return numOfPaths; + int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + public int uniquePathsIII(int[][] grid) { + if (grid.length == 0 || grid[0].length == 0) { + return 0; } - - private void dfsHelper(int[][] grid, - int startX, - int startY, - int emptyObstacleCount, - int currObstacleCount, - boolean[][] visited) { - if (startX < 0 || - startX >= grid.length || - startY < 0 || - startY >= grid[0].length || - visited[startX][startY] || - grid[startX][startY] == -1) { - return; + int rows = grid.length; + int cols = grid[0].length; + int startX = 0; + int startY = 0; + int numOfEmptySquare = 0; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + startX = i; + startY = j; } - - if (grid[startX][startY] == 2) { - if (currObstacleCount == emptyObstacleCount) { - numOfPaths++; - } - - return; + if (grid[i][j] == 0) { + numOfEmptySquare++; } - - visited[startX][startY] = true; - - dfsHelper(grid, startX + 1, startY, emptyObstacleCount, - grid[startX][startY] == 0 ? currObstacleCount + 1 : currObstacleCount, visited); - dfsHelper(grid, startX - 1, startY, emptyObstacleCount, - grid[startX][startY] == 0 ? currObstacleCount + 1 : currObstacleCount, visited); - dfsHelper(grid, startX, startY + 1, emptyObstacleCount, - grid[startX][startY] == 0 ? currObstacleCount + 1 : currObstacleCount, visited); - dfsHelper(grid, startX, startY - 1, emptyObstacleCount, - grid[startX][startY] == 0 ? currObstacleCount + 1 : currObstacleCount, visited); - - visited[startX][startY] = false; + } } + int[] count = {0}; + helper(grid, startX, startY, numOfEmptySquare, 0, new boolean[rows][cols], count); + return count[0]; + } + + private void helper( + int[][] grid, int startX, int startY, int numOfEmptySquare, + int currEmptySquare, boolean[][] visited, int[] count + ) { + if (startX < 0 || startX >= grid.length || startY < 0 || startY >= grid[0].length || grid[startX][startY] == -1 || visited[startX][startY]) { + return; + } + if (grid[startX][startY] == 2) { + if (currEmptySquare == numOfEmptySquare) { + count[0]++; + } + return; + } + visited[startX][startY] = true; + for (int[] dir : dirs) { + helper(grid, startX + dir[0], startY + dir[1], numOfEmptySquare, (grid[startX][startY] == 0 ? currEmptySquare + 1 : currEmptySquare), visited, count); + } + visited[startX][startY] = false; + } } + diff --git a/Hard/Valid Number.java b/Hard/Valid Number.java index d9a68285..1cdebfa8 100644 --- a/Hard/Valid Number.java +++ b/Hard/Valid Number.java @@ -1,90 +1,62 @@ class Solution { - public boolean isNumber(String s) { - s = s.trim(); - char[] ch = s.toCharArray(); + public boolean isNumber(String s) { int idx = 0; - int n = ch.length; - boolean signFound = false; - boolean decimalFound = false; - boolean numFound = false; - boolean expoFound = false; - + boolean isDecimal = false; + boolean isDigit = false; + boolean digitsBeforeDecimal = false; + boolean digitsAfterDecimal = false; + int n = s.length(); + if (s.charAt(idx) == '-' || s.charAt(idx) == '+') { + idx++; + } while (idx < n) { - if (ch[idx] == '+' || ch[idx] == '-') { - if (numFound || signFound || decimalFound) { + if (s.charAt(idx) == '.') { + if (isDecimal) { return false; } - - signFound = true; - } - else if (ch[idx] == '.') { - if (decimalFound) { + isDecimal = true; + } else if (s.charAt(idx) == 'e' || s.charAt(idx) == 'E') { + if (!isDigit) { return false; } - decimalFound = true; - } - else if (Character.isLetter(ch[idx])) { - if (ch[idx] == 'e') { - if (!numFound) { - return false; - } - idx++; - expoFound = true; - break; - } - else { + boolean valid = isValidExponent(s, idx + 1); + if (!valid) { return false; } - } - else if (Character.isDigit(ch[idx])) { - numFound = true; - } - else if (ch[idx] == ' ') { - if (numFound || signFound || decimalFound) { - return false; + break; + } else if (Character.isDigit(s.charAt(idx))) { + if (isDecimal) { + digitsAfterDecimal = true; + } else { + digitsBeforeDecimal = true; } + isDigit = true; + } else { + return false; } - idx++; } - - if (!numFound) { - return false; + if (isDecimal) { + return digitsBeforeDecimal || digitsAfterDecimal; } + return isDigit; + } - if (expoFound && idx == n) { + private boolean isValidExponent(String s, int idx) { + if (idx == s.length()) { return false; } - - signFound = false; - numFound = false; - while (idx < n) { - if (ch[idx] == '.') { - return false; - } - else if (ch[idx] == '+' || ch[idx] == '-') { - if (signFound) { - return false; - } - if (numFound) { - return false; - } - signFound = true; - } - else if (Character.isDigit(ch[idx])) { - numFound = true; - } - else { + if (s.charAt(idx) == '-' || s.charAt(idx) == '+') { + idx++; + } + boolean digitFound = false; + while (idx < s.length()) { + if (!Character.isDigit(s.charAt(idx))) { return false; } - + digitFound = true; idx++; } - - if (expoFound && !numFound) { - return false; - } - - return true; + return digitFound; } } diff --git a/Hard/Valid Palindrome III.java b/Hard/Valid Palindrome III.java new file mode 100644 index 00000000..dc97a304 --- /dev/null +++ b/Hard/Valid Palindrome III.java @@ -0,0 +1,26 @@ +class Solution { + public boolean isValidPalindrome(String s, int k) { + int n = s.length(); + Integer[][] dp = new Integer[n][n]; + return isValidPalindrome(s, 0, n - 1, dp) <= k; + } + + private int isValidPalindrome(String s, int left, int right, Integer[][] dp) { + if (left == right) { + return 0; + } + if (left == right - 1) { + return s.charAt(left) != s.charAt(right) ? 1 : 0; + } + if (dp[left][right] != null) { + return dp[left][right]; + } + if (s.charAt(left) == s.charAt(right)) { + return isValidPalindrome(s, left + 1, right - 1, dp); // move both pointers + } + return dp[left][right] = 1 + Math.min( + isValidPalindrome(s, left + 1, right, dp), // move only left pointer + isValidPalindrome(s, left, right - 1, dp) // move only right pointer + ); + } +} diff --git a/Hard/Vertical Order Traversal Of a Binary Tree.java b/Hard/Vertical Order Traversal Of a Binary Tree.java new file mode 100644 index 00000000..2c82d9f6 --- /dev/null +++ b/Hard/Vertical Order Traversal Of a Binary Tree.java @@ -0,0 +1,60 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List> verticalTraversal(TreeNode root) { + Map> map = new HashMap<>(); + Queue queue = new LinkedList<>(); + queue.add(new NodePair(0, 0, root)); + int minColumn = 0; + int maxColumn = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + NodePair removed = queue.remove(); + minColumn = Math.min(minColumn, removed.y); + maxColumn = Math.max(maxColumn, removed.y); + map.computeIfAbsent(removed.y, k -> new ArrayList<>()).add(removed); + if (removed.node.left != null) { + queue.add(new NodePair(removed.x + 1, removed.y - 1, removed.node.left)); + } + if (removed.node.right != null) { + queue.add(new NodePair(removed.x + 1, removed.y + 1, removed.node.right)); + } + } + } + List> result = new ArrayList<>(); + for (int key = minColumn; key <= maxColumn; key++) { + List list = map.get(key); + result.add(list.stream() + .sorted(Comparator.comparingInt((NodePair o) -> o.x).thenComparingInt(o -> o.node.val)) + .map(np -> np.node.val) + .collect(Collectors.toList())); + } + return result; + } + + class NodePair { + int x; + int y; + TreeNode node; + + public NodePair(int x, int y, TreeNode node) { + this.x = x; + this.y = y; + this.node = node; + } + } +} diff --git a/Hard/Wildcard Matching.java b/Hard/Wildcard Matching.java new file mode 100644 index 00000000..993a9f62 --- /dev/null +++ b/Hard/Wildcard Matching.java @@ -0,0 +1,32 @@ +class Solution { + public boolean isMatch(String s, String p) { + int sLen = s.length(); + int pLen = p.length(); + int sIdx = 0; + int pIdx = 0; + int startIdx = -1; + int sTempIdx = -1; + while (sIdx < sLen) { + if (pIdx < pLen && (p.charAt(pIdx) == '?' || p.charAt(pIdx) == s.charAt(sIdx))) { + sIdx++; + pIdx++; + } else if (pIdx < pLen && p.charAt(pIdx) == '*') { + startIdx = pIdx; + sTempIdx = sIdx; + pIdx++; + } else if (startIdx == -1) { + return false; + } else { + pIdx = startIdx + 1; + sIdx = sTempIdx + 1; + sTempIdx = sIdx; + } + } + for (int i = pIdx; i < pLen; i++) { + if (p.charAt(i) != '*') { + return false; + } + } + return true; + } +} diff --git a/Hard/Word Break II.java b/Hard/Word Break II.java new file mode 100644 index 00000000..86ff0a9c --- /dev/null +++ b/Hard/Word Break II.java @@ -0,0 +1,29 @@ +class Solution { + Map> map = new HashMap<>(); + public List wordBreak(String s, List wordDict) { + Set set = new HashSet<>(wordDict); + return helper(s, set, 0); + } + + private List helper(String s, Set set, int start) { + if (map.containsKey(start)) { + return map.get(start); + } + + List ans = new ArrayList <>(); + if (start == s.length()) { + ans.add(""); + } + for (int i = start + 1; i <= s.length(); i++) { + if (set.contains(s.substring(start, i))) { + List list = helper(s, set, i); + for (String word : list) { + ans.add(s.substring(start, i) + (word.equals("") ? "" : " ") + word); + } + } + } + + map.put(start, ans); + return ans; + } +} diff --git a/Hard/Word Search II.java b/Hard/Word Search II.java index 4fd55b93..3e9ce51a 100644 --- a/Hard/Word Search II.java +++ b/Hard/Word Search II.java @@ -1,66 +1,60 @@ class Solution { - public List findWords(char[][] board, String[] words) { - List result = new ArrayList<>(); - TrieNode root = buildTrie(words); - - for (int i = 0; i < board.length; i++) { - for (int j = 0; j < board[0].length; j++) { - helper(board, i, j, root, result); - } + + private final int[][] DIRS = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}}; + + public List findWords(char[][] board, String[] words) { + TrieNode root = new TrieNode(); + for (String word : words) { + TrieNode node = root; + for (Character letter : word.toCharArray()) { + if (node.children.containsKey(letter)) { + node = node.children.get(letter); + } else { + TrieNode newNode = new TrieNode(); + node.children.put(letter, newNode); + node = newNode; } - - return result; + } + node.word = word; } - - private void helper(char[][] board, int i, int j, TrieNode root, List result) { - if (i < 0 || i >= board.length || j >= board[i].length || j < 0) { - return; + List result = new ArrayList<>(); + for (int row = 0; row < board.length; ++row) { + for (int col = 0; col < board[row].length; ++col) { + if (root.children.containsKey(board[row][col])) { + backtracking(row, col, root, result, board); } - - char c = board[i][j]; - if (c == '@' || root.next[c - 'a'] == null) { - return; - } - - root = root.next[c - 'a']; - if (root.word != null) { - result.add(root.word); - root.word = null; - } - - // Choose - board[i][j] = '@'; - - // Explore - helper(board, i + 1, j, root, result); - helper(board, i, j + 1, root, result); - helper(board, i, j - 1, root, result); - helper(board, i - 1, j, root, result); - - // Un-choose - board[i][j] = c; + } } - - private TrieNode buildTrie(String[] words) { - TrieNode root = new TrieNode(); - for (String word : words) { - TrieNode temp =root; - for (char c : word.toCharArray()) { - if (temp.next[c - 'a'] == null) { - temp.next[c - 'a'] = new TrieNode(); - } - - temp = temp.next[c - 'a']; - } - - temp.word = word; - } - - return root; + return result; + } + + private void backtracking(int row, int col, TrieNode parent, List result, char[][] board) { + char letter = board[row][col]; + TrieNode currNode = parent.children.get(letter); + if (currNode.word != null) { + result.add(currNode.word); + currNode.word = null; + } + board[row][col] = '#'; + for (int[] dir : DIRS) { + int newRow = row + dir[0]; + int newCol = col + dir[1]; + if (newRow < 0 || newRow >= board.length || newCol < 0 || newCol >= board[0].length) { + continue; + } + if (currNode.children.containsKey(board[newRow][newCol])) { + backtracking(newRow, newCol, currNode, result, board); + } } - - class TrieNode { - TrieNode[] next = new TrieNode[26]; - String word; + board[row][col] = letter; + if (currNode.children.isEmpty()) { + parent.children.remove(letter); } + } + + private class TrieNode { + Map children = new HashMap(); + String word = null; + public TrieNode() {} + } } diff --git a/Medium/01 Matrix.java b/Medium/01 Matrix.java index 8892b6fc..1faa99d0 100644 --- a/Medium/01 Matrix.java +++ b/Medium/01 Matrix.java @@ -1,40 +1,33 @@ -public class Solution { - public int[][] updateMatrix(int[][] matrix) { - int m = matrix.length; - int n = matrix[0].length; - - Queue queue = new LinkedList<>(); - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - if (matrix[i][j] == 0) { - queue.offer(new int[] {i, j}); - } - else { - matrix[i][j] = Integer.MAX_VALUE; - } - } +class Solution { + private static final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int[][] updateMatrix(int[][] mat) { + int numRows = mat.length; + int numCols = mat[0].length; + int[][] distances = new int[numRows][numCols]; + Queue queue = new LinkedList<>(); + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + if (mat[i][j] == 0) { + queue.add(new int[]{i, j}); + } else { + distances[i][j] = Integer.MAX_VALUE; } - - int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; - - while (!queue.isEmpty()) { - int[] cell = queue.poll(); - for (int[] d : dirs) { - int r = cell[0] + d[0]; - int c = cell[1] + d[1]; - if (r < 0 || - r >= m || - c < 0 || - c >= n || - matrix[r][c] <= matrix[cell[0]][cell[1]] + 1) { - continue; - } - - queue.add(new int[] {r, c}); - matrix[r][c] = matrix[cell[0]][cell[1]] + 1; - } + } + } + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int currX = removed[0]; + int currY = removed[1]; + for (int[] dir : DIRS) { + int newX = currX + dir[0]; + int newY = currY + dir[1]; + if (newX >= 0 && newY >= 0 && newX < numRows && newY < numCols && distances[newX][newY] > distances[currX][currY] + 1) { + queue.add(new int[]{newX, newY}); + distances[newX][newY] = distances[currX][currY] + 1; } - - return matrix; + } } + return distances; + } } diff --git a/Medium/132 Pattern.java b/Medium/132 Pattern.java new file mode 100644 index 00000000..54937149 --- /dev/null +++ b/Medium/132 Pattern.java @@ -0,0 +1,23 @@ +class Solution { + public boolean find132pattern(int[] nums) { + int n = nums.length; + int[] uptoIdxMin = new int[n]; + uptoIdxMin[0] = nums[0]; + for (int i = 1; i < n; i++) { + uptoIdxMin[i] = Math.min(uptoIdxMin[i - 1], nums[i]); + } + Stack stack = new Stack<>(); + for (int i = n - 1; i >= 0; i--) { + if (nums[i] > uptoIdxMin[i]) { + while (!stack.isEmpty() && stack.peek() <= uptoIdxMin[i]) { + stack.pop(); + } + if (!stack.isEmpty() && stack.peek() < nums[i]) { + return true; + } + stack.push(nums[i]); + } + } + return false; + } +} diff --git a/Medium/3Sum Closest.java b/Medium/3Sum Closest.java index ed469e0e..7520f9ea 100644 --- a/Medium/3Sum Closest.java +++ b/Medium/3Sum Closest.java @@ -1,27 +1,22 @@ class Solution { - public int threeSumClosest(int[] nums, int target) { - int sum = Integer.MAX_VALUE; - Arrays.sort(nums); - - for (int i=0; i Math.abs(target - tempSum)) { - sum = tempSum; - } - - if (tempSum > target) { - k--; - } - else { - j++; - } - } + public int threeSumClosest(int[] nums, int target) { + Arrays.sort(nums); + int closestDiff = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + int start = i + 1; + int end = nums.length - 1; + while (start < end) { + int currSum = nums[i] + nums[start] + nums[end]; + if (Math.abs(target - currSum) < Math.abs(closestDiff)) { + closestDiff = target - currSum; } - - return sum; + if (currSum < target) { + start++; + } else { + end--; + } + } } + return target - closestDiff; + } } diff --git a/Medium/3Sum With Multiplicity.java b/Medium/3Sum With Multiplicity.java new file mode 100644 index 00000000..ca9315b3 --- /dev/null +++ b/Medium/3Sum With Multiplicity.java @@ -0,0 +1,37 @@ +class Solution { + public int threeSumMulti(int[] nums, int target) { + Arrays.sort(nums); + long answer = 0; + for (int i = 0; i < nums.length; i++) { + int updatedTarget = target - nums[i]; + int startIdx = i + 1; + int endIdx = nums.length - 1; + while (startIdx < endIdx) { + if (nums[startIdx] + nums[endIdx] < updatedTarget) { + startIdx++; + } else if (nums[startIdx] + nums[endIdx] > updatedTarget) { + endIdx--; + } else if (nums[startIdx] != nums[endIdx]) { + int leftIdx = 1; + int rightIdx = 1; + while (startIdx + 1 < endIdx && nums[startIdx] == nums[startIdx + 1]) { + leftIdx++; + startIdx++; + } + while (endIdx - 1 > startIdx && nums[endIdx] == nums[endIdx - 1]) { + rightIdx++; + endIdx--; + } + + answer = (answer + leftIdx * rightIdx) % 1000000007; + startIdx++; + endIdx--; + } else { + answer = (answer + ((endIdx - startIdx + 1) * (endIdx - startIdx) / 2)) % 1000000007; + break; + } + } + } + return (int) answer; + } +} diff --git a/Medium/3Sum.java b/Medium/3Sum.java index e6bdbc7b..3c615e51 100644 --- a/Medium/3Sum.java +++ b/Medium/3Sum.java @@ -1,45 +1,25 @@ class Solution { public List> threeSum(int[] nums) { - Set> set = new HashSet<>(); Arrays.sort(nums); - for (int i=0; i temp = new ArrayList<>(); - temp.add(nums[i]); - temp.add(nums[j]); - temp.add(nums[idx]); - - set.add(temp); - } + List> result = new ArrayList<>(); + for (int i = 0; i < nums.length; i++) { + if (i != 0 && nums[i] == nums[i - 1]) { + continue; } - } - - List> ans = new ArrayList<>(); - ans.addAll(set); - - return ans; - } - - private int findBinary(int[] nums, int start, int end, int target) { - while (start <= end) { - int mid = (start + end)/2; - - if(nums[mid] == target) { - return mid; - } - else if (nums[mid] > target) { - end = mid-1; - } - else { - start = mid + 1; + int low = i + 1; + int high = nums.length - 1; + while (low < high) { + int currSum = nums[low] + nums[high] + nums[i]; + if (currSum > 0 || (high < nums.length - 1 && nums[high] == nums[high + 1])) { + high--; + } else if (currSum < 0 || (low > i + 1 && nums[low] == nums[low - 1])) { + low++; + } else { + result.add(Arrays.asList(nums[i], nums[low++], nums[high--])); + } + } } - - return -1; + return result; } } diff --git a/Medium/4 Keys Keyboard.java b/Medium/4 Keys Keyboard.java new file mode 100644 index 00000000..2ca4bb8e --- /dev/null +++ b/Medium/4 Keys Keyboard.java @@ -0,0 +1,14 @@ +class Solution { + public int maxA(int n) { + int[] dp = new int[n + 1]; + for (int i = 0; i <= n; i++) { + dp[i] = i; + } + for (int i = 0; i <= n - 3; i++) { + for (int j = i + 3; j <= Math.min(n, i + 6); j++) { + dp[j] = Math.max(dp[j], (j - i - 1) * dp[i]); + } + } + return dp[n]; + } +} diff --git a/Medium/4Sum II.java b/Medium/4Sum II.java new file mode 100644 index 00000000..ecd8f47b --- /dev/null +++ b/Medium/4Sum II.java @@ -0,0 +1,18 @@ +class Solution { + public int fourSumCount(int[] A, int[] B, int[] C, int[] D) { + int n = A.length; + Map map = new HashMap<>(); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + map.put(A[i] + B[j], map.getOrDefault(A[i] + B[j], 0) + 1); + } + } + int count = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + count += map.getOrDefault(-1 * (C[i] + D[j]), 0); + } + } + return count; + } +} diff --git a/Medium/4Sum.java b/Medium/4Sum.java index 8c4fdf7b..50832c2c 100644 --- a/Medium/4Sum.java +++ b/Medium/4Sum.java @@ -1,37 +1,46 @@ class Solution { - public static List> fourSum(int[] nums, int target) { - Set> ans = new HashSet<>(); - - Arrays.sort(nums); - - for (int i=0; i list = new ArrayList<>(); - list.add(nums[i]); - list.add(nums[j]); - list.add(nums[start]); - list.add(nums[end]); - - ans.add(list); - start++; - end--; - } - else if (nums[start] + nums[end] < temp) { - start++; - } - else if (nums[start] + nums[end] > temp) { - end--; - } - } - } + public List> fourSum(int[] nums, int target) { + Arrays.sort(nums); + return kSum(nums, target, 0, 4); + } + + public List> kSum(int[] nums, long target, int start, int k) { + List> result = new ArrayList<>(); + if (start == nums.length) { + return result; + } + long averageValue = target / k; + if (nums[start] > averageValue || averageValue > nums[nums.length - 1]) { + return result; + } + if (k == 2) { + return twoSum(nums, target, start); + } + for (int i = start; i < nums.length; ++i) { + if (i == start || nums[i - 1] != nums[i]) { + for (List subset : kSum(nums, target - nums[i], i + 1, k - 1)) { + result.add(new ArrayList<>(Arrays.asList(nums[i]))); + result.get(result.size() - 1).addAll(subset); } - - return new ArrayList<>(ans); + } + } + return result; + } + + public List> twoSum(int[] nums, long target, int start) { + List> result = new ArrayList<>(); + int low = start; + int high = nums.length - 1; + while (low < high) { + int currSum = nums[low] + nums[high]; + if (currSum < target || (low > start && nums[low] == nums[low - 1])) { + ++low; + } else if (currSum > target || (high < nums.length - 1 && nums[high] == nums[high + 1])) { + --high; + } else { + result.add(Arrays.asList(nums[low++], nums[high--])); + } } + return result; + } } diff --git a/Medium/Accounts Merge.java b/Medium/Accounts Merge.java new file mode 100644 index 00000000..97b55568 --- /dev/null +++ b/Medium/Accounts Merge.java @@ -0,0 +1,38 @@ +class Solution { + public List> accountsMerge(List> accounts) { + Map> adjacencyList = new HashMap<>(); + for (List account : accounts) { + String firstEmail = account.get(1); + for (int i = 2; i < account.size(); i++) { + adjacencyList.computeIfAbsent(firstEmail, k -> new ArrayList<>()).add(account.get(i)); + adjacencyList.computeIfAbsent(account.get(i), k -> new ArrayList<>()).add(firstEmail); + } + } + Set visited = new HashSet<>(); + List> mergedAccounts = new ArrayList<>(); + for (List account : accounts) { + String name = account.get(0); + String firstEmail = account.get(1); + if (!visited.contains(firstEmail)) { + Stack stack = new Stack<>(); + stack.push(firstEmail); + List mergedAccount = new ArrayList<>(); + mergedAccount.add(name); + while (!stack.isEmpty()) { + String removedEmail = stack.pop(); + visited.add(removedEmail); + mergedAccount.add(removedEmail); + for (String neighbor : adjacencyList.getOrDefault(removedEmail, new ArrayList<>())) { + if (!visited.contains(neighbor)) { + visited.add(neighbor); + stack.push(neighbor); + } + } + } + Collections.sort(mergedAccount.subList(1, mergedAccount.size())); + mergedAccounts.add(mergedAccount); + } + } + return mergedAccounts; + } +} diff --git a/Medium/Add Bold Tag in String.java b/Medium/Add Bold Tag in String.java index 99e3c57f..024e1823 100644 --- a/Medium/Add Bold Tag in String.java +++ b/Medium/Add Bold Tag in String.java @@ -1,42 +1,44 @@ class Solution { - public String addBoldTag(String s, String[] dict) { - boolean[] bold = new boolean[s.length()]; - int end = 0; - - for (int i=0; i").append(s.substring(i, j) + ""); - i = j-1; - } + public String addBoldTag(String s, String[] words) { + List indexes = new ArrayList<>(); + for (String word : words) { + indexes.addAll(getIndexPair(s, word)); + } + Collections.sort(indexes, + Comparator.comparingInt((int[] o) -> o[0]).thenComparingInt(o -> o[1])); + Set startIdx = new HashSet<>(); + Set endIdx = new HashSet<>(); + int idx = 0; + while (idx < indexes.size()) { + int currStart = indexes.get(idx)[0]; + int currEnd = indexes.get(idx)[1]; + idx++; + while (idx < indexes.size() && indexes.get(idx)[0] <= currEnd + 1) { + currEnd = Math.max(currEnd, indexes.get(idx++)[1]); + } + startIdx.add(currStart); + endIdx.add(currEnd); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + if (startIdx.contains(i)) { + sb.append(""); + } + sb.append(s.charAt(i)); + if (endIdx.contains(i)) { + sb.append(""); + } + } + return sb.toString(); + } - return sb.toString(); + private List getIndexPair(String s, String word) { + List indexPairs = new ArrayList<>(); + for (int i = 0; i < s.length() - word.length() + 1; i++) { + if (s.startsWith(word, i)) { + indexPairs.add(new int[]{i, i + word.length() - 1}); + } } + return indexPairs; + } } diff --git a/Medium/Add Minimum Number of Rungs.java b/Medium/Add Minimum Number of Rungs.java new file mode 100644 index 00000000..f473ea61 --- /dev/null +++ b/Medium/Add Minimum Number of Rungs.java @@ -0,0 +1,11 @@ +class Solution { + public int addRungs(int[] rungs, int dist) { + int numOfRungs = 0; + int currPos = 0; + for (int rung : rungs) { + numOfRungs += (rung - currPos - 1) / dist; + currPos = rung; + } + return numOfRungs; + } +} diff --git a/Medium/Add One Row to Tree.java b/Medium/Add One Row to Tree.java index 06a5e253..38075d28 100644 --- a/Medium/Add One Row to Tree.java +++ b/Medium/Add One Row to Tree.java @@ -4,40 +4,48 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode addOneRow(TreeNode root, int v, int d) { - if (d == 1) { - TreeNode t = new TreeNode(v); - t.left = root; - return t; - } - - helper(root, v, d, 1); - return root; + public TreeNode addOneRow(TreeNode root, int val, int depth) { + if (depth == 1) { + TreeNode newRoot = new TreeNode(val); + newRoot.left = root; + return newRoot; } - - private void helper(TreeNode root, int v, int d, int currLevel) { - if (currLevel == d-1) { - TreeNode t1 = new TreeNode(v); - TreeNode t2 = new TreeNode(v); - - t1.left = root.left; - t2.right = root.right; - root.left = t1; - root.right = t2; - - return; - } - - if (root.left != null) { - helper(root.left, v, d, currLevel + 1); + int currDepth = 1; + Queue queue = new LinkedList<>(); + queue.add(root); + while (currDepth < depth - 1) { + Queue temp = new LinkedList<>(); + while (!queue.isEmpty()) { + TreeNode removed = queue.remove(); + if (removed.left != null) { + temp.add(removed.left); } - - if (root.right != null) { - helper(root.right, v, d, currLevel + 1); + if (removed.right != null) { + temp.add(removed.right); } + } + queue = temp; + currDepth++; + } + while (!queue.isEmpty()) { + TreeNode node = queue.remove(); + TreeNode temp = node.left; + node.left = new TreeNode(val); + node.left.left = temp; + temp = node.right; + node.right = new TreeNode(val); + node.right.right = temp; } + return root; + } } diff --git a/Medium/Add Two Numbers II.java b/Medium/Add Two Numbers II.java index ae9591cd..59d717cb 100644 --- a/Medium/Add Two Numbers II.java +++ b/Medium/Add Two Numbers II.java @@ -3,65 +3,46 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - ListNode l1Rev = reverse(l1); - ListNode l2Rev = reverse(l2); - - ListNode ans = new ListNode(-1); - ListNode curr = ans; + ListNode rev1 = reverse(l1); + ListNode rev2 = reverse(l2); + ListNode dummy = new ListNode(); + ListNode curr = dummy; int carry = 0; - - while (l1Rev != null || l2Rev != null) { - int temp = 0; - if (l1Rev != null && l2Rev != null) { - temp = l1Rev.val + l2Rev.val + carry; - l1Rev = l1Rev.next; - l2Rev = l2Rev.next; + while (rev1 != null || rev2 != null || carry > 0) { + if (rev1 != null && rev2 != null) { + carry += rev1.val + rev2.val; + rev1 = rev1.next; + rev2 = rev2.next; + } else if (rev1 == null && rev2 != null) { + carry += rev2.val; + rev2 = rev2.next; + } else if (rev1 != null && rev2 == null) { + carry += rev1.val; + rev1 = rev1.next; } - else if(l1Rev != null) { - temp = l1Rev.val + carry; - l1Rev = l1Rev.next; - } - else { - temp = l2Rev.val + carry; - l2Rev = l2Rev.next; - } - - if (temp > 9) { - carry = temp/10; - temp = temp%10; - } - else { - carry = 0; - } - curr.next = new ListNode(temp); - curr = curr.next; - } - - if (carry != 0) { - curr.next = new ListNode(carry); + curr.next = new ListNode(carry % 10); curr = curr.next; + carry /= 10; } - - return reverse(ans.next); + return reverse(dummy.next); } - private ListNode reverse(ListNode head) { - ListNode curr = head; + private ListNode reverse(ListNode node) { + ListNode curr = node; ListNode prev = null; - ListNode next = null; - while (curr != null) { - next = curr.next; + ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } - return prev; } } diff --git a/Medium/Add Two Numbers.java b/Medium/Add Two Numbers.java index 38a32906..8245945b 100644 --- a/Medium/Add Two Numbers.java +++ b/Medium/Add Two Numbers.java @@ -3,42 +3,34 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - ListNode ans = new ListNode(-1); - ListNode curr = ans; - int carry = 0; - - while (l1 != null || l2 != null) { - int temp = carry; - if (l1 != null && l2 != null) { - temp += l1.val + l2.val; - l1 = l1.next; - l2 = l2.next; - } - else if (l1 != null && l2 == null) { - temp += l1.val; - l1 = l1.next; - } - else { - temp += l2.val; - l2 = l2.next; - } - - carry = temp > 9 ? temp / 10 : 0; - temp = temp > 9 ? temp % 10 : temp; - - curr.next = new ListNode(temp); - curr = curr.next; - } - - if (carry > 0) { - curr.next = new ListNode(carry); - } - - return ans.next; + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + ListNode root = new ListNode(-1); + ListNode curr = root; + int carry = 0; + while (l1 != null || l2 != null || carry != 0) { + int currSum = carry; + if (l1 != null && l2 != null) { + currSum += l1.val + l2.val; + l1 = l1.next; + l2 = l2.next; + } else if (l1 != null && l2 == null) { + currSum += l1.val; + l1 = l1.next; + } else if (l1 == null && l2 != null) { + currSum += l2.val; + l2 = l2.next; + } + carry = currSum > 9 ? 1 : 0; + currSum %= 10; + curr.next = new ListNode(currSum); + curr = curr.next; } + return root.next; + } } diff --git a/Medium/Add Two Polynomials Represented as Linked Lists.java b/Medium/Add Two Polynomials Represented as Linked Lists.java new file mode 100644 index 00000000..f7eafe3a --- /dev/null +++ b/Medium/Add Two Polynomials Represented as Linked Lists.java @@ -0,0 +1,43 @@ +/** + * Definition for polynomial singly-linked list. + * class PolyNode { + * int coefficient, power; + * PolyNode next = null; + + * PolyNode() {} + * PolyNode(int x, int y) { this.coefficient = x; this.power = y; } + * PolyNode(int x, int y, PolyNode next) { this.coefficient = x; this.power = y; this.next = next; } + * } + */ + +class Solution { + public PolyNode addPoly(PolyNode poly1, PolyNode poly2) { + Map powerToValue = new HashMap<>(); + populateMap(powerToValue, poly1); + populateMap(powerToValue, poly2); + List powerKeys = new ArrayList<>(powerToValue.keySet()); + Collections.sort(powerKeys); + PolyNode dummy = new PolyNode(); + PolyNode curr = dummy; + for (int i = powerKeys.size() - 1; i >= 0; i--) { + if (powerToValue.get(powerKeys.get(i)) == 0) { + continue; + } + PolyNode node = new PolyNode(powerToValue.get(powerKeys.get(i)), powerKeys.get(i)); + curr.next = node; + curr = curr.next; + } + return dummy.next; + } + + private void populateMap(Map powerToValue, PolyNode poly) { + while (poly != null) { + PolyNode node = poly; + int power = node.power; + if (node.coefficient != 0) { + powerToValue.put(power, powerToValue.getOrDefault(power, 0) + node.coefficient); + } + poly = poly.next; + } + } +} diff --git a/Medium/Adding Spaces to a String.java b/Medium/Adding Spaces to a String.java new file mode 100644 index 00000000..f1a0dc5f --- /dev/null +++ b/Medium/Adding Spaces to a String.java @@ -0,0 +1,12 @@ +class Solution { + public String addSpaces(String s, int[] spaces) { + StringBuilder sb = new StringBuilder(); + int startIdx = 0; + for (int spaceIdx : spaces) { + sb.append(s.substring(startIdx, spaceIdx)).append(" "); + startIdx = spaceIdx; + } + sb.append(s.substring(startIdx)); + return sb.toString(); + } +} diff --git a/Medium/Adding Two Negabinary Numbers.java b/Medium/Adding Two Negabinary Numbers.java new file mode 100644 index 00000000..7f371f30 --- /dev/null +++ b/Medium/Adding Two Negabinary Numbers.java @@ -0,0 +1,23 @@ +class Solution { + public int[] addNegabinary(int[] arr1, int[] arr2) { + int idxOne = arr1.length - 1; + int idxTwo = arr2.length - 1; + int carry = 0; + Stack stack = new Stack<>(); + while (idxOne >= 0 || idxTwo >= 0 || carry != 0) { + int valOne = idxOne >= 0 ? arr1[idxOne--] : 0; + int valTwo = idxTwo >= 0 ? arr2[idxTwo--] : 0; + carry = valOne + valTwo + carry; + stack.push(carry & 1); + carry = -(carry >> 1); + } + while (!stack.isEmpty() && stack.peek() == 0) { + stack.pop(); + } + int[] result = new int[stack.size()]; + for (int i = 0; i < result.length; i++) { + result[i] = stack.pop(); + } + return result.length == 0 ? new int[]{0} : result; + } +} diff --git a/Medium/Advantage Shuffle.java b/Medium/Advantage Shuffle.java new file mode 100644 index 00000000..2bb3ba9b --- /dev/null +++ b/Medium/Advantage Shuffle.java @@ -0,0 +1,31 @@ +class Solution { + public int[] advantageCount(int[] A, int[] B) { + TreeMap map = new TreeMap<>(); + for (int num : A) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int[] result = new int[A.length]; + Arrays.fill(result, Integer.MIN_VALUE); + List indexesNotPopulated = new ArrayList<>(); + for (int i = 0; i < B.length; i++) { + Integer upper = map.higherKey(B[i]); + if (upper != null) { + result[i] = upper; + map.put(upper, map.get(upper) - 1); + if (map.get(upper) == 0) { + map.remove(upper); + } + } else { + indexesNotPopulated.add(i); + } + } + Iterator iterator = indexesNotPopulated.iterator(); + for (Integer key : map.keySet()) { + int value = map.get(key); + while (value-- > 0) { + result[iterator.next()] = key; + } + } + return result; + } +} diff --git a/Medium/Alert Using Same Key-Card Three or More Times in a One Hour Period.java b/Medium/Alert Using Same Key-Card Three or More Times in a One Hour Period.java new file mode 100644 index 00000000..604c8bfd --- /dev/null +++ b/Medium/Alert Using Same Key-Card Three or More Times in a One Hour Period.java @@ -0,0 +1,22 @@ +class Solution { + public List alertNames(String[] keyName, String[] keyTime) { + Map> map = new HashMap<>(); + for (int i = 0; i < keyName.length; i++) { + int numOfMinutes = Integer.parseInt(keyTime[i].split(":")[0]) * 60 + Integer.parseInt(keyTime[i].split(":")[1]); + map.computeIfAbsent(keyName[i], k -> new ArrayList<>()).add(numOfMinutes); + } + List ans = new ArrayList<>(); + for (String key : map.keySet()) { + List list = map.get(key); + Collections.sort(list); + for (int i = 0; i < list.size() - 2; i++) { + if (list.get(i + 1) <= (list.get(i) + 60) && list.get(i + 2) <= (list.get(i) + 60)) { + ans.add(key); + break; + } + } + } + Collections.sort(ans); + return ans; + } +} diff --git a/Medium/All Ancestors of a Node in a Directed Acyclic Graph.java b/Medium/All Ancestors of a Node in a Directed Acyclic Graph.java new file mode 100644 index 00000000..36063815 --- /dev/null +++ b/Medium/All Ancestors of a Node in a Directed Acyclic Graph.java @@ -0,0 +1,36 @@ +class Solution { + public List> getAncestors(int n, int[][] edges) { + Map> graph = new HashMap<>(); + int[] indegree = new int[n]; + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]); + indegree[edge[1]]++; + } + Queue queue = new LinkedList<>(); + Map> ancestors = new HashMap<>(); + for (int i = 0; i < n; i++) { + if (indegree[i] == 0) { + queue.offer(i); + } + } + while (!queue.isEmpty()) { + int node = queue.poll(); + ancestors.computeIfAbsent(node, k -> new HashSet<>()); + for (int dependents : graph.getOrDefault(node, Collections.emptyList())) { + ancestors.computeIfAbsent(dependents, k -> new HashSet<>()).add(node); + ancestors.get(dependents).addAll(ancestors.get(node)); + indegree[dependents]--; + if (indegree[dependents] == 0) { + queue.offer(dependents); + } + } + } + List> result = new ArrayList<>(); + for (int i = 0; i < n; i++) { + List currNodeAncestors = new ArrayList<>(ancestors.getOrDefault(i, Collections.emptySet())); + currNodeAncestors.sort(Comparator.naturalOrder()); + result.add(currNodeAncestors); + } + return result; + } +} diff --git a/Medium/All Divisions With the Highest Score of a Binary Array.java b/Medium/All Divisions With the Highest Score of a Binary Array.java new file mode 100644 index 00000000..f47caba5 --- /dev/null +++ b/Medium/All Divisions With the Highest Score of a Binary Array.java @@ -0,0 +1,25 @@ +class Solution { + public List maxScoreIndices(int[] nums) { + int n = nums.length; + int[] prefix = new int[n + 1]; + for (int i = 0; i < n; i++) { + prefix[i + 1] = nums[i] + prefix[i]; + } + int maxScore = 0; + Map map = new HashMap<>(); + for (int i = 0; i < n + 1; i++) { + int onesToRight = prefix[n] - prefix[i]; + int zerosToLeft = i - prefix[i]; + int currScore = zerosToLeft + onesToRight; + maxScore = Math.max(maxScore, currScore); + map.put(i, currScore); + } + List result = new ArrayList<>(); + for (Integer key : map.keySet()) { + if (map.get(key).equals(maxScore)) { + result.add(key); + } + } + return result; + } +} diff --git a/Medium/All Elements in Two Binary Search Trees.java b/Medium/All Elements in Two Binary Search Trees.java new file mode 100644 index 00000000..92fc3d9f --- /dev/null +++ b/Medium/All Elements in Two Binary Search Trees.java @@ -0,0 +1,59 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List getAllElements(TreeNode root1, TreeNode root2) { + Stack stackOne = new Stack<>(); + Stack stackTwo = new Stack<>(); + while (root1 != null) { + stackOne.push(root1); + root1 = root1.left; + } + while (root2 != null) { + stackTwo.push(root2); + root2 = root2.left; + } + List list = new ArrayList<>(); + while (!stackOne.isEmpty() || !stackTwo.isEmpty()) { + if (!stackOne.isEmpty() && !stackTwo.isEmpty()) { + if (stackOne.peek().val < stackTwo.peek().val) { + TreeNode popped = stackOne.pop(); + list.add(popped.val); + updateStack(stackOne, popped.right); + } else { + TreeNode popped = stackTwo.pop(); + list.add(popped.val); + updateStack(stackTwo, popped.right); + } + } else if (!stackOne.isEmpty() && stackTwo.isEmpty()) { + TreeNode popped = stackOne.pop(); + list.add(popped.val); + updateStack(stackOne, popped.right); + } else { + TreeNode popped = stackTwo.pop(); + list.add(popped.val); + updateStack(stackTwo, popped.right); + } + } + return list; + } + + private void updateStack(Stack stack, TreeNode node) { + while (node != null) { + stack.push(node); + node = node.left; + } + } +} diff --git a/Medium/All Nodes Distance K in Binary Tree.java b/Medium/All Nodes Distance K in Binary Tree.java index f00bad4a..9f88451e 100644 --- a/Medium/All Nodes Distance K in Binary Tree.java +++ b/Medium/All Nodes Distance K in Binary Tree.java @@ -8,58 +8,48 @@ * } */ class Solution { + public List distanceK(TreeNode root, TreeNode target, int k) { + List result = new ArrayList<>(); + dfs(root, target, k, result); + return result; + } - public Map parentMap; - public List distanceK(TreeNode root, TreeNode target, int K) { - parentMap = new HashMap<>(); - addParentHelper(root, null); - - Set visited = new HashSet<>(); - Queue queue = new LinkedList<>(); - int currLevel = 0; - - queue.add(target); - - while (!queue.isEmpty() && currLevel != K) { - int size = queue.size(); - - while (size-- > 0) { - TreeNode removed = queue.remove(); - visited.add(removed); - TreeNode parent = parentMap.get(removed); - - if (removed.left != null && !visited.contains(removed.left)) { - queue.add(removed.left); - } - - if (removed.right != null && !visited.contains(removed.right)) { - queue.add(removed.right); - } - - if (parent != null && !visited.contains(parent)) { - queue.add(parent); - } + private int dfs(TreeNode node, TreeNode target, int k, List result) { + if (node == null) { + return -1; + } + if (node == target) { + dfs(node, 0, k, result); + return 1; + } + int left = dfs(node.left, target, k, result); + if (left != -1) { + if (left == k) { + result.add(node.val); } - - currLevel++; + dfs(node.right, left + 1, k, result); + return left + 1; } - - List list = new ArrayList<>(); - while (!queue.isEmpty()) { - list.add(queue.remove().val); + int right = dfs(node.right, target, k, result); + if (right != -1) { + if (right == k) { + result.add(node.val); + } + dfs(node.left, right + 1, k, result); + return right + 1; } - - return list; + return -1; } - private void addParentHelper(TreeNode node, TreeNode parent) { - if (node == null) { + private void dfs(TreeNode node, int distance, int k, List result) { + if (node == null || distance > k) { + return; + } + if (distance == k) { + result.add(node.val); return; } - - parentMap.put(node, parent); - - addParentHelper(node.left, node); - addParentHelper(node.right, node); + dfs(node.left, distance + 1, k, result); + dfs(node.right, distance + 1, k, result); } } diff --git a/Medium/All Paths From Source to Target.java b/Medium/All Paths From Source to Target.java index d5ae70f2..e6fa3515 100644 --- a/Medium/All Paths From Source to Target.java +++ b/Medium/All Paths From Source to Target.java @@ -1,51 +1,24 @@ class Solution { - public List> allPathsSourceTarget(int[][] graph) { - int[][] newPath = getPath(graph); - - int start = 0; - int destination = newPath.length-1; - - List> ans = printPossiblePaths(newPath, start, destination); - - return ans; + public List> allPathsSourceTarget(int[][] graph) { + List> list = new ArrayList<>(); + int target = graph.length - 1; + List temp = new ArrayList<>(); + temp.add(0); + helper(list, temp, 0, graph, target); + return list; + } + + private void helper(List> list, List temp, int curr, int[][] graph, int target) { + if (curr == target) { + list.add(new ArrayList<>(temp)); } - - private static int[][] getPath(int[][] graph) { - int[][] path = new int[graph.length][graph.length]; - - for (int i=0; i> printPossiblePaths(int[][] paths, int start, int destination) { - List> ans = new ArrayList<>(); - printPossiblePathsHelper(paths, start, destination, new StringBuilder().append(start).append("-"), ans); - - return ans; - } - - private void printPossiblePathsHelper(int[][] paths, int start, int destination, StringBuilder sb, List> ans) { - int[] possiblePaths = paths[start]; - if (start == destination) { - List list = Arrays. - stream(sb.toString().split("-")). - mapToInt(Integer::parseInt). - boxed(). - collect(Collectors.toList()); - - ans.add(list); - return; - } - - for (int i=0; i> graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new HashSet<>()).add(edge[1]); + } + return leadsToDestinationHelper(graph, source, destination, new State[n]); + } + + private boolean leadsToDestinationHelper( + Map> graph, int source, int destination, State[] states + ) { + if (states[source] != null) { + return states[source] == State.PROCESSED; + } + if (!graph.containsKey(source)) { + return source == destination; + } + states[source] = State.PROCESSING; + for (Integer child : graph.getOrDefault(source, new HashSet<>())) { + if (!leadsToDestinationHelper(graph, child, destination, states)) { + return false; + } + } + states[source] = State.PROCESSED; + return true; + } +} diff --git a/Medium/All Possible Full Binary Trees.java b/Medium/All Possible Full Binary Trees.java index 7c7853c4..868b8271 100644 --- a/Medium/All Possible Full Binary Trees.java +++ b/Medium/All Possible Full Binary Trees.java @@ -4,40 +4,42 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public List allPossibleFBT(int N) { - List ans = new LinkedList<>(); - if (N % 2 == 0) { - return ans; - } - - return helper(N); + public List allPossibleFBT(int n) { + Map> dp = new HashMap<>(); + return allPossibleFBTHelper(n, dp); + } + + private List allPossibleFBTHelper(int n, Map> dp) { + if (dp.containsKey(n)) { + return dp.get(n); } - - private List helper(int N) { - List ans = new LinkedList<>(); - if (N == 1) { - ans.add(new TreeNode(0)); - return ans; - } - - for (int i = 1; i <= N - 2; i += 2) { - List left = helper(i); - List right = helper(N - i - 1); - - for (TreeNode leftNode : left) { - for (TreeNode rightNode : right) { - TreeNode node = new TreeNode(0); - node.left = leftNode; - node.right = rightNode; - ans.add(node); - } - } + List result = new ArrayList<>(); + if (n == 1) { + result.add(new TreeNode(0)); + } else if (n % 2 == 1) { + for (int i = 0; i < n; i++) { + int j = n - 1 - i; + for (TreeNode left : allPossibleFBTHelper(i, dp)) { + for (TreeNode right : allPossibleFBTHelper(j, dp)) { + TreeNode root = new TreeNode(0); + root.left = left; + root.right = right; + result.add(root); + } } - - return ans; + } } + dp.put(n, result); + return dp.get(n); + } } diff --git a/Medium/Amount of Time for Binary Tree to Be Infected.java b/Medium/Amount of Time for Binary Tree to Be Infected.java new file mode 100644 index 00000000..8d5540ab --- /dev/null +++ b/Medium/Amount of Time for Binary Tree to Be Infected.java @@ -0,0 +1,65 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int amountOfTime(TreeNode root, int start) { + Map nodeToParent = new HashMap<>(); + buildNodeToParentRelationship(root, null, nodeToParent); + TreeNode startNode = nodeToParent.keySet() + .stream() + .filter(node -> node.val == start) + .findFirst() + .orElse(null); + return calculateInfectionTime(nodeToParent, startNode); + } + + private void buildNodeToParentRelationship(TreeNode root, TreeNode parent, Map nodeToParent) { + if (root == null) { + return; + } + nodeToParent.put(root, parent); + buildNodeToParentRelationship(root.left, root, nodeToParent); + buildNodeToParentRelationship(root.right, root, nodeToParent); + } + + private int calculateInfectionTime(Map nodeToParent, TreeNode startNode) { + int time = 0; + Set isInfected = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add(startNode); + isInfected.add(startNode.val); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + TreeNode parent = nodeToParent.get(removed); + if (nodeToParent.get(removed) != null && isInfected.add(nodeToParent.get(removed).val)) { + queue.add(nodeToParent.get(removed)); + } + if (removed.left != null && isInfected.add(removed.left.val)) { + queue.add(removed.left); + } + if (removed.right != null && isInfected.add(removed.right.val)) { + queue.add(removed.right); + } + } + if (queue.isEmpty()) { + break; + } + time++; + } + return time; + } +} diff --git a/Medium/Analyze User Website Visit Pattern.java b/Medium/Analyze User Website Visit Pattern.java new file mode 100644 index 00000000..1fbb2fc3 --- /dev/null +++ b/Medium/Analyze User Website Visit Pattern.java @@ -0,0 +1,41 @@ +class Solution { + public List mostVisitedPattern(String[] username, int[] timestamp, String[] website) { + Map> userToVisitMapping = new HashMap<>(); + for (int i = 0; i < username.length; i++) { + userToVisitMapping.computeIfAbsent(username[i], k -> new ArrayList<>()).add(i); + } + Map> patternToUserMapping = new HashMap<>(); + int maxCount = 0; + String resultingPattern = null; + for (String key : userToVisitMapping.keySet()) { + List visitedWebsiteInOrder = + userToVisitMapping.get(key).stream() + .sorted(Comparator.comparingInt(a -> timestamp[a])) + .map(i -> website[i]) + .collect(Collectors.toList()); + for (int i = 0; i < visitedWebsiteInOrder.size() - 2; i++) { + for (int j = i + 1; j < visitedWebsiteInOrder.size() - 1; j++) { + for (int k = j + 1; k < visitedWebsiteInOrder.size(); k++) { + String pattern = + visitedWebsiteInOrder.get(i) + + " " + + visitedWebsiteInOrder.get(j) + + " " + + visitedWebsiteInOrder.get(k); + patternToUserMapping.computeIfAbsent(pattern, l -> new HashSet<>()).add(key); + if (maxCount <= patternToUserMapping.get(pattern).size()) { + if (maxCount < patternToUserMapping.get(pattern).size()) { + resultingPattern = pattern; + maxCount = patternToUserMapping.get(pattern).size(); + } else if (pattern.compareTo(resultingPattern) < 0) { + resultingPattern = pattern; + } + } + maxCount = Math.max(maxCount, patternToUserMapping.get(pattern).size()); + } + } + } + } + return Arrays.stream(resultingPattern.split("\\s+")).collect(Collectors.toList()); + } +} diff --git a/Medium/Angle Between Hands of a Clock.java b/Medium/Angle Between Hands of a Clock.java new file mode 100644 index 00000000..036ea3d8 --- /dev/null +++ b/Medium/Angle Between Hands of a Clock.java @@ -0,0 +1,8 @@ +class Solution { + public double angleClock(int hour, int minutes) { + double angleByHourHand = (hour % 12 + minutes / 60.0) * 30; + double angleByMinuteHand = (double) 6 * minutes; + double diff = Math.abs(angleByHourHand - angleByMinuteHand); + return Math.min(diff, 360 - diff); + } +} diff --git a/Medium/Append Characters to String to Make Subsequence.java b/Medium/Append Characters to String to Make Subsequence.java new file mode 100644 index 00000000..af35ca3d --- /dev/null +++ b/Medium/Append Characters to String to Make Subsequence.java @@ -0,0 +1,13 @@ +class Solution { + public int appendCharacters(String s, String t) { + int idxS = 0; + int idxT = 0; + while (idxS < s.length() && idxT < t.length()) { + if (s.charAt(idxS) == t.charAt(idxT)) { + idxT++; + } + idxS++; + } + return idxT == t.length() ? 0 : t.length() - idxT; + } +} diff --git a/Medium/Append K Integers With Minimal Sum.java b/Medium/Append K Integers With Minimal Sum.java new file mode 100644 index 00000000..bea57e93 --- /dev/null +++ b/Medium/Append K Integers With Minimal Sum.java @@ -0,0 +1,20 @@ +class Solution { + public long minimalKSum(int[] nums, int k) { + Arrays.sort(nums); + long sum = 0; + long low = 1; + for (int num : nums) { + if (num > low) { + long high = Math.min(num - 1, low + k - 1); + int count = (int) (high - low + 1); + sum += (low + high) * count / 2; + k -= count; + if (k == 0) { + return sum; + } + } + low = num + 1; + } + return sum + (2 * low + k - 1) * k / 2; + } +} diff --git a/Medium/Apply Discount Every n Orders.java b/Medium/Apply Discount Every n Orders.java new file mode 100644 index 00000000..18fcf078 --- /dev/null +++ b/Medium/Apply Discount Every n Orders.java @@ -0,0 +1,37 @@ +class Cashier { + int n; + int discount; + int currCount; + Map priceMap; + public Cashier(int n, int discount, int[] products, int[] prices) { + this.n = n; + this.currCount = 0; + this.discount = discount; + priceMap = new HashMap<>(); + for (int i = 0; i < products.length; i++) { + priceMap.put(products[i], prices[i]); + } + } + + public double getBill(int[] product, int[] amount) { + currCount++; + double totalBill = 0; + for (int i = 0; i < product.length; i++) { + totalBill += amount[i] * priceMap.get(product[i]); + } + if (currCount % n == 0) { + totalBill -= getDiscount(totalBill); + } + return totalBill; + } + + private double getDiscount(double totalBill) { + return (totalBill * discount) / 100; + } +} + +/** + * Your Cashier object will be instantiated and called as such: + * Cashier obj = new Cashier(n, discount, products, prices); + * double param_1 = obj.getBill(product,amount); + */ diff --git a/Medium/Apply Discount to Prices.java b/Medium/Apply Discount to Prices.java new file mode 100644 index 00000000..6c3974c9 --- /dev/null +++ b/Medium/Apply Discount to Prices.java @@ -0,0 +1,48 @@ +class Solution { + public String discountPrices(String sentence, int discount) { + StringBuilder sb = new StringBuilder(); + int idx = 0; + int n = sentence.length(); + while (idx < n) { + if (sentence.charAt(idx) == '$') { + if (idx == 0 || sentence.charAt(idx - 1) == ' ') { + sb.append(sentence.charAt(idx++)); + StringBuilder possibleDigit = new StringBuilder(); + boolean isDigit = true; + while (idx < n && sentence.charAt(idx) != ' ') { + if (!Character.isDigit(sentence.charAt(idx))) { + isDigit = false; + } + possibleDigit.append(sentence.charAt(idx++)); + } + if (possibleDigit.length() == 0) { + continue; + } + if (isDigit) { + long price = Long.parseLong(possibleDigit.toString()); + long updatedPrice = price * (100 - discount); + sb.append(getFormattedPrice(updatedPrice)); + } else { + sb.append(possibleDigit); + } + } else { + sb.append(sentence.charAt(idx++)); + } + } else { + sb.append(sentence.charAt(idx++)); + } + } + return sb.toString(); + } + + private String getFormattedPrice(long price) { + if (price < 10) { + return "0.0" + price; + } else if (price < 100) { + return "0." + price; + } else { + String priceString = String.valueOf(price); + return priceString.substring(0, priceString.length() - 2) + "." + priceString.substring(priceString.length() - 2); + } + } +} diff --git a/Medium/Apply Operations to Make String Empty.java b/Medium/Apply Operations to Make String Empty.java new file mode 100644 index 00000000..c378a060 --- /dev/null +++ b/Medium/Apply Operations to Make String Empty.java @@ -0,0 +1,18 @@ +class Solution { + public String lastNonEmptyString(String s) { + Map map = new HashMap<>(); + int maxFrequency = 0; + for (int i = 0; i < s.length(); i++) { + map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); + maxFrequency = Math.max(maxFrequency, map.get(s.charAt(i))); + } + StringBuilder result = new StringBuilder(); + for (int i = s.length() - 1; i >= 0; i--) { + if (map.get(s.charAt(i)) == maxFrequency) { + result.append(s.charAt(i)); + map.put(s.charAt(i), map.get(s.charAt(i)) - 1); + } + } + return result.reverse().toString(); + } +} diff --git a/Medium/Arithmetic Slices.java b/Medium/Arithmetic Slices.java index 4424c084..0b620a90 100644 --- a/Medium/Arithmetic Slices.java +++ b/Medium/Arithmetic Slices.java @@ -1,16 +1,13 @@ class Solution { - public int numberOfArithmeticSlices(int[] A) { - - int curr = 0, sum = 0; - for (int i=2; i checkArithmeticSubarrays(int[] nums, int[] l, int[] r) { + List queryResult = new ArrayList<>(); + for (int idx = 0; idx < l.length; idx++) { + queryResult.add(isArithmeticProgressionPossible(nums, l[idx], r[idx])); + } + return queryResult; + } + + private boolean isArithmeticProgressionPossible(int[] nums, int startIdx, int endIdx) { + List sequence = new ArrayList<>(); + for (int idx = startIdx; idx <= endIdx; idx++) { + sequence.add(nums[idx]); + } + Collections.sort(sequence); + Integer diff = sequence.get(1) - sequence.get(0); + for (int idx = 2; idx < sequence.size(); idx++) { + if (diff != (sequence.get(idx) - sequence.get(idx - 1))) { + return false; + } + } + return true; + } +} diff --git a/Medium/As Far from Land as Possible.java b/Medium/As Far from Land as Possible.java new file mode 100644 index 00000000..6e1ba29a --- /dev/null +++ b/Medium/As Far from Land as Possible.java @@ -0,0 +1,38 @@ +class Solution { + + private static final int[][] DIRS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; + + public int maxDistance(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + Queue queue = new LinkedList<>(); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + queue.add(new int[]{i, j}); + } + } + } + if (queue.isEmpty() || queue.size() == rows * cols) { + return -1; + } + int distance = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + for (int[] dir : DIRS) { + int x = removed[0] + dir[0]; + int y = removed[1] + dir[1]; + if (x < 0 || y < 0 || x >= rows || y >= cols || grid[x][y] == 1) { + continue; + } + grid[x][y] = 1; + queue.add(new int[]{x, y}); + } + } + distance++; + } + return distance - 1; + } +} diff --git a/Medium/Asteroid Collision.java b/Medium/Asteroid Collision.java index cfae942f..64a10bf3 100644 --- a/Medium/Asteroid Collision.java +++ b/Medium/Asteroid Collision.java @@ -1,46 +1,33 @@ class Solution { public int[] asteroidCollision(int[] asteroids) { - int[] ans; - int i = 0; - Stack stack = new Stack<>(); - - while (i < asteroids.length) { - if (stack.isEmpty()) { - stack.push(asteroids[i]); - } - else if (asteroids[i] < 0) { - if (stack.peek() > 0) { - int temp = stack.pop(); - if (temp > Math.abs(asteroids[i])) { - stack.push(temp); - } - else if (temp == Math.abs(asteroids[i])) { - i++; - continue; + List result = new ArrayList<>(); + int idx = 0; + while (idx < asteroids.length && asteroids[idx] < 0) { + result.add(asteroids[idx++]); + } + while (idx < asteroids.length) { + if (asteroids[idx] > 0) { + result.add(asteroids[idx++]); + } else { + if (result.isEmpty() || result.get(result.size() - 1) < 0) { + result.add(asteroids[idx]); + } else { + while (!result.isEmpty() && + result.get(result.size() - 1) > 0 && + result.get(result.size() - 1) < Math.abs(asteroids[idx])) { + result.remove(result.size() - 1); } - else { - continue; + if (!result.isEmpty() && result.get(result.size() - 1) > 0) { + if (result.get(result.size() - 1) == Math.abs(asteroids[idx])) { + result.remove(result.size() - 1); + } + } else { + result.add(asteroids[idx]); } } - else { - stack.push(asteroids[i]); - } - } - else { - stack.push(asteroids[i]); + idx++; } - - i++; - } - - ans = new int[stack.size()]; - i = stack.size()-1; - - while (i >= 0) { - ans[i] = stack.pop(); - i--; } - - return ans; + return result.stream().mapToInt(Integer::valueOf).toArray(); } } diff --git a/Medium/Average Waiting Time.java b/Medium/Average Waiting Time.java new file mode 100644 index 00000000..afba5388 --- /dev/null +++ b/Medium/Average Waiting Time.java @@ -0,0 +1,20 @@ +class Solution { + public double averageWaitingTime(int[][] customers) { + double totalWaitingTime = 0.0; + int lastFreeTime = 0; + for (int[] customer : customers) { + int arrivalTime = customer[0]; + // Wait time before chef finishes previous task + if (lastFreeTime > arrivalTime) { + totalWaitingTime += lastFreeTime - arrivalTime; + } else { + lastFreeTime = arrivalTime; + } + // Wait time to finish task for current customer + int taskTime = customer[1]; + totalWaitingTime += taskTime; + lastFreeTime += taskTime; + } + return totalWaitingTime / customers.length; + } +} diff --git a/Medium/Bag of Tokens.java b/Medium/Bag of Tokens.java new file mode 100644 index 00000000..1a409e0c --- /dev/null +++ b/Medium/Bag of Tokens.java @@ -0,0 +1,23 @@ +class Solution { + public int bagOfTokensScore(int[] tokens, int power) { + int score = 0; + int currScore = 0; + Arrays.sort(tokens); + int left = 0; + int right = tokens.length - 1; + while (left <= right) { + if (power >= tokens[left]) { + currScore++; + power -= tokens[left++]; + } else { + if (currScore == 0) { + break; + } + currScore--; + power += tokens[right--]; + } + score = Math.max(score, currScore); + } + return score; + } +} diff --git a/Medium/Balance a Binary Search Tree.java b/Medium/Balance a Binary Search Tree.java new file mode 100644 index 00000000..dd07996e --- /dev/null +++ b/Medium/Balance a Binary Search Tree.java @@ -0,0 +1,50 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode balanceBST(TreeNode root) { + List inorder = getInorderNodes(root); + return createBST(inorder, 0, inorder.size() - 1); + } + + private List getInorderNodes(TreeNode root) { + Stack stack = new Stack<>(); + while (root != null) { + stack.push(root); + root = root.left; + } + List list = new ArrayList<>(); + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + list.add(node.val); + TreeNode rightNode = node.right; + while (rightNode != null) { + stack.push(rightNode); + rightNode = rightNode.left; + } + } + return list; + } + + private TreeNode createBST(List list, int start, int end) { + if (start > end) { + return null; + } + int mid = (start + end) / 2; + TreeNode leftTree = createBST(list, start, mid - 1); + TreeNode rightTree = createBST(list, mid + 1, end); + return new TreeNode(list.get(mid), leftTree, rightTree); + } +} diff --git a/Medium/Basic Calculator II.java b/Medium/Basic Calculator II.java index 8343edef..dd97e966 100644 --- a/Medium/Basic Calculator II.java +++ b/Medium/Basic Calculator II.java @@ -1,39 +1,28 @@ class Solution { - public int calculate(String s) { - Stack stack = new Stack<>(); - int num = 0; - char sign = '+'; - - for (int i=0; i 0 && board[i-1][j] == 'X')continue; - if (j > 0 && board[i][j-1] == 'X')continue; - - count++; - } + + public int countBattleships(char[][] board) { + int count = 0; + int rows = board.length; + int cols = board[0].length; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (board[i][j] == '.' || (i > 0 && board[i - 1][j] == 'X') || (j > 0 && board[i][j - 1] == 'X')) { + continue; } - - return count; + count++; + } } + return count; + } } diff --git a/Medium/Best Time to Buy and Sell Stock II.java b/Medium/Best Time to Buy and Sell Stock II.java new file mode 100644 index 00000000..675762b3 --- /dev/null +++ b/Medium/Best Time to Buy and Sell Stock II.java @@ -0,0 +1,15 @@ +class Solution { + public int maxProfit(int[] prices) { + int stockBuyPrice = Integer.MAX_VALUE; + int profit = 0; + for (int i = 0; i < prices.length; i++) { + if (prices[i] > stockBuyPrice) { + profit += prices[i] - stockBuyPrice; + stockBuyPrice = prices[i]; + } else { + stockBuyPrice = prices[i]; + } + } + return profit; + } +} diff --git a/Medium/Best Time to Buy and Sell Stock with Cooldown.java b/Medium/Best Time to Buy and Sell Stock with Cooldown.java new file mode 100644 index 00000000..bb6693c2 --- /dev/null +++ b/Medium/Best Time to Buy and Sell Stock with Cooldown.java @@ -0,0 +1,39 @@ +class Solution { + int[] prices; + Integer[] buyCache; + Integer[] sellCache; + public int maxProfit(int[] prices) { + this.prices = prices; + this.buyCache = new Integer[prices.length]; + this.sellCache = new Integer[prices.length]; + return buy(0); + } + + private int buy(int idx) { + if (idx >= prices.length) { + return 0; + } + if (buyCache[idx] != null) { + return buyCache[idx]; + } + int cost = -prices[idx]; + int bestProfitBuying = sell(idx + 1) + cost; + int bestProfitNotBuying = buy(idx + 1); + buyCache[idx] = Math.max(bestProfitBuying, bestProfitNotBuying); + return buyCache[idx]; + } + + private int sell(int idx) { + if (idx == prices.length) { + return 0; + } + if (sellCache[idx] != null) { + return sellCache[idx]; + } + int price = prices[idx]; + int bestProftSelling = buy(idx + 2) + price; + int bestProfitNotSelling = sell(idx + 1); + sellCache[idx] = Math.max(bestProftSelling, bestProfitNotSelling); + return sellCache[idx]; + } +} diff --git a/Medium/Best Time to Buy and Sell Stock with Transaction Fee.java b/Medium/Best Time to Buy and Sell Stock with Transaction Fee.java new file mode 100644 index 00000000..1251e8d0 --- /dev/null +++ b/Medium/Best Time to Buy and Sell Stock with Transaction Fee.java @@ -0,0 +1,13 @@ +class Solution { + public int maxProfit(int[] prices, int fee) { + int n = prices.length; + int[] notHolding = new int[n]; + int[] holding = new int[n]; + holding[0] = -prices[0]; + for (int i = 1; i < n; i++) { + holding[i] = Math.max(holding[i - 1], notHolding[i - 1] - prices[i]); + notHolding[i] = Math.max(notHolding[i - 1], holding[i - 1] + prices[i] - fee); + } + return notHolding[n - 1]; + } +} diff --git a/Medium/Binary Search Tree Iterator II.java b/Medium/Binary Search Tree Iterator II.java new file mode 100644 index 00000000..61ab1d10 --- /dev/null +++ b/Medium/Binary Search Tree Iterator II.java @@ -0,0 +1,67 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class BSTIterator { + + private final Deque primary; + private final List secondary; + private int index; + + public BSTIterator(TreeNode root) { + this.primary = new ArrayDeque<>(); + this.secondary = new ArrayList<>(); + this.index = -1; + traverse(root); + } + + public boolean hasNext() { + return !primary.isEmpty() || index < secondary.size() - 1; + } + + public int next() { + index++; + if (index == secondary.size()) { + TreeNode curr = primary.pop(); + secondary.add(curr.val); + traverse(curr.right); + } + return secondary.get(index); + } + + public boolean hasPrev() { + return index > 0; + } + + public int prev() { + index--; + return secondary.get(index); + } + + private void traverse(TreeNode root) { + while (root != null) { + primary.push(root); + root = root.left; + } + } +} + +/** + * Your BSTIterator object will be instantiated and called as such: + * BSTIterator obj = new BSTIterator(root); + * boolean param_1 = obj.hasNext(); + * int param_2 = obj.next(); + * boolean param_3 = obj.hasPrev(); + * int param_4 = obj.prev(); + */ diff --git a/Medium/Binary Search Tree Iterator.java b/Medium/Binary Search Tree Iterator.java index 7dcce82e..01b26971 100644 --- a/Medium/Binary Search Tree Iterator.java +++ b/Medium/Binary Search Tree Iterator.java @@ -1,43 +1,48 @@ /** - * Definition for binary tree + * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ +class BSTIterator { + + private Stack stack; + + public BSTIterator(TreeNode root) { + this.stack = new Stack<>(); + updateStack(root); + } -public class BSTIterator { - Stack stack; - public BSTIterator(TreeNode root) { - stack = new Stack<>(); - pushLeft(root); - } - - private void pushLeft(TreeNode root) { - while(root != null) { - stack.push(root); - root = root.left; - } - } - - /** @return whether we have a next smallest number */ - public boolean hasNext() { - return !stack.isEmpty(); - } + public int next() { + TreeNode node = this.stack.pop(); + updateStack(node.right); + return node.val; + } - /** @return the next smallest number */ - public int next() { - TreeNode node = stack.pop(); - pushLeft(node.right); - - return node.val; + public boolean hasNext() { + return !this.stack.isEmpty(); + } + + private void updateStack(TreeNode node) { + while (node != null) { + this.stack.push(node); + node = node.left; } + } } /** - * Your BSTIterator will be called like this: - * BSTIterator i = new BSTIterator(root); - * while (i.hasNext()) v[f()] = i.next(); + * Your BSTIterator object will be instantiated and called as such: + * BSTIterator obj = new BSTIterator(root); + * int param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); */ diff --git a/Medium/Binary Search Tree to Greater Sum Tree.java b/Medium/Binary Search Tree to Greater Sum Tree.java index af760c96..912e0699 100644 --- a/Medium/Binary Search Tree to Greater Sum Tree.java +++ b/Medium/Binary Search Tree to Greater Sum Tree.java @@ -4,23 +4,30 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode bstToGst(TreeNode root) { - inorderReverse(root, new int[]{0}); - return root; - } - - private void inorderReverse(TreeNode root, int[] currVal) { - if (root == null) { - return; - } - - inorderReverse(root.right, currVal); - currVal[0] += root.val; - root.val = currVal[0]; - inorderReverse(root.left, currVal); + public TreeNode bstToGst(TreeNode root) { + int sum = 0; + TreeNode node = root; + Stack stack = new Stack<>(); + while (!stack.isEmpty() || node != null) { + while (node != null) { + stack.add(node); + node = node.right; + } + node = stack.pop(); + sum += node.val; + node.val = sum; + node = node.left; } + return root; + } } diff --git a/Medium/Binary Tree Coloring Game.java b/Medium/Binary Tree Coloring Game.java new file mode 100644 index 00000000..77a4d9e2 --- /dev/null +++ b/Medium/Binary Tree Coloring Game.java @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + int leftCount; + int rightCount; + public boolean btreeGameWinningMove(TreeNode root, int n, int x) { + leftCount = 0; + rightCount = 0; + countNodes(root, x); + return Math.max(Math.max(leftCount, rightCount), n - leftCount - rightCount - 1) > n / 2; + } + + private int countNodes(TreeNode root, int x) { + if (root == null) { + return 0; + } + int l = countNodes(root.left, x); + int r = countNodes(root.right, x); + if (root.val == x) { + leftCount = l; + rightCount = r; + } + return l + r + 1; + } +} diff --git a/Medium/Binary Tree Inorder Traversal.java b/Medium/Binary Tree Inorder Traversal.java deleted file mode 100644 index d071d5e0..00000000 --- a/Medium/Binary Tree Inorder Traversal.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - public List inorderTraversal(TreeNode root) { - Stack s = new Stack<>(); - ArrayList arr = new ArrayList<>(); - - TreeNode curr = root; - - while(curr != null) { - s.push(curr); - curr = curr.left; - } - - while(s.size() > 0) { - curr = s.pop(); - arr.add(curr.val); - - if (curr.right != null) { - curr = curr.right; - - while(curr != null) { - s.push(curr); - curr = curr.left; - } - } - } - - return arr; - } -} diff --git a/Medium/Binary Tree Level Order Traversal.java b/Medium/Binary Tree Level Order Traversal.java new file mode 100644 index 00000000..84664d71 --- /dev/null +++ b/Medium/Binary Tree Level Order Traversal.java @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List> levelOrder(TreeNode root) { + if (root == null) { + return new ArrayList<>(); + } + Queue queue = new LinkedList<>(); + List> result = new ArrayList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + List currLevel = new ArrayList<>(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + currLevel.add(removed.val); + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + result.add(currLevel); + } + return result; + } +} diff --git a/Medium/Binary Tree Longest Consecutive Sequence II.java b/Medium/Binary Tree Longest Consecutive Sequence II.java index db766780..41e04cba 100644 --- a/Medium/Binary Tree Longest Consecutive Sequence II.java +++ b/Medium/Binary Tree Longest Consecutive Sequence II.java @@ -4,46 +4,45 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int longestConsecutive(TreeNode root) { - int[] ans = new int[1]; - helper(root, ans); - return ans[0]; + public int longestConsecutive(TreeNode root) { + int[] result = {0}; + helper(root, result); + return result[0]; + } + + private int[] helper(TreeNode root, int[] result) { + if (root == null) { + return new int[]{0, 0}; } - - private int[] helper(TreeNode root, int[] ans) { - if (root == null) { - return new int[]{0,0}; - } - - int increase = 1; - int decrease = 1; - - if (root.left != null) { - int[] left = helper(root.left, ans); - if (root.val == root.left.val - 1) { - increase = left[0] + 1; - } - if (root.val == root.left.val + 1) { - decrease = left[1] + 1; - } - } - - if (root.right != null) { - int[] right = helper(root.right, ans); - if (root.val == root.right.val - 1) { - increase = Math.max(right[0] + 1, increase); - } - if (root.val == root.right.val + 1) { - decrease = Math.max(right[1] + 1, decrease); - } - } - - ans[0] = Math.max(ans[0], increase + decrease - 1); - - return new int[]{increase, decrease}; + int increment = 1; + int decrement = 1; + if (root.left != null) { + int[] left = helper(root.left, result); + if (root.val == root.left.val + 1) { + decrement = left[1] + 1; + } else if (root.val == root.left.val - 1) { + increment = left[0] + 1; + } } + if (root.right != null) { + int[] right = helper(root.right, result); + if (root.val == root.right.val + 1) { + decrement = Math.max(decrement, right[1] + 1); + } else if (root.val == root.right.val - 1) { + increment = Math.max(increment, right[0] + 1); + } + } + result[0] = Math.max(result[0], increment + decrement - 1); + return new int[]{increment, decrement}; + } } diff --git a/Medium/Binary Tree Longest Consecutive Sequence.java b/Medium/Binary Tree Longest Consecutive Sequence.java index b5f278aa..92a3e1b4 100644 --- a/Medium/Binary Tree Longest Consecutive Sequence.java +++ b/Medium/Binary Tree Longest Consecutive Sequence.java @@ -4,37 +4,44 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int longestConsecutive(TreeNode root) { - if (root == null) { - return 0; - } - - int[] ans = {1}; - helper(root, ans, null, 1); - - return ans[0]; + public int longestConsecutive(TreeNode root) { + int maxLength = 0; + Queue queue = new LinkedList<>(); + queue.add(new NodePair(root, 1)); + while (!queue.isEmpty()) { + NodePair removed = queue.remove(); + maxLength = Math.max(maxLength, removed.currLength); + if (removed.node.left != null) { + int sequenceLength = (removed.node.left.val == removed.node.val + 1 + ? removed.currLength + 1 : 1); + queue.add(new NodePair(removed.node.left, sequenceLength)); + } + if (removed.node.right != null) { + int sequenceLength = (removed.node.right.val == removed.node.val + 1 + ? removed.currLength + 1 : 1); + queue.add(new NodePair(removed.node.right, sequenceLength)); + } } + return maxLength; + } + + private class NodePair { + TreeNode node; + int currLength; - private void helper(TreeNode root, int[] ans, TreeNode parent, int count) { - if (root == null) { - return; - } - - if (parent != null) { - if (root.val == parent.val + 1) { - count++; - ans[0] = Math.max(ans[0], count); - } - else { - count = 1; - } - } - - helper(root.left, ans, root, count); - helper(root.right, ans, root, count); + public NodePair(TreeNode node, int currLength) { + this.node = node; + this.currLength = currLength; } + } } diff --git a/Medium/Binary Tree Preorder Traversal.java b/Medium/Binary Tree Preorder Traversal.java index e2f64ac4..61765340 100644 --- a/Medium/Binary Tree Preorder Traversal.java +++ b/Medium/Binary Tree Preorder Traversal.java @@ -4,31 +4,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public List preorderTraversal(TreeNode root) { - ArrayList ans = new ArrayList<>(); if (root == null) { - return ans; + return List.of(); } - Stack s = new Stack<>(); - - s.push(root); - - while(s.size() > 0) { - TreeNode curr = s.pop(); - ans.add(curr.val); - if(curr.right != null) { - s.push(curr.right); + Stack stack = new Stack<>(); + stack.push(root); + List result = new ArrayList<>(); + while (!stack.isEmpty()) { + TreeNode removed = stack.pop(); + result.add(removed.val); + if (removed.right != null) { + stack.push(removed.right); } - - if(curr.left != null) { - s.push(curr.left); + if (removed.left != null) { + stack.push(removed.left); } } - - return ans; + return result; } } diff --git a/Medium/Binary Tree Pruning.java b/Medium/Binary Tree Pruning.java index 8bcf8f80..9269db06 100644 --- a/Medium/Binary Tree Pruning.java +++ b/Medium/Binary Tree Pruning.java @@ -4,32 +4,32 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode pruneTree(TreeNode root) { - return checker(root); + public TreeNode pruneTree(TreeNode root) { + return subtreeContainsOne(root) ? root : null; + } + + private boolean subtreeContainsOne(TreeNode root) { + if (root == null) { + return false; } - -// A checker method which checks every node and makes it null if it doesn't contain a 1 - public TreeNode checker(TreeNode root) { - if (!checkForOnes(root)) { - root = null; - return root; - } - - root.left = checker(root.left); - root.right = checker(root.right); - - return root; + boolean leftContains = subtreeContainsOne(root.left); + boolean rightContains = subtreeContainsOne(root.right); + if (!leftContains) { + root.left = null; } - -// Checks for a 1 in the node - public boolean checkForOnes(TreeNode root) { - if (root == null) return false; - if (root.val == 1) return true; - - return checkForOnes(root.left) || checkForOnes(root.right); + if (!rightContains) { + root.right = null; } + return leftContains || rightContains || root.val == 1; + } } diff --git a/Medium/Binary Tree Right Side View.java b/Medium/Binary Tree Right Side View.java index 47330c6f..6aa6e40b 100644 --- a/Medium/Binary Tree Right Side View.java +++ b/Medium/Binary Tree Right Side View.java @@ -4,41 +4,38 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - List list; - public List rightSideView(TreeNode root) { - list = new ArrayList<>(); - if (root == null) { - return list; - } - - helper(root); - return list; + public List rightSideView(TreeNode root) { + if (root == null) { + return new ArrayList<>(); } - - private void helper(TreeNode root) { - Queue queue = new LinkedList<>(); - queue.add(root); - - while (!queue.isEmpty()) { - int size = queue.size(); - - for (int i=1; i<=size; i++) { - TreeNode popped = queue.remove(); - if (popped.left != null) { - queue.add(popped.left); - } - if (popped.right != null) { - queue.add(popped.right); - } - - if (i == size) { - list.add(popped.val); - } - } + List result = new ArrayList<>(); + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + int rightMostValue = -1; + while (size-- > 0) { + TreeNode removed = queue.remove(); + rightMostValue = removed.val; + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); } + } + result.add(rightMostValue); } + return result; + } } diff --git a/Medium/Binary Tree Upside Down.java b/Medium/Binary Tree Upside Down.java index dde329cc..b93f1b75 100644 --- a/Medium/Binary Tree Upside Down.java +++ b/Medium/Binary Tree Upside Down.java @@ -4,35 +4,35 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode upsideDownBinaryTree(TreeNode root) { - if (root == null || root.left == null) { - return root; - } - - TreeNode left = root.left; - TreeNode right = root.right; - - root.left = null; - root.right = null; - - return helper(left, root, right); + public TreeNode upsideDownBinaryTree(TreeNode root) { + if (root == null || root.left == null) { + return root; } - - private TreeNode helper(TreeNode rootLeft, TreeNode root, TreeNode rootRight) { - if (rootLeft == null) { - return root; - } - - TreeNode rootLeftLeft = rootLeft.left; - TreeNode rootLeftRight = rootLeft.right; - - rootLeft.left = rootRight; - rootLeft.right = root; - - return helper(rootLeftLeft, rootLeft, rootLeftRight); + TreeNode rightNode = root.right; + TreeNode leftNode = root.left; + root.left = null; + root.right = null; + return helper(root, leftNode, rightNode); + } + + private TreeNode helper(TreeNode root, TreeNode leftNode, TreeNode rightNode) { + if (leftNode == null) { + return root; } + TreeNode leftNodeLeft = leftNode.left; + TreeNode leftNodeRight = leftNode.right; + leftNode.left = rightNode; + leftNode.right = root; + return helper(leftNode, leftNodeLeft, leftNodeRight); + } } diff --git a/Medium/Binary Tree Vertical Order Traversal.java b/Medium/Binary Tree Vertical Order Traversal.java index bab9f0fc..5d0e954f 100644 --- a/Medium/Binary Tree Vertical Order Traversal.java +++ b/Medium/Binary Tree Vertical Order Traversal.java @@ -4,62 +4,47 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - Map> map = new TreeMap<>(); - public List> verticalOrder(TreeNode root) { - List> ans = new ArrayList<>(); - updateMap(root, 0); - - for (int key : map.keySet()) { - ans.add(map.get(key)); - } - - return ans; + public List> verticalOrder(TreeNode root) { + if (root == null) { + return new ArrayList<>(); } - - private void updateMap(TreeNode root, int level) { - if (root == null) { - return; + Map> map = new TreeMap<>(); + Queue queue = new LinkedList<>(); + queue.add(new TreeLevel(root, 0)); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeLevel removed = queue.remove(); + map.computeIfAbsent(removed.level, k -> new ArrayList<>()).add(removed.node.val); + if (removed.node.left != null) { + queue.add(new TreeLevel(removed.node.left, removed.level - 1)); } - - Queue queue = new LinkedList<>(); - queue.add(new Element(root, 0)); - - while (!queue.isEmpty()) { - int size = queue.size(); - - while (size-- > 0) { - Element temp = queue.remove(); - if (map.containsKey(temp.level)) { - map.get(temp.level).add(temp.node.val); - } - else { - List list = new ArrayList<>(); - list.add(temp.node.val); - map.put(temp.level, list); - } - - if (temp.node.left != null) { - queue.add(new Element(temp.node.left, temp.level-1)); - } - - if (temp.node.right != null) { - queue.add(new Element(temp.node.right, temp.level+1)); - } - } + if (removed.node.right != null) { + queue.add(new TreeLevel(removed.node.right, removed.level + 1)); } + } } -} + return new ArrayList<>(map.values()); + } + -class Element { - public TreeNode node; - public int level; + private class TreeLevel { + TreeNode node; + int level; - public Element(TreeNode node, int level) { - this.node = node; - this.level = level; + public TreeLevel(TreeNode node, int level) { + this.node = node; + this.level = level; } + } } diff --git a/Medium/Binary Tree Zigzag Level Order Traversal.java b/Medium/Binary Tree Zigzag Level Order Traversal.java new file mode 100644 index 00000000..94f520ad --- /dev/null +++ b/Medium/Binary Tree Zigzag Level Order Traversal.java @@ -0,0 +1,46 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List> zigzagLevelOrder(TreeNode root) { + List> ans = new ArrayList<>(); + if (root == null) { + return ans; + } + Queue queue = new LinkedList<>(); + boolean leftToRight = true; + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + List temp = new ArrayList<>(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + temp.add(removed.val); + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + if (!leftToRight) { + Collections.reverse(temp); + } + ans.add(temp); + leftToRight = !leftToRight; + } + return ans; + } +} diff --git a/Medium/Binary Trees With Factors.java b/Medium/Binary Trees With Factors.java new file mode 100644 index 00000000..be7e38be --- /dev/null +++ b/Medium/Binary Trees With Factors.java @@ -0,0 +1,29 @@ +class Solution { + private final int MOD = 1_000_000_007; + + public int numFactoredBinaryTrees(int[] arr) { + int n = arr.length; + Arrays.sort(arr); + long[] dp = new long[n]; + Arrays.fill(dp, 1); + Map indexMap = new HashMap<>(); + for (int i = 0; i < n; i++) { + indexMap.put(arr[i], i); + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < i; j++) { + if (arr[i] % arr[j] == 0) { + int right = arr[i] / arr[j]; + if (indexMap.containsKey(right)) { + dp[i] = (dp[i] + dp[j] * dp[indexMap.get(right)]) % MOD; + } + } + } + } + long result = 0; + for (long count : dp) { + result += count; + } + return (int) (result % MOD); + } +} diff --git a/Medium/Bitwise AND of Numbers Range.java b/Medium/Bitwise AND of Numbers Range.java index a5823908..c0645dd1 100644 --- a/Medium/Bitwise AND of Numbers Range.java +++ b/Medium/Bitwise AND of Numbers Range.java @@ -1,34 +1,8 @@ class Solution { - public int rangeBitwiseAnd(int m, int n) { - int temp1 = m; - int temp2 = n; - - int cnt1 = 0; - int cnt2 = 0; - - while (temp1 > 1 || temp2 > 1) { - if (temp1 > 1) { - temp1 /= 2; - cnt1++; - } - - if (temp2 > 1) { - temp2 /= 2; - cnt2++; - } - } - - if (cnt1 != cnt2) { - return 0; - } - - int res = ~0; - for (int i=m;i left) { + right = right & (right - 1); } + return left & right; + } } diff --git a/Medium/Bitwise XOR of All Pairings.java b/Medium/Bitwise XOR of All Pairings.java new file mode 100644 index 00000000..88dfbd41 --- /dev/null +++ b/Medium/Bitwise XOR of All Pairings.java @@ -0,0 +1,20 @@ +class Solution { + public int xorAllNums(int[] nums1, int[] nums2) { + int m = nums1.length; + int n = nums2.length; + Map freq = new HashMap<>(); + for (int num : nums1) { + freq.put(num, freq.getOrDefault(num, 0) + n); + } + for (int num : nums2) { + freq.put(num, freq.getOrDefault(num, 0) + m); + } + int result = 0; + for (Integer key : freq.keySet()) { + if (freq.get(key) % 2 == 1) { + result ^= key; + } + } + return result; + } +} diff --git a/Medium/Boats to Save People.java b/Medium/Boats to Save People.java index 167a9e4d..dab79035 100644 --- a/Medium/Boats to Save People.java +++ b/Medium/Boats to Save People.java @@ -1,19 +1,16 @@ class Solution { public int numRescueBoats(int[] people, int limit) { Arrays.sort(people); + int left = 0; + int right = people.length - 1; int count = 0; - int start = 0; - int end = people.length-1; - - while (end >= start) { - if (people[start] + people[end] <= limit) { - start++; + while (left <= right) { + int capacity = people[right--]; + if (left <= right && capacity + people[left] <= limit) { + left++; } - - end--; count++; - } - + } return count; } } diff --git a/Medium/Bold Words in String.java b/Medium/Bold Words in String.java new file mode 100644 index 00000000..3e19c0a0 --- /dev/null +++ b/Medium/Bold Words in String.java @@ -0,0 +1,44 @@ +class Solution { + public String boldWords(String[] words, String s) { + List indexes = new ArrayList<>(); + for (String word : words) { + indexes.addAll(getIndexPair(s, word)); + } + Collections.sort(indexes, + Comparator.comparingInt((int[] o) -> o[0]).thenComparingInt(o -> o[1])); + Set startIdx = new HashSet<>(); + Set endIdx = new HashSet<>(); + int idx = 0; + while (idx < indexes.size()) { + int currStart = indexes.get(idx)[0]; + int currEnd = indexes.get(idx)[1]; + idx++; + while (idx < indexes.size() && indexes.get(idx)[0] <= currEnd + 1) { + currEnd = Math.max(currEnd, indexes.get(idx++)[1]); + } + startIdx.add(currStart); + endIdx.add(currEnd); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + if (startIdx.contains(i)) { + sb.append(""); + } + sb.append(s.charAt(i)); + if (endIdx.contains(i)) { + sb.append(""); + } + } + return sb.toString(); + } + + private List getIndexPair(String s, String word) { + List indexPairs = new ArrayList<>(); + for (int i = 0; i < s.length() - word.length() + 1; i++) { + if (s.startsWith(word, i)) { + indexPairs.add(new int[]{i, i + word.length() - 1}); + } + } + return indexPairs; + } +} diff --git a/Medium/Bomb Enemy.java b/Medium/Bomb Enemy.java new file mode 100644 index 00000000..c6259b7a --- /dev/null +++ b/Medium/Bomb Enemy.java @@ -0,0 +1,42 @@ +class Solution { + public int maxKilledEnemies(char[][] grid) { + if (grid.length == 0) { + return 0; + } + int rows = grid.length; + int cols = grid[0].length; + int maxCount = 0; + int rowHits = 0; + int[] colHits = new int[cols]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (j == 0 || grid[i][j - 1] == 'W') { + rowHits = 0; + for (int k = j; k < cols; k++) { + if (grid[i][k] == 'W') { + break; + } + if (grid[i][k] == 'E') { + rowHits++; + } + } + } + if (i == 0 || grid[i - 1][j] == 'W') { + colHits[j] = 0; + for (int k = i; k < rows; k++) { + if (grid[k][j] == 'W') { + break; + } + if (grid[k][j] == 'E') { + colHits[j]++; + } + } + } + if (grid[i][j] == '0') { + maxCount = Math.max(maxCount, rowHits + colHits[j]); + } + } + } + return maxCount; + } +} diff --git a/Medium/Boundary of Binary Tree.java b/Medium/Boundary of Binary Tree.java index 140f5c25..a6e26f56 100644 --- a/Medium/Boundary of Binary Tree.java +++ b/Medium/Boundary of Binary Tree.java @@ -4,62 +4,75 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - List list; - int backIdx; - public List boundaryOfBinaryTree(TreeNode root) { - list = new ArrayList<>(); - backIdx = 0; - - if (root == null) { - return list; - } - - list.add(root.val); - - addLeft(root.left); - addLeaves(root.left); - addLeaves(root.right); - addRight(root.right); - - return list; + public List boundaryOfBinaryTree(TreeNode root) { + List result = new ArrayList<>(); + if (!isLeaf(root)) { + result.add(root.val); } - - private void addLeft(TreeNode node) { - if (node == null || (node.left == null && node.right == null)) { - return; - } - - list.add(node.val); - - addLeft(node.left == null ? node.right : node.left); + if (root.left != null) { + addLeft(result, root.left); } - - private void addRight(TreeNode node) { - if (node == null || (node.right == null && node.left == null)) { - return; - } - - list.add(list.size() - backIdx, node.val); - backIdx++; - - addRight(node.right == null ? node.left : node.right); + addLeaves(result, root); + if (root.right != null) { + addRight(result, root.right); } - - private void addLeaves(TreeNode node) { - if (node == null) { - return; - } - - if (node.left == null && node.right == null) { - list.add(node.val); - return; - } - - addLeaves(node.left); - addLeaves(node.right); + return result; + } + + private void addRight(List result, TreeNode node) { + Stack stack = new Stack<>(); + while (node != null) { + if (!isLeaf(node)) { + stack.push(node.val); + } + if (node.right != null) { + node = node.right; + } else { + node = node.left; + } } + while (!stack.isEmpty()) { + result.add(stack.pop()); + } + } + + private void addLeft(List result, TreeNode node) { + while (node != null) { + if (!isLeaf(node)) { + result.add(node.val); + } + if (node.left != null) { + node = node.left; + } else { + node = node.right; + } + } + } + + private void addLeaves(List result, TreeNode root) { + if (isLeaf(root)) { + result.add(root.val); + } else { + if (root.left != null) { + addLeaves(result, root.left); + } + if (root.right != null) { + addLeaves(result, root.right); + } + } + } + + private boolean isLeaf(TreeNode node) { + return node.left == null && node.right == null; + } } diff --git a/Medium/Brace Expansion.java b/Medium/Brace Expansion.java new file mode 100644 index 00000000..38f0d5a4 --- /dev/null +++ b/Medium/Brace Expansion.java @@ -0,0 +1,47 @@ +class Solution { + public String[] expand(String s) { + List> splits = parseInput(s); + List result = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + helper(splits, result, sb, 0); + Collections.sort(result); + String[] answer = new String[result.size()]; + for (int i = 0; i < result.size(); i++) { + answer[i] = result.get(i); + } + return answer; + } + + private void helper(List> splits, List result, StringBuilder sb, int idx) { + if (idx >= splits.size()) { + if (sb.length() == splits.size()) { + result.add(new StringBuilder(sb.toString()).toString()); + } + } else { + for (int i = idx; i < splits.size(); i++) { + List currentSplit = splits.get(i); + for (String section : currentSplit) { + sb.append(section); + helper(splits, result, sb, i + 1); + sb.deleteCharAt(sb.length() - 1); + } + } + } + } + + private List> parseInput(String s) { + List> splits = new ArrayList<>(); + int idx = 0; + while (idx < s.length()) { + if (s.charAt(idx) == '{') { + int endIdx = s.indexOf('}', idx); + String[] segements = s.substring(idx + 1, endIdx).split(","); + splits.add(Arrays.asList(segements)); + idx = endIdx + 1; + } else { + splits.add(List.of(String.valueOf(s.charAt(idx++)))); + } + } + return splits; + } +} diff --git a/Medium/Break a Palindrome.java b/Medium/Break a Palindrome.java new file mode 100644 index 00000000..3da29e2e --- /dev/null +++ b/Medium/Break a Palindrome.java @@ -0,0 +1,14 @@ +class Solution { + public String breakPalindrome(String palindrome) { + if (palindrome.length() == 1) { + return ""; + } + for (int i = 0; i < palindrome.length(); i++) { + if (palindrome.charAt(i) != 'a' && + (palindrome.length() % 2 == 0 || i != palindrome.length() / 2)) { + return palindrome.substring(0, i) + "a" + palindrome.substring(i + 1); + } + } + return palindrome.substring(0, palindrome.length() - 1) + "b"; + } +} diff --git a/Medium/Broken Calculator.java b/Medium/Broken Calculator.java index 9b89d8c0..ea40c3e7 100644 --- a/Medium/Broken Calculator.java +++ b/Medium/Broken Calculator.java @@ -1,18 +1,14 @@ class Solution { - public int brokenCalc(int X, int Y) { - int count = 0; - - while (Y > X) { - if (Y % 2 == 0) { - Y = Y / 2; - } - else { - Y++; - } - - count++; - } - - return count + X - Y; + public int brokenCalc(int startValue, int target) { + int numOfSteps = 0; + while (target > startValue) { + numOfSteps++; + if (target % 2 == 1) { + target++; + } else { + target /= 2; + } } + return numOfSteps + startValue - target; + } } diff --git a/Medium/Build an Array With Stack Operations.java b/Medium/Build an Array With Stack Operations.java new file mode 100644 index 00000000..f36177cd --- /dev/null +++ b/Medium/Build an Array With Stack Operations.java @@ -0,0 +1,23 @@ +class Solution { + + private static final String PUSH = "Push"; + private static final String POP = "Pop"; + + public List buildArray(int[] target, int n) { + int idx = 0; + List result = new ArrayList<>(); + for (int i = 1; i <= n; i++) { + if (target[idx] == i) { + idx++; + result.add(PUSH); + } else { + result.add(PUSH); + result.add(POP); + } + if (idx == target.length) { + break; + } + } + return result; + } +} diff --git a/Medium/Buildings With an Ocean View.java b/Medium/Buildings With an Ocean View.java new file mode 100644 index 00000000..6d52576e --- /dev/null +++ b/Medium/Buildings With an Ocean View.java @@ -0,0 +1,18 @@ +class Solution { + public int[] findBuildings(int[] heights) { + List result = new ArrayList<>(); + int maxHeight = -1; + for (int i = heights.length - 1; i >= 0; i--) { + if (heights[i] > maxHeight) { + result.add(i); + } + maxHeight = Math.max(maxHeight, heights[i]); + } + int[] ans = new int[result.size()]; + Collections.reverse(result); + for (int i = 0; i < result.size(); i++) { + ans[i] = result.get(i); + } + return ans; + } +} diff --git a/Medium/Bulb Switcher.java b/Medium/Bulb Switcher.java index 1d9b580e..fe756a18 100644 --- a/Medium/Bulb Switcher.java +++ b/Medium/Bulb Switcher.java @@ -1,5 +1,5 @@ class Solution { - public int bulbSwitch(int n) { - return (int)Math.sqrt(n); - } + public int bulbSwitch(int n) { + return (int) Math.sqrt(n); + } } diff --git a/Medium/Bulls and Cows.java b/Medium/Bulls and Cows.java deleted file mode 100644 index 733ab621..00000000 --- a/Medium/Bulls and Cows.java +++ /dev/null @@ -1,36 +0,0 @@ -class Solution { - public String getHint(String secret, String guess) { - char[] secretChar = secret.toCharArray(); - char[] guessChar = guess.toCharArray(); - - int[] secCount = new int[10]; - int[] guessCount = new int[10]; - - for (int c : secretChar) { - secCount[c - '0']++; - } - - for (int c : guessChar) { - guessCount[c - '0']++; - } - - int sames = 0; - for (int i=0; i executed = new HashSet<>(); + while (idx < n && idx >= 0) { + if (!executed.add(idx)) { + break; + } + if (instructions[idx].equals("add")) { + result += values[idx++]; + } else { + idx += values[idx]; + } + } + return result; + } +} diff --git a/Medium/Camelcase Matching.java b/Medium/Camelcase Matching.java new file mode 100644 index 00000000..034db73d --- /dev/null +++ b/Medium/Camelcase Matching.java @@ -0,0 +1,34 @@ +class Solution { + public List camelMatch(String[] queries, String pattern) { + List list = new ArrayList<>(); + for (String query : queries) { + list.add(isMatch(query, pattern)); + } + return list; + } + + private boolean isMatch(String query, String pattern) { + int idxQuery = 0; + int idxPattern = 0; + int lenQuery = query.length(); + int lenPattern = pattern.length(); + while (idxQuery < lenQuery && idxPattern < lenPattern) { + char queryC = query.charAt(idxQuery); + char patternC = pattern.charAt(idxPattern); + if (queryC == patternC) { + idxQuery++; + idxPattern++; + } + else if (Character.isUpperCase(queryC)) { + return false; + } + else { + idxQuery++; + } + } + while (idxQuery < lenQuery && Character.isLowerCase(query.charAt(idxQuery))) { + idxQuery++; + } + return idxPattern == lenPattern && idxQuery == lenQuery; + } +} diff --git a/Medium/Campus Bikes II.java b/Medium/Campus Bikes II.java new file mode 100644 index 00000000..692725d0 --- /dev/null +++ b/Medium/Campus Bikes II.java @@ -0,0 +1,28 @@ +class Solution { + public int assignBikes(int[][] workers, int[][] bikes) { + Integer[] dp = new Integer[1024]; + return minDistance(workers, bikes, 0, 0, dp); + } + + private int minDistance(int[][] workers, int[][] bikes, int workerIdx, int mask, Integer[] dp) { + if (workerIdx >= workers.length) { + return 0; + } + if (dp[mask] != null) { + return dp[mask]; + } + int distance = Integer.MAX_VALUE; + for (int i = 0; i < bikes.length; i++) { + // if bike is available + if ((mask & (1 << i)) == 0) { + // assign the bike & traverse for remaining bikes + distance = Math.min(distance, calculateManhattanDistance(workers[workerIdx], bikes[i]) + minDistance(workers, bikes, workerIdx + 1, mask | (1 << i), dp)); + } + } + return dp[mask] = distance; + } + + private static int calculateManhattanDistance(int[] worker, int[] bike) { + return Math.abs(worker[0] - bike[0]) + Math.abs(worker[1] - bike[1]); + } +} diff --git a/Medium/Campus Bikes.java b/Medium/Campus Bikes.java new file mode 100644 index 00000000..129f4fbc --- /dev/null +++ b/Medium/Campus Bikes.java @@ -0,0 +1,39 @@ +class Solution { + public int[] assignBikes(int[][] workers, int[][] bikes) { + int workerCount = workers.length; + int bikeCount = bikes.length; + PriorityQueue priorityQueue = new PriorityQueue<>(); + for (int i = 0; i < workerCount; i++) { + for (int j = 0; j < bikeCount; j++) { + priorityQueue.add(new WorkerBikePair(manhattanDistance(workers[i], bikes[j]), i, j)); + } + } + Set bikeDone = new HashSet<>(); + int[] result = new int[workerCount]; + Arrays.fill(result, Integer.MIN_VALUE); + while (!priorityQueue.isEmpty()) { + WorkerBikePair removed = priorityQueue.remove(); + if (result[removed.workerIdx] == Integer.MIN_VALUE && !bikeDone.contains(removed.bikeIdx)) { + result[removed.workerIdx] = removed.bikeIdx; + bikeDone.add(removed.bikeIdx); + } + } + return result; + } + + private record WorkerBikePair(int manhattanDistance, int workerIdx, int bikeIdx) implements Comparable { + @Override + public int compareTo(WorkerBikePair o) { + int c = manhattanDistance - o.manhattanDistance; + if (c != 0) { + return c; + } + c = workerIdx - o.workerIdx; + return c != 0 ? c : bikeIdx - o.bikeIdx; + } + } + + private static int manhattanDistance(int[] p1, int[] p2) { + return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]); + } +} diff --git a/Medium/Can Convert String in K Moves.java b/Medium/Can Convert String in K Moves.java new file mode 100644 index 00000000..fe496fbb --- /dev/null +++ b/Medium/Can Convert String in K Moves.java @@ -0,0 +1,24 @@ +class Solution { + public boolean canConvertString(String s, String t, int k) { + if (s.length() != t.length()) { + return false; + } + Map map = new HashMap<>(); + for (int i = 0; i < s.length(); i++) { + int possibleMove = getDifference(s.charAt(i), t.charAt(i)); + if (possibleMove > 0 && (possibleMove + map.getOrDefault(possibleMove, 0) * 26) > k) { + return false; + } + map.put(possibleMove, map.getOrDefault(possibleMove, 0) + 1); + } + return true; + } + + private int getDifference(char c1, char c2) { + int diff = ((int) c2) - ((int) c1); + if (diff >= 0) { + return diff; + } + return diff + 26; + } +} diff --git a/Medium/Can Make Palindrome from Substring.java b/Medium/Can Make Palindrome from Substring.java new file mode 100644 index 00000000..3640e74f --- /dev/null +++ b/Medium/Can Make Palindrome from Substring.java @@ -0,0 +1,18 @@ +class Solution { + public List canMakePaliQueries(String s, int[][] queries) { + int[][] count = new int[s.length() + 1][26]; + for (int i = 0; i < s.length(); i++) { + count[i + 1] = count[i].clone(); + count[i + 1][s.charAt(i) - 'a']++; + } + List list = new ArrayList<>(); + for (int[] query : queries) { + int sum = 0; + for (int i = 0; i < 26; i++) { + sum += (count[query[1] + 1][i] - count[query[0]][i]) % 2; + } + list.add(sum / 2 <= query[2]); + } + return list; + } +} diff --git a/Medium/Candy Crush.java b/Medium/Candy Crush.java new file mode 100644 index 00000000..627ba3bb --- /dev/null +++ b/Medium/Candy Crush.java @@ -0,0 +1,37 @@ +class Solution { + public int[][] candyCrush(int[][] board) { + int rows = board.length; + int cols = board[0].length; + boolean flag = false; + for (int r = 0; r < rows; r++) { + for (int c = 0; c + 2 < cols; c++) { + int val = Math.abs(board[r][c]); + if (val != 0 && val == Math.abs(board[r][c + 1]) && val == Math.abs(board[r][c + 2])) { + board[r][c] = board[r][c + 1] = board[r][c + 2] = -val; + flag = true; + } + } + } + for (int r = 0; r + 2 < rows; r++) { + for (int c = 0; c < cols; c++) { + int val = Math.abs(board[r][c]); + if (val != 0 && val == Math.abs(board[r + 1][c]) && val == Math.abs(board[r + 2][c])) { + board[r][c] = board[r + 1][c] = board[r + 2][c] = -val; + flag = true; + } + } + } + for (int c = 0; c < cols; c++) { + int currRow = rows - 1; + for (int r = rows - 1; r >= 0; r--) { + if (board[r][c] > 0) { + board[currRow--][c] = board[r][c]; + } + } + while (currRow >= 0) { + board[currRow--][c] = 0; + } + } + return flag ? candyCrush(board) : board; + } +} diff --git a/Medium/Capacity To Ship Packages Within D Days.java b/Medium/Capacity To Ship Packages Within D Days.java new file mode 100644 index 00000000..8d7ff38e --- /dev/null +++ b/Medium/Capacity To Ship Packages Within D Days.java @@ -0,0 +1,31 @@ +class Solution { + public int shipWithinDays(int[] weights, int days) { + int maximumWeight = 0; + int minimumWeight = weights[0]; + for (int weight : weights) { + maximumWeight += weight; + minimumWeight = Math.max(minimumWeight, weight); + } + while (minimumWeight <= maximumWeight) { + int currCapacity = (maximumWeight + minimumWeight) / 2; + if (isShipmentPossible(weights, days, currCapacity)) { + maximumWeight = currCapacity - 1; + } else { + minimumWeight = currCapacity + 1; + } + } + return minimumWeight; + } + + private boolean isShipmentPossible(int[] weights, int days, int capacity) { + int idx = 0; + while (idx < weights.length) { + int currWeight = 0; + while (idx < weights.length && currWeight + weights[idx] <= capacity) { + currWeight += weights[idx++]; + } + days--; + } + return days >= 0; + } +} diff --git a/Medium/Car Pooling.java b/Medium/Car Pooling.java index 82c43aaa..9d09b2c4 100644 --- a/Medium/Car Pooling.java +++ b/Medium/Car Pooling.java @@ -1,22 +1,17 @@ class Solution { - public boolean carPooling(int[][] trips, int capacity) { - PriorityQueue end = new PriorityQueue<>(Comparator.comparingInt(o -> trips[o][2])); - Arrays.sort(trips, Comparator.comparingInt(o -> o[1])); - end.add(0); - int currCapacity = trips[0][0]; - for (int i = 1; i < trips.length; i++) { - while (!end.isEmpty() && trips[i][1] >= trips[end.peek()][2]) { - currCapacity -= trips[end.poll()][0]; - } - - if (currCapacity + trips[i][0] > capacity) { - return false; - } - - currCapacity += trips[i][0]; - end.add(i); - } - - return true; + public boolean carPooling(int[][] trips, int capacity) { + Arrays.sort(trips, Comparator.comparingInt(o -> o[1])); + PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[2])); + for (int[] trip : trips) { + while (!pq.isEmpty() && pq.peek()[2] <= trip[1]) { + capacity += pq.poll()[0]; + } + if (capacity < trip[0]) { + return false; + } + pq.add(trip); + capacity -= trip[0]; } + return true; + } } diff --git a/Medium/Champagne Tower.java b/Medium/Champagne Tower.java new file mode 100644 index 00000000..ccd07a8b --- /dev/null +++ b/Medium/Champagne Tower.java @@ -0,0 +1,13 @@ +class Solution { + public double champagneTower(int poured, int query_row, int query_glass) { + double[] glass = new double[query_row + 2]; + glass[0] = poured; + for (int row = 1; row <= query_row; row++) { + for (int idx = row; idx >= 0; idx--) { + glass[idx] = Math.max(0.0, (glass[idx] - 1) / 2); + glass[idx + 1] += glass[idx]; + } + } + return Math.min(glass[query_glass], 1.0); + } +} diff --git a/Medium/Cheapest Flights Within K Stops.java b/Medium/Cheapest Flights Within K Stops.java new file mode 100644 index 00000000..e937fdaf --- /dev/null +++ b/Medium/Cheapest Flights Within K Stops.java @@ -0,0 +1,32 @@ +class Solution { + public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) { + Map> graph = new HashMap<>(); + for (int[] flight : flights) { + graph.computeIfAbsent(flight[0], ArrayList::new).add(new int[]{flight[1], flight[2]}); + } + int[] price = new int[n]; + Arrays.fill(price, Integer.MAX_VALUE); + Queue queue = new LinkedList<>(); + queue.add(new int[]{src, 0}); + while (k-- >= 0 && !queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + int currCity = removed[0]; + int currPrice = removed[1]; + if (!graph.containsKey(currCity)) { + continue; + } + for (int[] node : graph.get(currCity)) { + int nextCity = node[0]; + int flightPrice = node[1]; + if (currPrice + flightPrice < price[nextCity]) { + price[nextCity] = currPrice + flightPrice; + queue.add(new int[]{nextCity, price[nextCity]}); + } + } + } + } + return price[dst] == Integer.MAX_VALUE ? -1 : price[dst]; + } +} diff --git a/Medium/Check Completeness of a Binary Tree.java b/Medium/Check Completeness of a Binary Tree.java new file mode 100644 index 00000000..2d0c94f0 --- /dev/null +++ b/Medium/Check Completeness of a Binary Tree.java @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean isCompleteTree(TreeNode root) { + Queue queue = new LinkedList<>(); + boolean isEnd = false; + queue.add(root); + while (!queue.isEmpty()) { + TreeNode removed = queue.remove(); + if (removed == null) { + isEnd = true; + } + if (removed != null) { + if (isEnd) { + return false; + } + queue.add(removed.left); + queue.add(removed.right); + } + } + return true; + } +} diff --git a/Medium/Check If All 1's Are at Least Length K Places Away.java b/Medium/Check If All 1's Are at Least Length K Places Away.java new file mode 100644 index 00000000..bc272afa --- /dev/null +++ b/Medium/Check If All 1's Are at Least Length K Places Away.java @@ -0,0 +1,13 @@ +class Solution { + public boolean kLengthApart(int[] nums, int k) { + for (int start = -1, idx = 0; idx < nums.length; idx++) { + if (nums[idx] == 1) { + if (start != -1 && idx - start - 1 < k) { + return false; + } + start = idx; + } + } + return true; + } +} diff --git a/Medium/Check If Array Pairs Are Divisible by k.java b/Medium/Check If Array Pairs Are Divisible by k.java new file mode 100644 index 00000000..d942915f --- /dev/null +++ b/Medium/Check If Array Pairs Are Divisible by k.java @@ -0,0 +1,20 @@ +class Solution { + public boolean canArrange(int[] arr, int k) { + Map map = new HashMap<>(); + for (int num : arr) { + int remainder = ((num % k) + k) % k; + map.put(remainder, map.getOrDefault(remainder, 0) + 1); + } + for (int num : arr) { + int remainder = ((num % k) + k) % k; + if (remainder == 0) { + if (map.get(remainder) % 2 == 1) { + return false; + } + } else if (!map.get(remainder).equals(map.get(k - remainder))) { + return false; + } + } + return true; + } +} diff --git a/Medium/Check If a String Can Break Another String.java b/Medium/Check If a String Can Break Another String.java new file mode 100644 index 00000000..0e9e9f55 --- /dev/null +++ b/Medium/Check If a String Can Break Another String.java @@ -0,0 +1,30 @@ +class Solution { + public boolean checkIfCanBreak(String s1, String s2) { + int n = s1.length(); + int[] counterS1 = new int[26]; + int[] counterS2 = new int[26]; + for (int idx = 0; idx < n; idx++) { + counterS1[s1.charAt(idx) - 'a']++; + counterS2[s2.charAt(idx) - 'a']++; + } + int countS1 = 0; + int countS2 = 0; + int side = 0; + for (int idx = 0; idx < 26; idx++) { + countS1 += counterS1[idx]; + countS2 += counterS2[idx]; + if (countS1 > countS2) { + if (side == 1) { + return false; + } + side = -1; + } else if (countS2 > countS1) { + if (side == -1) { + return false; + } + side = 1; + } + } + return true; + } +} diff --git a/Medium/Check If a String Contains All Binary Codes of Size K.java b/Medium/Check If a String Contains All Binary Codes of Size K.java new file mode 100644 index 00000000..d202d57c --- /dev/null +++ b/Medium/Check If a String Contains All Binary Codes of Size K.java @@ -0,0 +1,17 @@ +class Solution { + public boolean hasAllCodes(String s, int k) { + Set set = new HashSet<>(); + int counter = 1 << k; + for (int i = k; i <= s.length(); i++) { + String temp = s.substring(i - k, i); + if (!set.contains(temp)) { + set.add(temp); + counter--; + } + if (counter == 0) { + return true; + } + } + return false; + } +} diff --git a/Medium/Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree.java b/Medium/Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree.java new file mode 100644 index 00000000..df07904f --- /dev/null +++ b/Medium/Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree.java @@ -0,0 +1,33 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean isValidSequence(TreeNode root, int[] arr) { + return helper(root, arr, 0); + } + + private boolean helper(TreeNode root, int[] arr, int idx) { + if (root == null || idx >= arr.length) { + return false; + } + if (root.val != arr[idx]) { + return false; + } + if (root.left == null && root.right == null && idx == (arr.length - 1)) { + return true; + } + return helper(root.left, arr, idx + 1) || helper(root.right, arr, idx + 1); + } +} diff --git a/Medium/Check if Strings Can be Made Equal With Operations II.java b/Medium/Check if Strings Can be Made Equal With Operations II.java new file mode 100644 index 00000000..7507b140 --- /dev/null +++ b/Medium/Check if Strings Can be Made Equal With Operations II.java @@ -0,0 +1,21 @@ +class Solution { + public boolean checkStrings(String s1, String s2) { + int[] odd = new int[26]; + int[] even = new int[26]; + for (int i = 0; i < s1.length(); i++) { + if (i % 2 == 0) { + even[s1.charAt(i) - 'a']++; + even[s2.charAt(i) - 'a']--; + } else { + odd[s1.charAt(i) - 'a']++; + odd[s2.charAt(i) - 'a']--; + } + } + for (int i = 0; i < 26; i++) { + if (odd[i] != 0 || even[i] != 0) { + return false; + } + } + return true; + } +} diff --git a/Medium/Check if There is a Valid Path in a Grid.java b/Medium/Check if There is a Valid Path in a Grid.java new file mode 100644 index 00000000..bb3af343 --- /dev/null +++ b/Medium/Check if There is a Valid Path in a Grid.java @@ -0,0 +1,39 @@ +class Solution { + public boolean hasValidPath(int[][] grid) { + int[][][] dirs = { + {{0, -1}, {0, 1}}, + {{-1, 0}, {1, 0}}, + {{0, -1}, {1, 0}}, + {{0, 1}, {1, 0}}, + {{0, -1}, {-1, 0}}, + {{0, 1}, {-1, 0}} + }; + int rows = grid.length; + int cols = grid[0].length; + Queue queue = new LinkedList<>(); + boolean[][] visited = new boolean[rows][cols]; + queue.add(new int[]{0, 0}); + visited[0][0] = true; + while (!queue.isEmpty()) { + int[] curr = queue.remove(); + int x = curr[0]; + int y = curr[1]; + int num = grid[x][y] - 1; + for (int[] dir : dirs[num]) { + int newX = x + dir[0]; + int newY = y + dir[1]; + // Check if valid co-ordinate + if (newX >= 0 && newX < grid.length && newY >= 0 && newY < grid[0].length && !visited[newX][newY]) { + for (int[] prevDir : dirs[grid[newX][newY] - 1]) { + // Check if connected to previous direction + if (newX + prevDir[0] == x && newY + prevDir[1] == y) { + visited[newX][newY] = true; + queue.add(new int[]{newX, newY}); + } + } + } + } + } + return visited[rows - 1][cols - 1]; + } +} diff --git a/Medium/Check if a Parentheses String Can Be Valid.java b/Medium/Check if a Parentheses String Can Be Valid.java new file mode 100644 index 00000000..c240176d --- /dev/null +++ b/Medium/Check if a Parentheses String Can Be Valid.java @@ -0,0 +1,30 @@ +class Solution { + public boolean canBeValid(String s, String locked) { + if (s.length() % 2 != 0) { + return false; + } + Stack openBrackets = new Stack<>(); + Stack unlocked = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (locked.charAt(i) == '0') { + unlocked.push(i); + } else if (c == '(') { + openBrackets.push(i); + } else if (c == ')') { + if (!openBrackets.isEmpty()) { + openBrackets.pop(); + } else if (!unlocked.isEmpty()) { + unlocked.pop(); + } else { + return false; + } + } + } + while (!openBrackets.isEmpty() && !unlocked.isEmpty() && openBrackets.peek() < unlocked.peek()) { + openBrackets.pop(); + unlocked.pop(); + } + return openBrackets.isEmpty(); + } +} diff --git a/Medium/Cinema Seat Allocation.java b/Medium/Cinema Seat Allocation.java new file mode 100644 index 00000000..946d5839 --- /dev/null +++ b/Medium/Cinema Seat Allocation.java @@ -0,0 +1,29 @@ +class Solution { + public int maxNumberOfFamilies(int n, int[][] reservedSeats) { + int numOfReservedSeats = reservedSeats.length; + Map> map = new HashMap<>(); + for(int i = 0; i < numOfReservedSeats; i++) { + if(!map.containsKey(reservedSeats[i][0])) { + map.put(reservedSeats[i][0], new HashSet<>()); + } + map.get(reservedSeats[i][0]).add(reservedSeats[i][1]); + } + int count = 2 * n - 2 * map.size(); + for(Integer i : map.keySet()) { + boolean flag = false; + Set reserved = map.get(i); + if(!reserved.contains(2) && !reserved.contains(3) && !reserved.contains(4) && !reserved.contains(5)) { + count++; + flag = true; + } + if(!reserved.contains(6) && !reserved.contains(7) && !reserved.contains(8) && !reserved.contains(9)) { + count++; + flag = true; + } + if(!flag && !reserved.contains(4) && !reserved.contains(5) && !reserved.contains(6) && !reserved.contains(7)) { + count++; + } + } + return count; + } +} diff --git a/Medium/Clone Binary Tree With Random Pointer.java b/Medium/Clone Binary Tree With Random Pointer.java new file mode 100644 index 00000000..cf43c71a --- /dev/null +++ b/Medium/Clone Binary Tree With Random Pointer.java @@ -0,0 +1,59 @@ +/** + * Definition for Node. + * public class Node { + * int val; + * Node left; + * Node right; + * Node random; + * Node() {} + * Node(int val) { this.val = val; } + * Node(int val, Node left, Node right, Node random) { + * this.val = val; + * this.left = left; + * this.right = right; + * this.random = random; + * } + * } + */ + +class Solution { + public NodeCopy copyRandomBinaryTree(Node root) { + if (root == null) { + return null; + } + Map map = new HashMap<>(); + copyOnlyNode(root, map); + copyNodePointers(root, map); + return map.get(root); + } + + private void copyNodePointers(Node root, Map map) { + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + Node removed = queue.remove(); + NodeCopy copied = map.get(removed); + if (removed.left != null) { + queue.add(removed.left); + copied.left = map.get(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + copied.right = map.get(removed.right); + } + if (removed.random != null) { + copied.random = map.get(removed.random); + } + } + } + + private void copyOnlyNode(Node root, Map map) { + if (root == null) { + return; + } + NodeCopy copiedNode = new NodeCopy(root.val); + map.put(root, copiedNode); + copyOnlyNode(root.left, map); + copyOnlyNode(root.right, map); + } +} diff --git a/Medium/Clone Graph.java b/Medium/Clone Graph.java index 02c97aee..cddb7b81 100644 --- a/Medium/Clone Graph.java +++ b/Medium/Clone Graph.java @@ -3,33 +3,40 @@ class Node { public int val; public List neighbors; - - public Node() {} - - public Node(int _val,List _neighbors) { + public Node() { + val = 0; + neighbors = new ArrayList(); + } + public Node(int _val) { + val = _val; + neighbors = new ArrayList(); + } + public Node(int _val, ArrayList _neighbors) { val = _val; neighbors = _neighbors; } -}; +} */ + class Solution { - Map map = new HashMap<>(); public Node cloneGraph(Node node) { if (node == null) { return null; } - - if (map.containsKey(node)) { - return map.get(node); - } - - Node newNode = new Node(node.val, new ArrayList<>()); - map.put(node, newNode); - - for (Node n : node.neighbors) { - newNode.neighbors.add(cloneGraph(n)); + Map map = new HashMap(); + Queue queue = new LinkedList<>(); + queue.add(node); + map.put(node, new Node(node.val)); + while (!queue.isEmpty()) { + Node removed = queue.remove(); + for (Node neighbor : removed.neighbors) { + if (!map.containsKey(neighbor)) { + map.put(neighbor, new Node(neighbor.val)); + queue.add(neighbor); + } + map.get(removed).neighbors.add(map.get(neighbor)); + } } - - return newNode; + return map.get(node); } } diff --git a/Medium/Clone N-ary Tree.java b/Medium/Clone N-ary Tree.java new file mode 100644 index 00000000..819cb14d --- /dev/null +++ b/Medium/Clone N-ary Tree.java @@ -0,0 +1,46 @@ +/* +// Definition for a Node. +class Node { + public int val; + public List children; + + + public Node() { + children = new ArrayList(); + } + + public Node(int _val) { + val = _val; + children = new ArrayList(); + } + + public Node(int _val,ArrayList _children) { + val = _val; + children = _children; + } +}; +*/ + +class Solution { + public Node cloneTree(Node root) { + if (root == null) { + return root; + } + Queue queue = new LinkedList<>(); + Map map = new HashMap<>(); + queue.add(root); + map.put(root, new Node(root.val)); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + Node removed = queue.remove(); + for (Node child : removed.children) { + queue.add(child); + map.put(child, new Node(child.val)); + map.get(removed).children.add(map.get(child)); + } + } + } + return map.get(root); + } +} diff --git a/Medium/Closest Nodes Queries in a Binary Search Tree.java b/Medium/Closest Nodes Queries in a Binary Search Tree.java new file mode 100644 index 00000000..e1c19211 --- /dev/null +++ b/Medium/Closest Nodes Queries in a Binary Search Tree.java @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List> closestNodes(TreeNode root, List queries) { + TreeSet set = new TreeSet<>(); + traverse(root, set); + List> result = new ArrayList<>(); + for (Integer query : queries) { + Integer lower = set.floor(query); + Integer upper = set.ceiling(query); + result.add(Arrays.asList((lower == null ? -1 : lower), (upper == null ? -1 : upper))); + } + return result; + } + + private void traverse(TreeNode root, TreeSet set) { + if (root == null) { + return; + } + set.add(root.val); + traverse(root.left, set); + traverse(root.right, set); + } +} diff --git a/Medium/Coin Change.java b/Medium/Coin Change.java index d87a7963..f728e957 100644 --- a/Medium/Coin Change.java +++ b/Medium/Coin Change.java @@ -1,18 +1,57 @@ class Solution { - public int coinChange(int[] coins, int amount) { - int max = amount + 1; - int[] cache = new int[amount + 1]; - Arrays.fill(cache, max); - cache[0] = 0; - - for (int i=1; i<=amount; i++) { - for (int j=0; j amount ? -1 : cache[amount]; + private int coinChangeMemoization(int[] coins, int amount, Integer[] memo) { + if (amount < 0) { + return -1; + } + if (amount == 0) { + return 0; + } + if (memo[amount] != null) { + return memo[amount]; + } + int minCount = Integer.MAX_VALUE; + for (int coin : coins) { + int count = coinChangeMemoization(coins, amount - coin, memo); + if (count == -1) { + continue; + } + minCount = Math.min(minCount, count + 1); + } + memo[amount] = minCount == Integer.MAX_VALUE ? -1 : minCount; + return memo[amount]; + } + + // This approach times out due to overlapping subproblems + private int coinChangeRecursive(int[] coins, int amount) { + if (amount < 0) { + return -1; + } + if (amount == 0) { + return 0; + } + int minCount = Integer.MAX_VALUE; + for (int coin : coins) { + int count = coinChangeRecursive(coins, amount - coin); + if (count == -1) { + continue; + } + minCount = Math.min(minCount, count); } + return minCount == Integer.MAX_VALUE ? -1 : minCount; + } } diff --git a/Medium/Combination Sum II.java b/Medium/Combination Sum II.java index 7e66b79d..954373f5 100644 --- a/Medium/Combination Sum II.java +++ b/Medium/Combination Sum II.java @@ -1,30 +1,25 @@ class Solution { - public static List> combinationSum2(int[] candidates, int target) { - Arrays.sort(candidates); - List> perms = new ArrayList<>(); - List temp = new ArrayList<>(); - - combinationSumHelper(candidates, target, perms, temp, 0); - - return perms; + public List> combinationSum2(int[] candidates, int target) { + List> result = new ArrayList<>(); + Arrays.sort(candidates); + helper(candidates, target, result, new ArrayList<>(), 0); + return result; + } + + private void helper(int[] candidates, int target, List> result, List currCombination, int idx) { + if (target <= 0) { + if (target == 0) { + result.add(new ArrayList<>(currCombination)); + } + return; } - - private static void combinationSumHelper(int[] candidates, int target, List> perms, List temp, int start) { - if (target < 0) { - return; - } - if (target == 0) { - perms.add(new ArrayList<>(temp)); - } - else { - for (int i=start; i start && candidates[i] == candidates[i-1]) { - continue; - } - temp.add(candidates[i]); - combinationSumHelper(candidates, target-candidates[i], perms, temp, i+1); - temp.remove(temp.size()-1); - } - } + for (int i = idx; i < candidates.length; i++) { + if (i > idx && candidates[i] == candidates[i - 1]) { + continue; + } + currCombination.add(candidates[i]); + helper(candidates, target - candidates[i], result, currCombination, i + 1); + currCombination.remove(currCombination.size() - 1); } + } } diff --git a/Medium/Combination Sum III.java b/Medium/Combination Sum III.java index 61fa4257..4acafbfc 100644 --- a/Medium/Combination Sum III.java +++ b/Medium/Combination Sum III.java @@ -1,30 +1,21 @@ class Solution { - public List> combinationSum3(int k, int n) { - List> list = new ArrayList<>(); - List temp = new ArrayList<>(); - - helper(list, temp, k, n, 0, 1); - - return list; + public List> combinationSum3(int k, int n) { + List> lists = new ArrayList<>(); + helper(n, lists, new ArrayList<>(), 0, k, 1); + return lists; + } + + private void helper(int n, List> lists, List list, int currSum, int k, int currNum) { + if (list.size() == k) { + if (currSum == n) { + lists.add(new ArrayList<>(list)); + } + return; } - - private void helper(List> list, List temp, int k, int n, int sum, int start) { - if (sum == n && temp.size() == k) { - list.add(new ArrayList<>(temp)); - return; - } - - for (int i=start; i<=9; i++) { - // Choose - temp.add(i); - sum += i; - - // Explore - helper(list, temp, k, n, sum, i+1); - - // Un-choose - sum -= temp.get(temp.size() - 1); - temp.remove(temp.size() - 1); - } + for (int i = currNum; i <= 9; i++) { + list.add(i); + helper(n, lists, list, currSum + i, k, i + 1); + list.remove(list.size() - 1); } + } } diff --git a/Medium/Combination Sum IV.java b/Medium/Combination Sum IV.java new file mode 100644 index 00000000..3a0eb51e --- /dev/null +++ b/Medium/Combination Sum IV.java @@ -0,0 +1,22 @@ +class Solution { + public int combinationSum4(int[] nums, int target) { + Integer[] dp = new Integer[target + 1]; + return helper(nums, target, dp); + } + + private int helper(int[] nums, int target, Integer[] dp) { + if (dp[target] != null) { + return dp[target]; + } + if (target == 0) { + return 1; + } + int count = 0; + for (int num : nums) { + if (target >= num) { + count += helper(nums, target - num, dp); + } + } + return dp[target] = count; + } +} diff --git a/Medium/Combination Sum.java b/Medium/Combination Sum.java index 4e116b8e..6d9e8f77 100644 --- a/Medium/Combination Sum.java +++ b/Medium/Combination Sum.java @@ -1,38 +1,22 @@ class Solution { - Set> set; public List> combinationSum(int[] candidates, int target) { - set = new HashSet<>(); - Arrays.sort(candidates); - combinationSumHelper(candidates, 0, target, new ArrayList<>()); - - return new ArrayList<>(set); + List> result = new ArrayList<>(); + helper(candidates, target, new ArrayList<>(), result, 0); + return result; } - - private void combinationSumHelper(int[] candidates, int currVal, int target, List list) { - if (currVal == target) { - set.add(new ArrayList<>(list)); + + private void helper(int[] candidates, int target, List combination, List> result, int idx) { + if (target < 0 || idx == candidates.length) { return; } - - if (currVal > target) { + if (target == 0) { + result.add(combination); return; } - - for (int i = 0; i < candidates.length; i++) { - if (list.size() > 0 && list.get(list.size() - 1) > candidates[i]) { - continue; - } - - // Choose - currVal += candidates[i]; - list.add(candidates[i]); - - // Explore - combinationSumHelper(candidates, currVal, target, list); - - // Unchoose - list.remove(list.size() - 1); - currVal -= candidates[i]; + for (int i = idx; i < candidates.length; i++) { + combination.add(candidates[i]); + helper(candidates, target - candidates[i], new ArrayList<>(combination), result, i); + combination.remove(combination.size() - 1); } - } + } } diff --git a/Medium/Combinations.java b/Medium/Combinations.java index 23b1c7e6..425b44ff 100644 --- a/Medium/Combinations.java +++ b/Medium/Combinations.java @@ -1,27 +1,22 @@ class Solution { public List> combine(int n, int k) { - List temp = new ArrayList<>(); - List> ans = new ArrayList<>(); - helper(n, 1, temp, ans, k); - - return ans; + List> result = new ArrayList<>(); + helper(result, n, k, new ArrayList<>(), 1); + return result; } - - private void helper(int n, int start, List temp, List> ans, int len) { - if (temp.size() == len) { - ans.add(new ArrayList<>(temp)); + + private void helper(List> result, int n, int k, List curr, int currValue) { + if (curr.size() == k) { + result.add(new ArrayList<>(curr)); return; } - - for (int i=start; i<=n; i++) { - // Choose - temp.add(i); - - // Explore - helper(n, i+1, temp, ans, len); - - // Un-choose - temp.remove(temp.size() - 1); + for (int i = currValue; i <= n; i++) { + if (!curr.isEmpty() && curr.get(curr.size() - 1) >= i) { + continue; + } + curr.add(i); + helper(result, n, k, curr, currValue + 1); + curr.remove(curr.size() - 1); } } -} +} diff --git a/Medium/Compare Version Numbers.java b/Medium/Compare Version Numbers.java index e2b72daf..b7b13684 100644 --- a/Medium/Compare Version Numbers.java +++ b/Medium/Compare Version Numbers.java @@ -1,41 +1,25 @@ class Solution { - public static int compareVersion(String version1, String version2) { - String[] v1 = version1.split("\\."); - String[] v2 = version2.split("\\."); - - int v1Start = 0; - int v2Start = 0; - - while (v1Start < v1.length || v2Start < v2.length) { - - if (v1Start < v1.length && v2Start < v2.length) { - if (Integer.parseInt(v1[v1Start]) < Integer.parseInt(v2[v2Start])) { - return -1; - } else if (Integer.parseInt(v1[v1Start]) > Integer.parseInt(v2[v2Start])) { - return 1; - } - - v1Start++; - v2Start++; - } - else if (v1Start < v1.length && v2Start == v2.length) { - if (Integer.parseInt(v1[v1Start]) > 0) { - return 1; - } - else { - v1Start++; - } - } - else { - if (Integer.parseInt(v2[v2Start]) > 0) { - return -1; - } - else { - v2Start++; - } - } - } - - return 0; + public int compareVersion(String version1, String version2) { + String[] splitOne = version1.split("\\."); + String[] splitTwo = version2.split("\\."); + int i = 0; + for (i = 0; i < Math.min(splitOne.length, splitTwo.length); i++) { + int diff = Integer.parseInt(splitOne[i]) - Integer.parseInt(splitTwo[i]); + if (diff == 0) { + continue; + } + return diff < 0 ? -1 : 1; } + while (i < splitOne.length) { + if (Integer.parseInt(splitOne[i++]) > 0) { + return 1; + } + } + while (i < splitTwo.length) { + if (Integer.parseInt(splitTwo[i++]) > 0) { + return -1; + } + } + return 0; + } } diff --git a/Medium/Complex Number Multiplication.java b/Medium/Complex Number Multiplication.java index 61731cb1..f6d2500b 100644 --- a/Medium/Complex Number Multiplication.java +++ b/Medium/Complex Number Multiplication.java @@ -1,17 +1,63 @@ class Solution { - public String complexNumberMultiply(String a, String b) { - String[] strA = a.trim().split("\\+"); - String[] strB = b.trim().split("\\+"); - - int realA = Integer.parseInt(strA[0]); - int realB = Integer.parseInt(strB[0]); - - int compA = Integer.parseInt(strA[1].substring(0,strA[1].length()-1)); - int compB = Integer.parseInt(strB[1].substring(0,strB[1].length()-1)); - - int realAns = (realA*realB) - (compA*compB); - int compAns = (realA*compB) + (realB*compA); - - return String.valueOf(realAns) + "+" + String.valueOf(compAns) + "i"; + public String complexNumberMultiply(String num1, String num2) { + ComplexNumber result = ComplexNumber.buildComplexNumber(num1).multiply(ComplexNumber.buildComplexNumber(num2)); + return result.toString(); + } + + + private static class ComplexNumber { + + private final int real; + private final int imaginary; + + private ComplexNumber(int real, int imaginary) { + this.real = real; + this.imaginary = imaginary; } + + public static ComplexNumber buildComplexNumber(String s) { + int[] idx = {0}; + int realPart = parseRealPart(s, idx); + int imaginaryPart = parseImaginaryPart(s, idx); + return new ComplexNumber(realPart, imaginaryPart); + } + + public ComplexNumber multiply(ComplexNumber anotherNumber) { + int realPart = this.real * anotherNumber.real + (this.imaginary * anotherNumber.imaginary * -1); + int imaginaryPart = this.real * anotherNumber.imaginary + this.imaginary * anotherNumber.real; + return new ComplexNumber(realPart, imaginaryPart); + } + + public String toString() { + return this.real + "+" + this.imaginary + "i"; + } + + private static int parseRealPart(String s, int[] idx) { + int realSign = 1; + if (s.charAt(idx[0]) == '+' || s.charAt(idx[0]) == '-') { + realSign = s.charAt(idx[0]) == '-' ? -1 : 1; + idx[0]++; + } + int realNum = 0; + while (idx[0] < s.length() && Character.isDigit(s.charAt(idx[0]))) { + realNum = realNum * 10 + Character.getNumericValue(s.charAt(idx[0]++)); + } + realNum *= realSign; + idx[0]++; + return realNum; + } + + private static int parseImaginaryPart(String s, int[] idx) { + int imaginarySign = 1; + if (idx[0] < s.length() && (s.charAt(idx[0]) == '+' || s.charAt(idx[0]) == '-')) { + imaginarySign = s.charAt(idx[0]) == '-' ? -1 : 1; + idx[0]++; + } + int imaginaryNum = 0; + while (idx[0] < s.length() && s.charAt(idx[0]) != 'i') { + imaginaryNum = imaginaryNum * 10 + Character.getNumericValue(s.charAt(idx[0]++)); + } + return imaginarySign * imaginaryNum; + } + } } diff --git a/Medium/Concatenation of Consecutive Binary Numbers.java b/Medium/Concatenation of Consecutive Binary Numbers.java new file mode 100644 index 00000000..fa27285f --- /dev/null +++ b/Medium/Concatenation of Consecutive Binary Numbers.java @@ -0,0 +1,14 @@ +class Solution { + public int concatenatedBinary(int n) { + final int MOD = 1000_000_007; + int length = 0; + long result = 0; + for (int i = 1; i <= n; i++) { + if (Math.pow(2, (int) (Math.log(i) / Math.log(2))) == i) { + length++; + } + result = ((result * (int) Math.pow(2, length)) + i) % MOD; + } + return (int) result; + } +} diff --git a/Medium/Connecting Cities With Minimum Cost.java b/Medium/Connecting Cities With Minimum Cost.java new file mode 100644 index 00000000..e1a90f09 --- /dev/null +++ b/Medium/Connecting Cities With Minimum Cost.java @@ -0,0 +1,59 @@ +class Solution { + public int minimumCost(int n, int[][] connections) { + Arrays.sort(connections, Comparator.comparingInt(a -> a[2])); + UnionFind unionFind = new UnionFind(n); + int totalCost = 0; + for (int[] connection : connections) { + int nodeOne = connection[0] - 1; + int nodeTwo = connection[1] - 1; + if (!unionFind.isConnected(nodeOne, nodeTwo)) { + totalCost += connection[2]; + unionFind.union(nodeOne, nodeTwo); + n--; + } + } + return n == 1 ? totalCost : -1; + } + + private static class UnionFind { + + private final int[] root; + private final int[] rank; + + public UnionFind(int size) { + this.root = new int[size]; + this.rank = new int[size]; + for (int i = 0; i < size; i++) { + this.root[i] = i; + this.rank[i] = 1; + } + } + + public void union(int nodeOne, int nodeTwo) { + int rootOne = find(nodeOne); + int rootTwo = find(nodeTwo); + if (rootOne != rootTwo) { + if (this.rank[rootOne] > this.rank[rootTwo]) { + this.root[rootTwo] = rootOne; + } else if (this.rank[rootOne] < this.rank[rootTwo]) { + this.root[rootOne] = rootTwo; + } else { + this.root[rootTwo] = rootOne; + this.rank[rootOne]++; + } + } + } + + + public int find(int node) { + if (node == root[node]) { + return node; + } + return root[node] = find(root[node]); + } + + public boolean isConnected(int nodeOne, int nodeTwo) { + return find(nodeOne) == find(nodeTwo); + } + } +} diff --git a/Medium/Construct Binary Search Tree from Preorder Traversal.java b/Medium/Construct Binary Search Tree from Preorder Traversal.java new file mode 100644 index 00000000..e2e044a8 --- /dev/null +++ b/Medium/Construct Binary Search Tree from Preorder Traversal.java @@ -0,0 +1,39 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode bstFromPreorder(int[] preorder) { + if (preorder.length == 0) { + return null; + } + TreeNode root = new TreeNode(preorder[0]); + Stack stack = new Stack<>(); + stack.push(root); + for (int i = 1; i < preorder.length; i++) { + TreeNode node = stack.peek(); + TreeNode child = new TreeNode(preorder[i]); + while (!stack.isEmpty() && stack.peek().val < child.val) { + node = stack.pop(); + } + if (node.val < child.val) { + node.right = child; + } else { + node.left = child; + } + stack.push(child); + } + return root; + } +} diff --git a/Medium/Construct Binary Tree from Inorder and Postorder Traversal.java b/Medium/Construct Binary Tree from Inorder and Postorder Traversal.java index aef2c5d3..ce312c11 100644 --- a/Medium/Construct Binary Tree from Inorder and Postorder Traversal.java +++ b/Medium/Construct Binary Tree from Inorder and Postorder Traversal.java @@ -4,41 +4,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode buildTree(int[] inorder, int[] postorder) { - if (postorder.length == 0) { - return null; - } - - TreeNode root = constructTree(inorder, 0, inorder.length - 1, postorder, postorder.length-1); - - return root; + public TreeNode buildTree(int[] inorder, int[] postorder) { + Map map = new HashMap<>(); + for (int i = 0; i < inorder.length; i++) { + map.put(inorder[i], i); } - - private TreeNode constructTree(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart) { - if (inStart > inEnd) { - return null; - } - - int idx = getIndex(inorder, postorder[postStart], inStart, inEnd); - - TreeNode node = new TreeNode(inorder[idx]); - node.left = constructTree(inorder, inStart, idx - 1, postorder, postStart-(inEnd - idx) - 1); - node.right = constructTree(inorder, idx + 1, inEnd, postorder, postStart-1); - - return node; - } - - private int getIndex(int[] arr, int num, int start, int end) { - for (int i=start; i<=end; i++) { - if (arr[i] == num) { - return i; - } - } - - return -1; + int[] postIdx = {postorder.length - 1}; + return helper(postorder, map, 0, inorder.length - 1, postIdx); + } + + private TreeNode helper(int[] postorder, Map map, int leftIdx, int rightIdx, int[] postIdx) { + if (leftIdx > rightIdx) { + return null; } + TreeNode root = new TreeNode(postorder[postIdx[0]--]); + int index = map.get(root.val); + root.right = helper(postorder, map, index + 1, rightIdx, postIdx); + root.left = helper(postorder, map, leftIdx, index - 1, postIdx); + return root; + } } diff --git a/Medium/Construct Binary Tree from Preorder and Inorder Traversal.java b/Medium/Construct Binary Tree from Preorder and Inorder Traversal.java new file mode 100644 index 00000000..1c2c1083 --- /dev/null +++ b/Medium/Construct Binary Tree from Preorder and Inorder Traversal.java @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode buildTree(int[] preorder, int[] inorder) { + Map map = new HashMap<>(); + int[] preorderIndex = {0}; + for (int i = 0; i < inorder.length; i++) { + map.put(inorder[i], i); + } + return buildTree(preorder, 0, preorder.length - 1, map, preorderIndex); + } + + private TreeNode buildTree(int[] preorder, int left, int right, Map map, int[] preorderIndex) { + if (left > right) { + return null; + } + int rootVal = preorder[preorderIndex[0]++]; + TreeNode root = new TreeNode(rootVal); + root.left = buildTree(preorder, left, map.get(rootVal) - 1, map, preorderIndex); + root.right = buildTree(preorder, map.get(rootVal) + 1, right, map, preorderIndex); + return root; + } +} diff --git a/Medium/Construct Binary Tree from Preorder and Postorder Traversal.java b/Medium/Construct Binary Tree from Preorder and Postorder Traversal.java new file mode 100644 index 00000000..ca7aa35d --- /dev/null +++ b/Medium/Construct Binary Tree from Preorder and Postorder Traversal.java @@ -0,0 +1,40 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode constructFromPrePost(int[] preorder, int[] postorder) { + int n = preorder.length; + Map postorderIndex = new HashMap<>(); + for (int i = 0; i < n; i++) { + postorderIndex.put(postorder[i], i); + } + return constructTree(0, n - 1, 0, preorder, postorderIndex); + } + + private TreeNode constructTree(int preStart, int preEnd, int postStart, int[] preorder, Map postorderIndex) { + if (preStart > preEnd) { + return null; + } + if (preStart == preEnd) { + return new TreeNode(preorder[preStart]); + } + int leftRoot = preorder[preStart + 1]; + int leftCount = postorderIndex.get(leftRoot) - postStart + 1; + TreeNode root = new TreeNode(preorder[preStart]); + root.left = constructTree(preStart + 1, preStart + leftCount, postStart, preorder, postorderIndex); + root.right = constructTree(preStart + leftCount + 1, preEnd, postStart + leftCount, preorder, postorderIndex); + return root; + } +} diff --git a/Medium/Construct K Palindrome Strings.java b/Medium/Construct K Palindrome Strings.java new file mode 100644 index 00000000..04f54681 --- /dev/null +++ b/Medium/Construct K Palindrome Strings.java @@ -0,0 +1,14 @@ +class Solution { + public boolean canConstruct(String s, int k) { + if (s.length() < k) { + return false; + } + int[] counter = new int[26]; + int numOfOddOccurence = 0; + for (char c : s.toCharArray()) { + counter[c - 'a']++; + numOfOddOccurence += counter[c - 'a'] % 2 == 0 ? -1 : 1; + } + return numOfOddOccurence <= k; + } +} diff --git a/Medium/Construct Quad Tree.java b/Medium/Construct Quad Tree.java index c9df19ec..c9aa0f6e 100644 --- a/Medium/Construct Quad Tree.java +++ b/Medium/Construct Quad Tree.java @@ -8,45 +8,68 @@ class Node { public Node bottomLeft; public Node bottomRight; - public Node() {} - - public Node(boolean _val,boolean _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { - val = _val; - isLeaf = _isLeaf; - topLeft = _topLeft; - topRight = _topRight; - bottomLeft = _bottomLeft; - bottomRight = _bottomRight; + + public Node() { + this.val = false; + this.isLeaf = false; + this.topLeft = null; + this.topRight = null; + this.bottomLeft = null; + this.bottomRight = null; + } + + public Node(boolean val, boolean isLeaf) { + this.val = val; + this.isLeaf = isLeaf; + this.topLeft = null; + this.topRight = null; + this.bottomLeft = null; + this.bottomRight = null; + } + + public Node(boolean val, boolean isLeaf, Node topLeft, Node topRight, Node bottomLeft, Node bottomRight) { + this.val = val; + this.isLeaf = isLeaf; + this.topLeft = topLeft; + this.topRight = topRight; + this.bottomLeft = bottomLeft; + this.bottomRight = bottomRight; } }; */ + class Solution { - public Node construct(int[][] grid) { - return helper(grid, 0, 0, grid.length); + public Node construct(int[][] grid) { + return helper(grid, 0, 0, grid.length); + } + + private Node helper(int[][] grid, int x, int y, int len) { + if (len == 1) { + return new Node(grid[x][y] != 0, true, null, null, null, null); } - - private Node helper(int[][] grid, int x, int y, int len) { - if (len == 1) { - return new Node(grid[x][y] != 0, true, null, null, null, null); - } - - Node result = new Node(); - Node topLeft = helper(grid, x, y, len / 2); - Node topRight = helper(grid, x, y + len / 2, len / 2); - Node bottomLeft = helper(grid, x + len / 2, y, len / 2); - Node bottomRight = helper(grid, x + len / 2, y + len / 2, len / 2); - - if (topLeft.isLeaf && topRight.isLeaf && bottomLeft.isLeaf && bottomRight.isLeaf - && topLeft.val == topRight.val && topRight.val == bottomLeft.val && bottomLeft.val == bottomRight.val) { - result.isLeaf = true; - result.val = topLeft.val; - } else { - result.topLeft = topLeft; - result.topRight = topRight; - result.bottomLeft = bottomLeft; - result.bottomRight = bottomRight; - } - - return result; + Node result = new Node(); + Node topLeft = helper(grid, x, y, len / 2); + Node topRight = helper(grid, x, y + len / 2, len / 2); + Node bottomLeft = helper(grid, x + len / 2, y, len / 2); + Node bottomRight = helper(grid, x + len / 2, y + len / 2, len / 2); + if ( + topLeft.isLeaf && + topRight.isLeaf && + bottomLeft.isLeaf && + bottomRight.isLeaf && + topLeft.val == topRight.val && + topRight.val == bottomLeft.val && + bottomLeft.val == bottomRight.val + ) { + result.isLeaf = true; + result.val = topLeft.val; + } + else { + result.topLeft = topLeft; + result.topRight = topRight; + result.bottomLeft = bottomLeft; + result.bottomRight = bottomRight; } + return result; + } } diff --git a/Medium/Construct Smallest Number From DI String.java b/Medium/Construct Smallest Number From DI String.java new file mode 100644 index 00000000..64e39262 --- /dev/null +++ b/Medium/Construct Smallest Number From DI String.java @@ -0,0 +1,15 @@ +class Solution { + public String smallestNumber(String pattern) { + StringBuilder result = new StringBuilder(); + Stack stack = new Stack<>(); + for (int i = 0; i <= pattern.length(); i++) { + stack.push(i + 1); + if (i == pattern.length() || pattern.charAt(i) == 'I') { + while (!stack.isEmpty()) { + result.append(stack.pop()); + } + } + } + return result.toString(); + } +} diff --git a/Medium/Construct String With Repeat Limit.java b/Medium/Construct String With Repeat Limit.java new file mode 100644 index 00000000..4ac21148 --- /dev/null +++ b/Medium/Construct String With Repeat Limit.java @@ -0,0 +1,37 @@ +class Solution { + public String repeatLimitedString(String s, int repeatLimit) { + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> o2 - o1); + for (char c : s.toCharArray()) { + pq.add(c); + } + StringBuilder sb = new StringBuilder(); + Stack stack = new Stack<>(); + int currentCharacterCount = 0; + char previousCharacter = pq.peek(); + while (!pq.isEmpty()) { + char currChar = pq.poll(); + if (currChar == previousCharacter) { + if (currentCharacterCount < repeatLimit) { + sb.append(currChar); + } else { + stack.add(currChar); + } + currentCharacterCount++; + } else { + if (stack.isEmpty()) { + sb.append(currChar); + previousCharacter = currChar; + currentCharacterCount = 1; + } else { + sb.append(currChar); + currentCharacterCount = 0; + while (!stack.isEmpty() && currentCharacterCount < repeatLimit) { + sb.append(stack.pop()); + currentCharacterCount++; + } + } + } + } + return sb.toString(); + } +} diff --git a/Medium/Container With Most Water.java b/Medium/Container With Most Water.java index 3bf46cf0..17fc1799 100644 --- a/Medium/Container With Most Water.java +++ b/Medium/Container With Most Water.java @@ -1,24 +1,18 @@ class Solution { - public int maxArea(int[] height) { - int start = 0; - int end = height.length - 1; - int mul = end; - int res = Integer.MIN_VALUE; - - while (end - start >= 1) { - int temp = mul * Math.min(height[start], height[end]); - res = Math.max(res, temp); - - if (height[start] < height[end]) { - start++; - } - else { - end--; - } - - mul--; - } - - return res; + public int maxArea(int[] height) { + int maximumArea = 0; + int leftIdx = 0; + int rightIdx = height.length - 1; + while (leftIdx < rightIdx) { + int maxHeight = Math.min(height[leftIdx], height[rightIdx]); + int currArea = maxHeight * (rightIdx - leftIdx); + maximumArea = Math.max(currArea, maximumArea); + if (maxHeight == height[leftIdx]) { + leftIdx++; + } else { + rightIdx--; + } } + return maximumArea; + } } diff --git a/Medium/Contains Duplicate III.java b/Medium/Contains Duplicate III.java index 431d9e0a..7e271137 100644 --- a/Medium/Contains Duplicate III.java +++ b/Medium/Contains Duplicate III.java @@ -1,23 +1,18 @@ class Solution { - public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { - TreeSet treeSet = new TreeSet<>(); - for (int i=0; i= nums[i] || - ceil != null && ceil <= nums[i]) { - return true; - } - - treeSet.add(num); - - if (i >= k) { - treeSet.remove((long) nums[i - k]); - } - } - - return false; + public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { + TreeSet set = new TreeSet<>(); + for (int i = 0; i < nums.length; i++) { + long num = nums[i]; + Long floor = set.floor(num + t); + Long ceil = set.ceiling(num - t); + if ((floor != null && floor >= num) || (ceil != null && ceil <= num)) { + return true; + } + set.add(num); + if (i >= k) { + set.remove((long) nums[i - k]); + } } + return false; + } } diff --git a/Medium/Contiguous Array.java b/Medium/Contiguous Array.java index e466caf1..204c9102 100644 --- a/Medium/Contiguous Array.java +++ b/Medium/Contiguous Array.java @@ -1,20 +1,17 @@ class Solution { - public int findMaxLength(int[] nums) { - Map map = new HashMap<>(); - map.put(0, -1); - int maxLen = 0; - int count = 0; - - for (int i=0; i map = new HashMap<>(); + map.put(0, -1); + int maxLength = 0; + int count = 0; + for (int i = 0; i < nums.length; i++) { + count += nums[i] == 0 ? -1 : 1; + if (map.containsKey(count)) { + maxLength = Math.max(maxLength, i - map.get(count)); + } else { + map.put(count, i); + } } + return maxLength; + } } diff --git a/Medium/Continuous Subarray Sum.java b/Medium/Continuous Subarray Sum.java new file mode 100644 index 00000000..267857ab --- /dev/null +++ b/Medium/Continuous Subarray Sum.java @@ -0,0 +1,19 @@ +class Solution { + public boolean checkSubarraySum(int[] nums, int k) { + Map map = new HashMap<>(); + map.put(0, -1); + int currSum = 0; + for (int i = 0; i < nums.length; i++) { + currSum += nums[i]; + int rem = currSum % k; + if (map.containsKey(rem)) { + if (i - map.get(rem) >= 2) { + return true; + } + } else { + map.put(rem, i); + } + } + return false; + } +} diff --git a/Medium/Convert Binary Search Tree to Sorted Doubly Linked List.java b/Medium/Convert Binary Search Tree to Sorted Doubly Linked List.java index 6276ea15..eaf92f02 100644 --- a/Medium/Convert Binary Search Tree to Sorted Doubly Linked List.java +++ b/Medium/Convert Binary Search Tree to Sorted Doubly Linked List.java @@ -7,6 +7,10 @@ class Node { public Node() {} + public Node(int _val) { + val = _val; + } + public Node(int _val,Node _left,Node _right) { val = _val; left = _left; @@ -14,36 +18,37 @@ public Node(int _val,Node _left,Node _right) { } }; */ + class Solution { - Node prev; - public Node treeToDoublyList(Node r) { - if (r == null) { - return r; - } - - prev = null; - Node dummy = new Node(0); - prev = dummy; - - inorderHelper(r); - - prev.right = dummy.right; - dummy.right.left = prev; - - return dummy.right; + public Node treeToDoublyList(Node root) { + if (root == null) { + return root; + } + Stack stack = new Stack<>(); + while (root != null) { + stack.push(root); + root = root.left; } - - private void inorderHelper(Node root) { - if (root == null) { - return; - } - - inorderHelper(root.left); - - prev.right = root; - root.left = prev; - prev = root; - - inorderHelper(root.right); + Node head = null; + Node prev = null; + while (!stack.isEmpty()) { + Node removed = stack.pop(); + Node rightNode = removed.right; + while (rightNode != null) { + stack.push(rightNode); + rightNode = rightNode.left; + } + if (head == null) { + head = removed; + } + if (prev != null) { + prev.right = removed; + } + removed.left = prev; + prev = removed; } + head.left = prev; + prev.right = head; + return head; + } } diff --git a/Medium/Convert Sorted List to Binary Search Tree.java b/Medium/Convert Sorted List to Binary Search Tree.java index 5b49c0f3..c1258059 100644 --- a/Medium/Convert Sorted List to Binary Search Tree.java +++ b/Medium/Convert Sorted List to Binary Search Tree.java @@ -3,7 +3,9 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ /** @@ -12,35 +14,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - ListNode curr; - - public TreeNode sortedListToBST(ListNode head) { - curr = head; - return generate(count(head)); - } - - public int count(ListNode node) { - int n = 0; - while (node != null) { - node = node.next; - ++n; + public TreeNode sortedListToBST(ListNode head) { + List list = new ArrayList<>(); + while (head != null) { + list.add(head.val); + head = head.next; } - return n; + return helper(list, 0, list.size() - 1); } - public TreeNode generate(int n) { - if (n==0) return null; - - TreeNode node = new TreeNode(0); - node.left = generate(n/2); - node.val = curr.val; - curr = curr.next; - node.right = generate(n-(n/2)-1); - - return node; + private TreeNode helper(List list, int start, int end) { + if (start > end) { + return null; + } + int mid = (start + end) / 2; + TreeNode root = new TreeNode(list.get(mid)); + root.left = helper(list, start, mid - 1); + root.right = helper(list, mid + 1, end); + return root; } } diff --git a/Medium/Convert an Array Into a 2D Array With Conditions.java b/Medium/Convert an Array Into a 2D Array With Conditions.java new file mode 100644 index 00000000..c774bda6 --- /dev/null +++ b/Medium/Convert an Array Into a 2D Array With Conditions.java @@ -0,0 +1,25 @@ +class Solution { + public List> findMatrix(int[] nums) { + Map frequencyMap = new HashMap<>(); + for (int num : nums) { + frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1); + } + Queue queue = new LinkedList<>(); + queue.addAll(frequencyMap.keySet()); + List> result = new ArrayList<>(); + while (!queue.isEmpty()) { + int size = queue.size(); + List row = new ArrayList<>(); + while (size-- > 0) { + int removed = queue.remove(); + row.add(removed); + if (frequencyMap.get(removed) > 1) { + frequencyMap.put(removed, frequencyMap.get(removed) - 1); + queue.add(removed); + } + } + result.add(row); + } + return result; + } +} diff --git a/Medium/Copy List with Random Pointer.java b/Medium/Copy List with Random Pointer.java index f86d0155..071731bc 100644 --- a/Medium/Copy List with Random Pointer.java +++ b/Medium/Copy List with Random Pointer.java @@ -1,28 +1,58 @@ -/** - * Definition for singly-linked list with a random pointer. - * class RandomListNode { - * int label; - * RandomListNode next, random; - * RandomListNode(int x) { this.label = x; } - * }; - */ -public class Solution { - public RandomListNode copyRandomList(RandomListNode head) { - if (head == null) { - return null; - } - - RandomListNode ans = new RandomListNode(head.label); - RandomListNode curr = ans; - - while (head != null) { - curr.next = head.next == null ? null : new RandomListNode(head.next.label); - curr.random = head.random == null ? null : new RandomListNode(head.random.label); - - curr = curr.next; - head = head.next; - } - - return ans; +/* +// Definition for a Node. +class Node { + int val; + Node next; + Node random; + + public Node(int val) { + this.val = val; + this.next = null; + this.random = null; } } +*/ + +class Solution { + public Node copyRandomList(Node head) { + if (head == null) { + return head; + } + Node curr = head; + /* + List A->B->C + Expected outcome: A->A`->B->B`->C->C` + Where node marked with ` is copied node + */ + while (curr != null) { + Node newNode = new Node(curr.val); + newNode.next = curr.next; + curr.next = newNode; + curr = newNode.next; + } + curr = head; + /* + List A->A`->B->B`->C->C` + | | | (Random pointers) + C A B + Expected outcome: A->A`->B->B`->C->C` + | | | | | | + C C` A A` B B` + */ + while (curr != null) { + curr.next.random = curr.random != null ? curr.random.next : null; + curr = curr.next.next; + } + Node oldCurr = head; + Node newCurr = head.next; + Node newHead = head.next; // Retain a pointer to copied list's head + // Separate merged lists into original list & copied list. + while (oldCurr != null) { + oldCurr.next = oldCurr.next.next; + newCurr.next = newCurr.next != null ? newCurr.next.next : null; + oldCurr = oldCurr.next; + newCurr = newCurr.next; + } + return newHead; + } +} diff --git a/Medium/Corporate Flight Bookings.java b/Medium/Corporate Flight Bookings.java new file mode 100644 index 00000000..2441a222 --- /dev/null +++ b/Medium/Corporate Flight Bookings.java @@ -0,0 +1,24 @@ +class Solution { + public int[] corpFlightBookings(int[][] bookings, int n) { + int[] ans = new int[n]; + + for (int[] booking : bookings) { + int tickets = booking[2]; + int from = booking[0]; + int to = booking[1]; + + ans[from - 1] += tickets; + if (to < n) { + ans[to] -= tickets; + } + } + + int currSum = 0; + for (int i = 0; i < n; i++) { + currSum += ans[i]; + ans[i] = currSum; + } + + return ans; + } +} diff --git a/Medium/Count Collisions on a Road.java b/Medium/Count Collisions on a Road.java new file mode 100644 index 00000000..aa3d6358 --- /dev/null +++ b/Medium/Count Collisions on a Road.java @@ -0,0 +1,20 @@ +class Solution { + public int countCollisions(String directions) { + int idx = 0; + while (idx < directions.length() && directions.charAt(idx) == 'L') { + idx++; + } + int carsFromRight = 0; + int collisionCount = 0; + while (idx < directions.length()) { + if (directions.charAt(idx) == 'R') { + carsFromRight++; + } else { + collisionCount += directions.charAt(idx) == 'S' ? carsFromRight : carsFromRight + 1; + carsFromRight = 0; + } + idx++; + } + return collisionCount; + } +} diff --git a/Medium/Count Complete Substrings.java b/Medium/Count Complete Substrings.java new file mode 100644 index 00000000..995cf4b0 --- /dev/null +++ b/Medium/Count Complete Substrings.java @@ -0,0 +1,54 @@ +class Solution { + public int countCompleteSubstrings(String word, int k) { + int count = 0; + StringBuilder sb = new StringBuilder(); + int n = word.length(); + for (int i = 0; i < n; i++) { + sb.append(word.charAt(i)); + if (i < n - 1 && Math.abs(word.charAt(i) - word.charAt(i + 1)) > 2) { + count += calculateSubstrings(sb.toString(), k); + sb.setLength(0); + } + } + count += calculateSubstrings(sb.toString(), k); + return count; + } + + private int calculateSubstrings(String s, int k) { + int count = 0; + int n = s.length(); + for (int i = 1; i <= 26; i++) { + int len = k * i; + int[] freq = new int[26]; + if (len > n) { + break; + } + for (int j = 0; j < len; j++) { + freq[s.charAt(j) - 'a']++; + } + if (check(freq, i, k)) { + count++; + } + for (int j = len; j < n; j++) { + freq[s.charAt(j - len) - 'a']--; + freq[s.charAt(j) - 'a']++; + if (check(freq, i, k)) { + count++; + } + } + } + return count; + } + + private boolean check(int[] freq, int i, int k) { + for (int value : freq) { + if (value == 0) { + continue; + } + if (value != k) { + return false; + } + } + return true; + } +} diff --git a/Medium/Count Complete Tree Nodes.java b/Medium/Count Complete Tree Nodes.java index 2ee43014..822c178d 100644 --- a/Medium/Count Complete Tree Nodes.java +++ b/Medium/Count Complete Tree Nodes.java @@ -4,36 +4,35 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public int countNodes(TreeNode root) { - if (root == null) { - return 0; + int leftDepth = getDepth(root, -1); + int rightDepth = getDepth(root, 1); + if (leftDepth == rightDepth) { + return (1 << leftDepth) - 1; } - - int leftHeight = getHeight(root, 0); - int rightHeight = getHeight(root, 1); - - if (leftHeight == rightHeight) { - return (2 << (leftHeight - 1)) - 1; - } - - return countNodes(root.left) + countNodes(root.right) + 1; + return 1 + countNodes(root.left) + countNodes(root.right); } - private int getHeight(TreeNode root, int dir) { - if (root == null) { - return 0; - } - - int height = 1; + private int getDepth(TreeNode root, int dir) { + int depth = 0; while (root != null) { - root = dir == 0 ? root.left : root.right; - height++; + depth++; + if (dir == -1) { + root = root.left; + } else { + root = root.right; + } } - - return height - 1; + return depth; } } diff --git a/Medium/Count Days Without Meetings.java b/Medium/Count Days Without Meetings.java new file mode 100644 index 00000000..1630e6df --- /dev/null +++ b/Medium/Count Days Without Meetings.java @@ -0,0 +1,24 @@ +class Solution { + public int countDays(int days, int[][] meetings) { + Arrays.sort(meetings, (o1, o2) -> { + int c = Integer.compare(o1[0], o2[0]); + if (c != 0) { + return c; + } + return Integer.compare(o2[1], o1[1]); + }); + int meetingDays = 0; + int idx = 0; + while (idx < meetings.length) { + int start = meetings[idx][0]; + int end = meetings[idx][1]; + idx++; + while (idx < meetings.length && meetings[idx][0] <= end) { + end = Math.max(end, meetings[idx][1]); + idx++; + } + meetingDays += (end - start + 1); + } + return days - meetingDays; + } +} diff --git a/Medium/Count Good Nodes in Binary Tree.java b/Medium/Count Good Nodes in Binary Tree.java new file mode 100644 index 00000000..d3888f9d --- /dev/null +++ b/Medium/Count Good Nodes in Binary Tree.java @@ -0,0 +1,65 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int goodNodes(TreeNode root) { + int[] count = {0}; + getGoodNodesCountRecursive(root, Integer.MIN_VALUE, count); + return count[0]; + } + + private void getGoodNodesCountRecursive(TreeNode root, int currMax, int[] count) { + if (root == null) { + return; + } + if (root.val >= currMax) { + count[0]++; + } + getGoodNodesCountRecursive(root.left, Math.max(currMax, root.val), count); + getGoodNodesCountRecursive(root.right, Math.max(currMax, root.val), count); + } + + private int getGoodNodesCountNonRecursive(TreeNode root) { + if (root == null) { + return 0; + } + int count = 0; + Queue queue = new LinkedList<>(); + queue.add(new TreePair(root, Integer.MIN_VALUE)); + while (!queue.isEmpty()) { + TreePair removed = queue.remove(); + if (removed.node.val >= removed.currMax) { + count++; + } + if (removed.node.left != null) { + queue.add(new TreePair(removed.node.left, Math.max(removed.node.val, removed.currMax))); + } + if (removed.node.right != null) { + queue.add(new TreePair(removed.node.right, Math.max(removed.node.val, removed.currMax))); + } + } + return count; + } + + class TreePair { + int currMax; + TreeNode node; + + public TreePair(TreeNode node, int currMax) { + this.currMax = currMax; + this.node = node; + } + } +} diff --git a/Medium/Count Mentions Per User.java b/Medium/Count Mentions Per User.java new file mode 100644 index 00000000..7fa42668 --- /dev/null +++ b/Medium/Count Mentions Per User.java @@ -0,0 +1,61 @@ +class Solution { + public int[] countMentions(int numberOfUsers, List> eventLog) { + List events = eventLog.stream() + .map(Event::buildEvent) + .sorted() + .collect(Collectors.toList()); + Map offlineUsers = new HashMap<>(); + int[] mentions = new int[numberOfUsers]; + for (Event event : events) { + if (event.message().equals("OFFLINE")) { + offlineUsers.put(Integer.parseInt(event.mentionString()), event.timestamp()); + } else { + int timestamp = event.timestamp(); + List onlineUsers = offlineUsers.entrySet() + .stream() + .filter(t -> timestamp - t.getValue() >= 60) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + onlineUsers.forEach(offlineUsers::remove); + String mentionString = event.mentionString(); + if (mentionString.equals("ALL")) { + for (int i = 0; i < numberOfUsers; i++) { + mentions[i]++; + } + } else if (mentionString.equals("HERE")) { + for (int i = 0; i < numberOfUsers; i++) { + if (!offlineUsers.containsKey(i)) { + mentions[i]++; + } + } + } else { + String[] usersMentioned = mentionString.split(" "); + for (String user : usersMentioned) { + int userId = Integer.parseInt(user.substring(2)); + mentions[userId]++; + } + } + } + } + return mentions; + } + + private record Event(String message, int timestamp, String mentionString) implements Comparable { + + public static Event buildEvent(List event) { + String message = event.get(0); + int timestamp = Integer.parseInt(event.get(1)); + String mentionString = event.get(2); + return new Event(message, timestamp, mentionString); + } + + @Override + public int compareTo(Event o) { + int c = this.timestamp - o.timestamp; + if (c != 0) { + return c; + } + return o.message().compareTo(this.message()); + } + } +} diff --git a/Medium/Count Nodes Equal to Average of Subtree.java b/Medium/Count Nodes Equal to Average of Subtree.java new file mode 100644 index 00000000..5a6d2d75 --- /dev/null +++ b/Medium/Count Nodes Equal to Average of Subtree.java @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int averageOfSubtree(TreeNode root) { + int[] result = {0}; + recurse(root, result); + return result[0]; + } + + private int[] recurse(TreeNode root, int[] result) { + if (root == null) { + return new int[]{0, 0}; + } + int[] left = recurse(root.left, result); + int[] right = recurse(root.right, result); + int sum = left[0] + right[0] + root.val; + int count = left[1] + right[1] + 1; + if (count != 0 && sum / count == root.val) { + result[0]++; + } + return new int[]{sum, count}; + } +} diff --git a/Medium/Count Nodes Equal to Sum of Descendants.java b/Medium/Count Nodes Equal to Sum of Descendants.java new file mode 100644 index 00000000..85597629 --- /dev/null +++ b/Medium/Count Nodes Equal to Sum of Descendants.java @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int equalToDescendants(TreeNode root) { + int[] count = {0}; + helper(root, count); + return count[0]; + } + + private int helper(TreeNode root, int[] count) { + if (root == null) { + return 0; + } + int leftSum = helper(root.left, count); + int rightSum = helper(root.right, count); + if (root.val == leftSum + rightSum) { + count[0]++; + } + return root.val + leftSum + rightSum; + } +} diff --git a/Medium/Count Number of Bad Pairs.java b/Medium/Count Number of Bad Pairs.java new file mode 100644 index 00000000..e1002897 --- /dev/null +++ b/Medium/Count Number of Bad Pairs.java @@ -0,0 +1,12 @@ +class Solution { + public long countBadPairs(int[] nums) { + long result = 0; + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + int prevCount = map.getOrDefault(i - nums[i], 0); + result += i - prevCount; + map.put(i - nums[i], prevCount + 1); + } + return result; + } +} diff --git a/Medium/Count Number of Distinct Integers After Reverse Operations.java b/Medium/Count Number of Distinct Integers After Reverse Operations.java new file mode 100644 index 00000000..ecf51e81 --- /dev/null +++ b/Medium/Count Number of Distinct Integers After Reverse Operations.java @@ -0,0 +1,19 @@ +class Solution { + public int countDistinctIntegers(int[] nums) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + set.add(reverse(num)); + } + return set.size(); + } + + private int reverse(int num) { + int reversed = 0; + while (num > 0) { + reversed = reversed * 10 + num % 10; + num /= 10; + } + return reversed; + } +} diff --git a/Medium/Count Number of Homogenous Substrings.java b/Medium/Count Number of Homogenous Substrings.java new file mode 100644 index 00000000..4a543690 --- /dev/null +++ b/Medium/Count Number of Homogenous Substrings.java @@ -0,0 +1,18 @@ +class Solution { + + private static final int MOD = 1_000_000_007; + + public int countHomogenous(String s) { + int result = 0; + int streak = 0; + for (int i = 0; i < s.length(); i++) { + if (i == 0 || s.charAt(i) == s.charAt(i - 1)) { + streak++; + } else { + streak = 1; + } + result = (result + streak) % MOD; + } + return result; + } +} diff --git a/Medium/Count Number of Maximum Bitwise-OR Subsets.java b/Medium/Count Number of Maximum Bitwise-OR Subsets.java new file mode 100644 index 00000000..973e1818 --- /dev/null +++ b/Medium/Count Number of Maximum Bitwise-OR Subsets.java @@ -0,0 +1,23 @@ +class Solution { + public int countMaxOrSubsets(int[] nums) { + int n = nums.length; + int maxValue = 0; + for (int num : nums) { + maxValue |= num; + } + Integer[][] dp = new Integer[n][maxValue + 1]; + return countMaxOrSubsets(nums, 0, 0, maxValue, dp); + } + + private int countMaxOrSubsets(int[] nums, int idx, int current, int maxValue, Integer[][] dp) { + if (idx == nums.length) { + return (current == maxValue) ? 1 : 0; + } + if (dp[idx][current] != null) { + return dp[idx][current]; + } + int countWithout = countMaxOrSubsets(nums, idx + 1, current, maxValue, dp); + int countWith = countMaxOrSubsets(nums, idx + 1, current | nums[idx], maxValue, dp); + return dp[idx][current] = countWith + countWithout; + } +} diff --git a/Medium/Count Number of Nice Subarrays.java b/Medium/Count Number of Nice Subarrays.java new file mode 100644 index 00000000..e2648bd3 --- /dev/null +++ b/Medium/Count Number of Nice Subarrays.java @@ -0,0 +1,14 @@ +class Solution { + public int numberOfSubarrays(int[] nums, int k) { + int sum = 0; + int count = 0; + Map map = new HashMap<>(); + map.put(sum, 1); + for (int i = 0; i < nums.length; i++) { + sum += nums[i] % 2; + count += map.getOrDefault(sum - k, 0); + map.put(sum, map.getOrDefault(sum, 0) + 1); + } + return count; + } +} diff --git a/Medium/Count Number of Teams.java b/Medium/Count Number of Teams.java new file mode 100644 index 00000000..26e0771e --- /dev/null +++ b/Medium/Count Number of Teams.java @@ -0,0 +1,19 @@ +class Solution { + public int numTeams(int[] rating) { + int res = 0; + for (int i = 0; i < rating.length - 1; i++) { + int[] less = new int[2]; + int[] great = new int[2]; + for (int j = 0; j < rating.length; j++) { + if (rating[i] < rating[j]) { + less[i > j ? 0 : 1]++; + } + if (rating[i] > rating[j]) { + great[i > j ? 0 : 1]++; + } + } + res += less[0] * great[1] + less[1] * great[0]; + } + return res; + } +} diff --git a/Medium/Count Servers That Communicate.java b/Medium/Count Servers That Communicate.java new file mode 100644 index 00000000..34de8d30 --- /dev/null +++ b/Medium/Count Servers That Communicate.java @@ -0,0 +1,25 @@ +class Solution { + public int countServers(int[][] grid) { + int m = grid.length; + int n = grid[0].length; + int[] rowCount = new int[m]; + int[] colCount = new int[n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1) { + rowCount[i]++; + colCount[j]++; + } + } + } + int connectedServerCount = 0; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1 && (rowCount[i] > 1 || colCount[j] > 1)) { + connectedServerCount++; + } + } + } + return connectedServerCount; + } +} diff --git a/Medium/Count Sorted Vowel Strings.java b/Medium/Count Sorted Vowel Strings.java new file mode 100644 index 00000000..757bf96e --- /dev/null +++ b/Medium/Count Sorted Vowel Strings.java @@ -0,0 +1,19 @@ +class Solution { + public int countVowelStrings(int n) { + Integer[][] memo = new Integer[n + 1][5]; + return topDownDP(n, 0, memo); + } + + private int topDownDP(int n, int idx, Integer[][] memo) { + if (n == 0) { + return 1; + } else if (idx == 5) { + return 0; + } else if (memo[n][idx] != null) { + return memo[n][idx]; + } + int numOfPermutations = topDownDP(n, idx + 1, memo); + numOfPermutations += topDownDP(n - 1, idx, memo); + return memo[n][idx] = numOfPermutations; + } +} diff --git a/Medium/Count Square Submatrices with All Ones.java b/Medium/Count Square Submatrices with All Ones.java new file mode 100644 index 00000000..03e98e58 --- /dev/null +++ b/Medium/Count Square Submatrices with All Ones.java @@ -0,0 +1,16 @@ +class Solution { + public int countSquares(int[][] matrix) { + int ans = 0; + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[i].length; j++) { + if (matrix[i][j] > 0 && i > 0 && j > 0) { + matrix[i][j] = Math.min( + matrix[i - 1][j - 1], Math.min(matrix[i - 1][j], matrix[i][j - 1]) + ) + 1; + } + ans += matrix[i][j]; + } + } + return ans; + } +} diff --git a/Medium/Count Sub Islands.java b/Medium/Count Sub Islands.java new file mode 100644 index 00000000..adee5af9 --- /dev/null +++ b/Medium/Count Sub Islands.java @@ -0,0 +1,42 @@ +class Solution { + private final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int countSubIslands(int[][] grid1, int[][] grid2) { + int numRows = grid1.length; + int numCols = grid1[0].length; + int subIslandCount = 0; + boolean[][] visited = new boolean[numRows][numCols]; + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + if (!visited[i][j] && grid2[i][j] == 1) { + Queue queue = new LinkedList<>(); + queue.add(new int[]{i, j}); + boolean isSubisland = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + if (visited[x][y]) { + continue; + } + if (grid1[x][y] != 1) { + isSubisland = false; + } + visited[x][y] = true; + for (int[] dir : DIRS) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newY >= 0 && newX < numRows && newY < numCols && !visited[newX][newY] && grid2[newX][newY] == 1) { + queue.add(new int[]{newX, newY}); + } + } + } + if (isSubisland) { + subIslandCount++; + } + } + } + } + return subIslandCount; + } +} diff --git a/Medium/Count Subarrays Where Max Element Appears at Least K Times.java b/Medium/Count Subarrays Where Max Element Appears at Least K Times.java new file mode 100644 index 00000000..d917693d --- /dev/null +++ b/Medium/Count Subarrays Where Max Element Appears at Least K Times.java @@ -0,0 +1,24 @@ +class Solution { + public long countSubarrays(int[] nums, int k) { + int maxElement = 0; + for (int num : nums) { + maxElement = Math.max(maxElement, num); + } + long result = 0; + int start = 0; + int maxElementsInWindow = 0; + for (int end = 0; end < nums.length; end++) { + if (nums[end] == maxElement) { + maxElementsInWindow++; + } + while (k == maxElementsInWindow) { + if (nums[start] == maxElement) { + maxElementsInWindow--; + } + start++; + } + result += start; + } + return result; + } +} diff --git a/Medium/Count Submatrices With All Ones.java b/Medium/Count Submatrices With All Ones.java new file mode 100644 index 00000000..d1175355 --- /dev/null +++ b/Medium/Count Submatrices With All Ones.java @@ -0,0 +1,27 @@ +class Solution { + public int numSubmat(int[][] mat) { + int m = mat.length; + int n = mat[0].length; + int res = 0; + for (int i = 0; i < m; i++) { + int[] arr = new int[n]; + Arrays.fill(arr, 1); + for (int j = i; j < m; j++) { + for (int k = 0; k < n; k++) { + arr[k] &= mat[j][k]; + } + res += countOneRow(arr); + } + } + return res; + } + + private int countOneRow(int[] A) { + int res = 0, length = 0; + for (int i = 0; i < A.length; ++i) { + length = (A[i] == 0 ? 0 : length + 1); + res += length; + } + return res; + } +} diff --git a/Medium/Count Substrings Without Repeating Character.java b/Medium/Count Substrings Without Repeating Character.java new file mode 100644 index 00000000..6ffcf7cd --- /dev/null +++ b/Medium/Count Substrings Without Repeating Character.java @@ -0,0 +1,19 @@ +class Solution { + public int numberOfSpecialSubstrings(String s) { + int start = 0; + int end = 0; + int n = s.length(); + int result = 0; + Map map = new HashMap<>(); + while (end < n) { + map.put(s.charAt(end), map.getOrDefault(s.charAt(end), 0) + 1); + while (start < end && map.get(s.charAt(end)) > 1) { + map.put(s.charAt(start), map.get(s.charAt(start)) - 1); + start++; + } + end++; + result += end - start; + } + return result; + } +} diff --git a/Medium/Count Total Number of Colored Cells.java b/Medium/Count Total Number of Colored Cells.java new file mode 100644 index 00000000..81c10a8c --- /dev/null +++ b/Medium/Count Total Number of Colored Cells.java @@ -0,0 +1,11 @@ +class Solution { + public long coloredCells(int n) { + long count = 1; + int increment = 4; + while (n-- > 1) { + count += increment; + increment += 4; + } + return count; + } +} diff --git a/Medium/Count Univalue Subtrees.java b/Medium/Count Univalue Subtrees.java index db729e21..73ac6599 100644 --- a/Medium/Count Univalue Subtrees.java +++ b/Medium/Count Univalue Subtrees.java @@ -4,37 +4,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - int count = 0; - public int countUnivalSubtrees(TreeNode root) { - updateCount(root); - return count; + public int countUnivalSubtrees(TreeNode root) { + if (root == null) { + return 0; } - - private void updateCount(TreeNode root) { - if (root == null) { - return; - } - - if (isUnivalue(root, root.val)) { - count++; - } - - updateCount(root.left); - updateCount(root.right); + int[] count = {0}; + helper(root, count, root.val); + return count[0]; + } + + private boolean helper(TreeNode root, int[] count, int val) { + if (root == null) { + return true; } - - private boolean isUnivalue(TreeNode root, int val) { - if (root == null) { - return true; - } - if (root.val != val) { - return false; - } - - return isUnivalue(root.left, val) && isUnivalue(root.right, val); + if (!helper(root.left, count, root.val) | !helper(root.right, count, root.val)) { + return false; } + count[0]++; + return root.val == val; + } } diff --git a/Medium/Count Unreachable Pairs of Nodes in an Undirected Graph.java b/Medium/Count Unreachable Pairs of Nodes in an Undirected Graph.java new file mode 100644 index 00000000..4b927bce --- /dev/null +++ b/Medium/Count Unreachable Pairs of Nodes in an Undirected Graph.java @@ -0,0 +1,36 @@ +class Solution { + public long countPairs(int n, int[][] edges) { + Map> graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new HashSet<>()).add(edge[1]); + graph.computeIfAbsent(edge[1], k -> new HashSet<>()).add(edge[0]); + } + boolean[] visited = new boolean[n]; + long unreachableNodeCount = (((long) n) * (n - 1)) / 2; + for (int i = 0; i < n; i++) { + if (!visited[i]) { + long reachCount = traverseHelper(i, graph, visited); + unreachableNodeCount -= (reachCount * (reachCount - 1)) / 2; + } + } + return unreachableNodeCount; + } + + private long traverseHelper(int node, Map> graph, boolean[] visited) { + Queue queue = new LinkedList<>(); + long count = 0; + queue.add(node); + visited[node] = true; + while (!queue.isEmpty()) { + int removed = queue.remove(); + count++; + for (Integer conn : graph.getOrDefault(removed, new HashSet<>())) { + if (!visited[conn]) { + visited[conn] = true; + queue.add(conn); + } + } + } + return count; + } +} diff --git a/Medium/Count Vowel Strings in Ranges.java b/Medium/Count Vowel Strings in Ranges.java new file mode 100644 index 00000000..8f836610 --- /dev/null +++ b/Medium/Count Vowel Strings in Ranges.java @@ -0,0 +1,26 @@ +class Solution { + + public int[] vowelStrings(String[] words, int[][] queries) { + int[] counter = new int[words.length]; + int currCounter = 0; + for (int i = 0; i < words.length; i++) { + String word = words[i]; + if (isVowel(word.charAt(0)) && isVowel(word.charAt(word.length() - 1))) { + currCounter++; + } + counter[i] = currCounter; + } + int[] result = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int left = queries[i][0]; + int right = queries[i][1]; + result[i] = counter[right]; + result[i] -= left == 0 ? 0 : counter[left - 1]; + } + return result; + } + + private static boolean isVowel(char c) { + return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'; + } +} diff --git a/Medium/Count Ways To Build Good Strings.java b/Medium/Count Ways To Build Good Strings.java new file mode 100644 index 00000000..16991f0c --- /dev/null +++ b/Medium/Count Ways To Build Good Strings.java @@ -0,0 +1,23 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int countGoodStrings(int low, int high, int zero, int one) { + int[] dp = new int[high + 1]; + dp[0] = 1; + for (int i = 1; i <= high; i++) { + if (i >= zero) { + dp[i] += dp[i - zero]; + } + if (i >= one) { + dp[i] += dp[i - one]; + } + dp[i] %= MOD; + } + int result = 0; + for (int i = low; i <= high; i++) { + result = (result + dp[i]) % MOD; + } + return result; + } +} diff --git a/Medium/Count and Say.java b/Medium/Count and Say.java new file mode 100644 index 00000000..a32318be --- /dev/null +++ b/Medium/Count and Say.java @@ -0,0 +1,19 @@ +class Solution { + public String countAndSay(int n) { + String s = "1"; + for (int i = 1; i < n; i++) { + StringBuilder sb = new StringBuilder(); + for (int j = 1, count = 1; j <= s.length(); j++) { + if (j == s.length() || s.charAt(j - 1) != s.charAt(j)) { + sb.append(count); + sb.append(s.charAt(j - 1)); + count = 1; + } else { + count++; + } + } + s = sb.toString(); + } + return s; + } +} diff --git a/Medium/Count the Number of Complete Components.java b/Medium/Count the Number of Complete Components.java new file mode 100644 index 00000000..d198b0b2 --- /dev/null +++ b/Medium/Count the Number of Complete Components.java @@ -0,0 +1,38 @@ +class Solution { + public int countCompleteComponents(int n, int[][] edges) { + Map> graph = new HashMap<>(); + for (int[] edge : edges) { + int nodeOne = edge[0]; + int nodeTwo = edge[1]; + graph.computeIfAbsent(nodeOne, k -> new HashSet<>()).add(nodeTwo); + graph.computeIfAbsent(nodeTwo, k -> new HashSet<>()).add(nodeOne); + } + int count = 0; + Set visited = new HashSet<>(); + for (int i = 0; i < n; i++) { + if (visited.add(i)) { + int[] componentInfo = new int[2]; + dfs(i, graph, visited, componentInfo); + if (componentInfo[0] * (componentInfo[0] - 1) == componentInfo[1]) { + count++; + } + } + } + return count; + } + + private void dfs( + int node, + Map> graph, + Set visited, + int[] componentInfo) { + componentInfo[0]++; + Set connections = graph.getOrDefault(node, new HashSet<>()); + componentInfo[1] += connections.size(); + for (Integer conn : connections) { + if (visited.add(conn)) { + dfs(conn, graph, visited, componentInfo); + } + } + } +} diff --git a/Medium/Count the Number of Good Nodes.java b/Medium/Count the Number of Good Nodes.java new file mode 100644 index 00000000..d100513d --- /dev/null +++ b/Medium/Count the Number of Good Nodes.java @@ -0,0 +1,34 @@ +class Solution { + public int countGoodNodes(int[][] edges) { + Map> map = new HashMap<>(); + for (int[] edge : edges) { + map.computeIfAbsent(edge[0], k -> new HashSet<>()).add(edge[1]); + map.computeIfAbsent(edge[1], k -> new HashSet<>()).add(edge[0]); + } + int[] result = {0}; + recurse(map, result, 0, -1); + return result[0]; + } + + private int recurse(Map> map, int[] result, int node, int prevNode) { + int count = -1; + int total = 1; + boolean flag = true; + for (Integer conn : map.getOrDefault(node, new HashSet<>())) { + if (conn == prevNode) { + continue; + } + int temp = recurse(map, result, conn, node); + total += temp; + if (count == -1) { + count = temp; + } else if (count != temp) { + flag = false; + } + } + if (flag) { + result[0]++; + } + return total; + } +} diff --git a/Medium/Counting Bits.java b/Medium/Counting Bits.java deleted file mode 100644 index ee39c468..00000000 --- a/Medium/Counting Bits.java +++ /dev/null @@ -1,13 +0,0 @@ -class Solution { - public int[] countBits(int num) { - int result[] = new int[num + 1]; - int offset = 1; - for (int index = 1; index < num + 1; ++index){ - if (offset * 2 == index){ - offset *= 2; - } - result[index] = result[index - offset] + 1; - } - return result; - } -} diff --git a/Medium/Course Schedule II.java b/Medium/Course Schedule II.java index 3fa48520..ce957faf 100644 --- a/Medium/Course Schedule II.java +++ b/Medium/Course Schedule II.java @@ -1,47 +1,32 @@ class Solution { public int[] findOrder(int numCourses, int[][] prerequisites) { - Map> map = new HashMap<>(); + Map> map = new HashMap<>(); + int[] indegree = new int[numCourses]; for (int[] prerequisite : prerequisites) { - map.computeIfAbsent(prerequisite[0], k -> new ArrayList<>()).add(prerequisite[1]); + int course = prerequisite[0]; + int dependency = prerequisite[1]; + map.computeIfAbsent(dependency, k -> new HashSet<>()).add(course); + indegree[course]++; } - - boolean[] registered = new boolean[numCourses]; - Stack stack = new Stack<>(); + Queue queue = new LinkedList<>(); + int[] result = new int[numCourses]; + int resultIdx = 0; + Set taken = new HashSet<>(); for (int i = 0; i < numCourses; i++) { - if (!isDeadlock(i, map, stack, registered, new boolean[numCourses])) { - return new int[]{}; + if (indegree[i] == 0) { + queue.add(i); } } - - int[] ans = new int[numCourses]; - int idx = numCourses - 1; - while (!stack.isEmpty()) { - ans[idx--] = stack.pop(); - } - - return ans; - } - - private boolean isDeadlock(int c1, Map> map, Stack stack, boolean[] registered, boolean[] visited) { - if (registered[c1]) { - return true; - } - - if (visited[c1]) { - return false; - } - - visited[c1] = true; - for (Integer prereq : map.getOrDefault(c1, new ArrayList<>())) { - if (!isDeadlock(prereq, map, stack, registered, visited)) { - return false; + while (!queue.isEmpty()) { + int removed = queue.remove(); + result[resultIdx++] = removed; + for (Integer dependent : map.getOrDefault(removed, new HashSet<>())) { + indegree[dependent]--; + if (indegree[dependent] == 0) { + queue.add(dependent); + } } } - - registered[c1] = true; - stack.push(c1); - - return true; + return resultIdx == numCourses ? result : new int[0]; } - } diff --git a/Medium/Course Schedule.java b/Medium/Course Schedule.java index 5d651ec9..1f8c0693 100644 --- a/Medium/Course Schedule.java +++ b/Medium/Course Schedule.java @@ -1,31 +1,31 @@ class Solution { - Set set = new HashSet<>(); public boolean canFinish(int numCourses, int[][] prerequisites) { + int[] indegree = new int[numCourses]; Map> map = new HashMap<>(); - for (int[] prereq : prerequisites) { - map.computeIfAbsent(prereq[0], k -> new HashSet<>()).add(prereq[1]); + for (int[] prerequisite : prerequisites) { + int course = prerequisite[0]; + int prereq = prerequisite[1]; + indegree[course]++; + map.computeIfAbsent(prereq, k -> new HashSet<>()).add(course); } - + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); for (int i = 0; i < numCourses; i++) { - set.clear(); - dfsHelper(map, i); - - if (set.contains(i)) { - return false; - } + if (indegree[i] == 0) { + queue.add(i); + visited.add(i); + } } - - return true; - } - - private void dfsHelper(Map> map, int courseNum) { - Iterator iterator = map.getOrDefault(courseNum, new HashSet<>()).iterator(); - while (iterator.hasNext()) { - int course = iterator.next(); - if (!set.contains(course)) { - set.add(course); - dfsHelper(map, course); + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer conn : map.getOrDefault(removed, new HashSet<>())) { + indegree[conn]--; + if (indegree[conn] == 0) { + queue.add(conn); + visited.add(conn); + } } } + return visited.size() == numCourses; } } diff --git a/Medium/Cousins in Binary Tree II.java b/Medium/Cousins in Binary Tree II.java new file mode 100644 index 00000000..ee1b4b21 --- /dev/null +++ b/Medium/Cousins in Binary Tree II.java @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode replaceValueInTree(TreeNode root) { + Queue queue = new LinkedList<>(); + queue.add(root); + int prevLevelSum = root.val; + while (!queue.isEmpty()) { + int size = queue.size(); + int levelSum = 0; + for (int i = 0; i < size; i++) { + TreeNode node = queue.remove(); + node.val = prevLevelSum - node.val; + int siblingSum = (node.left != null ? node.left.val : 0) + + (node.right != null ? node.right.val : 0); + if (node.left != null) { + levelSum += node.left.val; + node.left.val = siblingSum; + queue.add(node.left); + } + if (node.right != null) { + levelSum += node.right.val; + node.right.val = siblingSum; + queue.add(node.right); + } + } + prevLevelSum = levelSum; + } + return root; + } +} diff --git a/Medium/Create Binary Tree From Descriptions.java b/Medium/Create Binary Tree From Descriptions.java new file mode 100644 index 00000000..bb04e8d2 --- /dev/null +++ b/Medium/Create Binary Tree From Descriptions.java @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode createBinaryTree(int[][] descriptions) { + Map nodeMapping = new HashMap<>(); + Set childNodes = new HashSet<>(); + for (int[] description : descriptions) { + nodeMapping.putIfAbsent(description[0], new TreeNode(description[0])); + nodeMapping.putIfAbsent(description[1], new TreeNode(description[1])); + if (description[2] == 1) { + nodeMapping.get(description[0]).left = nodeMapping.get(description[1]); + } else { + nodeMapping.get(description[0]).right = nodeMapping.get(description[1]); + } + childNodes.add(description[1]); + } + for (Integer key : nodeMapping.keySet()) { + if (!childNodes.contains(key)) { + return nodeMapping.get(key); + } + } + return null; + } +} diff --git a/Medium/Custom Sort String.java b/Medium/Custom Sort String.java index 15bd4cbd..ecdcb98d 100644 --- a/Medium/Custom Sort String.java +++ b/Medium/Custom Sort String.java @@ -1,27 +1,23 @@ class Solution { - public String customSortString(String S, String T) { - int[] counter = new int[26]; - for (char c : T.toCharArray()) { - counter[c - 'a']++; - } - - StringBuilder sb = new StringBuilder(); - for (char c : S.toCharArray()) { - int count = counter[c - 'a']; - for (int i = 0; i < count; i++) { - sb.append(c); - } - - counter[c - 'a'] = 0; - } - - for (char c ='a'; c <= 'z'; c++) { - int count = counter[c - 'a']; - for (int i = 0; i < count; i++) { - sb.append(c); - } - } - - return sb.toString(); + public String customSortString(String order, String s) { + Map frequency = new HashMap<>(); + for (char c : s.toCharArray()) { + frequency.put(c, frequency.getOrDefault(c, 0) + 1); } + StringBuilder sb = new StringBuilder(); + for (char c : order.toCharArray()) { + int count = frequency.getOrDefault(c, 0); + while (count-- > 0) { + sb.append(c); + } + frequency.put(c, 0); + } + for (Character key : frequency.keySet()) { + int count = frequency.getOrDefault(key, 0); + while (count-- > 0) { + sb.append(key); + } + } + return sb.toString(); + } } diff --git a/Medium/Daily Temperatures.java b/Medium/Daily Temperatures.java index 2c1f7b91..5189f7ee 100644 --- a/Medium/Daily Temperatures.java +++ b/Medium/Daily Temperatures.java @@ -1,17 +1,15 @@ class Solution { - public int[] dailyTemperatures(int[] T) { + public int[] dailyTemperatures(int[] temperatures) { + int n = temperatures.length; + int[] result = new int[n]; Stack stack = new Stack<>(); - int[] ans = new int[T.length]; - - for (int i = T.length - 1; i >= 0; i--) { - while (!stack.isEmpty() && T[i] >= T[stack.peek()]) { + for (int i = n - 1; i >= 0; i--) { + while (!stack.isEmpty() && temperatures[i] >= temperatures[stack.peek()]) { stack.pop(); } - - ans[i] = stack.isEmpty() ? 0 : stack.peek() - i; + result[i] = stack.isEmpty() ? 0 : stack.peek() - i; stack.push(i); } - - return ans; + return result; } } diff --git a/Medium/Decode String.java b/Medium/Decode String.java index 7381fd10..fb2f81de 100644 --- a/Medium/Decode String.java +++ b/Medium/Decode String.java @@ -1,39 +1,32 @@ class Solution { - public static String decodeString(String s) { - Stack count = new Stack<>(); - Stack str = new Stack<>(); - int i = 0; - str.push(""); - while(i < s.length()) { - if (s.charAt(i) >= '0' && s.charAt(i) <= '9') { - int start = i; - while (s.charAt(i+1) >= '0' && s.charAt(i+1) <= '9') { - i++; - } - count.push(Integer.parseInt(s.substring(start, i + 1))); - } - else if (s.charAt(i) == '[') { - str.push(""); - } - else if (s.charAt(i) == ']') { - String st = str.pop(); - StringBuilder sb = new StringBuilder(); - int n = count.pop(); - - for (int j = 0; j < n; j++) { - sb.append(st); - } - - str.push(str.pop() + sb.toString()); - } - else { - str.push(str.pop() + s.charAt(i)); - } - - i++; + public String decodeString(String s) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (c == ']') { + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty() && stack.peek() != '[') { + sb.append(stack.pop()); } - - return str.pop(); + stack.pop(); + String temp = sb.toString(); + sb.setLength(0); + while (!stack.isEmpty() && Character.isDigit(stack.peek())) { + sb.append(stack.pop()); + } + int count = Integer.parseInt(sb.reverse().toString()); + while (count-- > 0) { + for (int i = temp.length() - 1; i >= 0; i--) { + stack.push(temp.charAt(i)); + } + } + } else { + stack.push(c); + } + } + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + sb.append(stack.pop()); } + return sb.reverse().toString(); + } } - diff --git a/Medium/Decode Ways.java b/Medium/Decode Ways.java index cbba3c77..a959c15a 100644 --- a/Medium/Decode Ways.java +++ b/Medium/Decode Ways.java @@ -1,58 +1,28 @@ class Solution { - int[] memo; - public int numDecodings(String s) { - if (s.length() == 0) { - return 0; - } - - memo = new int[s.length() + 1]; - Arrays.fill(memo, -1); - - return helperDp(0, s); + + public int numDecodings(String s) { + Map map = new HashMap<>(); + return helper(s, 0, map); + } + + private int helper(String s, int idx, Map map) { + if (map.containsKey(idx)) { + return map.get(idx); } - - private int helperDp(int idx, String s) { - if (memo[idx] > -1) { - return memo[idx]; - } - - int n = s.length(); - if (idx == n) { - return memo[idx] = 1; - } - - if (s.charAt(idx) == '0') { - return memo[idx] = 0; - } - - int temp = helperRecursive(idx + 1, s); - memo[idx + 1] = temp; - - if (idx < n - 1 && (s.charAt(idx) == '1' || (s.charAt(idx) == '2' && s.charAt(idx + 1) < '7'))) { - memo[idx + 2] = helperRecursive(idx + 2, s); - temp += memo[idx + 2]; - } - - return temp; + if (idx == s.length()) { + return 1; } - - private int helperRecursive(int idx, String s) { - int n = s.length(); - - if (idx == n) { - return 1; - } - - if (s.charAt(idx) == '0') { - return 0; - } - - int temp = helperRecursive(idx + 1, s); - - if (idx < n - 1 && (s.charAt(idx) == '1' || (s.charAt(idx) == '2' && s.charAt(idx + 1) < '7'))) { - temp += helperRecursive(idx + 2, s); - } - - return temp; + if (s.charAt(idx) == '0') { + return 0; } + if (idx == s.length() - 1) { + return 1; + } + int result = helper(s, idx + 1, map); + if (Integer.parseInt(s.substring(idx, idx + 2)) <= 26) { + result += helper(s, idx + 2, map); + } + map.put(idx, result); + return result; + } } diff --git a/Medium/Decoded String at Index.java b/Medium/Decoded String at Index.java new file mode 100644 index 00000000..a0c94968 --- /dev/null +++ b/Medium/Decoded String at Index.java @@ -0,0 +1,27 @@ +class Solution { + public String decodeAtIndex(String s, int k) { + long size = 0; + int n = s.length(); + for (int i = 0; i < n; i++) { + char c = s.charAt(i); + if (Character.isDigit(c)) { + size *= (c - '0'); + } else { + size++; + } + } + for (int i = n - 1; i >= 0; i--) { + char c = s.charAt(i); + k %= size; + if (k == 0 && Character.isLetter(c)) { + return Character.toString(c); + } + if (Character.isDigit(c)) { + size /= (c - '0'); + } else { + size--; + } + } + return ""; + } +} diff --git a/Medium/Decrease Elements To Make Array Zigzag.java b/Medium/Decrease Elements To Make Array Zigzag.java new file mode 100644 index 00000000..4dcfd567 --- /dev/null +++ b/Medium/Decrease Elements To Make Array Zigzag.java @@ -0,0 +1,28 @@ +class Solution { + public int movesToMakeZigzag(int[] nums) { + return Math.min(calculateMove(nums, true), calculateMove(nums, false)); + } + + private int calculateMove(int[] nums, boolean isEven) { + int count = 0; + + for (int i = (isEven ? 0 : 1); i < nums.length; i += 2) { + int curr = 0; + if (i + 1 < nums.length) { + if (nums[i] >= nums[i + 1]) { + curr = nums[i] - nums[i + 1] + 1; + } + } + + if (i - 1 >= 0) { + if (nums[i] >= nums[i - 1]) { + curr = Math.max(curr, nums[i] - nums[i - 1] + 1); + } + } + + count += curr; + } + + return count; + } +} diff --git a/Medium/Deepest Leaves Sum.java b/Medium/Deepest Leaves Sum.java new file mode 100644 index 00000000..df67a081 --- /dev/null +++ b/Medium/Deepest Leaves Sum.java @@ -0,0 +1,33 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int deepestLeavesSum(TreeNode root) { + Map map = new HashMap<>(); + helper(root, 0, map); + return map.getOrDefault( + map.keySet().stream().mapToInt(Integer::valueOf).max().orElse(0), 0 + ); + } + + private void helper(TreeNode root, int currLevel, Map map) { + if (root == null) { + return; + } + map.put(currLevel, map.getOrDefault(currLevel, 0) + root.val); + helper(root.left, currLevel + 1, map); + helper(root.right, currLevel + 1, map); + } +} diff --git a/Medium/Delete Leaves With a Given Value.java b/Medium/Delete Leaves With a Given Value.java new file mode 100644 index 00000000..6d55f07c --- /dev/null +++ b/Medium/Delete Leaves With a Given Value.java @@ -0,0 +1,67 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + Map map; // A Node-Parent map + public TreeNode removeLeafNodes(TreeNode root, int target) { + map = new HashMap<>(); + updateParentMap(root, null); + deleteLeaf(root, target); + return map.get(root) != null ? null : root; + } + + public TreeNode removeLeafNodesRecursive(TreeNode root, int target) { + if (root.left != null) { + root.left = removeLeafNodes(root.left, target); + } + if (root.right != null) { + root.right = removeLeafNodes(root.right, target); + } + return root.left == root.right && root.val == target ? null : root; + } + + private void updateParentMap(TreeNode curr, TreeNode parent) { + if (curr == null) { + return; + } + map.put(curr, parent); + updateParentMap(curr.left, curr); + updateParentMap(curr.right, curr); + } + + private void deleteLeaf(TreeNode curr, int target) { + if (curr == null) { + return; + } + if (curr.left == null && curr.right == null) { + if (curr.val == target) { + TreeNode parent = map.get(curr); + if (parent == null) { // If parent is null then mark the parent as -1 + map.put(curr, new TreeNode(-1)); + return; + } + // Else delete the node + if (parent.left == curr) { + parent.left = null; + } + else { + parent.right = null; + } + // If parent is leaf with target value then call recursion on parent + if (parent.left == null && parent.right == null && parent.val == target) { + deleteLeaf(parent, target); + } + } + } + else { + deleteLeaf(curr.left, target); + deleteLeaf(curr.right, target); + } + } +} diff --git a/Medium/Delete Node in a BST.java b/Medium/Delete Node in a BST.java index bcd23624..becc3b24 100644 --- a/Medium/Delete Node in a BST.java +++ b/Medium/Delete Node in a BST.java @@ -4,54 +4,35 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode deleteNode(TreeNode root, int key) { - if (root == null) { - return root; - } - - if (key < root.val) { - root.left = deleteNode(root.left, key); - } - else if (key > root.val) { - root.right = deleteNode(root.right, key); - } - else { - if (root.left == null || root.right == null) { - TreeNode temp = root.left == null ? root.right : root.left; - - if (temp == null) { - return null; - } - else { - return temp; - } - } - else { - TreeNode rightSuccessor = getRightSuccessor(root); - root.val = rightSuccessor.val; - root.right = deleteNode(root.right, rightSuccessor.val); - } - } - - return root; + public TreeNode deleteNode(TreeNode root, int key) { + if (root == null) { + return null; } - - private TreeNode getRightSuccessor(TreeNode node) { - if (node == null) { - return null; - } - - TreeNode temp = node.right; - if (temp != null) { - while (temp.left != null) { - temp = temp.left; - } - } - - return temp; + if (key > root.val) { + root.right = deleteNode(root.right, key); + } else if (key < root.val) { + root.left = deleteNode(root.left, key); + } else { + if (root.left == null || root.right == null) { + return root.left == null ? root.right : root.left; + } + TreeNode inorderSuccessor = root.right; + while (inorderSuccessor.left != null) { + inorderSuccessor = inorderSuccessor.left; + } + root.val = inorderSuccessor.val; + root.right = deleteNode(root.right, inorderSuccessor.val); } + return root; + } } diff --git a/Medium/Delete Nodes And Return Forest.java b/Medium/Delete Nodes And Return Forest.java new file mode 100644 index 00000000..344770b5 --- /dev/null +++ b/Medium/Delete Nodes And Return Forest.java @@ -0,0 +1,47 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List delNodes(TreeNode root, int[] toDelete) { + Set set = new HashSet<>(); + for (int val : toDelete) { + set.add(val); + } + List result = new ArrayList<>(); + recurse(root, result, set, null); + return result; + } + + private void recurse(TreeNode root, List result, Set set, TreeNode parent) { + if (root == null) { + return; + } + if (set.contains(root.val)) { + if (parent != null && parent.left == root) { + parent.left = null; + } else if (parent != null && parent.right == root) { + parent.right = null; + } + recurse(root.left, result, set, null); + recurse(root.right, result, set, null); + return; + } + if (parent == null) { + result.add(root); + } + recurse(root.left, result, set, root); + recurse(root.right, result, set, root); + } +} diff --git a/Medium/Delete Nodes From Linked List Present in Array.java b/Medium/Delete Nodes From Linked List Present in Array.java new file mode 100644 index 00000000..ff184902 --- /dev/null +++ b/Medium/Delete Nodes From Linked List Present in Array.java @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode modifiedList(int[] nums, ListNode head) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + while (head != null && set.contains(head.val)) { + head = head.next; + } + ListNode newHead = head; + ListNode curr = head; + while (curr.next != null) { + if (set.contains(curr.next.val)) { + curr.next = curr.next.next; + } else { + curr = curr.next; + } + } + return newHead; + } +} diff --git a/Medium/Delete Operation for Two Strings.java b/Medium/Delete Operation for Two Strings.java new file mode 100644 index 00000000..f5e48340 --- /dev/null +++ b/Medium/Delete Operation for Two Strings.java @@ -0,0 +1,21 @@ +class Solution { + public int minDistance(String word1, String word2) { + int[][] dp = new int[word1.length() + 1][word2.length() + 1]; + return word1.length() + word2.length() - 2 * longestCommonSubsequence(word1, word2, word1.length(), word2.length(), dp); + } + + private int longestCommonSubsequence(String word1, String word2, int m, int n, int[][] dp) { + if (m == 0 || n == 0) { + return 0; + } + if (dp[m][n] > 0) { + return dp[m][n]; + } + if (word1.charAt(m - 1) == word2.charAt(n - 1)) { + dp[m][n] = 1 + longestCommonSubsequence(word1, word2, m - 1, n - 1, dp); + } else { + dp[m][n] = Math.max(longestCommonSubsequence(word1, word2, m - 1, n, dp), longestCommonSubsequence(word1, word2, m, n - 1, dp)); + } + return dp[m][n]; + } +} diff --git a/Medium/Delete Tree Nodes.java b/Medium/Delete Tree Nodes.java new file mode 100644 index 00000000..ff35d30a --- /dev/null +++ b/Medium/Delete Tree Nodes.java @@ -0,0 +1,17 @@ +class Solution { + public int deleteTreeNodes(int nodes, int[] parent, int[] value) { + for (int i = nodes - 1; i > 0; i--) { + value[parent[i]] += value[i]; + } + Set set = new HashSet<>(); + for (int i = 0; i < nodes; i++) { + if (set.contains(parent[i])) { + value[i] = 0; + } + if (value[i] == 0) { + set.add(i); + } + } + return nodes - set.size(); + } +} diff --git a/Medium/Delete the Middle Node of a Linked List.java b/Medium/Delete the Middle Node of a Linked List.java new file mode 100644 index 00000000..1fe07371 --- /dev/null +++ b/Medium/Delete the Middle Node of a Linked List.java @@ -0,0 +1,25 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode deleteMiddle(ListNode head) { + if (head.next == null) { + return null; + } + ListNode slow = head; + ListNode fast = head.next.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + slow.next = slow.next.next; + return head; + } +} diff --git a/Medium/Design A Leaderboard.java b/Medium/Design A Leaderboard.java new file mode 100644 index 00000000..8ae6740f --- /dev/null +++ b/Medium/Design A Leaderboard.java @@ -0,0 +1,49 @@ +class Leaderboard { + + private Map playerToScoreMapping; + private Map> scoreToPlayerMapping; + + public Leaderboard() { + this.playerToScoreMapping = new HashMap<>(); + this.scoreToPlayerMapping = new TreeMap<>(Collections.reverseOrder()); + } + + public void addScore(int playerId, int score) { + if (playerToScoreMapping.containsKey(playerId)) { + int previousScore = playerToScoreMapping.get(playerId); + if (scoreToPlayerMapping.getOrDefault(previousScore, new HashSet<>()).contains(playerId)) { + scoreToPlayerMapping.get(previousScore).remove(playerId); + } + score += previousScore; + } + playerToScoreMapping.put(playerId, score); + scoreToPlayerMapping.computeIfAbsent(score, k -> new HashSet<>()).add(playerId); + } + + public int top(int K) { + int totalScore = 0; + for (Integer currScore : scoreToPlayerMapping.keySet()) { + int totalPlayersWithScore = scoreToPlayerMapping.get(currScore).size(); + int playersRemaining = Math.min(K, totalPlayersWithScore); + totalScore += playersRemaining * currScore; + K -= playersRemaining; + if (K == 0) { + break; + } + } + return totalScore; + } + + public void reset(int playerId) { + scoreToPlayerMapping.get(playerToScoreMapping.get(playerId)).remove(playerId); + playerToScoreMapping.put(playerId, 0); + } +} + +/** + * Your Leaderboard object will be instantiated and called as such: + * Leaderboard obj = new Leaderboard(); + * obj.addScore(playerId,score); + * int param_2 = obj.top(K); + * obj.reset(playerId); + */ diff --git a/Medium/Design Add and Search Words Data Structure.java b/Medium/Design Add and Search Words Data Structure.java new file mode 100644 index 00000000..17814eb0 --- /dev/null +++ b/Medium/Design Add and Search Words Data Structure.java @@ -0,0 +1,58 @@ +class WordDictionary { + + private final TrieNode root; + + public WordDictionary() { + this.root = new TrieNode(); + } + + public void addWord(String word) { + TrieNode curr = root; + for (char c : word.toCharArray()) { + if (!curr.children.containsKey(c)) { + curr.children.put(c, new TrieNode()); + } + curr = curr.children.get(c); + } + curr.isWord = true; + } + + public boolean search(String word) { + return searchHelper(word, 0, root); + } + + private boolean searchHelper(String word, int idx, TrieNode node) { + if (idx == word.length()) { + return node.isWord; + } + if (node.children.containsKey(word.charAt(idx))) { + return searchHelper(word, idx + 1, node.children.get(word.charAt(idx))); + } + if (word.charAt(idx) == '.') { + for (TrieNode child : node.children.values()) { + if (searchHelper(word, idx + 1, child)) { + return true; + } + } + } + return false; + } + + + static class TrieNode { + private final Map children; + private boolean isWord; + + public TrieNode() { + this.children = new HashMap<>(); + this.isWord = false; + } + } +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * WordDictionary obj = new WordDictionary(); + * obj.addWord(word); + * boolean param_2 = obj.search(word); + */ diff --git a/Medium/Design Authentication Manager.java b/Medium/Design Authentication Manager.java new file mode 100644 index 00000000..93071b1d --- /dev/null +++ b/Medium/Design Authentication Manager.java @@ -0,0 +1,33 @@ +class AuthenticationManager { + + Map map; + int timeToLive; + + public AuthenticationManager(int timeToLive) { + map = new HashMap<>(); + this.timeToLive = timeToLive; + } + + public void generate(String tokenId, int currentTime) { + map.put(tokenId, currentTime); + } + + public void renew(String tokenId, int currentTime) { + if (map.containsKey(tokenId) && map.get(tokenId) + timeToLive > currentTime) { + map.put(tokenId, currentTime); + } + } + + public int countUnexpiredTokens(int currentTime) { + return (int) map.entrySet().stream() + .filter(entry -> entry.getValue() + timeToLive > currentTime).count(); + } +} + +/** + * Your AuthenticationManager object will be instantiated and called as such: + * AuthenticationManager obj = new AuthenticationManager(timeToLive); + * obj.generate(tokenId,currentTime); + * obj.renew(tokenId,currentTime); + * int param_3 = obj.countUnexpiredTokens(currentTime); + */ diff --git a/Medium/Design Browser History.java b/Medium/Design Browser History.java new file mode 100644 index 00000000..63799e9d --- /dev/null +++ b/Medium/Design Browser History.java @@ -0,0 +1,38 @@ +class BrowserHistory { + + private final Stack history; + private final Stack future; + + public BrowserHistory(String homepage) { + this.history = new Stack<>(); + this.future = new Stack<>(); + this.history.push(homepage); + } + + public void visit(String url) { + future.removeAllElements(); + history.push(url); + } + + public String back(int steps) { + while (steps-- > 0 && history.size() > 1) { + future.push(history.pop()); + } + return history.peek(); + } + + public String forward(int steps) { + while (steps-- > 0 && !future.isEmpty()) { + history.push(future.pop()); + } + return history.peek(); + } +} + +/** + * Your BrowserHistory object will be instantiated and called as such: + * BrowserHistory obj = new BrowserHistory(homepage); + * obj.visit(url); + * String param_2 = obj.back(steps); + * String param_3 = obj.forward(steps); + */ diff --git a/Medium/Design Circular Deque.java b/Medium/Design Circular Deque.java index 5f6fe4c8..66667ed5 100644 --- a/Medium/Design Circular Deque.java +++ b/Medium/Design Circular Deque.java @@ -1,117 +1,89 @@ class MyCircularDeque { - /** Initialize your data structure here. Set the size of the deque to be k. */ - Queue main; - Queue backup; - int capacity; - + private final Node head; + private final Node tail; + private final int capacity; + private int size; + public MyCircularDeque(int k) { - main = new LinkedList<>(); - backup = new LinkedList<>(); + head = new Node(-1); + tail = new Node(-1); + head.next = tail; + tail.prev = head; capacity = k; + size = 0; } - - /** Adds an item at the front of Deque. Return true if the operation is successful. */ + public boolean insertFront(int value) { - if (main.size() == capacity) { + if (size == capacity) { return false; } - - while(!main.isEmpty()) { - backup.add(main.remove()); - } - - main.add(value); - - while (!backup.isEmpty()) { - main.add(backup.remove()); - } - + Node node = new Node(value); + node.next = head.next; + node.prev = head; + head.next.prev = node; + head.next = node; + size++; return true; } - - /** Adds an item at the rear of Deque. Return true if the operation is successful. */ + public boolean insertLast(int value) { - if (main.size() == capacity) { + if (size == capacity) { return false; } - - main.add(value); - + Node node = new Node(value); + node.prev = tail.prev; + node.next = tail; + tail.prev.next = node; + tail.prev = node; + size++; return true; } - - /** Deletes an item from the front of Deque. Return true if the operation is successful. */ + public boolean deleteFront() { - if (main.isEmpty()) { + if (size == 0) { return false; } - - main.remove(); - + head.next.next.prev = head; + head.next = head.next.next; + size--; return true; } - - /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ + public boolean deleteLast() { - if (main.isEmpty()) { + if (size == 0) { return false; } - - while(!main.isEmpty()) { - backup.add(main.remove()); - } - - int size = backup.size(); - - while (size-- > 1) { - main.add(backup.remove()); - } - - backup.remove(); - + tail.prev.prev.next = tail; + tail.prev = tail.prev.prev; + size--; return true; } - - /** Get the front item from the deque. */ + public int getFront() { - if (main.isEmpty()) { - return -1; - } - - return main.peek(); + return head.next.value; } - - /** Get the last item from the deque. */ + public int getRear() { - if (main.isEmpty()) { - return -1; - } - - while(!main.isEmpty()) { - backup.add(main.remove()); - } - - int size = backup.size(); - - while (size-- > 1) { - main.add(backup.remove()); - } - - int ans = backup.peek(); - main.add(backup.remove()); - - return ans; + return tail.prev.value; } - - /** Checks whether the circular deque is empty or not. */ + public boolean isEmpty() { - return main.isEmpty(); + return size == 0; } - - /** Checks whether the circular deque is full or not. */ + public boolean isFull() { - return main.size() == capacity; + return size == capacity; + } + + static class Node { + int value; + Node next; + Node prev; + + Node(int value) { + this.value = value; + } } } diff --git a/Medium/Design Circular Queue.java b/Medium/Design Circular Queue.java index 236711ae..d5f90b31 100644 --- a/Medium/Design Circular Queue.java +++ b/Medium/Design Circular Queue.java @@ -1,92 +1,53 @@ class MyCircularQueue { - - /** Initialize your data structure here. Set the size of the queue to be k. */ - Node head; - Node curr; - int capacity; - int count = 0; - - public MyCircularQueue(int k) { - head = new Node(-1); - curr = head; - capacity = k; - } - - /** Insert an element into the circular queue. Return true if the operation is successful. */ - public boolean enQueue(int value) { - if (count == capacity) { - return false; - } - - curr.next = new Node(value); - curr = curr.next; - count++; - - return true; - } - - /** Delete an element from the circular queue. Return true if the operation is successful. */ - public boolean deQueue() { - if (count <= 0) { - return false; - } - - if (head.next == curr) { - curr = head; - head.next = null; - } - else { - head.next = head.next.next; - } - - count--; - - return true; - } - - /** Get the front item from the queue. */ - public int Front() { - if (count == 0) { - return -1; - } - - return head.next.value; - } - - /** Get the last item from the queue. */ - public int Rear() { - if (count == 0) { - return -1; - } - - return curr.value; - } - - /** Checks whether the circular queue is empty or not. */ - public boolean isEmpty() { - return count == 0; - } - - /** Checks whether the circular queue is full or not. */ - public boolean isFull() { - return count == capacity; - } - - private void printList(Node node) { - while (node != null) { - System.out.print(node.value + " "); - } - - System.out.println(); - } - - class Node { - int value; - Node next; - Node(int value) { - this.value = value; - } - } + + private Integer[] queue; + private int valueCursor; + private int emptyCursor; + + public MyCircularQueue(int k) { + this.queue = new Integer[k]; + this.valueCursor = 0; + this.emptyCursor = 0; + } + + public boolean enQueue(int value) { + if (queue[emptyCursor] != null) { + return false; + } + queue[emptyCursor++] = value; + if (emptyCursor == queue.length) { + emptyCursor = 0; + } + return true; + } + + public boolean deQueue() { + if (queue[valueCursor] == null) { + return false; + } + queue[valueCursor++] = null; + if (valueCursor == queue.length) { + valueCursor = 0; + } + return true; + } + + public int Front() { + return queue[valueCursor] == null ? -1 : queue[valueCursor]; + } + + public int Rear() { + int idx = emptyCursor == 0 ? queue.length - 1 : emptyCursor - 1; + return queue[idx] == null ? -1 : queue[idx]; + } + + public boolean isEmpty() { + return queue[valueCursor] == null; + } + + public boolean isFull() { + return queue[emptyCursor] != null; + } } /** diff --git a/Medium/Design File System.java b/Medium/Design File System.java new file mode 100644 index 00000000..aef4ab97 --- /dev/null +++ b/Medium/Design File System.java @@ -0,0 +1,57 @@ +class FileSystem { + + private FileNode root; + + public FileSystem() { + this.root = new FileNode(); + } + + public boolean createPath(String path, int value) { + String[] split = path.split("/"); + FileNode node = root; + for (int i = 1; i < split.length - 1; i++) { + if (!node.children.containsKey(split[i])) { + return false; + } + node = node.children.get(split[i]); + } + if (node.children.containsKey(split[split.length - 1])) { + return false; + } + node.children.put(split[split.length - 1], new FileNode(value)); + return true; + } + + public int get(String path) { + String[] split = path.split("/"); + FileNode node = root; + for (int i = 1; i < split.length; i++) { + if (!node.children.containsKey(split[i])) { + return -1; + } + node = node.children.get(split[i]); + } + return node.value == null ? -1 : node.value; + } + + private static class FileNode { + private final Map children; + private Integer value; + + public FileNode() { + this.children = new HashMap<>(); + } + + public FileNode(Integer value) { + this.children = new HashMap<>(); + this.value = value; + } + } +} + +/** + * Your FileSystem object will be instantiated and called as such: + * FileSystem obj = new FileSystem(); + * boolean param_1 = obj.createPath(path,value); + * int param_2 = obj.get(path); + */ diff --git a/Medium/Design Front Middle Back Queue.java b/Medium/Design Front Middle Back Queue.java new file mode 100644 index 00000000..cee37d34 --- /dev/null +++ b/Medium/Design Front Middle Back Queue.java @@ -0,0 +1,64 @@ +class FrontMiddleBackQueue { + + Deque frontQueue; + Deque backQueue; + + public FrontMiddleBackQueue() { + frontQueue = new ArrayDeque<>(); + backQueue = new ArrayDeque<>(); + } + + public void pushFront(int val) { + frontQueue.addFirst(val); + } + + public void pushMiddle(int val) { + while (frontQueue.size() + 1 < backQueue.size()) { + frontQueue.addLast(backQueue.removeFirst()); + } + while (frontQueue.size() > backQueue.size()) { + backQueue.addFirst(frontQueue.removeLast()); + } + frontQueue.addLast(val); + } + + public void pushBack(int val) { + backQueue.addLast(val); + } + + public int popFront() { + return frontQueue.isEmpty() + ? (backQueue.isEmpty() ? -1 : backQueue.removeFirst()) + : frontQueue.removeFirst(); + } + + public int popMiddle() { + if (frontQueue.isEmpty() && backQueue.isEmpty()) { + return -1; + } + while (frontQueue.size() < backQueue.size()) { + frontQueue.addLast(backQueue.removeFirst()); + } + while (frontQueue.size() > backQueue.size() + 1) { + backQueue.addFirst(frontQueue.removeLast()); + } + return !frontQueue.isEmpty() ? frontQueue.removeLast() : backQueue.removeFirst(); + } + + public int popBack() { + return backQueue.isEmpty() + ? (frontQueue.isEmpty() ? -1 : frontQueue.removeLast()) + : backQueue.removeLast(); + } +} + +/** + * Your FrontMiddleBackQueue object will be instantiated and called as such: + * FrontMiddleBackQueue obj = new FrontMiddleBackQueue(); + * obj.pushFront(val); + * obj.pushMiddle(val); + * obj.pushBack(val); + * int param_4 = obj.popFront(); + * int param_5 = obj.popMiddle(); + * int param_6 = obj.popBack(); + */ diff --git a/Medium/Design Hit Counter.java b/Medium/Design Hit Counter.java index bab20249..c241a419 100644 --- a/Medium/Design Hit Counter.java +++ b/Medium/Design Hit Counter.java @@ -1,26 +1,28 @@ class HitCounter { + + private Deque record; + private int count; + + public HitCounter() { + this.record = new LinkedList<>(); + this.count = 0; + } - /** Initialize your data structure here. */ - Queue queue; - public HitCounter() { - queue = new LinkedList<>(); + public void hit(int timestamp) { + if (!record.isEmpty() && record.getLast()[0] == timestamp) { + record.getLast()[1]++; + } else { + record.add(new int[]{timestamp, 1}); } + this.count++; + } - /** Record a hit. - @param timestamp - The current timestamp (in seconds granularity). */ - public void hit(int timestamp) { - queue.add(timestamp); - } - - /** Return the number of hits in the past 5 minutes. - @param timestamp - The current timestamp (in seconds granularity). */ - public int getHits(int timestamp) { - while (!queue.isEmpty() && timestamp - queue.peek() >= 300) { - queue.remove(); - } - - return queue.size(); + public int getHits(int timestamp) { + while (!record.isEmpty() && timestamp - record.getFirst()[0] >= 300) { + this.count -= record.removeFirst()[1]; } + return this.count; + } } /** diff --git a/Medium/Design Phone Directory.java b/Medium/Design Phone Directory.java index 2ee6f1ef..137153dd 100644 --- a/Medium/Design Phone Directory.java +++ b/Medium/Design Phone Directory.java @@ -1,43 +1,42 @@ class PhoneDirectory { - /** Initialize your data structure here - @param maxNumbers - The maximum numbers that can be stored in the phone directory. */ - int[] directory; - int pos; - public PhoneDirectory(int maxNumbers) { - directory = new int[maxNumbers]; - for (int i=0; i>> database; + private final Map tableIdMap; + + public SQL(List tableNames, List columns) { + this.database = new HashMap<>(); + this.tableIdMap = new HashMap<>(); + for (String name : tableNames) { + database.put(name, new HashMap<>()); + tableIdMap.put(name, 1); + } + } + + public void insertRow(String tableName, List row) { + // Select the table + Map> table = this.database.get(tableName); + // Insert row in the table + table.put(tableIdMap.get(tableName), row); + // Increment rowId for the table + tableIdMap.put(tableName, tableIdMap.get(tableName) + 1); + } + + public void deleteRow(String tableName, int rowId) { + // Select the table + Map> table = this.database.get(tableName); + // Delete the row against the rowId + table.remove(rowId); + } + + public String selectCell(String tableName, int rowId, int columnId) { + // Select the table + Map> table = this.database.get(tableName); + // Select row + List row = table.get(rowId); + // Select column + return row.get(columnId - 1); + } +} + +/** + * Your SQL object will be instantiated and called as such: + * SQL obj = new SQL(names, columns); + * obj.insertRow(name,row); + * obj.deleteRow(name,rowId); + * String param_3 = obj.selectCell(name,rowId,columnId); + */ diff --git a/Medium/Design Snake Game.java b/Medium/Design Snake Game.java new file mode 100644 index 00000000..dd645d15 --- /dev/null +++ b/Medium/Design Snake Game.java @@ -0,0 +1,78 @@ +class SnakeGame { + + private final Deque snake; + private final Queue foodQueue; + private final Set snakeBody; + private final int width; + private final int height; + private int score; + + public SnakeGame(int width, int height, int[][] food) { + this.snake = new ArrayDeque<>(); + this.snake.addFirst(new int[]{0, 0}); + this.foodQueue = new LinkedList<>(); + this.foodQueue.addAll(Arrays.asList(food)); + this.snakeBody = new HashSet<>(); + this.snakeBody.add(0 + "|" + 0); + this.width = width; + this.height = height; + this.score = 0; + } + + public int move(String direction) { + int[] nextMove = getNextMove(direction); + if (!isMoveWithInBound(nextMove)) { + return -1; + } + moveSnake(nextMove); + if (isBitingItself(nextMove)) { + return -1; + } + this.snakeBody.add(nextMove[0] + "|" + nextMove[1]); + return score; + } + + private int[] getNextMove(String direction) { + int[] nextMove = Arrays.copyOf(this.snake.peekFirst(), 2); + switch (direction) { + case "L" -> nextMove[1]--; + case "R" -> nextMove[1]++; + case "U" -> nextMove[0]--; + case "D" -> nextMove[0]++; + default -> {} + } + return nextMove; + } + + private boolean isMoveWithInBound(int[] move) { + int x = move[0]; + int y = move[1]; + return x >= 0 && y >= 0 && x < this.height && y < this.width; + } + + private void moveSnake(int[] move) { + this.snake.addFirst(move); + if (snakeEatsFood(move)) { + this.foodQueue.remove(); + this.score++; + } else { + int[] tail = this.snake.removeLast(); + this.snakeBody.remove(tail[0] + "|" + tail[1]); + } + } + + private boolean snakeEatsFood(int[] move) { + return !this.foodQueue.isEmpty() && move[0] == this.foodQueue.peek()[0] && move[1] == this.foodQueue.peek()[1]; + } + + private boolean isBitingItself(int[] move) { + String key = move[0] + "|" + move[1]; + return this.snakeBody.contains(key); + } +} + +/** + * Your SnakeGame object will be instantiated and called as such: + * SnakeGame obj = new SnakeGame(width, height, food); + * int param_1 = obj.move(direction); + */ diff --git a/Medium/Design Spreadsheet.java b/Medium/Design Spreadsheet.java new file mode 100644 index 00000000..e41fc142 --- /dev/null +++ b/Medium/Design Spreadsheet.java @@ -0,0 +1,47 @@ +class Spreadsheet { + + private final Map> sheet; + + public Spreadsheet(int rows) { + sheet = new HashMap<>(); + for (char c = 'A'; c <= 'Z'; c++) { + sheet.put(c, new HashMap<>()); + } + } + + public void setCell(String cell, int value) { + char column = cell.charAt(0); + int rowNumber = Integer.parseInt(cell.substring(1)); + Map row = sheet.get(column); + row.put(rowNumber, value); + } + + public void resetCell(String cell) { + setCell(cell, 0); + } + + public int getValue(String formula) { + String[] split = formula.split("\\+"); + String cellOne = split[0].substring(1); + String cellTwo = split[1]; + return getCellValue(cellOne) + getCellValue(cellTwo); + } + + private int getCellValue(String cell) { + if (!Character.isLetter(cell.charAt(0))) { + return Integer.parseInt(cell); + } + char column = cell.charAt(0); + int rowNumber = Integer.parseInt(cell.substring(1)); + Map row = sheet.get(column); + return row.getOrDefault(rowNumber, 0); + } +} + +/** + * Your Spreadsheet object will be instantiated and called as such: + * Spreadsheet obj = new Spreadsheet(rows); + * obj.setCell(cell,value); + * obj.resetCell(cell); + * int param_3 = obj.getValue(formula); + */ diff --git a/Medium/Design Tic-Tac-Toe.java b/Medium/Design Tic-Tac-Toe.java index defa38c2..50b57aea 100644 --- a/Medium/Design Tic-Tac-Toe.java +++ b/Medium/Design Tic-Tac-Toe.java @@ -1,122 +1,55 @@ class TicTacToe { - /** Initialize your data structure here. */ - int[][] board; - int n; - boolean win; - - public TicTacToe(int n) { - this.n = n; - board = new int[n][n]; - } - - /** Player {player} makes a move at ({row}, {col}). - @param row The row of the board. - @param col The column of the board. - @param player The player, can be either 1 or 2. - @return The current winning condition, can be either: - 0: No one wins. - 1: Player 1 wins. - 2: Player 2 wins. */ - public int move(int row, int col, int player) { - if (win) { - return 0; - } - - board[row][col] = player; - - boolean cCheck = columnCheck(col, n, player); - boolean rCheck = rowCheck(row, n, player); - boolean diagCheck = diagonalCheck(row, col, n, player); - - if (cCheck || rCheck || diagCheck) { - win = true; - return player; - } - - return 0; - } - - private boolean diagonalCheck(int row, int col, int n, int player) { - int count = 0; - - int rowNum = row; - int colNum = col; - - while (rowNum < n && colNum < n) { - if (board[rowNum][colNum] == player) { - count++; - } - - rowNum++; - colNum++; - } - - rowNum = row-1; - colNum = col-1; - - while (rowNum >= 0 && colNum >= 0) { - if (board[rowNum][colNum] == player) { - count++; - } - - rowNum--; - colNum--; - } - - if (count == n) { - return true; - } - - count = 0; - rowNum = row; - colNum = col; - - while (rowNum >= 0 && colNum < n) { - if (board[rowNum][colNum] == player) { - count++; - } - - rowNum--; - colNum++; - } - - rowNum = row; - colNum = col; - - while (rowNum < n && colNum >= 0) { - if (board[rowNum][colNum] == player) { - count++; - } - - rowNum++; - colNum--; - } - - if (count == n+1) { - return true; - } - - return false; + private int n; + private Map> rowMapping; + private Map> colMapping; + private Map> diagonalMapping; + + private final int LEFT_DIAGONAL = 1; + private final int RIGHT_DIAGONAL = -1; + + public TicTacToe(int n) { + this.n = n; + this.rowMapping = new HashMap<>(); + this.colMapping = new HashMap<>(); + this.diagonalMapping = new HashMap<>(); + this.diagonalMapping.put(LEFT_DIAGONAL, new HashMap<>()); + this.diagonalMapping.put(RIGHT_DIAGONAL, new HashMap<>()); + } + + public int move(int row, int col, int player) { + recordMove(row, col, player); + if (isWinnerFound(row, col, player)) { + return player; } - - private boolean rowCheck(int row, int n, int player) { - for (int i=0; i new HashMap<>()); + this.colMapping.computeIfAbsent(col, k -> new HashMap<>()); + this.rowMapping.get(row).put(player, this.rowMapping.get(row).getOrDefault(player, 0) + 1); + this.colMapping.get(col).put(player, this.colMapping.get(col).getOrDefault(player, 0) + 1); + if (row == col) { + this.diagonalMapping.get(LEFT_DIAGONAL) + .put(player, this.diagonalMapping.get(LEFT_DIAGONAL).getOrDefault(player, 0) + 1); + } + if (row + col + 1 == this.n) { + this.diagonalMapping.get(RIGHT_DIAGONAL) + .put(player, this.diagonalMapping.get(RIGHT_DIAGONAL).getOrDefault(player, 0) + 1); } + } + + private boolean isWinnerFound(int row, int col, int player) { + return this.rowMapping.get(row).get(player) == this.n || + this.colMapping.get(col).get(player) == this.n || + this.diagonalMapping.get(LEFT_DIAGONAL).getOrDefault(player, 0) == this.n || + this.diagonalMapping.get(RIGHT_DIAGONAL).getOrDefault(player, 0) == this.n; + } } + +/** + * Your TicTacToe object will be instantiated and called as such: + * TicTacToe obj = new TicTacToe(n); + * int param_1 = obj.move(row,col,player); + */ diff --git a/Medium/Design Twitter.java b/Medium/Design Twitter.java index 65b71c71..8009a1d6 100644 --- a/Medium/Design Twitter.java +++ b/Medium/Design Twitter.java @@ -1,160 +1,72 @@ -class Twitter { - - /** Initialize your data structure here. */ - Map userMap; - Map> followingMap; - Map> followerMap; - int tweetTimeStamp; - - public Twitter() { - followingMap = new HashMap<>(); - userMap = new HashMap<>(); - followerMap = new HashMap<>(); - tweetTimeStamp = 0; - } - - /** Compose a new tweet. */ - public void postTweet(int userId, int tweetId) { - Tweet tweet = new Tweet(tweetId, userId, tweetTimeStamp); - tweetTimeStamp++; - - createUserIfAbsent(userId); - - userMap.get(userId).topTweets.add(tweet); - List followers = followerMap.getOrDefault(userMap.get(userId), new ArrayList<>()); - for (User follower : followers) { - follower.topTweets.add(tweet); - } - } - - /** 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) { - if (!userMap.containsKey(userId)) { - return new ArrayList<>(); - } - - List topTweetIds = new ArrayList<>(); - Set tweetIdSet = new HashSet<>(); - List topTweets = new ArrayList<>(); - - PriorityQueue pq = userMap.get(userId).topTweets; - int count = 10; - - while (count > 0 && !pq.isEmpty()) { - Tweet tweet = pq.poll(); - topTweets.add(tweet); - - List usersFollowing = followingMap.get(userMap.get(userId)); - - if ((userMap.containsKey(tweet.userId) && usersFollowing.contains(userMap.get(tweet.userId))) || - tweet.userId == userId) { - if (!tweetIdSet.contains(tweet.tweetId)) { - topTweetIds.add(tweet.tweetId); - tweetIdSet.add(tweet.tweetId); - count--; - } - } - } - - pq.addAll(topTweets); - - return topTweetIds; - } - - /** Follower follows a followee. If the operation is invalid, it should be a no-op. */ - public void follow(int followerId, int followeeId) { - if (followeeId == followerId) { - return; - } +import java.util.Map.Entry; - createUserIfAbsent(followeeId); - createUserIfAbsent(followerId); - if (!followingMap.get(userMap.get(followerId)).contains(userMap.get(followeeId))) { - followingMap.get(userMap.get(followerId)).add(userMap.get(followeeId)); - userMap.get(followerId).topTweets.addAll(userMap.get(followeeId).topTweets); - } - - if (!followerMap.getOrDefault(userMap.get(followeeId), new ArrayList<>()).contains(userMap.get(followerId))) { - followerMap.get(userMap.get(followeeId)).add(userMap.get(followerId)); - } +class Twitter { - } + private final Map> userFollowing; + private final Map userToTweet; + private int timestamp; - private void createUserIfAbsent(int id) { - if (!userMap.containsKey(id)) { - User newUser = new User(id); - userMap.put(id, newUser); - List followers = new ArrayList<>(); - List following = new ArrayList<>(); + public Twitter() { + this.userFollowing = new HashMap<>(); + this.timestamp = 0; + this.userToTweet = new HashMap<>(); + } - followingMap.put(newUser, following); - followerMap.put(newUser, followers); - } + public void postTweet(int userId, int tweetId) { + TweetNode tweetNode = new TweetNode(tweetId, this.timestamp++); + if (this.userToTweet.containsKey(userId)) { + tweetNode.next = this.userToTweet.get(userId); } - - /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */ - public void unfollow(int followerId, int followeeId) { - if (!userMap.containsKey(followeeId)) { - return; - } - - if (!userMap.containsKey(followerId)) { - return; - } - - if (followingMap.get(userMap.get(followerId)).contains(userMap.get(followeeId))) { - followingMap.get(userMap.get(followerId)).remove(userMap.get(followeeId)); - } + this.userToTweet.put(userId, tweetNode); + } + + public List getNewsFeed(int userId) { + PriorityQueue priorityQueue = + new PriorityQueue<>((o1, o2) -> o2.timestamp - o1.timestamp); + priorityQueue.addAll( + this.userToTweet.entrySet().stream() + .filter( + entry -> + entry.getKey() == userId + || this.userFollowing + .getOrDefault(userId, new HashSet<>()) + .contains(entry.getKey())) + .map(Entry::getValue) + .collect(Collectors.toList())); + List result = new ArrayList<>(); + while (!priorityQueue.isEmpty() && result.size() < 10) { + TweetNode removed = priorityQueue.remove(); + result.add(removed.tweetId); + if (removed.next != null) { + priorityQueue.add(removed.next); + } } -} - -class User { - public int id; - public List followers; - PriorityQueue topTweets; + return result; + } - public User(int id) { - this.id = id; - this.followers = new ArrayList<>(); - this.topTweets = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Tweet o1, Tweet o2) { - return o2.timestamp - o1.timestamp; - } - }); - } + public void follow(int followerId, int followeeId) { + this.userFollowing.computeIfAbsent(followerId, k -> new HashSet<>()).add(followeeId); + } - @Override - public String toString() { - return "User{" + - "id=" + id + - '}'; + public void unfollow(int followerId, int followeeId) { + if (this.userFollowing.getOrDefault(followerId, new HashSet<>()).contains(followeeId)) { + this.userFollowing.get(followerId).remove(followeeId); } -} + } -class Tweet { - public int tweetId; - public int userId; - public int timestamp; + private static class TweetNode { + int tweetId; + int timestamp; + TweetNode next; - public Tweet(int tweetId, int userId, int timestamp) { - this.tweetId = tweetId; - this.userId = userId; - this.timestamp = timestamp; - } - - @Override - public String toString() { - return "Tweet{" + - "tweetId=" + tweetId + - ", userId=" + userId + - '}'; + public TweetNode(int tweetId, int timestamp) { + this.tweetId = tweetId; + this.timestamp = timestamp; } + } } - - /** * Your Twitter object will be instantiated and called as such: * Twitter obj = new Twitter(); diff --git a/Medium/Design Underground System.java b/Medium/Design Underground System.java new file mode 100644 index 00000000..6297656a --- /dev/null +++ b/Medium/Design Underground System.java @@ -0,0 +1,43 @@ +class UndergroundSystem { + + private final Map customerToCheckInMapping; + private final Map startEndStationTotalTimeMapping; + private final Map startEndStationCountMapping; + + public UndergroundSystem() { + this.customerToCheckInMapping = new HashMap<>(); + this.startEndStationTotalTimeMapping = new HashMap<>(); + this.startEndStationCountMapping = new HashMap<>(); + } + + public void checkIn(int id, String stationName, int t) { + StationTimePair pair = new StationTimePair(stationName, t); + customerToCheckInMapping.put(id, pair); + } + + public void checkOut(int id, String stationName, int t) { + StationTimePair pair = customerToCheckInMapping.get(id); + String key = pair.station() + "|" + stationName; + int totalTime = t - pair.time(); + startEndStationTotalTimeMapping.put(key, startEndStationTotalTimeMapping.getOrDefault(key, 0) + totalTime); + startEndStationCountMapping.put(key, startEndStationCountMapping.getOrDefault(key, 0) + 1); + } + + public double getAverageTime(String startStation, String endStation) { + String key = startStation + "|" + endStation; + if (!startEndStationTotalTimeMapping.containsKey(key)) { + return 0.0; + } + return ((double) startEndStationTotalTimeMapping.get(key)) / startEndStationCountMapping.get(key); + } + + static record StationTimePair(String station, int time) {} +} + +/** + * Your UndergroundSystem object will be instantiated and called as such: + * UndergroundSystem obj = new UndergroundSystem(); + * obj.checkIn(id,stationName,t); + * obj.checkOut(id,stationName,t); + * double param_3 = obj.getAverageTime(startStation,endStation); + */ diff --git a/Medium/Design a File Sharing System.java b/Medium/Design a File Sharing System.java new file mode 100644 index 00000000..b5bba82b --- /dev/null +++ b/Medium/Design a File Sharing System.java @@ -0,0 +1,56 @@ +class FileSharing { + + private final PriorityQueue userIdsInSystem; + private final Map> chunkToUserIdMapping; + private final Map> userIdToChunkMapping; + + public FileSharing(int m) { + this.userIdsInSystem = new PriorityQueue<>(); + this.userIdsInSystem.add(1); + this.chunkToUserIdMapping = new HashMap<>(); + for (int i = 1; i <= m; i++) { + chunkToUserIdMapping.put(i, new HashSet<>()); + } + this.userIdToChunkMapping = new HashMap<>(); + } + + public int join(List ownedChunks) { + int currUserId = this.userIdsInSystem.poll(); + if (this.userIdsInSystem.isEmpty()) { + this.userIdsInSystem.add(currUserId + 1); + } + this.userIdToChunkMapping.computeIfAbsent(currUserId, k -> new HashSet<>()); + for (Integer chunk : ownedChunks) { + this.chunkToUserIdMapping.get(chunk).add(currUserId); + this.userIdToChunkMapping.get(currUserId).add(chunk); + } + return currUserId; + } + + public void leave(int userID) { + this.userIdsInSystem.add(userID); + Set chunksOwned = this.userIdToChunkMapping.get(userID); + this.userIdToChunkMapping.remove(userID); + for (Integer chunk : chunksOwned) { + this.chunkToUserIdMapping.get(chunk).remove(userID); + } + } + + public List request(int userID, int chunkID) { + if (this.chunkToUserIdMapping.get(chunkID).isEmpty()) { + return new ArrayList<>(); + } + List usersOwningChunk = this.chunkToUserIdMapping.get(chunkID).stream().sorted().toList(); + this.userIdToChunkMapping.get(userID).add(chunkID); + this.chunkToUserIdMapping.get(chunkID).add(userID); + return usersOwningChunk; + } +} + +/** + * Your FileSharing object will be instantiated and called as such: + * FileSharing obj = new FileSharing(m); + * int param_1 = obj.join(ownedChunks); + * obj.leave(userID); + * List param_3 = obj.request(userID,chunkID); + */ diff --git a/Medium/Design a Food Rating System.java b/Medium/Design a Food Rating System.java new file mode 100644 index 00000000..71c55477 --- /dev/null +++ b/Medium/Design a Food Rating System.java @@ -0,0 +1,53 @@ +class FoodRatings { + + private final Map foodToRating; + + private final Map foodToCuisine; + + private final Map> cuisineToFood; + + public FoodRatings(String[] foods, String[] cuisines, int[] ratings) { + this.foodToRating = new HashMap<>(); + this.foodToCuisine = new HashMap<>(); + this.cuisineToFood = new HashMap<>(); + for (int i = 0; i < foods.length; i++) { + String food = foods[i]; + String cuisine = cuisines[i]; + int rating = ratings[i]; + foodToRating.put(food, rating); + foodToCuisine.put(food, cuisine); + cuisineToFood.computeIfAbsent(cuisine, k -> new PriorityQueue<>()).add(new Food(food, rating)); + } + } + + public void changeRating(String food, int newRating) { + this.foodToRating.put(food, newRating); + String cuisine = foodToCuisine.get(food); + cuisineToFood.get(cuisine).add(new Food(food, newRating)); + } + + public String highestRated(String cuisine) { + Food highestRatedFood = cuisineToFood.get(cuisine).peek(); + while (foodToRating.get(highestRatedFood.name) != highestRatedFood.rating) { + cuisineToFood.get(cuisine).poll(); + highestRatedFood = cuisineToFood.get(cuisine).peek(); + } + return highestRatedFood.name; + } + + private record Food(String name, int rating) implements Comparable { + @Override + public int compareTo(Food o) { + int c = o.rating - rating; + return c == 0 ? name.compareTo(o.name) : c; + } + } +} + + +/** + * Your FoodRatings object will be instantiated and called as such: + * FoodRatings obj = new FoodRatings(foods, cuisines, ratings); + * obj.changeRating(food,newRating); + * String param_2 = obj.highestRated(cuisine); + */ diff --git a/Medium/Design a Number Container System.java b/Medium/Design a Number Container System.java new file mode 100644 index 00000000..26a3e843 --- /dev/null +++ b/Medium/Design a Number Container System.java @@ -0,0 +1,34 @@ +class NumberContainers { + + private final Map> numberToIndex; + private final Map indexToNumber; + + public NumberContainers() { + this.numberToIndex = new HashMap<>(); + this.indexToNumber = new HashMap<>(); + } + + public void change(int index, int number) { + if (indexToNumber.containsKey(index)) { + int prevNumber = indexToNumber.get(index); + numberToIndex.get(prevNumber).remove(index); + } + indexToNumber.put(index, number); + numberToIndex.computeIfAbsent(number, k -> new TreeSet<>()).add(index); + } + + public int find(int number) { + TreeSet indices = numberToIndex.getOrDefault(number, new TreeSet<>()); + if (indices.isEmpty()) { + return -1; + } + return indices.first(); + } +} + +/** + * Your NumberContainers object will be instantiated and called as such: + * NumberContainers obj = new NumberContainers(); + * obj.change(index,number); + * int param_2 = obj.find(number); + */ diff --git a/Medium/Design a Stack With Increment Operation.java b/Medium/Design a Stack With Increment Operation.java new file mode 100644 index 00000000..9e4ec3a3 --- /dev/null +++ b/Medium/Design a Stack With Increment Operation.java @@ -0,0 +1,46 @@ +class CustomStack { + + private final int maxSize; + private final Stack stack; + private int[] increment; + + public CustomStack(int maxSize) { + this.maxSize = maxSize; + this.stack = new Stack<>(); + this.increment = new int[maxSize]; + } + + public void push(int x) { + if (stack.size() < maxSize) { + stack.push(x); + } + } + + public int pop() { + int idx = stack.size() - 1; + if (idx < 0) { + return -1; + } + if (idx > 0) { + increment[idx - 1] += increment[idx]; + } + int result = stack.pop() + increment[idx]; + increment[idx] = 0; + return result; + } + + public void increment(int k, int val) { + int idx = Math.min(k, stack.size()) - 1; + if (idx >= 0) { + increment[idx] += val; + } + } +} + +/** + * Your CustomStack object will be instantiated and called as such: + * CustomStack obj = new CustomStack(maxSize); + * obj.push(x); + * int param_2 = obj.pop(); + * obj.increment(k,val); + */ diff --git a/Medium/Design an ATM Machine.java b/Medium/Design an ATM Machine.java new file mode 100644 index 00000000..b4888a7a --- /dev/null +++ b/Medium/Design an ATM Machine.java @@ -0,0 +1,43 @@ +class ATM { + + private long[] noteCount; + private int[] noteValue; + + public ATM() { + this.noteCount = new long[5]; + this.noteValue = new int[]{20, 50, 100, 200, 500}; + } + + public void deposit(int[] banknotesCount) { + for (int i = 0; i < banknotesCount.length; i++) { + this.noteCount[i] += banknotesCount[i]; + } + } + + public int[] withdraw(int amount) { + int[] resultNoteCount = new int[5]; + for (int i = this.noteValue.length - 1; i >= 0 && amount > 0; i--) { + if (amount >= this.noteValue[i]) { + long numOfNotes = Math.min(amount / this.noteValue[i], this.noteCount[i]); + amount -= this.noteValue[i] * numOfNotes; + resultNoteCount[i] = (int) numOfNotes; + } + } + if (amount > 0) { + return new int[]{-1}; + } + if (amount == 0) { + for (int i = 0; i < resultNoteCount.length; i++) { + this.noteCount[i] -= resultNoteCount[i]; + } + } + return resultNoteCount; + } +} + +/** + * Your ATM object will be instantiated and called as such: + * ATM obj = new ATM(); + * obj.deposit(banknotesCount); + * int[] param_2 = obj.withdraw(amount); + */ diff --git a/Medium/Design an Expression Tree With Evaluate Function.java b/Medium/Design an Expression Tree With Evaluate Function.java new file mode 100644 index 00000000..e01eb49f --- /dev/null +++ b/Medium/Design an Expression Tree With Evaluate Function.java @@ -0,0 +1,93 @@ +/** + * This is the interface for the expression tree Node. + * You should not remove it, and you can define some classes to implement it. + */ + +abstract class Node { + public abstract int evaluate(); + // define your fields here +}; + + +class NumericNode extends Node { + private int val; + + public NumericNode(int val) { + this.val = val; + } + + @Override + public int evaluate() { + return this.val; + } +} + + +class OperatorNode extends Node { + private char operator; + private Node left; + private Node right; + + public OperatorNode(char operator) { + this.operator = operator; + this.left = null; + this.right = null; + } + + @Override + public int evaluate() { + return switch(operator) { + case '+' -> left.evaluate() + right.evaluate(); + case '-' -> left.evaluate() - right.evaluate(); + case '*' -> left.evaluate() * right.evaluate(); + case '/' -> left.evaluate() / right.evaluate(); + default -> 0; + }; + } + + public void setRightNode(Node right) { + this.right = right; + } + + public void setLeftNode(Node left) { + this.left = left; + } +} + +/** + * This is the TreeBuilder class. + * You can treat it as the driver code that takes the postinfix input + * and returns the expression tree represnting it as a Node. + */ + +class TreeBuilder { + private static final Set OPERATORS = Set.of("+", "-", "/", "*"); + + Node buildTree(String[] postfix) { + int[] idx = {postfix.length - 1}; + return buildTree(postfix, idx); + } + + private Node buildTree(String[] postfix, int[] idx) { + if (idx[0] < 0) { + return null; + } + String val = postfix[idx[0]--]; + if (OPERATORS.contains(val)) { + OperatorNode node = new OperatorNode(val.charAt(0)); + node.setRightNode(buildTree(postfix, idx)); + node.setLeftNode(buildTree(postfix, idx)); + return node; + } + NumericNode node = new NumericNode(Integer.parseInt(val)); + return node; + } +}; + + +/** + * Your TreeBuilder object will be instantiated and called as such: + * TreeBuilder obj = new TreeBuilder(); + * Node expTree = obj.buildTree(postfix); + * int ans = expTree.evaluate(); + */ diff --git a/Medium/Determine if Two Strings Are Close.java b/Medium/Determine if Two Strings Are Close.java new file mode 100644 index 00000000..3a43fd6a --- /dev/null +++ b/Medium/Determine if Two Strings Are Close.java @@ -0,0 +1,30 @@ +class Solution { + public boolean closeStrings(String word1, String word2) { + if (word1.length() != word2.length()) { + return false; + } + int[] frequencyOne = getFrequencyArray(word1); + int[] frequencyTwo = getFrequencyArray(word2); + for (int i = 0; i < 26; i++) { + if (frequencyOne[i] == 0 && frequencyTwo[i] != 0) { + return false; + } + } + Arrays.sort(frequencyOne); + Arrays.sort(frequencyTwo); + for (int i = 0; i < 26; i++) { + if (frequencyOne[i] != frequencyTwo[i]) { + return false; + } + } + return true; + } + + private static int[] getFrequencyArray(String s) { + int[] frequency = new int[26]; + for (int i = 0; i < s.length(); i++) { + frequency[s.charAt(i) - 'a']++; + } + return frequency; + } +} diff --git a/Medium/Determine if a Cell Is Reachable at a Given Time.java b/Medium/Determine if a Cell Is Reachable at a Given Time.java new file mode 100644 index 00000000..37878fa8 --- /dev/null +++ b/Medium/Determine if a Cell Is Reachable at a Given Time.java @@ -0,0 +1,10 @@ +class Solution { + public boolean isReachableAtTime(int sx, int sy, int fx, int fy, int t) { + int xDiff = Math.abs(sx - fx); + int yDiff = Math.abs(sy - fy); + if (xDiff == 0 && yDiff == 0 && t == 1) { + return false; + } + return (Math.min(xDiff, yDiff) + Math.abs(xDiff - yDiff)) <= t; + } +} diff --git a/Medium/Determine the Minimum Sum of a k-avoiding Array.java b/Medium/Determine the Minimum Sum of a k-avoiding Array.java new file mode 100644 index 00000000..3eab331f --- /dev/null +++ b/Medium/Determine the Minimum Sum of a k-avoiding Array.java @@ -0,0 +1,18 @@ +class Solution { + public int minimumSum(int n, int k) { + Set set = new HashSet<>(); + set.add(1); + int sum = 1; + int next = 2; + while (n > 1) { + if (set.contains(k - next)) { + next++; + continue; + } + set.add(next); + sum += next++; + n--; + } + return sum; + } +} diff --git a/Medium/Detonate the Maximum Bombs.java b/Medium/Detonate the Maximum Bombs.java new file mode 100644 index 00000000..2dbecdc0 --- /dev/null +++ b/Medium/Detonate the Maximum Bombs.java @@ -0,0 +1,37 @@ +class Solution { + public int maximumDetonation(int[][] bombs) { + Map> graph = new HashMap<>(); + int n = bombs.length; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + int x1 = bombs[i][0]; + int y1 = bombs[i][1]; + int r = bombs[i][2]; + int x2 = bombs[j][0]; + int y2 = bombs[j][1]; + if ((long) r * r >= (long) (x1 - x2) * (x1 - x2) + (long) (y1 - y2) * (y1 - y2)) { + graph.computeIfAbsent(i, k -> new ArrayList<>()).add(j); + } + } + } + int result = 0; + for (int i = 0; i < n; i++) { + result = Math.max(result, dfs(i, new HashSet<>(), graph)); + } + return result; + } + + private int dfs(int curr, Set visited, Map> graph) { + visited.add(curr); + int count = 1; + for (Integer neighbor : graph.getOrDefault(curr, new ArrayList<>())) { + if (!visited.contains(neighbor)) { + count += dfs(neighbor, visited, graph); + } + } + return count; + } +} diff --git a/Medium/Diagonal Traverse II.java b/Medium/Diagonal Traverse II.java new file mode 100644 index 00000000..dabfc5ef --- /dev/null +++ b/Medium/Diagonal Traverse II.java @@ -0,0 +1,26 @@ +class Solution { + public int[] findDiagonalOrder(List> nums) { + Queue queue = new LinkedList<>(); + List result = new ArrayList<>(); + queue.add(new int[]{0, 0}); + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + result.add(nums.get(x).get(y)); + // move down in column first + if (y == 0 && x + 1 < nums.size()) { + queue.add(new int[]{x + 1, y}); + } + // then pick the next element in row + if (y + 1 < nums.get(x).size()) { + queue.add(new int[]{x, y + 1}); + } + } + int[] ans = new int[result.size()]; + for (int i = 0; i < result.size(); i++) { + ans[i] = result.get(i); + } + return ans; + } +} diff --git a/Medium/Diagonal Traverse.java b/Medium/Diagonal Traverse.java index 0fc4371b..65c991a5 100644 --- a/Medium/Diagonal Traverse.java +++ b/Medium/Diagonal Traverse.java @@ -1,51 +1,33 @@ class Solution { - public int[] findDiagonalOrder(int[][] matrix) { - if (matrix.length == 0 || matrix[0].length == 0) { - return new int[]{}; + public int[] findDiagonalOrder(int[][] matrix) { + int dir = 0; + int x = 0; + int y = 0; + int numOfRows = matrix.length; + int numOfCols = matrix[0].length; + int[] ans = new int[numOfRows * numOfCols]; + for (int i = 0; i < numOfRows * numOfCols; i++) { + ans[i] = matrix[x][y]; + if ((x + y) % 2 == 0) { + if (y == numOfCols - 1) { + x++; + } else if (x == 0) { + y++; + } else { + x--; + y++; } - - int dir = 0; - int x = 0; - int y = 0; - int numOfRows = matrix.length; - int numOfCols = matrix[0].length; - int[] ans = new int[matrix.length * matrix[0].length]; - - for (int i = 0; i < numOfRows * numOfCols; i++) { - ans[i] = matrix[x][y]; - - if ((x + y) % 2 == 0) { - // If last column then go to next row - if (y == numOfCols - 1) { - x++; - } - // If first row but not last column then go to next column - else if (x == 0) { - y++; - } - // Go up - else { - x--; - y++; - } - } - else { - // If last row then go to next column - if (x == numOfRows - 1) { - y++; - } - // If first column but not last row then go to next row - else if (y == 0) { - x++; - } - // Go down - else { - x++; - y--; - } - } + } else { + if (x == numOfRows - 1) { + y++; + } else if (y == 0) { + x++; + } else { + x++; + y--; } - - return ans; + } } + return ans; + } } diff --git a/Medium/Diameter of N-ary Tree.java b/Medium/Diameter of N-ary Tree.java new file mode 100644 index 00000000..7bf358a5 --- /dev/null +++ b/Medium/Diameter of N-ary Tree.java @@ -0,0 +1,50 @@ +/* +// Definition for a Node. +class Node { + public int val; + public List children; + + + public Node() { + children = new ArrayList(); + } + + public Node(int _val) { + val = _val; + children = new ArrayList(); + } + + public Node(int _val,ArrayList _children) { + val = _val; + children = _children; + } +}; +*/ + +class Solution { + public int diameter(Node root) { + int[] diameter = {0}; + getHeight(root, diameter); + return diameter[0]; + } + + private int getHeight(Node node, int[] diameter) { + if (node.children.size() == 0) { + return 0; + } + int maxHeightOne = 0; + int maxHeightTwo = 0; + for (Node child : node.children) { + int parentHeight = getHeight(child, diameter) + 1; + if (parentHeight > maxHeightOne) { + maxHeightTwo = maxHeightOne; + maxHeightOne = parentHeight; + } else if (parentHeight > maxHeightTwo) { + maxHeightTwo = parentHeight; + } + int currentDiameter = maxHeightOne + maxHeightTwo; + diameter[0] = Math.max(diameter[0], currentDiameter); + } + return maxHeightOne; + } +} diff --git a/Medium/Difference Between Ones and Zeros in Row and Column.java b/Medium/Difference Between Ones and Zeros in Row and Column.java new file mode 100644 index 00000000..641b0b38 --- /dev/null +++ b/Medium/Difference Between Ones and Zeros in Row and Column.java @@ -0,0 +1,23 @@ +class Solution { + public int[][] onesMinusZeros(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + int[][] rowCount = new int[rows][2]; + int[][] colCount = new int[cols][2]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + rowCount[i][0] += grid[i][j] == 1 ? 1 : 0; + rowCount[i][1] += grid[i][j] != 1 ? 1 : 0; + colCount[j][0] += grid[i][j] == 1 ? 1 : 0; + colCount[j][1] += grid[i][j] != 1 ? 1 : 0; + } + } + int[][] result = new int[rows][cols]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + result[i][j] = rowCount[i][0] + colCount[j][0] - rowCount[i][1] - colCount[j][1]; + } + } + return result; + } +} diff --git a/Medium/Different Ways to Add Parentheses.java b/Medium/Different Ways to Add Parentheses.java new file mode 100644 index 00000000..706fcf6c --- /dev/null +++ b/Medium/Different Ways to Add Parentheses.java @@ -0,0 +1,42 @@ +class Solution { + public List diffWaysToCompute(String expression) { + List result = new ArrayList<>(); + if (expression.length() == 0) { + return result; + } + if (expression.length() == 1) { + result.add(Integer.parseInt(expression)); + return result; + } + if (expression.length() == 2 && Character.isDigit(expression.charAt(0))) { + result.add(Integer.parseInt(expression)); + return result; + } + for (int i = 0; i < expression.length(); i++) { + char c = expression.charAt(i); + if (Character.isDigit(c)) { + continue; + } + List leftResult = diffWaysToCompute(expression.substring(0, i)); + List rightResult = diffWaysToCompute(expression.substring(i + 1)); + for (int leftVal : leftResult) { + for (int rightVal : rightResult) { + int value = 0; + switch(c) { + case '+': + value = leftVal + rightVal; + break; + case '-': + value = leftVal - rightVal; + break; + case '*': + value = leftVal * rightVal; + break; + } + result.add(value); + } + } + } + return result; + } +} diff --git a/Medium/Display Table of Food Orders in a Restaurant.java b/Medium/Display Table of Food Orders in a Restaurant.java new file mode 100644 index 00000000..31b32703 --- /dev/null +++ b/Medium/Display Table of Food Orders in a Restaurant.java @@ -0,0 +1,33 @@ +class Solution { + public List> displayTable(List> orders) { + Map> map = new HashMap<>(); + Set tablesOrdered = new TreeSet<>(); + Set possibleItems = new TreeSet<>(); + for (List order : orders) { + int tableId = Integer.parseInt(order.get(1)); + for (int i = 2; i < order.size(); i++) { + map.computeIfAbsent(tableId, k -> new HashMap<>()); + Map tableMap = map.get(tableId); + tableMap.put(order.get(i), tableMap.getOrDefault(order.get(i), 0) + 1); + possibleItems.add(order.get(i)); + } + tablesOrdered.add(tableId); + } + List> list = new ArrayList<>(); + List temp = new ArrayList<>(); + temp.add("Table"); + temp.addAll(possibleItems); + list.add(temp); + temp = new ArrayList<>(); + for (Integer table : tablesOrdered) { + Map tableMap = map.get(table); + temp.add(String.valueOf(table)); + for (String item : possibleItems) { + temp.add(String.valueOf(tableMap.getOrDefault(item, 0))); + } + list.add(temp); + temp = new ArrayList<>(); + } + return list; + } +} diff --git a/Medium/Distribute Candies Among Children II.java b/Medium/Distribute Candies Among Children II.java new file mode 100644 index 00000000..aa9648f2 --- /dev/null +++ b/Medium/Distribute Candies Among Children II.java @@ -0,0 +1,14 @@ +class Solution { + public long distributeCandies(int n, int limit) { + long result = 0; + for (int i = 0; i <= Math.min(limit, n); i++) { + // distribution not possible as we will have to allocate at least one child with + // more than limit candies + if (n - i > 2 * limit) { + continue; + } + result += Math.min(n - i, limit) - Math.max(0, n - i - limit) + 1; + } + return result; + } +} diff --git a/Medium/Distribute Coins in Binary Tree.java b/Medium/Distribute Coins in Binary Tree.java index bab8bb39..e2b15fd4 100644 --- a/Medium/Distribute Coins in Binary Tree.java +++ b/Medium/Distribute Coins in Binary Tree.java @@ -8,30 +8,20 @@ * } */ class Solution { - int numOfSteps; - public int distributeCoins(TreeNode root) { - numOfSteps = 0; - postorder(root); - - return numOfSteps; - } - - private int postorder(TreeNode root) { - if (root == null) { - return 0; - } - - int coin = postorder(root.left) + postorder(root.right); - - if (root.val == 0) { - coin += -1; - } - else { - coin += root.val - 1; - } - - numOfSteps += Math.abs(coin); - - return coin; + int ans; + public int distributeCoins(TreeNode root) { + ans = 0; + dfs(root); + return ans; + } + + private int dfs(TreeNode root) { + if (root == null) { + return 0; } + int l = dfs(root.left); + int r = dfs(root.right); + ans += Math.abs(l) + Math.abs(r); + return root.val + l + r - 1; + } } diff --git a/Medium/Divide Array Into Arrays With Max Difference.java b/Medium/Divide Array Into Arrays With Max Difference.java new file mode 100644 index 00000000..77959768 --- /dev/null +++ b/Medium/Divide Array Into Arrays With Max Difference.java @@ -0,0 +1,15 @@ +class Solution { + public int[][] divideArray(int[] nums, int k) { + Arrays.sort(nums); + int n = nums.length; + int[][] result = new int[n / 3][3]; + int idx = 0; + for (int i = 2; i < nums.length; i += 3) { + if (nums[i] - nums[i - 2] > k) { + return new int[][]{}; + } + result[idx++] = new int[]{nums[i - 2], nums[i - 1], nums[i]}; + } + return result; + } +} diff --git a/Medium/Divide Array in Sets of K Consecutive Numbers.java b/Medium/Divide Array in Sets of K Consecutive Numbers.java new file mode 100644 index 00000000..1ec341d6 --- /dev/null +++ b/Medium/Divide Array in Sets of K Consecutive Numbers.java @@ -0,0 +1,30 @@ +class Solution { + public boolean isPossibleDivide(int[] nums, int k) { + int n = nums.length; + if (k == 0 || n < k || n % k != 0) { + return false; + } + PriorityQueue pq = new PriorityQueue<>(); + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + pq.addAll(map.keySet()); + while (!pq.isEmpty()) { + int polled = pq.poll(); + int times = map.get(polled); + if (times != 0) { + while (times-- > 0) { + for (int i = 0; i < k; i++) { + if (!map.containsKey(polled + i) || map.get(polled + i) == 0) { + return false; + } + map.put(polled + i, map.get(polled + i) - 1); + } + n -= k; + } + } + } + return true; + } +} diff --git a/Medium/Divide Intervals Into Minimum Number of Groups.java b/Medium/Divide Intervals Into Minimum Number of Groups.java new file mode 100644 index 00000000..b58d0dcb --- /dev/null +++ b/Medium/Divide Intervals Into Minimum Number of Groups.java @@ -0,0 +1,21 @@ +class Solution { + public int minGroups(int[][] intervals) { + Arrays.sort(intervals, (o1, o2) -> { + int c = Integer.compare(o1[0], o2[0]); + if (c == 0) { + return Integer.compare(o1[1], o2[1]); + } + return c; + }); + int max = 0; + PriorityQueue pq = new PriorityQueue<>(); + for (int[] interval : intervals) { + while (!pq.isEmpty() && pq.peek() < interval[0]) { + pq.poll(); + } + pq.add(interval[1]); + max = Math.max(max, pq.size()); + } + return max; + } +} diff --git a/Medium/Divide Players Into Teams of Equal Skill.java b/Medium/Divide Players Into Teams of Equal Skill.java new file mode 100644 index 00000000..41a5f1f7 --- /dev/null +++ b/Medium/Divide Players Into Teams of Equal Skill.java @@ -0,0 +1,25 @@ +class Solution { + public long dividePlayers(int[] skill) { + int n = skill.length; + int totalSkill = 0; + Map map = new HashMap<>(); + for (int s : skill) { + totalSkill += s; + map.put(s, map.getOrDefault(s, 0) + 1); + } + if (totalSkill % (n / 2) != 0) { + return -1; + } + int targetSkill = totalSkill / (n / 2); + long totalChemistry = 0; + for (int currSkill : map.keySet()) { + int partnerSkill = targetSkill - currSkill; + int currSkillFreq = map.get(currSkill); + if (!map.containsKey(partnerSkill) || currSkillFreq != map.get(partnerSkill)) { + return -1; + } + totalChemistry += (long) currSkill * (long) partnerSkill * (long) currSkillFreq; + } + return totalChemistry / 2; + } +} diff --git a/Medium/Divide Two Integers.java b/Medium/Divide Two Integers.java index 0df8c413..3ecf9dee 100644 --- a/Medium/Divide Two Integers.java +++ b/Medium/Divide Two Integers.java @@ -1,41 +1,32 @@ class Solution { - public int divide(int dividend, int divisor) { - - boolean isNeg = false; - if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) { - isNeg = true; - } - - int ans = 0; - - long Ldividend = Math.abs((long) dividend); - long Ldivisor = Math.abs((long) divisor); - - if (Ldivisor == 0) return Integer.MAX_VALUE; - if (Ldividend == 0 || (Ldividend < Ldivisor)) return 0; - - long quot = ldivide(Ldividend, Ldivisor); - - if(quot > Integer.MAX_VALUE) { - ans = isNeg == false ? Integer.MAX_VALUE : Integer.MIN_VALUE; - } - else { - ans = (int)(isNeg ? -quot : quot); - } - - return ans; + private static int HALF_INT_MIN = -1073741824; + public int divide(int dividend, int divisor) { + if (dividend == Integer.MIN_VALUE && divisor == -1) { + return Integer.MAX_VALUE; } - - private long ldivide(long ldividend, long ldivisor) { - if (ldividend < ldivisor) return 0; - - long sum = ldivisor; - long multiple = 1; - while ((sum+sum) <= ldividend) { - sum += sum; - multiple += multiple; - } - - return multiple + ldivide(ldividend - sum, ldivisor); + int negatives = 2; + if (dividend > 0) { + negatives--; + dividend = -dividend; } + if (divisor > 0) { + negatives--; + divisor = -divisor; + } + int quotient = 0; + while (divisor >= dividend) { + int powerOfTwo = -1; + int value = divisor; + while (value >= HALF_INT_MIN && value + value >= dividend) { + value += value; + powerOfTwo += powerOfTwo; + } + quotient += powerOfTwo; + dividend -= value; + } + if (negatives != 1) { + return -quotient; + } + return quotient; + } } diff --git a/Medium/Dot Product of Two Sparse Vectors.java b/Medium/Dot Product of Two Sparse Vectors.java new file mode 100644 index 00000000..824c407f --- /dev/null +++ b/Medium/Dot Product of Two Sparse Vectors.java @@ -0,0 +1,36 @@ +class SparseVector { + + private Map nonZeroRowMap; + + SparseVector(int[] nums) { + this.nonZeroRowMap = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + nonZeroRowMap.put(i, nums[i]); + } + } + } + +// Return the dotProduct of two sparse vectors + public int dotProduct(SparseVector vec) { + Map vecNonZeroRowMap = vec.getNonZeroRowMap(); + return this.nonZeroRowMap.size() < vecNonZeroRowMap.size() ? dotProductHelper(this.nonZeroRowMap, vecNonZeroRowMap) : dotProductHelper(vecNonZeroRowMap, this.nonZeroRowMap); + } + + private int dotProductHelper(Map mapOne, Map mapTwo) { + int product = 0; + for (Integer key : mapOne.keySet()) { + product += mapOne.get(key) * mapTwo.getOrDefault(key, 0); + } + return product; + } + + public Map getNonZeroRowMap() { + return new HashMap<>(nonZeroRowMap); + } +} + +// Your SparseVector object will be instantiated and called as such: +// SparseVector v1 = new SparseVector(nums1); +// SparseVector v2 = new SparseVector(nums2); +// int ans = v1.dotProduct(v2); diff --git a/Medium/Dota2 Senate.java b/Medium/Dota2 Senate.java new file mode 100644 index 00000000..56465cb4 --- /dev/null +++ b/Medium/Dota2 Senate.java @@ -0,0 +1,24 @@ +class Solution { + public String predictPartyVictory(String senate) { + int n = senate.length(); + Queue rValid = new LinkedList<>(); + Queue dValid = new LinkedList<>(); + for (int i = 0; i < n; i++) { + if (senate.charAt(i) == 'R') { + rValid.add(i); + } else { + dValid.add(i); + } + } + while (!rValid.isEmpty() && !dValid.isEmpty()) { + int rTurn = rValid.remove(); + int dTurn = dValid.remove(); + if (dTurn < rTurn) { + dValid.add(dTurn + n); + } else { + rValid.add(rTurn + n); + } + } + return rValid.isEmpty() ? "Dire" : "Radiant"; + } +} diff --git a/Medium/Double Modular Exponentiation.java b/Medium/Double Modular Exponentiation.java new file mode 100644 index 00000000..6dada495 --- /dev/null +++ b/Medium/Double Modular Exponentiation.java @@ -0,0 +1,23 @@ +class Solution { + public List getGoodIndices(int[][] variables, int target) { + List result = new ArrayList<>(); + for (int i = 0; i < variables.length; i++) { + int a = variables[i][0]; + int b = variables[i][1]; + int c = variables[i][2]; + int m = variables[i][3]; + int base = 1; + for (int j = 0; j < b; j++) { + base = (base * a) % 10; + } + int value = 1; + for (int j = 0; j < c; j++) { + value = (value * base) % m; + } + if (value == target) { + result.add(i); + } + } + return result; + } +} diff --git a/Medium/Double a Number Represented as a Linked List.java b/Medium/Double a Number Represented as a Linked List.java new file mode 100644 index 00000000..9e2bcbaa --- /dev/null +++ b/Medium/Double a Number Represented as a Linked List.java @@ -0,0 +1,40 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode doubleIt(ListNode head) { + ListNode rev = reverse(head); + ListNode curr = rev; + int carry = 0; + while (curr != null) { + int val = curr.val * 2 + carry; + carry = val / 10; + curr.val = val % 10; + if (curr.next == null && carry != 0) { + curr.next = new ListNode(carry); + break; + } + curr = curr.next; + } + return reverse(rev); + } + + private ListNode reverse(ListNode curr) { + ListNode next = null; + ListNode prev = null; + while (curr != null) { + next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } +} diff --git a/Medium/Encode and Decode Strings.java b/Medium/Encode and Decode Strings.java index cbdce47e..c39d5b6a 100644 --- a/Medium/Encode and Decode Strings.java +++ b/Medium/Encode and Decode Strings.java @@ -1,32 +1,43 @@ public class Codec { - // Encodes a list of strings to a single string. - public String encode(List strs) { - StringBuilder sb = new StringBuilder(""); - - for (String str : strs) { - sb.append(str.length()).append("|").append(str); - } - - return sb.toString(); + // Encodes a list of strings to a single string. + public String encode(List strs) { + StringBuilder sb = new StringBuilder(); + for (String s : strs) { + sb.append(lengthEncoding(s)).append(s); } + return sb.toString(); + } - // Decodes a single string to a list of strings. - public List decode(String s) { - List list = new ArrayList<>(); - - int idx = 0; - int n = s.length(); - - while (idx < n) { - int slashIdx = s.indexOf('|', idx); - int size = Integer.parseInt(s.substring(idx, slashIdx)); - idx = slashIdx + size + 1; - list.add(s.substring(slashIdx + 1, idx)); - } - - return list; + // Decodes a single string to a list of strings. + public List decode(String s) { + int idx = 0; + List result = new ArrayList<>(); + int n = s.length(); + while (idx < n) { + int currStringLength = lengthDecoding(s.substring(idx, idx + 4)); + idx += 4; + result.add(s.substring(idx, idx + currStringLength)); + idx += currStringLength; } + return result; + } + + private String lengthEncoding(String s) { + int n = s.length(); + char[] bytes = new char[4]; + for(int i = 3; i >= 0; i--) { + bytes[3 - i] = (char) (n >> (i * 8) & 0xff); + } + return new String(bytes); + } + + private int lengthDecoding(String bytesStr) { + int result = 0; + for(char b : bytesStr.toCharArray()) + result = (result << 8) + (int)b; + return result; + } } // Your Codec object will be instantiated and called as such: diff --git a/Medium/Equal Row and Column Pairs.java b/Medium/Equal Row and Column Pairs.java new file mode 100644 index 00000000..515fb2db --- /dev/null +++ b/Medium/Equal Row and Column Pairs.java @@ -0,0 +1,23 @@ +class Solution { + public int equalPairs(int[][] grid) { + Map rowMap = new HashMap<>(); + for (int[] value : grid) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < grid[0].length; j++) { + sb.append(value[j]).append("|"); + } + String key = sb.toString(); + rowMap.put(key, rowMap.getOrDefault(key, 0) + 1); + } + int count = 0; + for (int i = 0; i < grid[0].length; i++) { + StringBuilder sb = new StringBuilder(); + for (int[] ints : grid) { + sb.append(ints[i]).append("|"); + } + String key = sb.toString(); + count += rowMap.getOrDefault(key, 0); + } + return count; + } +} diff --git a/Medium/Evaluate Division.java b/Medium/Evaluate Division.java new file mode 100644 index 00000000..f4467f6e --- /dev/null +++ b/Medium/Evaluate Division.java @@ -0,0 +1,45 @@ +class Solution { + public double[] calcEquation(List> equations, double[] values, + List> queries) { + double[] ans = new double[queries.size()]; + Map> connectionMap = new HashMap<>(); + Map valueMap = new HashMap<>(); + for (int i = 0; i < equations.size(); i++) { + String equation = equations.get(i).get(0) + "/" + equations.get(i).get(1); + connectionMap.computeIfAbsent(equations.get(i).get(0), k -> new HashSet<>()) + .add(equations.get(i).get(1)); + connectionMap.computeIfAbsent(equations.get(i).get(1), k -> new HashSet<>()) + .add(equations.get(i).get(0)); + valueMap.put(equation, values[i]); + } + for (int i = 0; i < queries.size(); i++) { + String source = queries.get(i).get(0); + String target = queries.get(i).get(1); + double[] res = {-1.0}; + dfs(connectionMap, valueMap, source, target, new HashSet<>(), res, 1.0); + ans[i] = res[0]; + } + return ans; + } + + private void dfs(Map> connectionMap, Map valueMap, + String source, String target, Set visited, double[] res, double currVal) { + if (source.equals(target) && ( + connectionMap.containsKey(source) || connectionMap.containsKey(target)) + ) { + res[0] = currVal; + return; + } + for (String connection : connectionMap.getOrDefault(source, new HashSet<>())) { + if (!visited.contains(connection)) { + visited.add(connection); + double newwCurrVal = currVal * ( + valueMap.containsKey(source + "/" + connection) ? + valueMap.get(source + "/" + connection) : + (1 / valueMap.get(connection + "/" + source)) + ); + dfs(connectionMap, valueMap, connection, target, visited, res, newwCurrVal); + } + } + } +} diff --git a/Medium/Evaluate Reverse Polish Notation.java b/Medium/Evaluate Reverse Polish Notation.java index 8b606b68..17b3a709 100644 --- a/Medium/Evaluate Reverse Polish Notation.java +++ b/Medium/Evaluate Reverse Polish Notation.java @@ -1,31 +1,26 @@ class Solution { + + private static final Set OPERATIONS = Set.of("*", "+", "/", "-"); + public int evalRPN(String[] tokens) { Stack stack = new Stack<>(); - Set operations = new HashSet<>(Arrays.asList("-", "+", "*", "/")); for (String token : tokens) { - if (operations.contains(token)) { - int num1 = stack.pop(); - int num2 = stack.pop(); - stack.push(performOperation(num2, num1, token)); - } - else { + if (OPERATIONS.contains(token)) { + stack.push(performOperation(stack.pop(), stack.pop(), token)); + } else { stack.push(Integer.parseInt(token)); } } - return stack.pop(); } - private int performOperation(int a, int b, String operation) { - switch(operation) { - case "+": - return a + b; - case "-": - return a - b; - case "*": - return a * b; - default: - return a / b; - } + private static int performOperation(int num2, int num1, String operation) throws UnsupportedOperationException { + return switch(operation) { + case "+" -> num1 + num2; + case "-" -> num1 - num2; + case "*" -> num1 * num2; + case "/" -> num1 / num2; + default -> throw new UnsupportedOperationException("Operation not supported"); + }; } } diff --git a/Medium/Evaluate the Bracket Pairs of a String.java b/Medium/Evaluate the Bracket Pairs of a String.java new file mode 100644 index 00000000..3a90861a --- /dev/null +++ b/Medium/Evaluate the Bracket Pairs of a String.java @@ -0,0 +1,24 @@ +class Solution { + public String evaluate(String s, List> knowledge) { + Map map = new HashMap<>(); + for (List entry : knowledge) { + map.put(entry.get(0), entry.get(1)); + } + StringBuilder sb = new StringBuilder(); + int idx = 0; + int n = s.length(); + while (idx < n) { + if (s.charAt(idx) == '(') { + idx++; + int currIdx = idx; + while (idx < n && s.charAt(idx) != ')') { + idx++; + } + sb.append(map.getOrDefault(s.substring(currIdx, idx++), "?")); + } else { + sb.append(s.charAt(idx++)); + } + } + return sb.toString(); + } +} diff --git a/Medium/Even Odd Tree.java b/Medium/Even Odd Tree.java new file mode 100644 index 00000000..574ddf6b --- /dev/null +++ b/Medium/Even Odd Tree.java @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean isEvenOddTree(TreeNode root) { + Queue queue = new LinkedList<>(); + queue.add(root); + boolean even = true; + while (!queue.isEmpty()) { + int size = queue.size(); + int prev = even ? Integer.MIN_VALUE : Integer.MAX_VALUE; + while (size-- > 0) { + TreeNode removed = queue.remove(); + if ((even && removed.val % 2 == 0) || (!even && removed.val % 2 != 0)) { + return false; + } + if ((even && removed.val <= prev) || (!even && removed.val >= prev)) { + return false; + } + prev = removed.val; + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + even = !even; + } + return true; + } +} diff --git a/Medium/Exclusive Time of Functions.java b/Medium/Exclusive Time of Functions.java index ed23668b..cd85e84c 100644 --- a/Medium/Exclusive Time of Functions.java +++ b/Medium/Exclusive Time of Functions.java @@ -1,42 +1,25 @@ class Solution { public int[] exclusiveTime(int n, List logs) { - int[] time = new int[n]; - - Stack tasks = new Stack<>(); - + Stack stack = new Stack<>(); + int[] result = new int[n]; + int lastTimestamp = 0; for (String log : logs) { - Task task = new Task(log); - - if (task.status == Status.Start) { - tasks.push(task); - } - else { - Task top = tasks.pop(); - time[top.num] += task.time - top.time + 1; - - if (!tasks.isEmpty()) { - time[tasks.peek().num] -= task.time - top.time + 1; + String[] split = log.split(":"); + int id = Integer.parseInt(split[0]); + int timestamp = Integer.parseInt(split[2]); + if (split[1].equals("start")) { + // We consider timestamp as part of current computation + if (!stack.isEmpty()) { + result[stack.peek()] += timestamp - lastTimestamp; } + stack.push(id); + lastTimestamp = timestamp; + } else { + // We consider timestamp as part of previous computation + result[stack.pop()] += timestamp - lastTimestamp + 1; + lastTimestamp = timestamp + 1; } } - - return time; - } -} - -class Task { - public int num; - public int time; - public Status status; - - public Task(String log) { - String[] strs = log.split(":"); - this.num = Integer.parseInt(strs[0]); - this.time = Integer.parseInt(strs[2]); - this.status = strs[1].equals("start") ? Status.Start : Status.End; + return result; } } - -enum Status { - Start, End; -} diff --git a/Medium/Execution of All Suffix Instructions Staying in a Grid.java b/Medium/Execution of All Suffix Instructions Staying in a Grid.java new file mode 100644 index 00000000..4d231f93 --- /dev/null +++ b/Medium/Execution of All Suffix Instructions Staying in a Grid.java @@ -0,0 +1,25 @@ +class Solution { + public int[] executeInstructions(int n, int[] startPos, String s) { + int[] result = new int[s.length()]; + Map directionToMovementMap = Map.of( + 'R', new int[]{0, 1}, + 'L', new int[]{0, -1}, + 'U', new int[]{-1, 0}, + 'D', new int[]{1, 0} + ); + for (int i = 0; i < s.length(); i++) { + int startX = startPos[0]; + int startY = startPos[1]; + int j = i; + for (; j < s.length(); j++) { + startX += directionToMovementMap.get(s.charAt(j))[0]; + startY += directionToMovementMap.get(s.charAt(j))[1]; + if (startX < 0 || startY < 0 || startX >= n || startY >= n) { + break; + } + } + result[i] = j - i; + } + return result; + } +} diff --git a/Medium/Expressive Words.java b/Medium/Expressive Words.java index b9b70e1e..2903acba 100644 --- a/Medium/Expressive Words.java +++ b/Medium/Expressive Words.java @@ -1,47 +1,32 @@ class Solution { - public int expressiveWords(String S, String[] words) { - int count = 0; - char[] sChar = S.toCharArray(); - for (String word : words) { - char[] wChar = word.toCharArray(); - if (check(sChar, wChar)) { - count++; - } - } - - return count; - } - - private boolean check(char[] s, char[] w) { - int i = 0; - int j = 0; - - while (i < s.length && j < w.length) { - if (s[i] != w[j]) { - return false; - } - - int tempI = i; - int tempJ = j; - - while (i < s.length && s[i] == s[tempI]) { - i++; - } - - while (j < w.length && w[j] == w[tempJ]) { - j++; - } - - int l1 = i - tempI; - int l2 = j - tempJ; - - if (l1 == l2 || l1 >= 3 && l1 > l2) { - continue; - } - - return false; - } - - return i == s.length && j == w.length; + public int expressiveWords(String s, String[] words) { + return (int) Arrays.stream(words).filter(word -> isExpressive(s, word)).count(); + } + + private boolean isExpressive(String s, String word) { + int sIdx = 0; + int wordIdx = 0; + while (sIdx < s.length() && wordIdx < word.length()) { + if (s.charAt(sIdx) != word.charAt(wordIdx)) { + return false; + } + char c1 = s.charAt(sIdx); + int countC1 = 0; + while (sIdx < s.length() && s.charAt(sIdx) == c1) { + sIdx++; + countC1++; + } + char c2 = word.charAt(wordIdx); + int countC2 = 0; + while (wordIdx < word.length() && word.charAt(wordIdx) == c2) { + wordIdx++; + countC2++; + } + if (countC1 == countC2 || (countC1 > countC2 && countC1 >= 3)) { + continue; + } + return false; } + return sIdx == s.length() && wordIdx == word.length(); + } } diff --git a/Medium/Extra Characters in a String.java b/Medium/Extra Characters in a String.java new file mode 100644 index 00000000..4d43cc5c --- /dev/null +++ b/Medium/Extra Characters in a String.java @@ -0,0 +1,25 @@ +class Solution { + public int minExtraChar(String s, String[] dictionary) { + Integer[] dp = new Integer[s.length() + 1]; + return helper(0, s, Arrays.stream(dictionary).collect(Collectors.toSet()), dp); + } + + private int helper(int idx, String s, Set set, Integer[] dp) { + if (idx == s.length()) { + return 0; + } + if (dp[idx] != null) { + return dp[idx]; + } + int result = Integer.MAX_VALUE; + for (int i = idx; i < s.length(); i++) { + String sub = s.substring(idx, i + 1); + if (set.contains(sub)) { + result = Math.min(result, helper(i + 1, s, set, dp)); + } else { + result = Math.min(result, i - idx + 1 + helper(i + 1, s, set, dp)); + } + } + return dp[idx] = result; + } +} diff --git a/Medium/Fair Distribution of Cookies.java b/Medium/Fair Distribution of Cookies.java new file mode 100644 index 00000000..ad4b0f94 --- /dev/null +++ b/Medium/Fair Distribution of Cookies.java @@ -0,0 +1,23 @@ +class Solution { + public int distributeCookies(int[] cookies, int k) { + int[] share = new int[k]; + return helper(cookies, share, 0); + } + + private int helper(int[] cookies, int[] share, int idx) { + if (idx == cookies.length) { + int maxShare = share[0]; + for (int s : share) { + maxShare = Math.max(s, maxShare); + } + return maxShare; + } + int result = Integer.MAX_VALUE; + for(int i = 0; i < share.length; i++){ + share[i] += cookies[idx]; + result = Math.min(result, helper(cookies, share, idx + 1)); + share[i] -= cookies[idx]; + } + return result; + } +} diff --git a/Medium/Filter Restaurants by Vegan-Friendly, Price and Distance.java b/Medium/Filter Restaurants by Vegan-Friendly, Price and Distance.java new file mode 100644 index 00000000..a47d59da --- /dev/null +++ b/Medium/Filter Restaurants by Vegan-Friendly, Price and Distance.java @@ -0,0 +1,25 @@ +class Solution { + public List filterRestaurants(int[][] restaurants, int veganFriendly, int maxPrice, int maxDistance) { + List indexList = new ArrayList<>(); + for (int i = 0; i < restaurants.length; i++) { + int[] restaurant = restaurants[i]; + if ((veganFriendly == 0 || restaurant[2] == 1) && restaurant[3] <= maxPrice && restaurant[4] <= maxDistance) { + indexList.add(i); + } + } + Collections.sort(indexList, new Comparator() { + public int compare(Integer o1, Integer o2) { + int c = restaurants[o2][1] - restaurants[o1][1]; + if (c != 0) { + return c; + } + return restaurants[o2][0] - restaurants[o1][0]; + } + }); + List ans = new ArrayList<>(); + for (Integer index : indexList) { + ans.add(restaurants[index][0]); + } + return ans; + } +} diff --git a/Medium/Find All Anagrams in a String.java b/Medium/Find All Anagrams in a String.java new file mode 100644 index 00000000..e18917da --- /dev/null +++ b/Medium/Find All Anagrams in a String.java @@ -0,0 +1,24 @@ +class Solution { + public List findAnagrams(String s, String p) { + if (s.length() < p.length()) { + return new ArrayList<>(); + } + List result = new ArrayList<>(); + int[] patternCounter = new int[26]; + for (char c : p.toCharArray()) { + patternCounter[c - 'a']++; + } + int[] counter = new int[26]; + int start = 0; + for (int i = 0; i < s.length(); i++) { + counter[s.charAt(i) - 'a']++; + if (i >= p.length() - 1) { + if (Arrays.equals(patternCounter, counter)) { + result.add(start); + } + counter[s.charAt(start++) - 'a']--; + } + } + return result; + } +} diff --git a/Medium/Find All Groups of Farmland.java b/Medium/Find All Groups of Farmland.java new file mode 100644 index 00000000..130db6a1 --- /dev/null +++ b/Medium/Find All Groups of Farmland.java @@ -0,0 +1,49 @@ +class Solution { + + private static final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int[][] findFarmland(int[][] land) { + int rows = land.length; + int cols = land[0].length; + boolean[][] visited = new boolean[rows][cols]; + List result = new ArrayList<>(); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (land[i][j] == 1 && !visited[i][j]) { + traverse(land, i, j, visited, result); + } + } + } + return result.stream() + .map(int[]::clone) + .toArray(int[][]::new); + } + + private static void traverse(int[][] land, int i, int j, boolean[][] visited, List result) { + int rows = land.length; + int cols = land[0].length; + Queue queue = new LinkedList<>(); + int[] leftMost = {i, j}; + int[] rightMost = {i, j}; + queue.add(new int[]{i, j}); + visited[i][j] = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + leftMost[0] = Math.min(leftMost[0], x); + leftMost[1] = Math.min(leftMost[1], y); + rightMost[0] = Math.max(rightMost[0], x); + rightMost[1] = Math.max(rightMost[1], y); + for (int[] dir : DIRS) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newY >= 0 && newX < rows && newY < cols && !visited[newX][newY] && land[newX][newY] == 1) { + queue.add(new int[]{newX, newY}); + visited[newX][newY] = true; + } + } + } + result.add(new int[]{leftMost[0], leftMost[1], rightMost[0], rightMost[1]}); + } +} diff --git a/Medium/Find All Lonely Numbers in the Array.java b/Medium/Find All Lonely Numbers in the Array.java new file mode 100644 index 00000000..c55981d5 --- /dev/null +++ b/Medium/Find All Lonely Numbers in the Array.java @@ -0,0 +1,16 @@ +import java.util.Map.Entry; + + +class Solution { + public List findLonely(int[] nums) { + Map map = Arrays.stream(nums) + .boxed() + .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting())); + return map.entrySet().stream() + .filter( + entry -> entry.getValue().equals(1L) && !map.containsKey(entry.getKey() + 1) + && !map.containsKey(entry.getKey() - 1)) + .map(Entry::getKey) + .collect(Collectors.toList()); + } +} diff --git a/Medium/Find All Possible Recipes from Given Supplies.java b/Medium/Find All Possible Recipes from Given Supplies.java new file mode 100644 index 00000000..702d1d15 --- /dev/null +++ b/Medium/Find All Possible Recipes from Given Supplies.java @@ -0,0 +1,29 @@ +class Solution { + public List findAllRecipes(String[] recipes, List> ingredients, String[] supplies) { + Map> map = new HashMap<>(); + Map ingredientCounter = new HashMap<>(); + for (int i = 0; i < recipes.length; i++) { + List currentIngredientList = ingredients.get(i); + for (String ingredient : currentIngredientList) { + map.computeIfAbsent(ingredient, k -> new ArrayList<>()).add(recipes[i]); + ingredientCounter.put(recipes[i], ingredientCounter.getOrDefault(recipes[i], 0) + 1); + } + } + Queue queue = new LinkedList<>(); + Set prepared = new HashSet<>(); + for (String supply : supplies) { + queue.add(supply); + } + while (!queue.isEmpty()) { + String removed = queue.remove(); + for (String dependentRecipe : map.getOrDefault(removed, new ArrayList<>())) { + ingredientCounter.put(dependentRecipe, ingredientCounter.getOrDefault(dependentRecipe, 0) - 1); + if (ingredientCounter.get(dependentRecipe) == 0) { + queue.add(dependentRecipe); + prepared.add(dependentRecipe); + } + } + } + return new ArrayList<>(prepared); + } +} diff --git a/Medium/Find Bottom Left Tree Value.java b/Medium/Find Bottom Left Tree Value.java index 924cd09c..e4f55477 100644 --- a/Medium/Find Bottom Left Tree Value.java +++ b/Medium/Find Bottom Left Tree Value.java @@ -4,24 +4,31 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - int ans = 0; - int height = 0; - - public int findBottomLeftValue(TreeNode root) { - findBottomLeftValue(root, 1); - return ans; + public int findBottomLeftValue(TreeNode root) { + int[] ans = {0, 0}; + helper(root, 1, ans); + return ans[1]; + } + + private void helper(TreeNode root, int currLevel, int[] ans) { + if (root == null) { + return; } - - public void findBottomLeftValue(TreeNode root, int depth) { - if (height < depth) { - ans = root.val; - height = depth; - } - if (root.left!=null) findBottomLeftValue(root.left, depth+1); - if (root.right!=null) findBottomLeftValue(root.right, depth+1); + if (currLevel > ans[0]) { + ans[0] = currLevel; + ans[1] = root.val; } + helper(root.left, currLevel + 1, ans); + helper(root.right, currLevel + 1, ans); + } } diff --git a/Medium/Find Center of Star Graph.java b/Medium/Find Center of Star Graph.java new file mode 100644 index 00000000..8270ad2d --- /dev/null +++ b/Medium/Find Center of Star Graph.java @@ -0,0 +1,16 @@ +class Solution { + public int findCenter(int[][] edges) { + Map map = new HashMap<>(); + int n = edges.length; + for (int[] edge : edges) { + map.put(edge[0], map.getOrDefault(edge[0], 0) + 1); + map.put(edge[1], map.getOrDefault(edge[1], 0) + 1); + } + for (Integer key : map.keySet()) { + if (map.get(key) == n) { + return key; + } + } + return -1; + } +} diff --git a/Medium/Find Closest Node to Given Two Nodes.java b/Medium/Find Closest Node to Given Two Nodes.java new file mode 100644 index 00000000..4c68c333 --- /dev/null +++ b/Medium/Find Closest Node to Given Two Nodes.java @@ -0,0 +1,40 @@ +class Solution { + public int closestMeetingNode(int[] edges, int node1, int node2) { + int n = edges.length; + int[] distance1 = new int[n]; + int[] distance2 = new int[n]; + Arrays.fill(distance1, Integer.MAX_VALUE); + Arrays.fill(distance2, Integer.MAX_VALUE); + bfs(node1, edges, distance1); + bfs(node2, edges, distance2); + int minDistanceNode = -1; + int currMinDistance = Integer.MAX_VALUE; + for (int i = 0; i < n; i++) { + if (currMinDistance > Math.max(distance1[i], distance2[i])) { + minDistanceNode = i; + currMinDistance = Math.max(distance1[i], distance2[i]); + } + } + return minDistanceNode; + } + + private void bfs(int startNode, int[] edges, int[] distance) { + int n = edges.length; + Queue queue = new LinkedList<>(); + queue.add(startNode); + boolean[] visited = new boolean[n]; + distance[startNode] = 0; + while (!queue.isEmpty()) { + int node = queue.remove(); + if (visited[node]) { + continue; + } + visited[node] = true; + int neighbor = edges[node]; + if (neighbor != -1 && !visited[neighbor]) { + distance[neighbor] = 1 + distance[node]; + queue.add(neighbor); + } + } + } +} diff --git a/Medium/Find Consecutive Integers from a Data Stream.java b/Medium/Find Consecutive Integers from a Data Stream.java new file mode 100644 index 00000000..7f57b28d --- /dev/null +++ b/Medium/Find Consecutive Integers from a Data Stream.java @@ -0,0 +1,23 @@ +class DataStream { + + private int k; + private int value; + private int counter; + + public DataStream(int value, int k) { + this.k = k; + this.value = value; + this.counter = 0; + } + + public boolean consec(int num) { + counter = value == num ? (counter + 1) : 0; + return counter >= k; + } +} + +/** + * Your DataStream object will be instantiated and called as such: + * DataStream obj = new DataStream(value, k); + * boolean param_1 = obj.consec(num); + */ diff --git a/Medium/Find Distance in a Binary Tree.java b/Medium/Find Distance in a Binary Tree.java new file mode 100644 index 00000000..403e1190 --- /dev/null +++ b/Medium/Find Distance in a Binary Tree.java @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int findDistance(TreeNode root, int p, int q) { + if (p == q) { + return 0; + } + int[] result = {-1}; + dfs(root, p, q, result); + return result[0]; + } + + private int dfs(TreeNode root, int p, int q, int[] result) { + if (root == null) { + return -1; + } + int left = dfs(root.left, p, q, result); + int right = dfs(root.right, p, q, result); + if (root.val == p || root.val == q) { + if (left < 0 && right < 0) { + return 0; + } + result[0] = 1 + (left >= 0 ? left : right); + return -1; + } + if (left >= 0 && right >= 0) { + result[0] = left + right + 2; + return -1; + } + if (left >= 0) { + return left + 1; + } + if (right >= 0) { + return right + 1; + } + return -1; + } +} diff --git a/Medium/Find Duplicate File in System.java b/Medium/Find Duplicate File in System.java index 5ea4cd21..8aa53097 100644 --- a/Medium/Find Duplicate File in System.java +++ b/Medium/Find Duplicate File in System.java @@ -1,41 +1,20 @@ class Solution { - - public List> findDuplicate(String[] paths) { - - Map> map = new HashMap<>(); - List> ans = new ArrayList<>(); - - for (String s : paths) { - String[] temp = s.split("\\s"); - - for (int i=1;i tempList = map.get(message); - tempList.add(temp[0] + "/" + fileName); - map.put(message, tempList); - } - else { - ArrayList tempList = new ArrayList<>(); - tempList.add(temp[0] + "/" + fileName); - map.put(message, tempList); - } - - } - } - - for (Map.Entry> entry : map.entrySet()) { - - List l = entry.getValue(); - - if (l.size() > 1) { - ans.add(l); - } - - } - - return ans; + public List> findDuplicate(String[] paths) { + Map> contentToDirectoryMapping = new HashMap<>(); + for (String path : paths) { + String[] splits = path.split("\\s+"); + String directoryName = splits[0]; + for (int i = 1; i < splits.length; i++) { + int contentStartIdx = splits[i].indexOf('('); + String fileName = splits[i].substring(0, contentStartIdx); + String content = splits[i].substring(contentStartIdx + 1, splits[i].length() - 1); + contentToDirectoryMapping.computeIfAbsent(content, k -> new HashSet<>()) + .add(directoryName + "/" + fileName); + } } + return contentToDirectoryMapping.values().stream() + .filter(e -> e.size() > 1) + .map(ArrayList::new) + .collect(Collectors.toList()); + } } diff --git a/Medium/Find Duplicate Subtrees.java b/Medium/Find Duplicate Subtrees.java index b81a4bec..4800644b 100644 --- a/Medium/Find Duplicate Subtrees.java +++ b/Medium/Find Duplicate Subtrees.java @@ -4,35 +4,32 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - Map map; - public List findDuplicateSubtrees(TreeNode root) { - map = new HashMap<>(); - List ans = new ArrayList<>(); - - helper(root); - - for (TreeNode node : map.values()) { - if (node != null) { - ans.add(node); - } - } - - return ans; + List result = new LinkedList<>(); + traverse(root, new HashMap<>(), result); + return result; } - - private String helper(TreeNode root) { - if (root == null) { - return "#"; + + private String traverse(TreeNode node, Map frequencyMap, List result) { + if (node == null) { + return ""; + } + String key = ("(" + traverse(node.left, frequencyMap, result) + ")" + node.val + + "(" + traverse(node.right, frequencyMap, result) + ")"); + frequencyMap.put(key, frequencyMap.getOrDefault(key, 0) + 1); + if (frequencyMap.get(key) == 2) { + result.add(node); } - - String path = root.val + "|" + helper(root.left) + "|" + helper(root.right); - map.put(path, map.containsKey(path) ? root : null); - - return path; + return key; } } diff --git a/Medium/Find Elements in a Contaminated Binary Tree.java b/Medium/Find Elements in a Contaminated Binary Tree.java new file mode 100644 index 00000000..9048fbd2 --- /dev/null +++ b/Medium/Find Elements in a Contaminated Binary Tree.java @@ -0,0 +1,43 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class FindElements { + + private Set set; + + public FindElements(TreeNode root) { + set = new HashSet<>(); + recover(root, 0); + } + + private void recover(TreeNode root, int value) { + if (root == null) { + return; + } + set.add(value); + recover(root.left, 2 * value + 1); + recover(root.right, 2 * value + 2); + } + + public boolean find(int target) { + return set.contains(target); + } +} + +/** + * Your FindElements object will be instantiated and called as such: + * FindElements obj = new FindElements(root); + * boolean param_1 = obj.find(target); + */ diff --git a/Medium/Find Eventual Safe States.java b/Medium/Find Eventual Safe States.java new file mode 100644 index 00000000..2948587d --- /dev/null +++ b/Medium/Find Eventual Safe States.java @@ -0,0 +1,35 @@ +class Solution { + public List eventualSafeNodes(int[][] graph) { + int n = graph.length; + Map> map = new HashMap<>(); + int[] indegree = new int[n]; + for (int i = 0; i < n; i++) { + for (Integer conn : graph[i]) { + indegree[i]++; + map.computeIfAbsent(conn, k -> new HashSet<>()).add(i); + } + } + Queue queue = new LinkedList<>(); + for (int i = 0; i < n; i++) { + if (indegree[i] == 0) { + queue.add(i); + } + } + List result = new ArrayList<>(); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int removed = queue.remove(); + result.add(removed); + for (Integer conn : map.getOrDefault(removed, new HashSet<>())) { + indegree[conn]--; + if (indegree[conn] == 0) { + queue.add(conn); + } + } + } + } + Collections.sort(result); + return result; + } +} diff --git a/Medium/Find First and Last Position of Element in Sorted Array.java b/Medium/Find First and Last Position of Element in Sorted Array.java index 18909848..64e4ecec 100644 --- a/Medium/Find First and Last Position of Element in Sorted Array.java +++ b/Medium/Find First and Last Position of Element in Sorted Array.java @@ -1,58 +1,35 @@ class Solution { + + private static enum Position { + FIRST, LAST; + } + public int[] searchRange(int[] nums, int target) { - int idx = findBinary(nums, 0, nums.length-1, target); - int startIdx = idx; - int endIdx = idx; - - int start = 0; - int end = idx - 1; - - while (true) { - int temp = findBinary(nums, start, end, target); - if (temp != -1) { - startIdx = temp; - start = 0; - end = temp - 1; - } - else { - break; - } - } - - start = idx + 1; - end = nums.length - 1; - - while (true) { - int temp = findBinary(nums, start, end, target); - if (temp != -1) { - endIdx = temp; - start = temp + 1; - end = nums.length - 1; - } - else { - break; - } - } - - int[] ans = new int[]{startIdx, endIdx}; - - return ans; + return new int[]{ + search(nums, target, Position.FIRST), + search(nums, target, Position.LAST) + }; } - - private int findBinary(int[] nums, int start, int end, int target) { - while (start <= end) { - int mid = (start + end)/2; + + private static int search(int[] nums, int target, Position position) { + int left = 0; + int right = nums.length - 1; + int idx = -1; + while (left <= right) { + int mid = (left + right) / 2; if (nums[mid] == target) { - return mid; - } - else if (nums[mid] > target) { - end = mid-1; - } - else { - start = mid + 1; + idx = mid; + if (position == Position.FIRST) { + right = mid - 1; + } else { + left = mid + 1; + } + } else if (nums[mid] > target) { + right = mid - 1; + } else { + left = mid + 1; } } - - return -1; + return idx; } } diff --git a/Medium/Find K Closest Elements.java b/Medium/Find K Closest Elements.java index 5ffc56a8..eeddacba 100644 --- a/Medium/Find K Closest Elements.java +++ b/Medium/Find K Closest Elements.java @@ -1,29 +1,38 @@ class Solution { - public List findClosestElements(int[] arr, int k, int x) { - if (x <= arr[0]) { - return Arrays.stream(arr).boxed().collect(Collectors.toList()).subList(0, k); - } - else if (x >= arr[arr.length - 1]) { - return Arrays.stream(arr).boxed().collect(Collectors.toList()).subList(arr.length - k, arr.length); - } - else { - int idx = Arrays.binarySearch(arr, x); - if (idx < 0) { - idx = -idx - 1; - } - int low = Math.max(0, idx - k - 1); - int high = Math.min(arr.length - 1, idx + k - 1); - - while (high - low > k - 1) { - if (low < 0 || (x - arr[low]) <= (arr[high] - x)) { - high--; - } - else if ((high > arr.length - 1 || (x - arr[low]) > (arr[high] - x))) { - low++; - } - } - - return Arrays.stream(arr).boxed().collect(Collectors.toList()).subList(low, high + 1); - } + public List findClosestElements(int[] arr, int k, int x) { + List result = new ArrayList<>(); + if (arr.length == k) { + for (int num : arr) { + result.add(num); + } + return result; } + int left = 0; + int right = arr.length; + while (left < right) { + int mid = (left + right) / 2; + if (arr[mid] >= x) { + right = mid; + } else { + left = mid + 1; + } + } + left--; + right = left + 1; + while (right - left - 1 < k) { + if (left == -1) { + right++; + continue; + } + if (right == arr.length || Math.abs(arr[left] - x) <= Math.abs(arr[right] - x)) { + left--; + } else { + right++; + } + } + for (int i = left + 1; i < right; i++) { + result.add(arr[i]); + } + return result; + } } diff --git a/Medium/Find K Pairs with Smallest Sums.java b/Medium/Find K Pairs with Smallest Sums.java index 894ca10d..f29f5c15 100644 --- a/Medium/Find K Pairs with Smallest Sums.java +++ b/Medium/Find K Pairs with Smallest Sums.java @@ -1,54 +1,26 @@ -class Solution { - public List kSmallestPairs(int[] nums1, int[] nums2, int k) { - List ans = new ArrayList<>(); - - if (nums1.length == 0 || nums2.length == 0 || k == 0) { - return ans; - } - - PriorityQueue pq = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Element o1, Element o2) { - return (o1.x + o1.y) - (o2.x + o2.y); - } - }); - - for (int i=0; i> kSmallestPairs(int[] nums1, int[] nums2, int k) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[2] - b[2]); + List> result = new ArrayList<>(); + Set> visited = new HashSet<>(); + pq.add(new int[]{0, 0, nums1[0] + nums2[0]}); + visited.add(new Pair(0, 0)); while (k-- > 0 && !pq.isEmpty()) { - Element temp = pq.poll(); - ans.add(new int[]{temp.y, temp.x}); - - if (temp.idx >= nums1.length-1) { - continue; + int[] removed = pq.poll(); + int i = removed[0]; + int j = removed[1]; + result.add(List.of(nums1[i], nums2[j])); + Pair nums1Pair = new Pair(i + 1, j); + Pair nums2Pair = new Pair(i, j + 1); + if (i + 1 < nums1.length && !visited.contains(nums1Pair)) { + pq.add(new int[]{i + 1, j, nums1[i + 1] + nums2[j]}); + visited.add(nums1Pair); + } + if (j + 1 < nums2.length && !visited.contains(nums2Pair)) { + pq.add(new int[]{i, j + 1, nums1[i] + nums2[j + 1]}); + visited.add(nums2Pair); } - - pq.offer(new Element(temp.idx+1, temp.x, nums1[temp.idx+1])); - } - - return ans; - } - - class Element { - int idx; - int x; - int y; - - public Element(int val, int x, int y) { - this.idx = val; - this.x = x; - this.y = y; - } - - @Override - public String toString() { - return "Element{" + - "idx=" + idx + - ", x=" + x + - ", y=" + y + - '}'; } + return result; } } diff --git a/Medium/Find K-Length Substrings With No Repeated Characters.java b/Medium/Find K-Length Substrings With No Repeated Characters.java index 5c435fbf..fee2952d 100644 --- a/Medium/Find K-Length Substrings With No Repeated Characters.java +++ b/Medium/Find K-Length Substrings With No Repeated Characters.java @@ -1,26 +1,24 @@ class Solution { - public int numKLenSubstrNoRepeats(String S, int K) { - int count = 0; - int start = 0; - Map map = new HashMap<>(); - for (int i = 0; i < K - 1 && i < S.length(); i++) { - map.put(S.charAt(i), map.getOrDefault(S.charAt(i), 0) + 1); - } - - for (int i = K - 1; i < S.length(); i++) { - map.put(S.charAt(i), map.getOrDefault(S.charAt(i), 0) + 1); - if (map.size() == K) { - count++; - } - - map.put(S.charAt(start), map.get(S.charAt(start)) - 1); - if (map.get(S.charAt(start)) == 0) { - map.remove(S.charAt(start)); - } - - start++; - } - - return count; + public int numKLenSubstrNoRepeats(String s, int k) { + if (s.length() < k) { + return 0; } + Map map = new HashMap<>(); + for (int i = 0; i < k; i++) { + map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); + } + int resultCount = 0; + for (int i = k; i < s.length(); i++) { + if (map.size() == k) { + resultCount++; + } + int startIdx = i - k; + map.put(s.charAt(startIdx), map.getOrDefault(s.charAt(startIdx), 0) - 1); + if (map.get(s.charAt(startIdx)) == 0) { + map.remove(s.charAt(startIdx)); + } + map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); + } + return resultCount + (map.size() == k ? 1 : 0); + } } diff --git a/Medium/Find Kth Bit in Nth Binary String.java b/Medium/Find Kth Bit in Nth Binary String.java new file mode 100644 index 00000000..e98b29c7 --- /dev/null +++ b/Medium/Find Kth Bit in Nth Binary String.java @@ -0,0 +1,22 @@ +class Solution { + public char findKthBit(int n, int k) { + return nthString(n).charAt(k - 1); + } + + private String nthString(int n) { + if (n == 1) { + return "0"; + } + String prevString = nthString(n - 1); + return prevString + "1" + reverseAndInvert(prevString); + } + + private String reverseAndInvert(String s) { + char[] chars = s.toCharArray(); + for (int i = 0; i < s.length(); i++) { + chars[i] = chars[i] == '1' ? '0' : '1'; + } + StringBuilder sb = new StringBuilder(String.valueOf(chars)); + return sb.reverse().toString(); + } +} diff --git a/Medium/Find Largest Value in Each Tree Row.java b/Medium/Find Largest Value in Each Tree Row.java new file mode 100644 index 00000000..2f0c7883 --- /dev/null +++ b/Medium/Find Largest Value in Each Tree Row.java @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public List largestValues(TreeNode root) { + if (root == null) { + return new ArrayList<>(); + } + List result = new ArrayList<>(); + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + int maxValue = queue.peek().val; + while (size-- > 0) { + TreeNode removed = queue.remove(); + maxValue = Math.max(maxValue, removed.val); + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + result.add(maxValue); + } + return result; + } +} diff --git a/Medium/Find Largest Value in Tree Row.java b/Medium/Find Largest Value in Tree Row.java deleted file mode 100644 index 6c0d432a..00000000 --- a/Medium/Find Largest Value in Tree Row.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - - public List largestValues(TreeNode root) { - - List ans = new ArrayList<>(); - - if (root == null) return ans; - - ArrayList arr = new ArrayList<>(); - arr.add(root); - - while (arr.size() != 0) { - ArrayList roots = new ArrayList<>(); - ArrayList a = new ArrayList<>(); - - int i = 0; - - while (i < arr.size()) { - TreeNode p = arr.get(i); - if (p.left != null) { - roots.add(p.left); - } - if (p.right != null) { - roots.add(p.right); - } - - a.add(p.val); - - i++; - } - - Collections.sort(a); - - ans.add(a.get(a.size()-1)); - arr.clear(); - - i = 0; - while(i < roots.size()) { - arr.add(roots.get(i)); - i++; - } - } - - return ans; - } -} diff --git a/Medium/Find Leaves of Binary Tree.java b/Medium/Find Leaves of Binary Tree.java index af95d71a..c6449ce2 100644 --- a/Medium/Find Leaves of Binary Tree.java +++ b/Medium/Find Leaves of Binary Tree.java @@ -4,58 +4,54 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public List> findLeaves(TreeNode root) { - List> list = new ArrayList<>(); - - while (root != null) { - List leaves = getLeaves(root); - root = removeLeaves(root); - list.add(leaves); + public List> findLeaves(TreeNode root) { + Map parentMap = new HashMap<>(); + Queue leaves = new LinkedList<>(); + updateParentAndFindLeaves(root, null, parentMap, leaves); + List> result = new ArrayList<>(); + while (!leaves.isEmpty()) { + int size = leaves.size(); + List temp = new ArrayList<>(); + while (size-- > 0) { + TreeNode removed = leaves.remove(); + temp.add(removed.val); + if (parentMap.get(removed) == null) { + continue; } - - return list; - } - - private TreeNode removeLeaves(TreeNode root) { - if (root == null) { - return null; + if (parentMap.get(removed).left == removed) { + parentMap.get(removed).left = null; + } else { + parentMap.get(removed).right = null; } - - if (root.left == null && root.right == null) { - return null; + if (parentMap.get(removed).left == null && parentMap.get(removed).right == null) { + leaves.add(parentMap.get(removed)); } - - root.left = removeLeaves(root.left); - root.right = removeLeaves(root.right); - - return root; + } + result.add(temp); } - - private List getLeaves(TreeNode root) { - Queue queue = new LinkedList<>(); - queue.add(root); - List list = new ArrayList<>(); - - while (!queue.isEmpty()) { - TreeNode node = queue.remove(); - if (node.left == null && node.right == null) { - list.add(node.val); - } - else { - if (node.left != null) { - queue.add(node.left); - } - - if (node.right != null) { - queue.add(node.right); - } - } - } - - return list; - } + return result; + } + + private void updateParentAndFindLeaves(TreeNode node, TreeNode parent, Map parentMap, Queue leaves) { + if (node == null) { + return; + } + parentMap.put(node, parent); + if (node.left == null && node.right == null) { + leaves.add(node); + return; + } + updateParentAndFindLeaves(node.left, node, parentMap, leaves); + updateParentAndFindLeaves(node.right, node, parentMap, leaves); + } } diff --git a/Medium/Find Minimum Time to Reach Last Room I.java b/Medium/Find Minimum Time to Reach Last Room I.java new file mode 100644 index 00000000..0247baa4 --- /dev/null +++ b/Medium/Find Minimum Time to Reach Last Room I.java @@ -0,0 +1,36 @@ +class Solution { + + private static final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int minTimeToReach(int[][] moveTime) { + int n = moveTime.length; + int m = moveTime[0].length; + boolean[][] visited = new boolean[n][m]; + Integer[][] minTime = new Integer[n][m]; + minTime[0][0] = 0; + PriorityQueue pq = new PriorityQueue<>((a, b) -> a[2] - b[2]); + pq.add(new int[]{0, 0, 0}); + while (!pq.isEmpty()) { + int[] removed = pq.remove(); + int x = removed[0]; + int y = removed[1]; + if (visited[x][y]) { + continue; + } + visited[x][y] = true; + for (int[] dir : DIRS) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newY >= 0 && newX < n && newY < m) { + int distance = Math.max(minTime[x][y], moveTime[newX][newY]) + 1; + int currMinTime = minTime[newX][newY] == null ? Integer.MAX_VALUE : minTime[newX][newY]; + if (currMinTime > distance) { + minTime[newX][newY] = distance; + pq.add(new int[]{newX, newY, distance}); + } + } + } + } + return minTime[n - 1][m - 1]; + } +} diff --git a/Medium/Find Minimum in Rotated Sorted Array.java b/Medium/Find Minimum in Rotated Sorted Array.java index ef50804a..79ae6e51 100644 --- a/Medium/Find Minimum in Rotated Sorted Array.java +++ b/Medium/Find Minimum in Rotated Sorted Array.java @@ -1,21 +1,17 @@ class Solution { public int findMin(int[] nums) { int start = 0; - int end = nums.length-1; + int end = nums.length - 1; + int minValue = 5001; while (start <= end) { - int mid = (start + end)/2; - - if (((mid > 0 ? nums[mid] < nums[mid-1] : true) && (mid < nums.length-1 ? nums[mid] < nums[mid+1] : true))) { - return nums[mid]; - } - else if (nums[mid] < nums[end]) { - end = mid-1; - } - else { - start = mid+1; + int mid = (start + end) / 2; + minValue = Math.min(minValue, nums[mid]); + if (nums[end] > nums[mid]) { + end = mid - 1; + } else { + start = mid + 1; } } - - return -1; + return minValue; } } diff --git a/Medium/Find Missing Observations.java b/Medium/Find Missing Observations.java new file mode 100644 index 00000000..fe724572 --- /dev/null +++ b/Medium/Find Missing Observations.java @@ -0,0 +1,21 @@ +class Solution { + public int[] missingRolls(int[] rolls, int mean, int n) { + int m = rolls.length; + int sum = 0; + for (int roll : rolls) { + sum += roll; + } + int expectedSum = mean * (n + m); + int remaining = expectedSum - sum; + if (remaining > 6 * n || remaining < n) { + return new int[]{}; + } + int[] result = new int[n]; + Arrays.fill(result, remaining / n); + remaining = remaining % n; + for (int i = 0; i < remaining; i++) { + result[i]++; + } + return result; + } +} diff --git a/Medium/Find Nearest Right Node in Binary Tree.java b/Medium/Find Nearest Right Node in Binary Tree.java new file mode 100644 index 00000000..5fd92c97 --- /dev/null +++ b/Medium/Find Nearest Right Node in Binary Tree.java @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode findNearestRightNode(TreeNode root, TreeNode u) { + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size > 0) { + TreeNode removed = queue.remove(); + if (removed.equals(u)) { + return size == 1 ? null : queue.peek(); + } + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + size--; + } + } + return null; + } +} diff --git a/Medium/Find Original Array From Doubled Array.java b/Medium/Find Original Array From Doubled Array.java new file mode 100644 index 00000000..55554c81 --- /dev/null +++ b/Medium/Find Original Array From Doubled Array.java @@ -0,0 +1,27 @@ +class Solution { + public int[] findOriginalArray(int[] changed) { + if (changed.length % 2 != 0) { + return new int[]{}; + } + Arrays.sort(changed); + Map map = new HashMap<>(); + for (int num : changed) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int[] result = new int[changed.length / 2]; + int resultIdx = 0; + for (int num : changed) { + if (map.get(num) > 0) { + map.put(num, map.get(num) - 1); + int doubleValue = num * 2; + if (map.getOrDefault(doubleValue, 0) > 0) { + map.put(doubleValue, map.get(doubleValue) - 1); + result[resultIdx++] = num; + } else { + return new int[]{}; + } + } + } + return result; + } +} diff --git a/Medium/Find Peak Element.java b/Medium/Find Peak Element.java index 103b184e..5cc6feaa 100644 --- a/Medium/Find Peak Element.java +++ b/Medium/Find Peak Element.java @@ -1,39 +1,18 @@ class Solution { - public static int findPeakElement(int[] nums) { - if (nums.length == 1) { - return 0; - } - - return findPeakElementImpl(nums, 0, nums.length-1); + public int findPeakElement(int[] nums) { + return helper(nums, 0, nums.length - 1); + } + + private int helper(int[] nums, int startIdx, int endIdx) { + if (startIdx == endIdx) { + return startIdx; } - - private static int findPeakElementImpl(int[] nums, int start, int end) { - if (start > end) { - return -1; - } - - int mid = (start + end)/2; - - if (mid == 0 && nums.length > 1) { - if (nums[mid] > nums[mid+1]) { - return mid; - } - } - else if (mid == nums.length-1 && nums.length > 1) { - if (nums[mid] > nums[mid-1]) { - return mid; - } - } - else { - if (nums.length > 1) { - if (nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1]) { - return mid; - } - } - } - - int left = findPeakElementImpl(nums, start, mid-1); - - return left == -1 ? findPeakElementImpl(nums, mid+1, end) : left; + int midIdx = (startIdx + endIdx) / 2; + int nextToMid = midIdx + 1; + if (nums[midIdx] > nums[nextToMid]) { + return helper(nums, startIdx, midIdx); + } else { + return helper(nums, nextToMid, endIdx); } + } } diff --git a/Medium/Find Permutation.java b/Medium/Find Permutation.java new file mode 100644 index 00000000..0a081e7c --- /dev/null +++ b/Medium/Find Permutation.java @@ -0,0 +1,27 @@ +class Solution { + public int[] findPermutation(String s) { + int n = s.length(); + int[] result = new int[n + 1]; + for (int i = 0; i < result.length; i++) { + result[i] = i + 1; + } + int idx = 1; + while (idx <= n) { + int k = idx; + while (idx <= n && s.charAt(idx - 1) == 'D') { + idx++; + } + reverse(result, k - 1, idx); + idx++; + } + return result; + } + + private void reverse(int[] result, int start, int end) { + for (int i = 0; i < (end - start) / 2; i++) { + int temp = result[i + start]; + result[i + start] = result[end - i - 1]; + result[end - i - 1] = temp; + } + } +} diff --git a/Medium/Find Players With Zero or One Losses.java b/Medium/Find Players With Zero or One Losses.java new file mode 100644 index 00000000..1692f1e5 --- /dev/null +++ b/Medium/Find Players With Zero or One Losses.java @@ -0,0 +1,22 @@ +class Solution { + public List> findWinners(int[][] matches) { + Map playerToLossCount = new HashMap<>(); + for (int[] match : matches) { + int winner = match[0]; + int loser = match[1]; + playerToLossCount.putIfAbsent(winner, 0); + playerToLossCount.put(loser, playerToLossCount.getOrDefault(loser, 0) + 1); + } + List> result = new ArrayList<>( + Arrays.asList(new ArrayList<>(), new ArrayList<>()) + ); + for (Map.Entry entry : playerToLossCount.entrySet()) { + if (entry.getValue() <= 1) { + result.get(entry.getValue()).add(entry.getKey()); + } + } + Collections.sort(result.get(0)); + Collections.sort(result.get(1)); + return result; + } +} diff --git a/Medium/Find Polygon With the Largest Perimeter.java b/Medium/Find Polygon With the Largest Perimeter.java new file mode 100644 index 00000000..8b368cb2 --- /dev/null +++ b/Medium/Find Polygon With the Largest Perimeter.java @@ -0,0 +1,15 @@ +class Solution { + public long largestPerimeter(int[] nums) { + Arrays.sort(nums); + int n = nums.length; + long prefixSum = 0; + long result = -1; + for (int i = 0; i < n; i++) { + if (i >= 2 && nums[i] < prefixSum) { + result = nums[i] + prefixSum; + } + prefixSum += nums[i]; + } + return result; + } +} diff --git a/Medium/Find Right Interval.java b/Medium/Find Right Interval.java index 89769585..2932d5e8 100644 --- a/Medium/Find Right Interval.java +++ b/Medium/Find Right Interval.java @@ -1,42 +1,19 @@ -/** - * Definition for an interval. - * public class Interval { - * int start; - * int end; - * Interval() { start = 0; end = 0; } - * Interval(int s, int e) { start = s; end = e; } - * } - */ class Solution { - public int[] findRightInterval(Interval[] intervals) { - int n = intervals.length; - if (n == 1) { - return new int[]{-1}; - } - - int[] start = new int[n]; - Map map = new HashMap<>(); - for (int i=0; i 0) { - ans[i] = map.get(end); - } - else if (-x > n) { - ans[i] = -1; - } - else { - ans[i] = map.get(start[-x-1]); - } - } - - return ans; + public int[] findRightInterval(int[][] intervals) { + TreeMap> map = new TreeMap<>(); + for (int i = 0; i < intervals.length; i++) { + map.computeIfAbsent(intervals[i][0], k -> new PriorityQueue<>( + Comparator.comparingInt(o -> intervals[o][0])) + ).add(i); } + int[] ans = new int[intervals.length]; + Arrays.fill(ans, -1); + for (int i = 0; i < intervals.length; i++) { + Integer upper = map.ceilingKey(intervals[i][1]); + if (upper != null) { + ans[i] = map.get(upper).peek(); + } + } + return ans; + } } diff --git a/Medium/Find Root of N-Ary Tree.java b/Medium/Find Root of N-Ary Tree.java new file mode 100644 index 00000000..be5c9166 --- /dev/null +++ b/Medium/Find Root of N-Ary Tree.java @@ -0,0 +1,39 @@ +/* +// Definition for a Node. +class Node { + public int val; + public List children; + + + public Node() { + children = new ArrayList(); + } + + public Node(int _val) { + val = _val; + children = new ArrayList(); + } + + public Node(int _val,ArrayList _children) { + val = _val; + children = _children; + } +}; +*/ + +class Solution { + public Node findRoot(List tree) { + Set set = new HashSet<>(); + for (Node node : tree) { + for (Node child : node.children) { + set.add(child); + } + } + for (Node node : tree) { + if (!set.contains(node)) { + return node; + } + } + return null; + } +} diff --git a/Medium/Find Smallest Common Element in All Rows.java b/Medium/Find Smallest Common Element in All Rows.java new file mode 100644 index 00000000..120a3900 --- /dev/null +++ b/Medium/Find Smallest Common Element in All Rows.java @@ -0,0 +1,16 @@ +class Solution { + public int smallestCommonElement(int[][] mat) { + Map map = new HashMap<>(); + int numRows = mat.length; + int numCols = mat[0].length; + for (int i = 0; i < numCols; i++) { + for (int j = 0; j < numRows; j++) { + map.put(mat[j][i], map.getOrDefault(mat[j][i], 0) + 1); + if (map.get(mat[j][i]) == numRows) { + return mat[j][i]; + } + } + } + return -1; + } +} diff --git a/Medium/Find The First Player to win K Games in a Row.java b/Medium/Find The First Player to win K Games in a Row.java new file mode 100644 index 00000000..fe26c684 --- /dev/null +++ b/Medium/Find The First Player to win K Games in a Row.java @@ -0,0 +1,24 @@ +class Solution { + public int findWinningPlayer(int[] skills, int k) { + Map indexMap = new HashMap<>(); + for (int i = 0; i < skills.length; i++) { + indexMap.put(skills[i], i); + } + Map winCountMap = new HashMap<>(); + Deque deque = new ArrayDeque<>(); + for (int num : skills) { + deque.addFirst(num); + } + while (deque.size() > 1) { + int first = deque.pollLast(); + int second = deque.pollLast(); + int winner = Math.max(first, second); + winCountMap.put(winner, winCountMap.getOrDefault(winner, 0) + 1); + deque.addLast(winner); + if (winCountMap.get(winner) == k) { + return indexMap.get(winner); + } + } + return indexMap.get(deque.poll()); + } +} diff --git a/Medium/Find The Original Array of Prefix Xor.java b/Medium/Find The Original Array of Prefix Xor.java new file mode 100644 index 00000000..46732ae1 --- /dev/null +++ b/Medium/Find The Original Array of Prefix Xor.java @@ -0,0 +1,11 @@ +class Solution { + public int[] findArray(int[] pref) { + int n = pref.length; + int[] result = new int[n]; + result[0] = pref[0]; + for (int i = 1; i < n; i++) { + result[i] = pref[i - 1] ^ pref[i]; + } + return result; + } +} diff --git a/Medium/Find Triangular Sum of an Array.java b/Medium/Find Triangular Sum of an Array.java new file mode 100644 index 00000000..0da1ef52 --- /dev/null +++ b/Medium/Find Triangular Sum of an Array.java @@ -0,0 +1,12 @@ +class Solution { + public int triangularSum(int[] nums) { + int n = nums.length; + while (n > 1) { + for (int i = 0; i + 1 < n; i++) { + nums[i] = (nums[i] + nums[i + 1]) % 10; + } + n--; + } + return nums[0]; + } +} diff --git a/Medium/Find Unique Binary String.java b/Medium/Find Unique Binary String.java new file mode 100644 index 00000000..80cdfa9e --- /dev/null +++ b/Medium/Find Unique Binary String.java @@ -0,0 +1,25 @@ +class Solution { + + private static final char[] BINARY_CHARS = {'1', '0'}; + + public String findDifferentBinaryString(String[] nums) { + int n = nums.length; + Set binaryStrings = new HashSet<>(); + backtrack(new StringBuilder(), n, binaryStrings); + Set binaryStringsPresent = Arrays.stream(nums).collect(Collectors.toSet()); + binaryStrings.removeAll(binaryStringsPresent); + return binaryStrings.isEmpty() ? "" : binaryStrings.iterator().next(); + } + + private void backtrack(StringBuilder sb, int n, Set binaryStrings) { + if (sb.length() == n) { + binaryStrings.add(sb.toString()); + return; + } + for (char c : BINARY_CHARS) { + sb.append(c); + backtrack(sb, n, binaryStrings); + sb.deleteCharAt(sb.length() - 1); + } + } +} diff --git a/Medium/Find a Corresponding Node of a Binary Tree in a Clone of That Tree.java b/Medium/Find a Corresponding Node of a Binary Tree in a Clone of That Tree.java new file mode 100644 index 00000000..0373fe3f --- /dev/null +++ b/Medium/Find a Corresponding Node of a Binary Tree in a Clone of That Tree.java @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +class Solution { + public final TreeNode getTargetCopy(final TreeNode original, final TreeNode cloned, final TreeNode target) { + Deque stackOriginal = new ArrayDeque<>(); + Deque stackCloned = new ArrayDeque<>(); + TreeNode nodeOriginal = original; + TreeNode nodeCloned = cloned; + while (!stackOriginal.isEmpty() || nodeOriginal != null) { + while (nodeOriginal != null) { + stackOriginal.add(nodeOriginal); + stackCloned.add(nodeCloned); + nodeOriginal = nodeOriginal.left; + nodeCloned = nodeCloned.left; + } + nodeOriginal = stackOriginal.removeLast(); + nodeCloned = stackCloned.removeLast(); + if (nodeOriginal == target) { + return nodeCloned; + } + nodeOriginal = nodeOriginal.right; + nodeCloned = nodeCloned.right; + } + return null; + } +} diff --git a/Medium/Find all Duplicates in an Array.java b/Medium/Find all Duplicates in an Array.java index b1708766..d4219751 100644 --- a/Medium/Find all Duplicates in an Array.java +++ b/Medium/Find all Duplicates in an Array.java @@ -1,14 +1,12 @@ -public class Solution { - - public List findDuplicates(int[] nums) { - List res = new ArrayList<>(); - for (int i = 0; i < nums.length; ++i) { - int index = Math.abs(nums[i])-1; - if (nums[index] < 0) - res.add(Math.abs(index+1)); - nums[index] = -nums[index]; - } - return res; +class Solution { + public List findDuplicates(int[] nums) { + List list = new ArrayList<>(); + for (int i = 0; i < nums.length; i++) { + if (nums[Math.abs(nums[i]) - 1] < 0) { + list.add(Math.abs(nums[i])); + } + nums[Math.abs(nums[i]) - 1] *= -1; } + return list; + } } - diff --git a/Medium/Find and Replace Pattern.java b/Medium/Find and Replace Pattern.java index 839486ba..c3cd1593 100644 --- a/Medium/Find and Replace Pattern.java +++ b/Medium/Find and Replace Pattern.java @@ -1,34 +1,20 @@ class Solution { - public static List findAndReplacePattern(String[] words, String pattern) { - String givenPattern = getStringPattern(pattern); - List ans = new ArrayList<>(); - - for (String word : words) { - if (getStringPattern(word).equals(givenPattern)) { - ans.add(word); - } - } - - return ans; - } - - private static String getStringPattern(String pattern) { - StringBuilder sb = new StringBuilder(); - char[] chars = pattern.toCharArray(); - int val = 0; - Map map = new HashMap<>(); - - for (char c : chars) { - if (!map.containsKey(c)) { - map.put(c, val); - val++; - } - } - - for (int i=0; i findAndReplacePattern(String[] words, String pattern) { + String patternString = getPattern(pattern); + return Arrays.stream(words).filter(e -> getPattern(e).equals(patternString)) + .collect(Collectors.toList()); + } + + private String getPattern(String s) { + StringBuilder sb = new StringBuilder(); + Map map = new HashMap<>(); + int count = 1; + for (char c : s.toCharArray()) { + if (!map.containsKey(c)) { + map.put(c, count++); + } + sb.append(map.get(c)); } + return sb.toString(); + } } diff --git a/Medium/Find and Replace in String.java b/Medium/Find and Replace in String.java index 2706b81e..9c5c6810 100644 --- a/Medium/Find and Replace in String.java +++ b/Medium/Find and Replace in String.java @@ -1,24 +1,34 @@ class Solution { - public String findReplaceString(String S, int[] indexes, String[] sources, String[] targets) { - Map sourceMap = new HashMap<>(); - Map targetMap = new HashMap<>(); - - for (int i=0; i map = new HashMap<>(); + for (int i = 0; i < indexes.length; i++) { + map.put(indexes[i], new String[]{sources[i], targets[i]}); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < S.length(); i++) { + if (map.containsKey(i)) { + String source = map.get(i)[0]; + String target = map.get(i)[1]; + int currIdx = 0; + boolean mismatch = false; + while (currIdx + i < S.length() && currIdx < source.length()) { + if (source.charAt(currIdx) != S.charAt(currIdx + i)) { + mismatch = true; + break; + } + currIdx++; } - - StringBuilder sb = new StringBuilder(); - for (int i=0; i stack = new Stack<>(); - for (int i=0; i 1) { - int person1 = stack.pop(); - int person2 = stack.pop(); - - if (knows(person1, person2)) { - stack.push(person2); - } - else { - stack.push(person1); - } - } - - int person = stack.pop(); - for (int i=0; i> graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()) + .add(new int[]{edge[1], edge[2]}); + graph.computeIfAbsent(edge[1], k -> new ArrayList<>()) + .add(new int[]{edge[0], edge[2]}); + } + int minNeighborCount = n + 1; + int nodeWithMinNeighbor = -1; + for (int i = 0; i < n; i++) { + int numOfNeighbors = findNumberOfNeighborsWithinThresholdDistance(i, distanceThreshold, graph); + minNeighborCount = Math.min(numOfNeighbors, minNeighborCount); + nodeWithMinNeighbor = minNeighborCount == numOfNeighbors ? i : nodeWithMinNeighbor; + } + return nodeWithMinNeighbor; + } + + private int findNumberOfNeighborsWithinThresholdDistance(int node, int distanceThreshold, Map> graph) { + Queue queue = new PriorityQueue<>((a, b) -> (b[1] - a[1])); + Set visited = new HashSet<>(); + queue.add(new int[]{node, distanceThreshold}); + int numOfNeighbors = 0; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int currNode = removed[0]; + int currDistanceThreshold = removed[1]; + if (visited.contains(currNode)) { + continue; + } + visited.add(currNode); + numOfNeighbors++; + for (int[] neighbor : graph.getOrDefault(currNode, new ArrayList<>())) { + int neighborNode = neighbor[0]; + int neighborDistance = neighbor[1]; + if (!visited.contains(neighborNode) && + currDistanceThreshold >= neighborDistance) { + queue.add(new int[]{neighborNode, currDistanceThreshold - neighborDistance}); + } + } + } + return numOfNeighbors; + } +} diff --git a/Medium/Find the Duplicate Number.java b/Medium/Find the Duplicate Number.java new file mode 100644 index 00000000..bfd8908b --- /dev/null +++ b/Medium/Find the Duplicate Number.java @@ -0,0 +1,20 @@ +class Solution { + public int findDuplicate(int[] nums) { + int slow = nums[0]; + int fast = nums[0]; + while (true) { + slow = nums[slow]; + fast = nums[nums[fast]]; + if (slow == fast) { + break; + } + } + int idxOne = nums[0]; + int idxTwo = slow; + while (idxOne != idxTwo) { + idxOne = nums[idxOne]; + idxTwo = nums[idxTwo]; + } + return idxOne; + } +} diff --git a/Medium/Find the Index of the First Occurrence in a String.java b/Medium/Find the Index of the First Occurrence in a String.java new file mode 100644 index 00000000..4156d0ba --- /dev/null +++ b/Medium/Find the Index of the First Occurrence in a String.java @@ -0,0 +1,10 @@ +class Solution { + public int strStr(String haystack, String needle) { + for (int i = 0; i <= haystack.length() - needle.length(); i++) { + if (haystack.substring(i, i + needle.length()).equals(needle)) { + return i; + } + } + return -1; + } +} diff --git a/Medium/Find the Index of the Large Integer.java b/Medium/Find the Index of the Large Integer.java new file mode 100644 index 00000000..0b77a684 --- /dev/null +++ b/Medium/Find the Index of the Large Integer.java @@ -0,0 +1,38 @@ +/** + * // This is ArrayReader's API interface. + * // You should not implement it, or speculate about its implementation + * interface ArrayReader { + * // Compares the sum of arr[l..r] with the sum of arr[x..y] + * // return 1 if sum(arr[l..r]) > sum(arr[x..y]) + * // return 0 if sum(arr[l..r]) == sum(arr[x..y]) + * // return -1 if sum(arr[l..r]) < sum(arr[x..y]) + * public int compareSub(int l, int r, int x, int y) {} + * + * // Returns the length of the array + * public int length() {} + * } + */ + +class Solution { + public int getIndex(ArrayReader reader) { + int left = 0; + int right = reader.length() - 1; + while (left < right) { + int l = left; + int r = (right + left - 1) / 2; + int x = (right + left + 2) / 2; + int y = right; + int res = reader.compareSub(l, r, x, y); + if (res == 0) { + return (left + right) / 2; + } + else if (res == 1) { + right = r; + } + else { + left = x; + } + } + return left; + } +} diff --git a/Medium/Find the Kth Largest Integer in the Array.java b/Medium/Find the Kth Largest Integer in the Array.java new file mode 100644 index 00000000..cc335042 --- /dev/null +++ b/Medium/Find the Kth Largest Integer in the Array.java @@ -0,0 +1,7 @@ +class Solution { + public String kthLargestNumber(String[] nums, int k) { + Arrays.sort(nums, (o1, o2) -> + o1.length() == o2.length() ? o1.compareTo(o2) : o1.length() - o2.length()); + return nums[nums.length - k]; + } +} diff --git a/Medium/Find the Length of the Longest Common Prefix.java b/Medium/Find the Length of the Longest Common Prefix.java new file mode 100644 index 00000000..a626cd3a --- /dev/null +++ b/Medium/Find the Length of the Longest Common Prefix.java @@ -0,0 +1,52 @@ +class Solution { + public int longestCommonPrefix(int[] arr1, int[] arr2) { + TrieNodeManager nodeManager = new TrieNodeManager(); + for (int num : arr1) { + nodeManager.index(String.valueOf(num)); + } + int maxLength = 0; + for (int num : arr2) { + int length = nodeManager.find(String.valueOf(num)); + maxLength = Math.max(maxLength, length); + } + return maxLength; + } + + private static class TrieNodeManager { + + private Node root; + + public TrieNodeManager() { + this.root = new Node(); + } + + public void index(String s) { + Node curr = root; + for (char c : s.toCharArray()) { + if (!curr.children.containsKey(c)) { + curr.children.put(c, new Node()); + } + curr = curr.children.get(c); + } + } + + public int find(String s) { + Node curr = root; + for (int i = 0; i < s.length(); i++) { + if (!curr.children.containsKey(s.charAt(i))) { + return i; + } + curr = curr.children.get(s.charAt(i)); + } + return s.length(); + } + + class Node { + Map children; + + public Node() { + this.children = new HashMap<>(); + } + } + } +} diff --git a/Medium/Find the Lexicographically Largest String From the Box I.java b/Medium/Find the Lexicographically Largest String From the Box I.java new file mode 100644 index 00000000..1133cb93 --- /dev/null +++ b/Medium/Find the Lexicographically Largest String From the Box I.java @@ -0,0 +1,16 @@ +class Solution { + public String answerString(String word, int numFriends) { + if (numFriends == 1) { + return word; + } + int n = word.length(); + String result = ""; + for (int i = 0; i < n; i++) { + String curr = word.substring(i, Math.min(i + n - numFriends + 1, n)); + if (result.compareTo(curr) <= 0) { + result = curr; + } + } + return result; + } +} diff --git a/Medium/Find the Longest Semi-Repetitive Substring.java b/Medium/Find the Longest Semi-Repetitive Substring.java new file mode 100644 index 00000000..f6743a56 --- /dev/null +++ b/Medium/Find the Longest Semi-Repetitive Substring.java @@ -0,0 +1,22 @@ +class Solution { + public int longestSemiRepetitiveSubstring(String s) { + int start = 0; + int end = 0; + int maxLength = 1; + int consecutiveCount = 0; + while (end < s.length() - 1) { + if (s.charAt(end) == s.charAt(end + 1)) { + consecutiveCount++; + } + end++; + while (start < end && consecutiveCount > 1) { + if (s.charAt(start) == s.charAt(start + 1)) { + consecutiveCount--; + } + start++; + } + maxLength = Math.max(maxLength, end - start + 1); + } + return maxLength; + } +} diff --git a/Medium/Find the Longest Substring Containing Vowels in Even Counts.java b/Medium/Find the Longest Substring Containing Vowels in Even Counts.java new file mode 100644 index 00000000..66e33ef9 --- /dev/null +++ b/Medium/Find the Longest Substring Containing Vowels in Even Counts.java @@ -0,0 +1,22 @@ +class Solution { + public int findTheLongestSubstring(String s) { + int prefixXor = 0; + char[] frequency = new char[26]; + frequency['a' - 'a'] = 1; + frequency['e' - 'a'] = 2; + frequency['i' - 'a'] = 4; + frequency['o' - 'a'] = 8; + frequency['u' - 'a'] = 16; + int[] indexMap = new int[32]; + Arrays.fill(indexMap, -1); + int result = 0; + for (int i = 0; i < s.length(); i++) { + prefixXor ^= frequency[s.charAt(i) - 'a']; + if (indexMap[prefixXor] == -1 && prefixXor != 0) { + indexMap[prefixXor] = i; + } + result = Math.max(result, i - indexMap[prefixXor]); + } + return result; + } +} diff --git a/Medium/Find the Maximum Divisibility Score.java b/Medium/Find the Maximum Divisibility Score.java new file mode 100644 index 00000000..2e33ee9a --- /dev/null +++ b/Medium/Find the Maximum Divisibility Score.java @@ -0,0 +1,19 @@ +class Solution { + public int maxDivScore(int[] nums, int[] divisors) { + int maxScore = -1; + int maxScoreCandidate = -1; + for (int divisor : divisors) { + int currScore = 0; + for (int num : nums) { + currScore += num % divisor == 0 ? 1 : 0; + } + if (currScore > maxScore) { + maxScore = currScore; + maxScoreCandidate = divisor; + } else if (currScore == maxScore) { + maxScoreCandidate = Math.min(maxScoreCandidate, divisor); + } + } + return maxScoreCandidate; + } +} diff --git a/Medium/Find the Maximum Number of Elements in Subset.java b/Medium/Find the Maximum Number of Elements in Subset.java new file mode 100644 index 00000000..4c419cbc --- /dev/null +++ b/Medium/Find the Maximum Number of Elements in Subset.java @@ -0,0 +1,19 @@ +class Solution { + public int maximumLength(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int result = map.containsKey(1) ? (map.get(1) % 2 == 0 ? map.get(1) - 1 : map.get(1)) : 1; + for (int num : nums) { + int count = 0; + while (map.containsKey(num) && map.get(num) >= 2 && num != 1) { + count += 2; + num *= num; + } + count += map.containsKey(num) ? 1 : -1; + result = Math.max(result, count); + } + return result; + } +} diff --git a/Medium/Find the Minimum Area to Cover All Ones I.java b/Medium/Find the Minimum Area to Cover All Ones I.java new file mode 100644 index 00000000..538bf894 --- /dev/null +++ b/Medium/Find the Minimum Area to Cover All Ones I.java @@ -0,0 +1,24 @@ +class Solution { + public int minimumArea(int[][] grid) { + int minRow = Integer.MAX_VALUE; + int minCol = Integer.MAX_VALUE; + int maxRow = Integer.MIN_VALUE; + int maxCol = Integer.MIN_VALUE; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 1) { + minRow = Math.min(minRow, i); + minCol = Math.min(minCol, j); + maxRow = Math.max(maxRow, i); + maxCol = Math.max(maxCol, j); + } + } + } + if (minRow == Integer.MAX_VALUE) { + return 0; + } + int length = maxRow - minRow + 1; + int breadth = maxCol - minCol + 1; + return length * breadth; + } +} diff --git a/Medium/Find the Minimum and Maximum Number of Nodes Between Critical Points.java b/Medium/Find the Minimum and Maximum Number of Nodes Between Critical Points.java new file mode 100644 index 00000000..dfab1434 --- /dev/null +++ b/Medium/Find the Minimum and Maximum Number of Nodes Between Critical Points.java @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public int[] nodesBetweenCriticalPoints(ListNode head) { + int firstIdx = Integer.MAX_VALUE; + int lastIdx = 0; + int minDistance = Integer.MAX_VALUE; + int prevVal = head.val; + for (int i = 0; head.next != null; i++) { + if ((prevVal < head.val && head.next.val < head.val) || + (prevVal > head.val && head.next.val > head.val)) { + if (lastIdx != 0) { + minDistance = Math.min(minDistance, i - lastIdx); + } + firstIdx = Math.min(firstIdx, i); + lastIdx = i; + } + prevVal = head.val; + head = head.next; + } + return minDistance == Integer.MAX_VALUE ? new int[]{-1, -1} : new int[]{minDistance, lastIdx - firstIdx}; + } +} diff --git a/Medium/Find the N-th Value After K Seconds.java b/Medium/Find the N-th Value After K Seconds.java new file mode 100644 index 00000000..e457d0eb --- /dev/null +++ b/Medium/Find the N-th Value After K Seconds.java @@ -0,0 +1,15 @@ +class Solution { + + private final int MOD = 1000_000_007; + + public int valueAfterKSeconds(int n, int k) { + int[] arr = new int[n]; + Arrays.fill(arr, 1); + while (k-- > 0) { + for (int i = 1; i < n; i++) { + arr[i] = (arr[i] + arr[i - 1]) % MOD; + } + } + return arr[n - 1]; + } +} diff --git a/Medium/Find the Number of Distinct Colors Among the Balls.java b/Medium/Find the Number of Distinct Colors Among the Balls.java new file mode 100644 index 00000000..428e5406 --- /dev/null +++ b/Medium/Find the Number of Distinct Colors Among the Balls.java @@ -0,0 +1,23 @@ +class Solution { + public int[] queryResults(int limit, int[][] queries) { + Map ballToColor = new HashMap<>(); + Map colorToBallCount = new HashMap<>(); + int n = queries.length; + int[] result = new int[n]; + for (int i = 0; i < queries.length; i++) { + int ball = queries[i][0]; + int color = queries[i][1]; + if (ballToColor.containsKey(ball)) { + int prevColor = ballToColor.get(ball); + colorToBallCount.put(prevColor, colorToBallCount.get(prevColor) - 1); + if (colorToBallCount.get(prevColor) == 0) { + colorToBallCount.remove(prevColor); + } + } + ballToColor.put(ball, color); + colorToBallCount.put(color, colorToBallCount.getOrDefault(color, 0) + 1); + result[i] = colorToBallCount.size(); + } + return result; + } +} diff --git a/Medium/Find the Prefix Common Array of Two Arrays.java b/Medium/Find the Prefix Common Array of Two Arrays.java new file mode 100644 index 00000000..e6312a17 --- /dev/null +++ b/Medium/Find the Prefix Common Array of Two Arrays.java @@ -0,0 +1,20 @@ +class Solution { + public int[] findThePrefixCommonArray(int[] A, int[] B) { + int count = 0; + int n = A.length; + int[] result = new int[n]; + int[] frequency = new int[n + 1]; + for (int i = 0; i < n; i++) { + frequency[A[i]]++; + if (frequency[A[i]] == 2) { + count++; + } + frequency[B[i]]++; + if (frequency[B[i]] == 2) { + count++; + } + result[i] = count; + } + return result; + } +} diff --git a/Medium/Find the Score of All Prefixes of an Array.java b/Medium/Find the Score of All Prefixes of an Array.java new file mode 100644 index 00000000..ff88ca98 --- /dev/null +++ b/Medium/Find the Score of All Prefixes of an Array.java @@ -0,0 +1,17 @@ +class Solution { + public long[] findPrefixScore(int[] nums) { + int[] conver = new int[nums.length]; + int max = nums[0]; + for (int i = 0; i < nums.length; i++) { + max = Math.max(max, nums[i]); + conver[i] = nums[i] + max; + } + long[] result = new long[nums.length]; + long score = 0; + for (int i = 0; i < nums.length; i++) { + score += conver[i]; + result[i] = score; + } + return result; + } +} diff --git a/Medium/Find the Student that Will Replace the Chalk.java b/Medium/Find the Student that Will Replace the Chalk.java new file mode 100644 index 00000000..bdf79d9a --- /dev/null +++ b/Medium/Find the Student that Will Replace the Chalk.java @@ -0,0 +1,23 @@ +class Solution { + public int chalkReplacer(int[] chalk, int k) { + int n = chalk.length; + long[] prefixSum = new long[n]; + prefixSum[0] = chalk[0]; + for (int i = 1; i < n; i++) { + prefixSum[i] = chalk[i] + prefixSum[i - 1]; + } + long total = prefixSum[n - 1]; + long remaining = k % total; + int left = 0; + int right = n - 1; + while (left < right) { + int mid = (left + right) / 2; + if (prefixSum[mid] <= remaining) { + left = mid + 1; + } else { + right = mid; + } + } + return right; + } +} diff --git a/Medium/Find the Substring With Maximum Cost.java b/Medium/Find the Substring With Maximum Cost.java new file mode 100644 index 00000000..24e00548 --- /dev/null +++ b/Medium/Find the Substring With Maximum Cost.java @@ -0,0 +1,16 @@ +class Solution { + public int maximumCostSubstring(String s, String chars, int[] vals) { + Map valueMap = new HashMap<>(); + for (int i = 0; i < chars.length(); i++) { + valueMap.put(chars.charAt(i), vals[i]); + } + int maxCost = 0; + int currCost = 0; + for (char c : s.toCharArray()) { + int currCharCost = valueMap.containsKey(c) ? valueMap.get(c) : (c - 'a' + 1); + currCost = Math.max(currCharCost, currCost + currCharCost); + maxCost = Math.max(currCost, maxCost); + } + return maxCost; + } +} diff --git a/Medium/Find the Winner of an Array Game.java b/Medium/Find the Winner of an Array Game.java new file mode 100644 index 00000000..98932a1e --- /dev/null +++ b/Medium/Find the Winner of an Array Game.java @@ -0,0 +1,16 @@ +class Solution { + public int getWinner(int[] arr, int k) { + int curr = arr[0]; + int streak = 0; + for (int i = 1; i < arr.length; i++) { + if (curr < arr[i]) { + curr = arr[i]; + streak = 0; + } + if (++streak == k) { + break; + } + } + return curr; + } +} diff --git a/Medium/Find the Winner of the Circular Game.java b/Medium/Find the Winner of the Circular Game.java new file mode 100644 index 00000000..816b3aa4 --- /dev/null +++ b/Medium/Find the Winner of the Circular Game.java @@ -0,0 +1,15 @@ +class Solution { + public int findTheWinner(int n, int k) { + Queue circle = new LinkedList<>(); + for (int i = 1; i <= n; i++) { + circle.add(i); + } + while (circle.size() > 1) { + for (int i = 0; i < k - 1; i++) { + circle.add(circle.remove()); + } + circle.remove(); + } + return circle.peek(); + } +} diff --git a/Medium/Find the duplicate number.java b/Medium/Find the duplicate number.java deleted file mode 100644 index e4387706..00000000 --- a/Medium/Find the duplicate number.java +++ /dev/null @@ -1,17 +0,0 @@ -class Solution { - public int findDuplicate(int[] nums) { - int n = nums.length; - int slow = n; - int fast = n; - do{ - slow = nums[slow-1]; - fast = nums[nums[fast-1]-1]; - }while (slow != fast); - slow = n; - while (slow != fast) { - slow = nums[slow-1]; - fast = nums[fast-1]; - } - return slow; - } -} diff --git a/Medium/Finding the Users Active Minutes.java b/Medium/Finding the Users Active Minutes.java new file mode 100644 index 00000000..45c9c86c --- /dev/null +++ b/Medium/Finding the Users Active Minutes.java @@ -0,0 +1,16 @@ +class Solution { + public int[] findingUsersActiveMinutes(int[][] logs, int k) { + Map> map = new HashMap<>(); + for (int[] log : logs) { + int id = log[0]; + int minute = log[1]; + map.computeIfAbsent(id, j -> new HashSet<>()).add(minute); + } + int[] result = new int[k]; + for (Integer key : map.keySet()) { + int uam = map.get(key).size(); + result[uam - 1]++; + } + return result; + } +} diff --git a/Medium/First Unique Number.java b/Medium/First Unique Number.java new file mode 100644 index 00000000..6affb411 --- /dev/null +++ b/Medium/First Unique Number.java @@ -0,0 +1,32 @@ +class FirstUnique { + + private Map map; + private Queue queue; + + public FirstUnique(int[] nums) { + map = new HashMap<>(); + queue = new LinkedList<>(); + for (int num : nums) { + add(num); + } + } + + public int showFirstUnique() { + while (!queue.isEmpty() && map.get(queue.peek()) > 1) { + queue.remove(); + } + return queue.isEmpty() ? -1 : queue.peek(); + } + + public void add(int value) { + queue.add(value); + map.put(value, map.getOrDefault(value, 0) + 1); + } +} + +/** + * Your FirstUnique object will be instantiated and called as such: + * FirstUnique obj = new FirstUnique(nums); + * int param_1 = obj.showFirstUnique(); + * obj.add(value); + */ diff --git a/Medium/Flatten 2D Vector.java b/Medium/Flatten 2D Vector.java index d3d815bb..83fd6e2e 100644 --- a/Medium/Flatten 2D Vector.java +++ b/Medium/Flatten 2D Vector.java @@ -1,44 +1,31 @@ -class Vector2D implements Iterator { +import java.util.PrimitiveIterator.OfInt; - Iterator> listIterator; - Iterator iterator; - boolean flag; +class Vector2D { - public Vector2D(List> vec2d) { - listIterator = vec2d.iterator(); - check(); - } - - private void check() { - while (listIterator.hasNext()) { - List list = listIterator.next(); - if (list.size() > 0) { - iterator = list.iterator(); - break; - } - } - - flag = iterator != null; - } + private Iterator iterators; + private Iterator currIterator; - @Override - public Integer next() { - int num = iterator.next(); - if (!iterator.hasNext()) { - iterator = null; - check(); - } + public Vector2D(int[][] vec) { + this.iterators = Arrays.stream(vec).map(v -> Arrays.stream(v).iterator()).iterator(); + this.currIterator = Collections.emptyIterator();; + } - return num; - } + public int next() { + hasNext(); + return (int) this.currIterator.next(); + } - @Override - public boolean hasNext() { - return flag; + public boolean hasNext() { + while (!this.currIterator.hasNext() && this.iterators.hasNext()) { + this.currIterator = this.iterators.next(); } + return this.currIterator.hasNext(); + } } + /** * Your Vector2D object will be instantiated and called as such: - * Vector2D i = new Vector2D(vec2d); - * while (i.hasNext()) v[f()] = i.next(); + * Vector2D obj = new Vector2D(vec); + * int param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); */ diff --git a/Medium/Flatten Binary Tree to Linked List.java b/Medium/Flatten Binary Tree to Linked List.java index 2c2f5489..b3e79dac 100644 --- a/Medium/Flatten Binary Tree to Linked List.java +++ b/Medium/Flatten Binary Tree to Linked List.java @@ -4,33 +4,34 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public void flatten(TreeNode root) { - if (root == null) { - return; - } - - // Store left and right of root - TreeNode left = root.left; - TreeNode right = root.right; - - root.left = null; - - flatten(left); - flatten(right); - - // Make root.right to null and traverse to last node of right - root.right = left; - TreeNode curr = root; - - while (curr.right != null) { - curr = curr.right; - } - - // Make last node's right equal to stored right - curr.right = right; + public void flatten(TreeNode root) { + if (root == null) { + return; } + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode curr = stack.pop(); + if (curr.right != null) { + stack.push(curr.right); + } + if (curr.left != null) { + stack.push(curr.left); + } + if (!stack.isEmpty()) { + curr.right = stack.peek(); + } + curr.left = null; + } + } } diff --git a/Medium/Flatten Nested List Iterator.java b/Medium/Flatten Nested List Iterator.java index d0ac3dbc..087bc1ef 100644 --- a/Medium/Flatten Nested List Iterator.java +++ b/Medium/Flatten Nested List Iterator.java @@ -11,46 +11,39 @@ * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - List list; - int index; - int size; + + private Stack stack; + public NestedIterator(List nestedList) { - list = new ArrayList<>(); - index = 0; - for (NestedInteger n : nestedList) { - dfsHelper(n); - } - - size = list.size(); - } - - private void dfsHelper(NestedInteger n) { - if (n.isInteger()) { - list.add(n.getInteger()); - } - else { - for (NestedInteger ni : n.getList()) { - dfsHelper(ni); - } + this.stack = new Stack<>(); + for (int i = nestedList.size() - 1; i >= 0; i--) { + this.stack.push(nestedList.get(i)); } } @Override public Integer next() { - if (index < size) { - return list.get(index++); - } - return -1; + return stack.pop().getInteger(); } @Override public boolean hasNext() { - return !(index == size); + while (!stack.isEmpty() && !stack.peek().isInteger()) { + NestedInteger popped = stack.pop(); + if (popped == null) { + continue; + } + List list = popped.getList(); + for (int i = list.size() - 1; i >= 0; i--) { + stack.push(list.get(i)); + } + } + return !stack.isEmpty(); } } diff --git a/Medium/Flatten a Multilevel Doubly Linked List.java b/Medium/Flatten a Multilevel Doubly Linked List.java index 1c6c4894..3708998f 100644 --- a/Medium/Flatten a Multilevel Doubly Linked List.java +++ b/Medium/Flatten a Multilevel Doubly Linked List.java @@ -5,43 +5,30 @@ class Node { public Node prev; public Node next; public Node child; - - public Node() {} - - public Node(int _val,Node _prev,Node _next,Node _child) { - val = _val; - prev = _prev; - next = _next; - child = _child; - } }; */ + class Solution { - Node ans; - Node curr; - public Node flatten(Node head) { - ans = new Node(-1); - curr = ans; - - helper(head); - - return ans.next; + public Node flatten(Node head) { + if (head == null) { + return head; } - - private void helper(Node node) { - if (node == null) { - return; - } - - Node prev = curr; - curr.next = new Node(node.val); - curr = curr.next; - curr.prev = prev.val == -1 ? null : prev; - - if (node.child != null) { - helper(node.child); - } - - helper(node.next); + Stack stack = new Stack<>(); + stack.push(head); + while (!stack.isEmpty()) { + Node removed = stack.pop(); + if (removed.next != null) { + stack.push(removed.next); + } + if (removed.child != null) { + stack.push(removed.child); + } + removed.child = null; + if (!stack.isEmpty()) { + removed.next = stack.peek(); + stack.peek().prev = removed; + } } + return head; + } } diff --git a/Medium/Flip Equivalent Binary Trees.java b/Medium/Flip Equivalent Binary Trees.java new file mode 100644 index 00000000..8590505e --- /dev/null +++ b/Medium/Flip Equivalent Binary Trees.java @@ -0,0 +1,31 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean flipEquiv(TreeNode root1, TreeNode root2) { + if (root1 == null && root2 == null) { + return true; + } + if (root1 == null || root2 == null) { + return false; + } + if (root1.val != root2.val) { + return false; + } + boolean noSwap = flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right); + boolean swap = flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left); + return noSwap || swap; + } +} diff --git a/Medium/Four Divisors.java b/Medium/Four Divisors.java new file mode 100644 index 00000000..4b391129 --- /dev/null +++ b/Medium/Four Divisors.java @@ -0,0 +1,22 @@ +class Solution { + public int sumFourDivisors(int[] nums) { + int sum = 0; + for (int num : nums) { + Set set = new HashSet<>(); + for (int i = 1; i <= Math.sqrt(num); i++) { + int first = i; + int second = num % i; + if (second == 0) { + set.add(first); + set.add(num / i); + } + } + if (set.size() == 4) { + for (int d : set) { + sum += d; + } + } + } + return sum; + } +} diff --git a/Medium/Fraction Addition and Subtraction.java b/Medium/Fraction Addition and Subtraction.java new file mode 100644 index 00000000..3d26da63 --- /dev/null +++ b/Medium/Fraction Addition and Subtraction.java @@ -0,0 +1,42 @@ +class Solution { + public String fractionAddition(String expression) { + int numerator = 0; + int denominator = 1; + int idx = 0; + int n = expression.length(); + while (idx < n) { + int currNumerator = 0; + int currDenominator = 0; + boolean negative = false; + if (expression.charAt(idx) == '-' || expression.charAt(idx) == '+') { + negative = expression.charAt(idx) == '-' ? true : false; + idx++; + } + while (Character.isDigit(expression.charAt(idx))) { + currNumerator = currNumerator * 10 + Character.getNumericValue(expression.charAt(idx)); + idx++; + } + if (negative) { + currNumerator *= -1; + } + idx++; + while (idx < n && Character.isDigit(expression.charAt(idx))) { + currDenominator = currDenominator * 10 + Character.getNumericValue(expression.charAt(idx)); + idx++; + } + numerator = numerator * currDenominator + currNumerator * denominator; + denominator = denominator * currDenominator; + } + int gcd = Math.abs(gcd(numerator, denominator)); + numerator /= gcd; + denominator /= gcd; + return numerator + "/" + denominator; + } + + private int gcd(int a, int b) { + if (a == 0) { + return b; + } + return gcd(b % a, a); + } +} diff --git a/Medium/Fraction to Recurring Decimal.java b/Medium/Fraction to Recurring Decimal.java index 352a2c3e..dda64d6b 100644 --- a/Medium/Fraction to Recurring Decimal.java +++ b/Medium/Fraction to Recurring Decimal.java @@ -1,39 +1,32 @@ class Solution { - public String fractionToDecimal(int numerator, int denominator) { - if (numerator == 0) { - return "0"; - } - - StringBuilder fraction = new StringBuilder(); - if (numerator < 0 ^ denominator < 0) { - fraction.append("-"); - } - - long dividend = Math.abs(Long.valueOf(numerator)); - long divisor = Math.abs(Long.valueOf(denominator)); - - fraction.append(String.valueOf(dividend / divisor)); - long remainder = dividend % divisor; - - if (remainder == 0) { - return fraction.toString(); - } - - fraction.append('.'); - Map map = new HashMap<>(); - while (remainder != 0) { - if (map.containsKey(remainder)) { - fraction.insert(map.get(remainder), "("); - fraction.append(')'); - break; - } - - map.put(remainder, fraction.length()); - remainder *= 10; - fraction.append(String.valueOf(remainder / divisor)); - remainder %= divisor; - } - - return fraction.toString(); + public String fractionToDecimal(int numerator, int denominator) { + if (numerator == 0) { + return "0"; } + StringBuilder fraction = new StringBuilder(); + if ((numerator < 0 && denominator > 0) || (numerator > 0 && denominator < 0)) { + fraction.append('-'); + } + long dividend = Math.abs(Long.valueOf(numerator)); + long divisor = Math.abs(Long.valueOf(denominator)); + fraction.append(String.valueOf(dividend / divisor)); + long remainder = dividend % divisor; + if (remainder == 0) { + return fraction.toString(); + } + fraction.append('.'); + Map map = new HashMap<>(); + while (remainder != 0) { + if (map.containsKey(remainder)) { + fraction.insert(map.get(remainder), "("); + fraction.append(')'); + break; + } + map.put(remainder, fraction.length()); + remainder *= 10; + fraction.append(String.valueOf(remainder / divisor)); + remainder %= divisor; + } + return fraction.toString(); + } } diff --git a/Medium/Frequency Tracker.java b/Medium/Frequency Tracker.java new file mode 100644 index 00000000..e5e83453 --- /dev/null +++ b/Medium/Frequency Tracker.java @@ -0,0 +1,48 @@ +class FrequencyTracker { + + private final Map numToFrequencyMapping; + private final Map> frequencyToNumMapping; + + public FrequencyTracker() { + this.numToFrequencyMapping = new HashMap<>(); + this.frequencyToNumMapping = new HashMap<>(); + } + + public void add(int number) { + int prevFrequency = this.numToFrequencyMapping.getOrDefault(number, 0); + int newFrequency = prevFrequency + 1; + this.numToFrequencyMapping.put(number, newFrequency); + updateFreqToNumMapping(number, prevFrequency, newFrequency); + } + + public void deleteOne(int number) { + int prevFrequency = this.numToFrequencyMapping.getOrDefault(number, 0); + if (prevFrequency == 0) { + return; + } + int newFrequency = prevFrequency - 1; + this.numToFrequencyMapping.put(number, newFrequency); + updateFreqToNumMapping(number, prevFrequency, newFrequency); + } + + public boolean hasFrequency(int frequency) { + return this.frequencyToNumMapping.getOrDefault(frequency, new HashSet<>()).size() > 0; + } + + private void updateFreqToNumMapping(int number, int prevFrequency, int newFrequency) { + if (prevFrequency != 0) { + this.frequencyToNumMapping.get(prevFrequency).remove(number); + } + if (newFrequency != 0) { + this.frequencyToNumMapping.computeIfAbsent(newFrequency, k -> new HashSet<>()).add(number); + } + } +} + +/** + * Your FrequencyTracker object will be instantiated and called as such: + * FrequencyTracker obj = new FrequencyTracker(); + * obj.add(number); + * obj.deleteOne(number); + * boolean param_3 = obj.hasFrequency(frequency); + */ diff --git a/Medium/Friend Circles.java b/Medium/Friend Circles.java index ad214b9d..2ceb3c46 100644 --- a/Medium/Friend Circles.java +++ b/Medium/Friend Circles.java @@ -1,41 +1,40 @@ class Solution { - public int findCircleNum(int[][] M) { - Map> map = new HashMap<>(); - for (int i=0; i new ArrayList<>()).add(j); - map.computeIfAbsent(j, k -> new ArrayList<>()).add(i); - } - } - } - - Set set = new HashSet<>(); - int count = 0; - Queue queue = new LinkedList<>(); - - for (Map.Entry> entry : map.entrySet()) { - if (set.contains(entry.getKey())) { - continue; - } - - queue.add(entry.getKey()); - - while (!queue.isEmpty()) { - int popped = queue.remove(); - set.add(popped); - List list = map.get(popped); - - for (Integer integer : list) { - if (!set.contains(integer)) { - queue.add(integer); - } - } - } - - count++; + public int findCircleNum(int[][] M) { + Map> map = new HashMap<>(); + for (int i = 0; i < M.length; i++) { + for (int j = 0; j < M[i].length; j++) { + if (M[i][j] == 1) { + map.computeIfAbsent(i, k -> new HashSet<>()).add(j); + } + } + } + return dfs(map, M.length); + } + + private int dfs(Map> map, int n) { + int count = 0; + Set seen = new HashSet<>(); + for (int i = 0; i < n; i++) { + if (!seen.contains(i)) { + dfsHelper(map, i, seen); + count++; + } + } + return count; + } + + private void dfsHelper(Map> map, int curr, Set seen) { + Queue queue = new LinkedList<>(); + queue.add(curr); + seen.add(curr); + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer friend : map.getOrDefault(removed, new HashSet<>())) { + if (!seen.contains(friend)) { + queue.add(friend); + seen.add(friend); } - - return count; + } } + } } diff --git a/Medium/Friends Of Appropriate Ages.java b/Medium/Friends Of Appropriate Ages.java new file mode 100644 index 00000000..8d63064c --- /dev/null +++ b/Medium/Friends Of Appropriate Ages.java @@ -0,0 +1,17 @@ +class Solution { + public int numFriendRequests(int[] ages) { + Map map = new HashMap<>(); + for (int age : ages) { + map.put(age, map.getOrDefault(age, 0) + 1); + } + int totalFriendRequests = 0; + for (Integer ageOne : map.keySet()) { + for (Integer ageTwo : map.keySet()) { + if (!((ageTwo <= 0.5 * ageOne + 7) || (ageTwo > ageOne) || (ageTwo > 100 && ageOne < 100))) { + totalFriendRequests += map.get(ageOne) * (map.get(ageTwo) - (ageOne == ageTwo ? 1 : 0)); + } + } + } + return totalFriendRequests; + } +} diff --git a/Medium/Fruit Into Baskets.java b/Medium/Fruit Into Baskets.java index 2cec17aa..937fbbe9 100644 --- a/Medium/Fruit Into Baskets.java +++ b/Medium/Fruit Into Baskets.java @@ -1,27 +1,21 @@ class Solution { - public int totalFruit(int[] tree) { + public int totalFruit(int[] fruits) { + int maximumFruits = 0; Map map = new HashMap<>(); - int maxSize = 0; int start = 0; - int count = 0; - - for (int i = 0; i < tree.length; i++) { - map.put(tree[i], map.getOrDefault(tree[i], 0) + 1); - count++; - - while (map.size() > 2) { - map.put(tree[start], map.getOrDefault(tree[start], 0) - 1); - if (map.get(tree[start]) == 0) { - map.remove(tree[start]); + int end = 0; + while (end < fruits.length) { + map.put(fruits[end], map.getOrDefault(fruits[end], 0) + 1); + end++; + while (start < end && map.size() > 2) { + map.put(fruits[start], map.get(fruits[start]) - 1); + if (map.get(fruits[start]) == 0) { + map.remove(fruits[start]); } - - count--; start++; } - - maxSize = Math.max(maxSize, count); + maximumFruits = Math.max(maximumFruits, end - start); } - - return maxSize; + return maximumFruits; } } diff --git a/Medium/Furthest Building You Can Reach.java b/Medium/Furthest Building You Can Reach.java new file mode 100644 index 00000000..1e110678 --- /dev/null +++ b/Medium/Furthest Building You Can Reach.java @@ -0,0 +1,20 @@ +class Solution { + public int furthestBuilding(int[] heights, int bricks, int ladders) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + for (int i = 1; i < heights.length; i++) { + int diff = heights[i] - heights[i - 1]; + if (diff > 0) { + pq.add(diff); + bricks -= diff; + if (bricks < 0) { + if (ladders == 0) { + return i - 1; + } + ladders--; + bricks += pq.poll(); + } + } + } + return heights.length - 1; + } +} diff --git a/Medium/Game of Life.java b/Medium/Game of Life.java index 151b60b7..4341ee13 100644 --- a/Medium/Game of Life.java +++ b/Medium/Game of Life.java @@ -1,43 +1,48 @@ class Solution { - public void gameOfLife(int[][] board) { - for (int i=0; i 3) { - board[i][j] = selfAlive ? 2 : 0; - } - } - else { - if (aliveNeighbours == 3) { - board[i][j] = selfAlive ? 1 : 3; - } - } - } - } - - for (int i=0; i= 0 && row < board.length && col >= 0 && col < board[0].length && (board[row][col] == 1 || board[row][col] == 2); + public void gameOfLife(int[][] board) { + int rows = board.length; + int cols = board[0].length; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + int liveNeighborCount = getLiveNeighbours(board, i, j); + if (board[i][j] == 1) { + if (liveNeighborCount < 2 || liveNeighborCount > 3) { + board[i][j] = 2; + } + } else { + if (liveNeighborCount == 3) { + board[i][j] = 3; + } + } + } } - - private int getLiveCount(int[][] board, int i, int j) { - int liveCount = 0; - - int[][] possibleCoordinates = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}}; - for (int[] coordinate : possibleCoordinates) { - if (isAlive(board, i + coordinate[0], j + coordinate[1])) { - liveCount++; - } + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (board[i][j] == 2) { + board[i][j] = 0; + } else if (board[i][j] == 3) { + board[i][j] = 1; } - - return liveCount; + } + } + } + + private static int getLiveNeighbours(int[][] board, int i, int j) { + int count = 0; + for (int[] dir : DIRS) { + int x = i + dir[0]; + int y = j + dir[1]; + if (isValidCell(board, x, y) && (board[x][y] == 1 || board[x][y] == 2)) { + count++; + } } + return count; + } + + private static boolean isValidCell(int[][] board, int i, int j) { + return i >= 0 && j >= 0 && i < board.length && j < board[0].length; + } } diff --git a/Medium/Gas Station.java b/Medium/Gas Station.java new file mode 100644 index 00000000..8208abf6 --- /dev/null +++ b/Medium/Gas Station.java @@ -0,0 +1,17 @@ +class Solution { + public int canCompleteCircuit(int[] gas, int[] cost) { + int n = gas.length; + int tankCapacity = 0; + int currTankCapacity = 0; + int startingStation = 0; + for (int i = 0; i < n; i++) { + tankCapacity += gas[i] - cost[i]; + currTankCapacity += gas[i] - cost[i]; + if (currTankCapacity < 0) { + startingStation = i + 1; + currTankCapacity = 0; + } + } + return tankCapacity >= 0 ? startingStation : -1; + } +} diff --git a/Medium/Generate Parentheses.java b/Medium/Generate Parentheses.java index 8666391d..5d22b059 100644 --- a/Medium/Generate Parentheses.java +++ b/Medium/Generate Parentheses.java @@ -1,23 +1,28 @@ class Solution { - Set set; - public List generateParenthesis(int n) { - set = new HashSet<>(); - helper(0, 0, new StringBuilder(), n); - return new ArrayList<>(set); + public List generateParenthesis(int n) { + List result = new ArrayList<>(); + helper(result, 0, 0, n, new StringBuilder()); + return result; + } + + private void helper(List result, int start, int end, int n, StringBuilder sb) { + if (start + end == 2 * n) { + if (start == end) { + result.add(new StringBuilder(sb.toString()).toString()); + } + return; } - - private void helper(int left, int right, StringBuilder sb, int n) { - if (left > n || right > n || left < right) { - return; - } - - if (left == right && left == n) { - set.add(sb.toString()); - } - - helper(left + 1, right, sb.append('('), n); - sb.deleteCharAt(sb.length() - 1); - helper(left, right + 1, sb.append(')'), n); - sb.deleteCharAt(sb.length() - 1); + if (start > end) { + sb.append('('); + helper(result, start + 1, end, n, sb); + sb.deleteCharAt(sb.length() - 1); + sb.append(')'); + helper(result, start, end + 1, n, sb); + sb.deleteCharAt(sb.length() - 1); + } else if (start == end) { + sb.append('('); + helper(result, start + 1, end, n, sb); + sb.deleteCharAt(sb.length() - 1); } + } } diff --git a/Medium/Graph Valid Tree.java b/Medium/Graph Valid Tree.java index ded57df9..658608a4 100644 --- a/Medium/Graph Valid Tree.java +++ b/Medium/Graph Valid Tree.java @@ -1,31 +1,27 @@ class Solution { - public boolean validTree(int n, int[][] edges) { - if (edges.length != n - 1) { - return false; - } - - int[] points = new int[n]; - Arrays.fill(points, -1); - - for (int[] edge : edges) { - int parentPoint = getPosition(points, edge[0]); - int childPoint = getPosition(points, edge[1]); - - if (parentPoint == childPoint) { - return false; - } - - points[parentPoint] = childPoint; - } - - return true; + public boolean validTree(int n, int[][] edges) { + Map> map = new HashMap<>(); + for (int[] edge : edges) { + map.computeIfAbsent(edge[0], k -> new HashSet<>()).add(edge[1]); + map.computeIfAbsent(edge[1], k -> new HashSet<>()).add(edge[0]); } - - private int getPosition(int[] points, int num) { - if (points[num] == -1) { - return num; + Map parent = new HashMap<>(); + parent.put(0, -1); + Stack stack = new Stack<>(); + stack.push(0); + while (!stack.isEmpty()) { + int node = stack.pop(); + for (int neighbor : map.getOrDefault(node, new HashSet<>())) { + if (parent.get(node) == neighbor) { + continue; + } + if (parent.containsKey(neighbor)) { + return false; } - - return getPosition(points, points[num]); + stack.push(neighbor); + parent.put(neighbor, node); + } } + return parent.size() == n; + } } diff --git a/Medium/Group Anagrams.java b/Medium/Group Anagrams.java new file mode 100644 index 00000000..deca920f --- /dev/null +++ b/Medium/Group Anagrams.java @@ -0,0 +1,14 @@ +class Solution { + public List> groupAnagrams(String[] strs) { + return new ArrayList<>( + Arrays.stream(strs).collect(Collectors.groupingBy(Solution::getCodedString)).values()); + } + + public static String getCodedString(String s) { + return s.chars() + .mapToObj(c -> (char) c) + .sorted() + .map(Object::toString) + .collect(Collectors.joining()); + } +} diff --git a/Medium/Group Shifted Strings.java b/Medium/Group Shifted Strings.java index aa280633..b1209bbf 100644 --- a/Medium/Group Shifted Strings.java +++ b/Medium/Group Shifted Strings.java @@ -1,37 +1,17 @@ class Solution { - public static List> groupStrings(String[] strings) { - Map> map = new HashMap<>(); - - for (String s : strings) { - String key = getKey(s); - - if (map.containsKey(key)) { - map.get(key).add(s); - } - else { - List list = new ArrayList<>(); - list.add(s); - map.put(key, list); - } - } - - List> ans = new ArrayList<>(); - for (List list : map.values()) { - ans.add(list); - } - - return ans; + public List> groupStrings(String[] strings) { + Map> map = new HashMap<>(); + for (String s : strings) { + map.computeIfAbsent(getShiftedCode(s), k -> new ArrayList<>()).add(s); } + return new ArrayList<>(map.values()); + } - private static String getKey(String s) { - StringBuilder sb = new StringBuilder(""); - for (int i=1; i> groupThePeople(int[] groupSizes) { + Map> map = new HashMap<>(); + for (int i = 0; i < groupSizes.length; i++) { + map.computeIfAbsent(groupSizes[i], k -> new ArrayList<>()).add(i); + } + List> result = new ArrayList<>(); + for (Integer key : map.keySet()) { + List candidates = map.get(key); + int idx = 0; + while (idx < candidates.size()) { + result.add(candidates.subList(idx, idx + key)); + idx += key; + } + } + return result; + } +} diff --git a/Medium/Grumpy Bookstore Owner.java b/Medium/Grumpy Bookstore Owner.java index ac064c2a..996ac4d0 100644 --- a/Medium/Grumpy Bookstore Owner.java +++ b/Medium/Grumpy Bookstore Owner.java @@ -1,19 +1,16 @@ class Solution { - public int maxSatisfied(int[] customers, int[] grumpy, int X) { - int totalSum = 0; - int maxDiff = 0; - int grumpySum = 0; - - for (int i = 0; i < customers.length; i++) { - totalSum += grumpy[i] == 1 ? 0 : customers[i]; - grumpySum += grumpy[i] == 1 ? customers[i] : 0; - if (i >= X) { - grumpySum -= grumpy[i - X] == 1 ? customers[i - X] : 0; - } - - maxDiff = Math.max(maxDiff, grumpySum); - } - - return totalSum + maxDiff; + public int maxSatisfied(int[] customers, int[] grumpy, int minutes) { + int totalSum = 0; + int maxDiff = 0; + int grumpySum = 0; + for (int i = 0; i < customers.length; i++) { + totalSum += grumpy[i] == 1 ? 0 : customers[i]; + grumpySum += grumpy[i] == 1 ? customers[i] : 0; + if (i >= minutes) { + grumpySum -= grumpy[i - minutes] == 1 ? customers[i - minutes] : 0; + } + maxDiff = Math.max(maxDiff, grumpySum); } + return totalSum + maxDiff; + } } diff --git a/Medium/Guess Number Higher or Lower II.java b/Medium/Guess Number Higher or Lower II.java new file mode 100644 index 00000000..1cd79784 --- /dev/null +++ b/Medium/Guess Number Higher or Lower II.java @@ -0,0 +1,16 @@ +class Solution { + public int getMoneyAmount(int n) { + int[][] dp = new int[n + 1][n + 1]; + for (int i = 2; i <= n; i++) { + for (int j = 1; j <= n -i + 1; j++) { + int minres = Integer.MAX_VALUE; + for (int k = j; k < j + i - 1; k++) { + int res = k + Math.max(dp[j][k - 1], dp[k + 1][j + i - 1]); + minres = Math.min(minres, res); + } + dp[j][j + i - 1] = minres; + } + } + return dp[1][n]; + } +} diff --git a/Medium/H-Index.java b/Medium/H-Index.java index e872d3be..c16895b3 100644 --- a/Medium/H-Index.java +++ b/Medium/H-Index.java @@ -1,16 +1,12 @@ class Solution { - public int hIndex(int[] citations) { - Arrays.sort(citations); - int end = citations.length; - int ind = 0; - - for (int i=0; i= end - i) { - ind = end - i; - break; - } - } - - return ind; + public int hIndex(int[] citations) { + int n = citations.length; + Arrays.sort(citations); + for (int i = n - 1; i >= 0; i--) { + if (n - i > citations[i]) { + return n - i - 1; + } } + return n; + } } diff --git a/Medium/HTML Entity Parser.java b/Medium/HTML Entity Parser.java new file mode 100644 index 00000000..1e070ddd --- /dev/null +++ b/Medium/HTML Entity Parser.java @@ -0,0 +1,18 @@ +class Solution { + public String entityParser(String text) { + if (text == null || text.length() == 0) { + return ""; + } + Map map = Map.of( + """, "\"", + "'", "'", + ">", ">", + "<", "<", + "⁄", "/" + ); + for (String key : map.keySet()) { + text = text.replaceAll(key, map.get(key)); + } + return text.replaceAll("&", "&"); + } +} diff --git a/Medium/Hand of Straights.java b/Medium/Hand of Straights.java index 21675476..5f407cf0 100644 --- a/Medium/Hand of Straights.java +++ b/Medium/Hand of Straights.java @@ -1,41 +1,32 @@ class Solution { - public static boolean isNStraightHand(int[] hand, int W) { - if (hand.length%W != 0) { + public boolean isNStraightHand(int[] hand, int groupSize) { + if (hand.length % groupSize != 0) { return false; } - - Map map = new TreeMap<>(); - + Map map = new HashMap<>(); for (int num : hand) { - map.put(num, map.getOrDefault(num, 0)+1); + map.put(num, map.getOrDefault(num, 0) + 1); } - - Set keys; - int batches = hand.length/W; - int batchSize; - - while (batches-- > 0) { - keys = map.keySet(); - Iterator iterator = keys.iterator(); - batchSize = W; - int val = iterator.next(); - - while (batchSize-- > 0) { - if (map.containsKey(val)) { - if (map.get(val) == 1) { - map.remove(val); - } - else { - map.put(val, map.getOrDefault(val, 0)-1); - } - val++; + PriorityQueue pq = new PriorityQueue<>(map.keySet()); + while (!pq.isEmpty()) { + List temp = new ArrayList<>(); + int prev = -1; + for (int i = 0; i < groupSize; i++) { + if (pq.isEmpty()) { + return false; + } + int removed = pq.remove(); + map.put(removed, map.get(removed) - 1); + if (map.get(removed) > 0) { + temp.add(removed); } - else { + if (prev != -1 && removed != prev + 1) { return false; } + prev = removed; } + pq.addAll(temp); } - return true; } } diff --git a/Medium/High-Access Employees.java b/Medium/High-Access Employees.java new file mode 100644 index 00000000..8c881fc8 --- /dev/null +++ b/Medium/High-Access Employees.java @@ -0,0 +1,43 @@ +class Solution { + public List findHighAccessEmployees(List> accessTimeEntries) { + Map> map = new HashMap<>(); + for (List entry : accessTimeEntries) { + String employee = entry.get(0); + String time = entry.get(1); + map.computeIfAbsent(employee, k -> new ArrayList<>()).add(TimeRecord.buildTimeRecord(time)); + } + List result = new ArrayList<>(); + for (String key : map.keySet()) { + List entries = map.get(key); + if (entries.size() < 3) { + continue; + } + Collections.sort(entries); + for (int i = 0; i < entries.size() - 2; i++) { + if (TimeRecord.areWithinSameHour(entries.get(i), entries.get(i + 2))) { + result.add(key); + break; + } + } + } + return result; + } + + private record TimeRecord(int totalMinutes) implements Comparable { + + public static TimeRecord buildTimeRecord(String entry) { + int hour = Integer.parseInt(entry.substring(0, 2)); + int min = Integer.parseInt(entry.substring(2)); + return new TimeRecord(hour * 60 + min); + } + + public static boolean areWithinSameHour(TimeRecord startTime, TimeRecord endTime) { + return endTime.totalMinutes - startTime.totalMinutes < 60; + } + + @Override + public int compareTo(TimeRecord o) { + return this.totalMinutes - o.totalMinutes; + } + } +} diff --git a/Medium/House Robber II.java b/Medium/House Robber II.java new file mode 100644 index 00000000..5219984e --- /dev/null +++ b/Medium/House Robber II.java @@ -0,0 +1,20 @@ +class Solution { + public int rob(int[] nums) { + if (nums.length == 1) { + return nums[0]; + } + return Math.max(robHelper(nums, 0, nums.length - 2), robHelper(nums, 1, nums.length - 1)); + } + + private int robHelper(int[] nums, int lower, int higher) { + int include = 0; + int exclude = 0; + for (int j = lower; j <= higher; j++) { + int includeIdx = include; + int excludeIdx = exclude; + include = excludeIdx + nums[j]; + exclude = Math.max(excludeIdx, includeIdx); + } + return Math.max(include, exclude); + } +} diff --git a/Medium/House Robber III.java b/Medium/House Robber III.java new file mode 100644 index 00000000..924423a9 --- /dev/null +++ b/Medium/House Robber III.java @@ -0,0 +1,32 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int rob(TreeNode root) { + int[] ans = helper(root); + return Math.max(ans[0], ans[1]); + } + + private int[] helper(TreeNode root) { + if (root == null) { + return new int[]{0, 0}; + } + int[] left = helper(root.left); + int[] right = helper(root.right); + int robbed = root.val + left[1] + right[1]; + int notRobbed = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); + return new int[]{robbed, notRobbed}; + } +} diff --git a/Medium/House Robber.java b/Medium/House Robber.java new file mode 100644 index 00000000..3ebdc59b --- /dev/null +++ b/Medium/House Robber.java @@ -0,0 +1,11 @@ +class Solution { + public int rob(int[] nums) { + int n = nums.length; + int[] dp = new int[n + 1]; + dp[1] = nums[0]; + for (int i = 1; i < n; i++) { + dp[i + 1] = Math.max(dp[i], dp[i - 1] + nums[i]); + } + return dp[n]; + } +} diff --git a/Medium/Image Overlap.java b/Medium/Image Overlap.java new file mode 100644 index 00000000..680b1750 --- /dev/null +++ b/Medium/Image Overlap.java @@ -0,0 +1,29 @@ +class Solution { + public int largestOverlap(int[][] img1, int[][] img2) { + List> nonZeroCoordinates1 = getNonZeroCoordinates(img1); + List> nonZeroCoordinates2 = getNonZeroCoordinates(img2); + int maxOverlap = 0; + Map, Integer> groupCount = new HashMap<>(); + for (Pair c1 : nonZeroCoordinates1) { + for (Pair c2 : nonZeroCoordinates2) { + Pair vector = new Pair( + c2.getKey() - c1.getKey(), c2.getValue() - c1.getValue()); + groupCount.put(vector, groupCount.getOrDefault(vector, 0) + 1); + maxOverlap = Math.max(maxOverlap, groupCount.get(vector)); + } + } + return maxOverlap; + } + + private List> getNonZeroCoordinates(int[][] arr) { + List> coordinates = new ArrayList<>(); + for (int i = 0; i < arr.length; i++) { + for (int j = 0; j < arr[0].length; j++) { + if (arr[i][j] == 1) { + coordinates.add(new Pair(i, j)); + } + } + } + return coordinates; + } +} diff --git a/Medium/Implement Magic Dictionary.java b/Medium/Implement Magic Dictionary.java new file mode 100644 index 00000000..d3a1547d --- /dev/null +++ b/Medium/Implement Magic Dictionary.java @@ -0,0 +1,51 @@ +class MagicDictionary { + + /** Initialize your data structure here. */ + Set words; + Map count; + public MagicDictionary() { + words = new HashSet<>(); + count = new HashMap<>(); + } + + private List generalizedNeighbour(String word) { + List list = new ArrayList<>(); + char[] chars = word.toCharArray(); + for (int i = 0; i < chars.length; i++) { + char letter = chars[i]; + chars[i] = '*'; + String magic = new String(chars); + list.add(magic); + chars[i] = letter; + } + return list; + } + + /** Build a dictionary through a list of words */ + public void buildDict(String[] dict) { + for (String word : dict) { + words.add(word); + for (String neighbour : generalizedNeighbour(word)) { + count.put(neighbour, count.getOrDefault(neighbour, 0) + 1); + } + } + } + + /** 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) { + for (String neighbour : generalizedNeighbour(word)) { + int c = count.getOrDefault(neighbour, 0); + if (c > 1 || c == 1 && !words.contains(word)) { + return true; + } + } + return false; + } +} + +/** + * Your MagicDictionary object will be instantiated and called as such: + * MagicDictionary obj = new MagicDictionary(); + * obj.buildDict(dict); + * boolean param_2 = obj.search(word); + */ diff --git a/Medium/Implement Rand10() Using Rand7().java b/Medium/Implement Rand10() Using Rand7().java index 8e1d9cc1..4feb5a1f 100644 --- a/Medium/Implement Rand10() Using Rand7().java +++ b/Medium/Implement Rand10() Using Rand7().java @@ -4,15 +4,14 @@ * @return a random integer in the range 1 to 7 */ class Solution extends SolBase { - public int rand10() { - int temp = 0; - while (true) { - temp = (rand7() - 1) * 7 + (rand7() - 1); - if (temp < 40) { - break; - } - } - - return temp % 10 + 1; + public int rand10() { + int temp = 0; + while (true) { + temp = (rand7() - 1) * 7 + (rand7() - 1); + if (temp < 40) { + break; + } } + return temp % 10 + 1; + } } diff --git a/Medium/Implement Trie (Prefix Tree).java b/Medium/Implement Trie (Prefix Tree).java index fa3d1c71..353634fd 100644 --- a/Medium/Implement Trie (Prefix Tree).java +++ b/Medium/Implement Trie (Prefix Tree).java @@ -1,69 +1,57 @@ +import java.util.Optional; + class Trie { - Node trie; - /** Initialize your data structure here. */ + private final TrieNode root; + public Trie() { - trie = new Node(""); + root = new TrieNode(); } - /** Inserts a word into the trie. */ public void insert(String word) { - Node curr = trie; - for(int i=0; i node = searchHelper(word); + return node.isPresent() && node.get().isWord; } - /** Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { - Node curr = trie; - - for (int i=0; i node = searchHelper(prefix); + return node.isPresent(); + } + + public Optional searchHelper(String word) { + TrieNode curr = root; + for (char c : word.toCharArray()) { + if (!curr.children.containsKey(c)) { + return Optional.empty(); } + curr = curr.children.get(c); } - - return true; + return Optional.of(curr); } - private static final class Node { - String prefix; - Map childrens; - boolean isWord; + private static class TrieNode { + + private final Map children; + private boolean isWord; - public Node(String prefix) { - this.prefix = prefix; - this.childrens = new HashMap<>(); + private TrieNode() { + this.children = new HashMap<>(); + this.isWord = false; } } } + /** * Your Trie object will be instantiated and called as such: * Trie obj = new Trie(); diff --git a/Medium/Implement Trie II (Prefix Tree).java b/Medium/Implement Trie II (Prefix Tree).java new file mode 100644 index 00000000..7c5b1a36 --- /dev/null +++ b/Medium/Implement Trie II (Prefix Tree).java @@ -0,0 +1,76 @@ +import java.util.Optional; + + +class Trie { + + private final Node root; + + public Trie() { + root = new Node(); + } + + public void insert(String word) { + Node curr = root; + for (char c : word.toCharArray()) { + if (!curr.children.containsKey(c)) { + curr.children.put(c, new Node()); + } + curr = curr.children.get(c); + curr.startingWordCount++; + } + curr.endingWordCount++; + } + + public int countWordsEqualTo(String word) { + Optional curr = search(word); + return curr.map(node -> node.endingWordCount).orElse(0); + } + + public int countWordsStartingWith(String prefix) { + Optional curr = search(prefix); + return curr.map(node -> node.startingWordCount).orElse(0); + } + + public void erase(String word) { + Node curr = root; + for (char c : word.toCharArray()) { + curr = curr.children.get(c); + curr.startingWordCount--; + } + curr.endingWordCount--; + } + + private Optional search(String word) { + Node curr = root; + for (char c : word.toCharArray()) { + if (!curr.children.containsKey(c)) { + return Optional.empty(); + } + curr = curr.children.get(c); + } + return Optional.of(curr); + } + + private static class Node { + + private int startingWordCount; + private int endingWordCount; + + private final Map children; + + public Node() { + this.startingWordCount = 0; + this.endingWordCount = 0; + this.children = new HashMap<>(); + } + } +} + +/** + * Your Trie object will be instantiated and called as such: + * Trie obj = new Trie(); + * obj.insert(word); + * int param_2 = obj.countWordsEqualTo(word); + * int param_3 = obj.countWordsStartingWith(prefix); + * obj.erase(word); + */ diff --git a/Medium/Increasing Triplet Subsequence.java b/Medium/Increasing Triplet Subsequence.java new file mode 100644 index 00000000..9facec89 --- /dev/null +++ b/Medium/Increasing Triplet Subsequence.java @@ -0,0 +1,16 @@ +class Solution { + public boolean increasingTriplet(int[] nums) { + int firstNum = Integer.MAX_VALUE; + int secondNum = Integer.MAX_VALUE; + for (int num : nums) { + if (num <= firstNum) { + firstNum = num; + } else if (num <= secondNum) { + secondNum = num; + } else { + return true; + } + } + return false; + } +} diff --git a/Medium/Incremental Memory Leak.java b/Medium/Incremental Memory Leak.java new file mode 100644 index 00000000..7db5de79 --- /dev/null +++ b/Medium/Incremental Memory Leak.java @@ -0,0 +1,13 @@ +class Solution { + public int[] memLeak(int memory1, int memory2) { + int currentLeak = 1; + while (Math.max(memory1, memory2) >= currentLeak) { + if (memory1 >= memory2) { + memory1 -= currentLeak++; + } else { + memory2 -= currentLeak++; + } + } + return new int[]{currentLeak, memory1, memory2}; + } +} diff --git a/Medium/Inorder Successor in BST II.java b/Medium/Inorder Successor in BST II.java index c78e42b7..e8c672df 100644 --- a/Medium/Inorder Successor in BST II.java +++ b/Medium/Inorder Successor in BST II.java @@ -7,34 +7,23 @@ class Node { public Node parent; }; */ + class Solution { - public Node inorderSuccessor(Node x) { - - // If right node exists => Find lowest value in right node. - if (x.right != null) { - Node node = x.right; - - while (node.left != null) { - node = node.left; - } - - return node; - } - - // Find the first left which a node took to reach the node x - Node parent = x.parent; - Node lastNode = x; - Node lastLeft = null; - - while (parent != null) { - if (parent.left == lastNode && lastLeft == null) { - lastLeft = parent; - } - - lastNode = parent; - parent = parent.parent; - } - - return lastLeft; + public Node inorderSuccessor(Node node) { + if (node.right != null) { + Node rightNode = node.right; + while (rightNode.left != null) { + rightNode = rightNode.left; + } + return rightNode; } + while (node.parent != null) { + Node parent = node.parent; + if (parent.left == node) { + return parent; + } + node = parent; + } + return null; + } } diff --git a/Medium/Inorder Successor in BST.java b/Medium/Inorder Successor in BST.java index a69355e3..f7fb5702 100644 --- a/Medium/Inorder Successor in BST.java +++ b/Medium/Inorder Successor in BST.java @@ -8,35 +8,23 @@ * } */ class Solution { - public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { - if (p.right != null) { - TreeNode node = p.right; - while (node.left != null) { - node = node.left; - } - - return node; - } - - return getLastLeft(root, p); + public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { + if (p.right != null) { + TreeNode rightNode = p.right; + while (rightNode != null && rightNode.left != null) { + rightNode = rightNode.left; + } + return rightNode; } - - private TreeNode getLastLeft(TreeNode root, TreeNode p) { - TreeNode lastLeft = null; - - while (root != null) { - if (root == p) { - break; - } - else if (root.val < p.val) { - root = root.right; - } - else { - lastLeft = root; - root = root.left; - } - } - - return lastLeft; + TreeNode prev = null; + while (root != p) { + if (root.val > p.val) { + prev = root; + root = root.left; + } else { + root = root.right; + } } + return prev; + } } diff --git a/Medium/Insert Delete GetRandom O(1).java b/Medium/Insert Delete GetRandom O(1).java index ec85d2a9..9ef0fc92 100644 --- a/Medium/Insert Delete GetRandom O(1).java +++ b/Medium/Insert Delete GetRandom O(1).java @@ -1,54 +1,40 @@ class RandomizedSet { - /** Initialize your data structure here. */ - Map map; - List list; - int lastIndex; + private final List values; + private final Map valToIndexMap; + public RandomizedSet() { - map = new HashMap<>(); - list = new ArrayList<>(); - lastIndex = 0; + this.values = new ArrayList<>(); + this.valToIndexMap = new HashMap<>(); } - /** 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)) { + if (valToIndexMap.containsKey(val)) { return false; } - - list.add(val); - map.put(val, lastIndex); - lastIndex++; - + values.add(val); + valToIndexMap.put(val, values.size() - 1); 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)) { + if (!valToIndexMap.containsKey(val)) { return false; } - - map.put(list.get(lastIndex-1), map.get(val)); - swap(map.get(val), lastIndex-1); - list.remove(lastIndex-1); - map.remove(val); - lastIndex--; - + int valIdx = valToIndexMap.get(val); + int valAtLastIdx = values.get(values.size() - 1); + // update index for last element + values.set(valIdx, valAtLastIdx); + valToIndexMap.put(valAtLastIdx, valIdx); + // remove value + values.remove(values.size() - 1); + valToIndexMap.remove(val); return true; } - private void swap(int id1, int id2) { - int temp = list.get(id1); - list.set(id1, list.get(id2)); - list.set(id2, temp); - } - - /** Get a random element from the set. */ public int getRandom() { - Random rand = new Random(); - int idx = rand.nextInt(((lastIndex-1) - 0) + 1) + 0; - return list.get(idx); + int idx = new Random().nextInt(values.size()); + return values.get(idx); } } diff --git a/Medium/Insert Greatest Common Divisors in Linked List.java b/Medium/Insert Greatest Common Divisors in Linked List.java new file mode 100644 index 00000000..6dcf5fd0 --- /dev/null +++ b/Medium/Insert Greatest Common Divisors in Linked List.java @@ -0,0 +1,29 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode insertGreatestCommonDivisors(ListNode head) { + ListNode curr = head; + while (curr != null && curr.next != null) { + ListNode gcdNode = new ListNode(findGcd(curr.val, curr.next.val)); + gcdNode.next = curr.next; + curr.next = gcdNode; + curr = gcdNode.next; + } + return head; + } + + private static int findGcd(int numOne, int numTwo) { + if (numOne == numTwo) { + return numOne; + } + return numOne > numTwo ? findGcd(numOne - numTwo, numTwo) : findGcd(numOne, numTwo - numOne); + } +} diff --git a/Medium/Insert Interval.java b/Medium/Insert Interval.java new file mode 100644 index 00000000..a90a6884 --- /dev/null +++ b/Medium/Insert Interval.java @@ -0,0 +1,19 @@ +class Solution { + public int[][] insert(int[][] intervals, int[] newInterval) { + List result = new ArrayList<>(); + int idx = 0; + while (idx < intervals.length && intervals[idx][1] < newInterval[0]) { + result.add(intervals[idx++]); + } + while (idx < intervals.length && newInterval[1] >= intervals[idx][0]) { + newInterval[0] = Math.min(newInterval[0], intervals[idx][0]); + newInterval[1] = Math.max(newInterval[1], intervals[idx][1]); + idx++; + } + result.add(newInterval); + while (idx < intervals.length) { + result.add(intervals[idx++]); + } + return result.toArray(new int[result.size()][]); + } +} diff --git a/Medium/Insert into a Binary Search Tree.java b/Medium/Insert into a Binary Search Tree.java index 22046ec5..c7d1015b 100644 --- a/Medium/Insert into a Binary Search Tree.java +++ b/Medium/Insert into a Binary Search Tree.java @@ -4,24 +4,35 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public TreeNode insertIntoBST(TreeNode root, int val) { - if (root == null) { - root = new TreeNode(val); - return root; + public TreeNode insertIntoBST(TreeNode root, int val) { + TreeNode node = root; + while (node != null) { + if (val > node.val) { + if (node.right == null) { + node.right = new TreeNode(val); + return root; + } else { + node = node.right; } - - if (root.val < val) { - root.right = insertIntoBST(root.right, val); + } else { + if (node.left == null) { + node.left = new TreeNode(val); + return root; + } else { + node = node.left; } - - if (root.val > val) { - root.left = insertIntoBST(root.left, val); - } - - return root; + } } + return new TreeNode(val); + } } diff --git a/Medium/Insert into a Sorted Circular Linked List.java b/Medium/Insert into a Sorted Circular Linked List.java new file mode 100644 index 00000000..f8982d5e --- /dev/null +++ b/Medium/Insert into a Sorted Circular Linked List.java @@ -0,0 +1,49 @@ +/* +// Definition for a Node. +class Node { + public int val; + public Node next; + + public Node() {} + + public Node(int _val) { + val = _val; + } + + public Node(int _val, Node _next) { + val = _val; + next = _next; + } +}; +*/ + +class Solution { + public Node insert(Node head, int insertVal) { + if (head == null) { + Node newNode = new Node(insertVal); + newNode.next = newNode; + return newNode; + } + Node prev = head; + Node curr = head.next; + boolean insert = false; + do { + if (prev.val <= insertVal && insertVal <= curr.val) { + insert = true; + } + else if (prev.val > curr.val) { + if (insertVal >= prev.val || insertVal <= curr.val) { + insert = true; + } + } + if (insert) { + prev.next = new Node(insertVal, curr); + return head; + } + prev = curr; + curr = curr.next; + } while (prev != head); + prev.next = new Node(insertVal, curr); + return head; + } +} diff --git a/Medium/Insertion Sort List.java b/Medium/Insertion Sort List.java index b3817b60..798e311b 100644 --- a/Medium/Insertion Sort List.java +++ b/Medium/Insertion Sort List.java @@ -3,27 +3,27 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode insertionSortList(ListNode head) { - ListNode temp = head; - while (temp != null) { - ListNode curr =temp; - int v = curr.val; - ListNode t = temp; - while (curr != null) { - if (curr.val < v) { - v = curr.val; - t = curr; - } - curr = curr.next; - } - t.val = temp.val; - temp.val = v; - temp = temp.next; - } - return head; + public ListNode insertionSortList(ListNode head) { + ListNode dummy = new ListNode(0); + ListNode curr = head; + ListNode prev = dummy; + ListNode next = null; + while (curr != null) { + next = curr.next; + while (prev.next != null && prev.next.val < curr.val) { + prev = prev.next; + } + curr.next = prev.next; + prev.next = curr; + prev = dummy; + curr = next; } + return dummy.next; + } } diff --git a/Medium/Insufficient Nodes in Root to Leaf Paths.java b/Medium/Insufficient Nodes in Root to Leaf Paths.java new file mode 100644 index 00000000..7f1c80ce --- /dev/null +++ b/Medium/Insufficient Nodes in Root to Leaf Paths.java @@ -0,0 +1,22 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public TreeNode sufficientSubset(TreeNode root, int limit) { + if (root == null) { + return null; + } + if (root.left == null && root.right == null) { + return root.val < limit ? null : root; + } + root.left = sufficientSubset(root.left, limit - root.val); + root.right = sufficientSubset(root.right, limit - root.val); + return root.left == root.right ? null : root; + } +} diff --git a/Medium/Integer Break.java b/Medium/Integer Break.java new file mode 100644 index 00000000..10071c6f --- /dev/null +++ b/Medium/Integer Break.java @@ -0,0 +1,19 @@ +class Solution { + public int integerBreak(int n) { + if (n < 4) { + return n - 1; + } + int[] dp = new int[n + 1]; + for (int i = 1; i <= 3; i++) { + dp[i] = i; + } + for (int i = 4; i <= n; i++) { + int result = i; + for (int j = 2; j < i; j++) { + result = Math.max(result, j * dp[i - j]); + } + dp[i] = result; + } + return dp[n]; + } +} diff --git a/Medium/Integer To Roman.java b/Medium/Integer To Roman.java index 327be29a..33de2ba3 100644 --- a/Medium/Integer To Roman.java +++ b/Medium/Integer To Roman.java @@ -1,17 +1,20 @@ class Solution { - public String intToRoman(int num) { - int[] values = {1000,900,500,400,100,90,50,40,10,9,5,4,1}; - String[] strs = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < values.length; i++) { - while (num >= values[i]) { - num -= values[i]; - sb.append(strs[i]); - } + + private static final int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + private static final String[] symbols = { + "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + + public String intToRoman(int num) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < values.length && num > 0; i++) { + int factor = num / values[i]; + num %= values[i]; + if (factor > 0) { + for (int j = 1; j <= factor; j++) { + sb.append(symbols[i]); } - - return sb.toString(); + } } + return sb.toString(); + } } diff --git a/Medium/Interleaving String.java b/Medium/Interleaving String.java new file mode 100644 index 00000000..6e4408ce --- /dev/null +++ b/Medium/Interleaving String.java @@ -0,0 +1,24 @@ +class Solution { + public boolean isInterleave(String s1, String s2, String s3) { + if (s1.length() + s2.length() != s3.length()) { + return false; + } + Boolean[][] dp = new Boolean[s1.length()][s2.length()]; + return isInterleaveHelper(s1, 0, s2, 0, s3, 0, dp); + } + + private boolean isInterleaveHelper(String s1, int i1, String s2, int i2, String s3, int i3, Boolean[][] dp) { + if (i1 == s1.length()) { + return s2.substring(i2).equals(s3.substring(i3)); + } + if (i2 == s2.length()) { + return s1.substring(i1).equals(s3.substring(i3)); + } + if (dp[i1][i2] != null) { + return dp[i1][i2]; + } + dp[i1][i2] = (s3.charAt(i3) == s1.charAt(i1) && isInterleaveHelper(s1, i1 + 1, s2, i2, s3, i3 + 1, dp)) || + (s3.charAt(i3) == s2.charAt(i2) && isInterleaveHelper(s1, i1, s2, i2 + 1, s3, i3 + 1, dp)); + return dp[i1][i2]; + } +} diff --git a/Medium/Interval List Intersections.java b/Medium/Interval List Intersections.java index b65b26e8..6441b8ec 100644 --- a/Medium/Interval List Intersections.java +++ b/Medium/Interval List Intersections.java @@ -1,39 +1,21 @@ class Solution { - public int[][] intervalIntersection(int[][] A, int[][] B) { - List intersections = new ArrayList<>(); - int idx1 = 0; - int idx2 = 0; - - while (idx1 < A.length && idx2 < B.length) { - if (A[idx1][0] > B[idx2][1]) { - idx2++; - continue; - } - - if (A[idx1][1] < B[idx2][0]) { - idx1++; - continue; - } - - int maxStart = Math.max(A[idx1][0], B[idx2][0]); - int minEnd = Math.min(A[idx1][1], B[idx2][1]); - - int[] interval = {maxStart, minEnd}; - intersections.add(interval); - - if (A[idx1][1] > B[idx2][1]) { - idx2++; - } - else { - idx1++; - } - } - - int[][] ans = new int[intersections.size()][2]; - for (int i = 0; i < intersections.size(); i++) { - ans[i] = intersections.get(i); - } - - return ans; + public int[][] intervalIntersection(int[][] firstList, int[][] secondList) { + List list = new ArrayList<>(); + int idxOne = 0; + int idxTwo = 0; + while (idxOne < firstList.length && idxTwo < secondList.length) { + int maxStart = Math.max(firstList[idxOne][0], secondList[idxTwo][0]); + int minEnd = Math.min(firstList[idxOne][1], secondList[idxTwo][1]); + if (maxStart <= minEnd) { + list.add(new int[]{maxStart, minEnd}); + } + if (minEnd == firstList[idxOne][1]) { + idxOne++; + } else { + idxTwo++; + } } + int[][] result = new int[list.size()][2]; + return list.toArray(result); + } } diff --git a/Medium/Invalid Transactions.java b/Medium/Invalid Transactions.java new file mode 100644 index 00000000..aa48c7db --- /dev/null +++ b/Medium/Invalid Transactions.java @@ -0,0 +1,38 @@ +class Solution { + public List invalidTransactions(String[] transactions) { + Set invalidTransactionSet = new HashSet<>(); + Map> map = new HashMap<>(); + Map transactionOccurenceCount = new HashMap<>(); + for (String transactionString : transactions) { + transactionOccurenceCount.put(transactionString, transactionOccurenceCount.getOrDefault(transactionString, 0) + 1); + String[] transaction = transactionString.split(","); + String name = transaction[0]; + int amount = Integer.parseInt(transaction[2]); + String city = transaction[3]; + int time = Integer.parseInt(transaction[1]); + if (amount > 1000) { + invalidTransactionSet.add(transactionString); + } + map.computeIfAbsent(name, k -> new ArrayList<>()); + List currentTransactions = map.get(name); + for (String currentTransaction : currentTransactions) { + String currentCity = currentTransaction.split(",")[3]; + int currentTime = Integer.parseInt(currentTransaction.split(",")[1]); + if (!currentCity.equals(city) && Math.abs(time - currentTime) <= 60) { + invalidTransactionSet.add(currentTransaction); + invalidTransactionSet.add(transactionString); + } + } + currentTransactions.add(transactionString); + map.put(name, currentTransactions); + } + List result = new ArrayList<>(); + for (String trs : invalidTransactionSet) { + int count = transactionOccurenceCount.get(trs); + while (count-- > 0) { + result.add(trs); + } + } + return result; + } +} diff --git a/Medium/Is Graph Bipartite.java b/Medium/Is Graph Bipartite.java new file mode 100644 index 00000000..3a30604f --- /dev/null +++ b/Medium/Is Graph Bipartite.java @@ -0,0 +1,38 @@ +class Solution { + public boolean isBipartite(int[][] graph) { + int n = graph.length; + int[] color = new int[n]; + for (int i = 0; i < n; i++) { + if (color[i] == 0 && !isBipartite(graph, i, color)) { + return false; + } + } + return true; + } + + private boolean isBipartite(int[][] graph, int node, int[] color) { + Queue queue = new LinkedList<>(); + queue.add(node); + int currColor = 1; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int removed = queue.remove(); + if (color[removed] != 0) { + if (color[removed] != currColor) { + return false; + } + } else { + color[removed] = currColor; + for (int conn : graph[removed]) { + if (color[conn] == 0) { + queue.add(conn); + } + } + } + } + currColor = currColor == 1 ? 2 : 1; + } + return true; + } +} diff --git a/Medium/Is Subsequence.java b/Medium/Is Subsequence.java deleted file mode 100644 index cde06c72..00000000 --- a/Medium/Is Subsequence.java +++ /dev/null @@ -1,21 +0,0 @@ -class Solution { - public boolean isSubsequence(String s, String t) { - char[] sChar = s.toCharArray(); - char[] tChar = t.toCharArray(); - - int i=0; - int j=0; - int low = s.length(); - int high = t.length(); - - while(i list; + Iterator iter; + public CombinationIterator(String characters, int combinationLength) { + list = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + helper(characters, sb, 0, combinationLength); + iter = list.iterator(); + } + + private void helper(String characters, StringBuilder sb, int idx, int combinationLength) { + if (sb.length() == combinationLength) { + list.add(new String(sb.toString())); + } + else if (idx == characters.length() || sb.length() > combinationLength) { + return; + } + else { + for (int i = idx; i < characters.length(); i++) { + sb.append(characters.charAt(i)); + helper(characters, sb, i + 1, combinationLength); + sb.deleteCharAt(sb.length() - 1); + } + } + } + + public String next() { + return iter.next(); + } + + public boolean hasNext() { + return iter.hasNext(); + } +} + +/** + * Your CombinationIterator object will be instantiated and called as such: + * CombinationIterator obj = new CombinationIterator(characters, combinationLength); + * String param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); + */ diff --git a/Medium/Jump Game II.java b/Medium/Jump Game II.java new file mode 100644 index 00000000..0f3a792c --- /dev/null +++ b/Medium/Jump Game II.java @@ -0,0 +1,17 @@ +class Solution { + public int jump(int[] nums) { + int jumpCount = 0; + int left = 0; + int right = 0; + while (right < nums.length - 1) { + int farthest = 0; + for (int i = left; i <= right; i++) { + farthest = Math.max(farthest, i + nums[i]); + } + left = right + 1; + right = farthest; + jumpCount++; + } + return jumpCount; + } +} diff --git a/Medium/Jump Game III.java b/Medium/Jump Game III.java new file mode 100644 index 00000000..1862ad7c --- /dev/null +++ b/Medium/Jump Game III.java @@ -0,0 +1,27 @@ +class Solution { + public boolean canReach(int[] arr, int start) { + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); + queue.add(start); + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + int removed = queue.remove(); + if (arr[removed] == 0) { + return true; + } + if (visited.contains(removed)) { + continue; + } + visited.add(removed); + if (removed + arr[removed] < arr.length) { + queue.add(removed + arr[removed]); + } + if (removed - arr[removed] >= 0) { + queue.add(removed - arr[removed]); + } + } + } + return false; + } +} diff --git a/Medium/Jump Game VI.java b/Medium/Jump Game VI.java new file mode 100644 index 00000000..76ae982c --- /dev/null +++ b/Medium/Jump Game VI.java @@ -0,0 +1,16 @@ +class Solution { + public int maxResult(int[] nums, int k) { + int[] score = new int[nums.length]; + score[0] = nums[0]; + PriorityQueue queue = new PriorityQueue<>((a, b) -> b[0] - a[0]); + queue.add(new int[]{nums[0], 0}); + for (int i = 1; i < nums.length; i++) { + while (!queue.isEmpty() && queue.peek()[1] < i - k) { + queue.remove(); + } + score[i] = score[queue.peek()[1]] + nums[i]; + queue.add(new int[]{score[i], i}); + } + return score[nums.length - 1]; + } +} diff --git a/Medium/K Closest Points to Origin.java b/Medium/K Closest Points to Origin.java new file mode 100644 index 00000000..4f92b4a6 --- /dev/null +++ b/Medium/K Closest Points to Origin.java @@ -0,0 +1,20 @@ +class Solution { + public int[][] kClosest(int[][] points, int k) { + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> getDistance(o2) - getDistance(o1)); + for (int[] point : points) { + pq.add(point); + if (pq.size() > k) { + pq.poll(); + } + } + int[][] result = new int[pq.size()][2]; + for (int i = 0; i < result.length; i++) { + result[i] = pq.poll(); + } + return result; + } + + private int getDistance(int[] point) { + return (point[0] * point[0]) + (point[1] * point[1]); + } +} diff --git a/Medium/K Radius Subarray Averages.java b/Medium/K Radius Subarray Averages.java new file mode 100644 index 00000000..18cd8995 --- /dev/null +++ b/Medium/K Radius Subarray Averages.java @@ -0,0 +1,24 @@ +class Solution { + public int[] getAverages(int[] nums, int k) { + int[] result = new int[nums.length]; + Arrays.fill(result, -1); + int subarrayLength = 2 * k + 1; + if (subarrayLength > nums.length) { + return result; + } + long sum = 0; + for (int i = 0; i < subarrayLength; i++) { + sum += nums[i]; + } + int startIdx = 0; + int endIdx = subarrayLength; + for (int i = k; i < nums.length - k; i++) { + result[i] = (int) (sum / subarrayLength); + sum -= nums[startIdx++]; + if (endIdx < nums.length) { + sum += nums[endIdx++]; + } + } + return result; + } +} diff --git a/Medium/K-th Symbol in Grammar.java b/Medium/K-th Symbol in Grammar.java new file mode 100644 index 00000000..da370f11 --- /dev/null +++ b/Medium/K-th Symbol in Grammar.java @@ -0,0 +1,18 @@ +class Solution { + public int kthGrammar(int n, int k) { + return depthFirstSearch(n, k, 0); + } + + private int depthFirstSearch(int n, int k, int root) { + if (n == 1) { + return root; + } + int nodeCount = (int) Math.pow(2, n - 1); + if (k > (nodeCount / 2)) { + int nextRoot = (root == 0) ? 1 : 0; + return depthFirstSearch(n - 1, k - (nodeCount / 2), nextRoot); + } + int nextRoot = (root == 0) ? 0 : 1; + return depthFirstSearch(n - 1, k, nextRoot); + } +} diff --git a/Medium/Keys and Rooms.java b/Medium/Keys and Rooms.java index a62750df..a4fd783a 100644 --- a/Medium/Keys and Rooms.java +++ b/Medium/Keys and Rooms.java @@ -1,26 +1,18 @@ class Solution { - int[] keys; public boolean canVisitAllRooms(List> rooms) { - keys = new int[rooms.size()]; - keys[0] = 1; - - dfs(rooms, 0); - - for (int key : keys) { - if (key == 0) { - return false; - } - } - - return true; - } - - private void dfs(List> rooms, int k) { - for (int key : rooms.get(k)) { - if (keys[key] == 0) { - keys[key]++; - dfs(rooms, key); + Set visited = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add(0); + visited.add(0); + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer nextRoom : rooms.get(removed)) { + if (!visited.contains(nextRoom)) { + queue.add(nextRoom); + visited.add(nextRoom); + } } } + return visited.size() == rooms.size(); } } diff --git a/Medium/Kill Process.java b/Medium/Kill Process.java index 8279a01c..e0f5cbf7 100644 --- a/Medium/Kill Process.java +++ b/Medium/Kill Process.java @@ -1,27 +1,21 @@ class Solution { - public List killProcess(List pid, List ppid, int kill) { - - // Parent -> Children Map - Map> map = new HashMap<>(); - for (int i=0; i new ArrayList<>()).add(pid.get(i)); - } - - - List processesKilled = new ArrayList<>(); - Queue queue = new LinkedList<>(); - queue.add(kill); - - while (!queue.isEmpty()) { - int process = queue.remove(); - processesKilled.add(process); - List childrens = map.getOrDefault(process, new ArrayList<>()); - - for (Integer child : childrens) { - queue.add(child); - } + public List killProcess(List pid, List ppid, int kill) { + Map> map = new HashMap<>(); + for (int i = 0; i < pid.size(); i++) { + map.computeIfAbsent(ppid.get(i), k -> new HashSet<>()).add(pid.get(i)); + } + Stack stack = new Stack<>(); + stack.push(kill); + Set tasksKilled = new HashSet<>(); + while (!stack.isEmpty()) { + int removedTask = stack.pop(); + tasksKilled.add(removedTask); + for (Integer childTask : map.getOrDefault(removedTask, new HashSet<>())) { + if (!tasksKilled.contains(childTask)) { + stack.push(childTask); } - - return processesKilled; + } } + return new ArrayList<>(tasksKilled); + } } diff --git a/Medium/Knight Dialer.java b/Medium/Knight Dialer.java new file mode 100644 index 00000000..bebd4576 --- /dev/null +++ b/Medium/Knight Dialer.java @@ -0,0 +1,41 @@ +class Solution { + public static final int max = (int) Math.pow(10, 9) + 7; + + public int knightDialer(int n) { + // A 3D array to store the solutions to the subproblems + long M[][][] = new long[n + 1][4][3]; + long s = 0; + //do n hops from every i, j index (the very requirement of the problem) + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 3; j++) { + s = (s + paths(M, i, j, n)) % max; + } + } + return (int) s; + } + + private long paths(long[][][] M, int i, int j, int n) { + // if the knight hops outside of the matrix or to * return 0 + //as there are no unique paths from here + if(i < 0 || j < 0 || i >= 4 || j >= 3 || (i == 3 && j != 1)) { + return 0; + } + if(n == 1) { + return 1; + } + //if the subproblem's solution is already computed, then return it + if(M[n][i][j] > 0) { + return M[n][i][j]; + } + //else compute the subproblem's solution and save it in memory + M[n][i][j] = paths(M, i - 1, j - 2, n - 1) % max + // jump to a + paths(M, i - 2, j - 1, n - 1) % max + // jump to b + paths(M, i - 2, j + 1, n - 1) % max + // jump to c + paths(M, i - 1, j + 2, n - 1) % max + // jump to d + paths(M, i + 1, j + 2, n - 1) % max + // jump to e + paths(M, i + 2, j + 1, n - 1) % max + // jump to f + paths(M, i + 2, j - 1, n - 1) % max + // jump to g + paths(M, i + 1, j - 2, n - 1) % max; // jump to h + return M[n][i][j]; + } +} diff --git a/Medium/Knight Probability in Chessboard.java b/Medium/Knight Probability in Chessboard.java new file mode 100644 index 00000000..b879c626 --- /dev/null +++ b/Medium/Knight Probability in Chessboard.java @@ -0,0 +1,30 @@ +class Solution { + public double knightProbability(int N, int K, int r, int c) { + double[][] dp = new double[N][N]; + int[] rowMoves = new int[]{2, 2, 1, 1, -1, -1, -2, -2}; + int[] colMoves = new int[]{1, -1, 2, -2, 2, -2, 1, -1}; + dp[r][c] = 1; + while (K-- > 0) { + double[][] copy = new double[N][N]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + for (int k = 0; k < 8; k++) { + int destR = i + rowMoves[k]; + int destC = j + colMoves[k]; + if (destR >= 0 && destR < N && destC >= 0 && destC < N) { + copy[destR][destC] += dp[i][j] / 8.0; + } + } + } + } + dp = copy; + } + double ans = 0.0; + for (double[] row : dp) { + for (double val : row) { + ans += val; + } + } + return ans; + } +} diff --git a/Medium/Koko Eating Bananas.java b/Medium/Koko Eating Bananas.java new file mode 100644 index 00000000..821a21ca --- /dev/null +++ b/Medium/Koko Eating Bananas.java @@ -0,0 +1,26 @@ +class Solution { + public int minEatingSpeed(int[] piles, int h) { + int start = 1; + int end = 0; + for (int pile : piles) { + end = Math.max(end, pile); + } + while (start <= end) { + int mid = start + (end - start) / 2; + if (isPossible(piles, mid, h)) { + end = mid - 1; + } else { + start = mid + 1; + } + } + return start; + } + + private boolean isPossible(int[] piles, int k, int h) { + int numOfHours = 0; + for (int pile : piles) { + numOfHours += Math.ceil((double) pile / k); + } + return numOfHours <= h; + } +} diff --git a/Medium/Kth Largest Element in an Array.java b/Medium/Kth Largest Element in an Array.java index 8c2a6d59..c45d1f68 100644 --- a/Medium/Kth Largest Element in an Array.java +++ b/Medium/Kth Largest Element in an Array.java @@ -1,18 +1,16 @@ class Solution { - public static int findKthLargest(int[] nums, int k) { - PriorityQueue queue = new PriorityQueue<>(k); - for (int i=0; i queue.peek()) { - queue.remove(); - queue.add(nums[i]); - } - } - } - - return queue.remove(); + public int findKthLargest(int[] nums, int k) { + int[] counter = new int[20001]; + for (int num : nums) { + counter[num + 10000]++; } + for (int i = counter.length - 1; i >= 0; i--) { + if (counter[i] < k) { + k -= counter[i]; + } else { + return i - 10000; + } + } + return -1; + } } diff --git a/Medium/Kth Largest Sum in a Binary Tree.java b/Medium/Kth Largest Sum in a Binary Tree.java new file mode 100644 index 00000000..01955179 --- /dev/null +++ b/Medium/Kth Largest Sum in a Binary Tree.java @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public long kthLargestLevelSum(TreeNode root, int k) { + PriorityQueue pq = new PriorityQueue<>(); + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + long sum = 0l; + while (size-- > 0) { + TreeNode removed = queue.remove(); + sum += removed.val; + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + pq.add(sum); + if (pq.size() > k) { + pq.poll(); + } + } + return pq.size() < k ? -1 : pq.poll(); + } +} diff --git a/Medium/Kth Smallest Element in a BST.java b/Medium/Kth Smallest Element in a BST.java index afb379f1..6f77e133 100644 --- a/Medium/Kth Smallest Element in a BST.java +++ b/Medium/Kth Smallest Element in a BST.java @@ -4,29 +4,32 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public int kthSmallest(TreeNode root, int k) { - Stack stack = new Stack<>(); - - while (root != null || !stack.empty()) { - while (root != null) { - stack.push(root); - root = root.left; - } - - root = stack.peek(); - stack.pop(); - - if (--k == 0) { - return root.val; - } - - root = root.right; - } - - return -1; + public int kthSmallest(TreeNode root, int k) { + Integer result = null; + Stack stack = new Stack<>(); + while (root != null) { + stack.push(root); + root = root.left; } + while (k > 1 && !stack.isEmpty()) { + TreeNode removed = stack.pop(); + TreeNode rightNode = removed.right; + while (rightNode != null) { + stack.push(rightNode); + rightNode = rightNode.left; + } + k--; + } + return stack.peek().val; + } } diff --git a/Medium/Kth Smallest Element in a Sorted Matrix.java b/Medium/Kth Smallest Element in a Sorted Matrix.java index 37f81aec..37054ddf 100644 --- a/Medium/Kth Smallest Element in a Sorted Matrix.java +++ b/Medium/Kth Smallest Element in a Sorted Matrix.java @@ -1,37 +1,17 @@ class Solution { - public int kthSmallest(int[][] matrix, int k) { - PriorityQueue pq = new PriorityQueue<>(new Comparator() { - @Override - public int compare(Element o1, Element o2) { - return o1.val - o2.val; - } - }); - - for (int i=0; i pq = new PriorityQueue<>((o1, o2) -> o1[2] - o2[2]); + for (int j = 0; j < numOfRows; j++) { + pq.add(new int[]{0, j, matrix[0][j]}); } - - class Element { - int val; - int x; - int y; - - public Element(int val, int x, int y) { - this.val = val; - this.x = x; - this.y = y; - } + for (int i = 0; i < k - 1; i++) { + int[] removed = pq.poll(); + if (removed[0] == numOfRows - 1) { + continue; + } + pq.add(new int[]{removed[0] + 1, removed[1], matrix[removed[0] + 1][removed[1]]}); } + return pq.peek()[2]; + } } diff --git a/Medium/LRU Cache.java b/Medium/LRU Cache.java new file mode 100644 index 00000000..1e1b3ae6 --- /dev/null +++ b/Medium/LRU Cache.java @@ -0,0 +1,84 @@ +class LRUCache { + + private final Map map; + private final int capacity; + private final Node head; + private final Node tail; + + public LRUCache(int capacity) { + this.capacity = capacity; + this.map = new HashMap<>(); + this.head = new Node(-1, -1); + this.tail = new Node(-1, -1); + this.head.next = this.tail; + this.tail.prev = this.head; + } + + public int get(int key) { + if (!map.containsKey(key)) { + return -1; + } + Node node = map.get(key); + removeNode(node); + addToFront(node); + return node.value; + } + + public void put(int key, int value) { + if (map.containsKey(key)) { + updateExistingKey(key, value); + return; + } + if (map.size() == this.capacity) { + Node leastUsed = tail.prev; + removeNode(leastUsed); + map.remove(leastUsed.key); + } + Node newNode = new Node(key, value); + addToFront(newNode); + map.put(key, newNode); + } + + private void updateExistingKey(int key, int value) { + Node node = map.get(key); + Node updatedNode = new Node(key, value); + removeNode(node); + addToFront(updatedNode); + map.put(key, updatedNode); + } + + private void removeNode(Node node) { + Node prevToNode = node.prev; + Node nextToNode = node.next; + prevToNode.next = nextToNode; + nextToNode.prev = prevToNode; + } + + private void addToFront(Node node) { + Node nextToHead = head.next; + node.next = nextToHead; + nextToHead.prev = node; + node.prev = head; + head.next = node; + } + + private static class Node { + + private final int key; + private final int value; + private Node next; + private Node prev; + + public Node(int key, int value) { + this.key = key; + this.value = value; + } + } +} + +/** + * Your LRUCache object will be instantiated and called as such: + * LRUCache obj = new LRUCache(capacity); + * int param_1 = obj.get(key); + * obj.put(key,value); + */ diff --git a/Medium/Large Divisble Subset.java b/Medium/Large Divisble Subset.java new file mode 100644 index 00000000..a65f1d15 --- /dev/null +++ b/Medium/Large Divisble Subset.java @@ -0,0 +1,38 @@ +class Solution { + public List largestDivisibleSubset(int[] nums) { + int n = nums.length; + if (n == 0) { + return new ArrayList<>(); + } + Map> map = new HashMap<>(); + Arrays.sort(nums); + List maxSubset = new ArrayList<>(); + for (int i = 0; i < n; i++) { + List subset = helper(i, map, nums); + if (subset.size() > maxSubset.size()) { + maxSubset = subset; + } + } + return maxSubset; + } + + private List helper(int i, Map> map, int[] nums) { + if (map.containsKey(i)) { + return map.get(i); + } + List maxSubset = new ArrayList<>(); + for (int k = 0; k < i; k++) { + if (nums[i] % nums[k] == 0) { + List subset = helper(k, map, nums); + if (maxSubset.size() < subset.size()) { + maxSubset = subset; + } + } + } + List newEntry = new ArrayList<>(); + newEntry.addAll(maxSubset); + newEntry.add(nums[i]); + map.put(i, newEntry); + return newEntry; + } +} diff --git a/Medium/Largest BST Subtree.java b/Medium/Largest BST Subtree.java index 45c83c6f..18ddfeaf 100644 --- a/Medium/Largest BST Subtree.java +++ b/Medium/Largest BST Subtree.java @@ -4,43 +4,41 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public int largestBSTSubtree(TreeNode root) { - return largestBSTSubtreeHelper(root); - } - - private int largestBSTSubtreeHelper(TreeNode root) { - if (isBST(root)) { - return getNodeCount(root); - } - - return Math.max(-1, Math.max(largestBSTSubtreeHelper(root.left), largestBSTSubtreeHelper(root.right))); - } - - private boolean isBST(TreeNode root) { - return isBSTHelper(root, Integer.MAX_VALUE, Integer.MIN_VALUE); - } - - private boolean isBSTHelper(TreeNode root, int max, int min) { if (root == null) { - return true; + return 0; } - - if (root.val >= max || root.val <= min) { - return false; + int[] isBstResult = isBst(root, Integer.MIN_VALUE, Integer.MAX_VALUE); + if (isBstResult[0] == 1) { + return isBstResult[1]; } - - return isBSTHelper(root.left, root.val, min) && isBSTHelper(root.right, max, root.val); + return Math.max(largestBSTSubtree(root.left), largestBSTSubtree(root.right)); } - private int getNodeCount(TreeNode root) { + private int[] isBst(TreeNode root, int minValue, int maxValue) { if (root == null) { - return 0; + return new int[]{1, 0}; + } + int[] result = new int[2]; + if (!(root.val > minValue && root.val < maxValue)) { + return result; + } + int[] leftIsBst = isBst(root.left, minValue, root.val); + int[] rightIsBst = isBst(root.right, root.val, maxValue); + if (leftIsBst[0] == 1 && rightIsBst[0] == 1) { + result[0] = 1; + result[1] = 1 + leftIsBst[1] + rightIsBst[1]; } - - return 1 + getNodeCount(root.left) + getNodeCount(root.right); + return result; } } diff --git a/Medium/Largest Combination With Bitwise AND Greater Than Zero.java b/Medium/Largest Combination With Bitwise AND Greater Than Zero.java new file mode 100644 index 00000000..1399f1bb --- /dev/null +++ b/Medium/Largest Combination With Bitwise AND Greater Than Zero.java @@ -0,0 +1,17 @@ +class Solution { + public int largestCombination(int[] candidates) { + int[] bitCount = new int[24]; + for (int i = 0; i < 24; i++) { + for (int candidate : candidates) { + if ((candidate & (1 << i)) != 0) { + bitCount[i]++; + } + } + } + int result = 0; + for (int count : bitCount) { + result = Math.max(count, result); + } + return result; + } +} diff --git a/Medium/Largest Number.java b/Medium/Largest Number.java new file mode 100644 index 00000000..4fc51c79 --- /dev/null +++ b/Medium/Largest Number.java @@ -0,0 +1,10 @@ +class Solution { + public String largestNumber(int[] nums) { + String largestNum = Arrays.stream(nums) + .boxed() + .map(String::valueOf) + .sorted((o1, o2) -> (o2 + o1).compareTo(o1 + o2)) + .collect(Collectors.joining("")); + return largestNum.charAt(0) == '0' ? "0" : largestNum; + } +} diff --git a/Medium/Largest Time for Given Digits.java b/Medium/Largest Time for Given Digits.java new file mode 100644 index 00000000..ca920ebb --- /dev/null +++ b/Medium/Largest Time for Given Digits.java @@ -0,0 +1,33 @@ +class Solution { + public String largestTimeFromDigits(int[] arr) { + int[] maxTime = {-1}; + permute(arr, 0, maxTime); + return maxTime[0] == -1 ? "" : String.format("%02d:%02d", maxTime[0] / 60, maxTime[0] % 60); + } + + private void permute(int[] arr, int idx, int[] maxTime) { + if (idx == arr.length) { + buildTime(arr, maxTime); + return; + } + for (int i = idx; i < arr.length; i++) { + swap(arr, i, idx); + permute(arr, idx + 1, maxTime); + swap(arr, idx, i); + } + } + + private void buildTime(int[] arr, int[] maxTime) { + int hour = arr[0] * 10 + arr[1]; + int minutes = arr[2] * 10 + arr[3]; + if (hour < 24 && minutes < 60) { + maxTime[0] = Math.max(maxTime[0], hour * 60 + minutes); + } + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } +} diff --git a/Medium/Last Moment Before All Ants Fall Out of a Plank.java b/Medium/Last Moment Before All Ants Fall Out of a Plank.java new file mode 100644 index 00000000..e061b5d3 --- /dev/null +++ b/Medium/Last Moment Before All Ants Fall Out of a Plank.java @@ -0,0 +1,12 @@ +class Solution { + public int getLastMoment(int n, int[] left, int[] right) { + int result = 0; + for (int num : left) { + result = Math.max(result, num); + } + for (int num : right) { + result = Math.max(result, n - num); + } + return result; + } +} diff --git a/Medium/Last Stone Weight II.java b/Medium/Last Stone Weight II.java new file mode 100644 index 00000000..61c61dd6 --- /dev/null +++ b/Medium/Last Stone Weight II.java @@ -0,0 +1,15 @@ +class Solution { + public int lastStoneWeightII(int[] stones) { + int sum = 0; + for (int stone : stones) { + sum += stone; + } + int[] dp = new int[sum / 2 + 1]; + for (int i = 1; i <= stones.length; i++) { + for (int j = sum / 2; j >= stones[i - 1]; j--) { + dp[j] = Math.max(dp[j], dp[j - stones[i - 1]] + stones[i - 1]); + } + } + return sum - 2 * dp[sum / 2]; + } +} diff --git a/Medium/Least Number of Unique Integers after K Removals.java b/Medium/Least Number of Unique Integers after K Removals.java new file mode 100644 index 00000000..c6755d8e --- /dev/null +++ b/Medium/Least Number of Unique Integers after K Removals.java @@ -0,0 +1,19 @@ +class Solution { + public int findLeastNumOfUniqueInts(int[] arr, int k) { + Map map = new HashMap<>(); + for (int num : arr) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + PriorityQueue pq = new PriorityQueue<>((a, b) -> map.get(a).compareTo(map.get(b))); + pq.addAll(map.keySet()); + while (k > 0 && !pq.isEmpty()) { + int count = map.get(pq.peek()); + if (count > k) { + break; + } + k -= count; + pq.poll(); + } + return pq.size(); + } +} diff --git a/Medium/Leftmost Column with at Least a One.java b/Medium/Leftmost Column with at Least a One.java new file mode 100644 index 00000000..8b804b8f --- /dev/null +++ b/Medium/Leftmost Column with at Least a One.java @@ -0,0 +1,26 @@ +/** + * // This is the BinaryMatrix's API interface. + * // You should not implement it, or speculate about its implementation + * interface BinaryMatrix { + * public int get(int row, int col) {} + * public List dimensions {} + * }; + */ + +class Solution { + public int leftMostColumnWithOne(BinaryMatrix binaryMatrix) { + List dimension = binaryMatrix.dimensions(); + int numRows = dimension.get(0); + int numCols = dimension.get(1); + int currRow = 0; + int currCol = numCols - 1; + while (currRow < numRows && currCol >= 0) { + if (binaryMatrix.get(currRow, currCol) == 0) { + currRow++; + } else { + currCol--; + } + } + return currCol == numCols - 1 ? -1 : currCol + 1; + } +} diff --git a/Medium/Length of Longest Subarray With at Most K Frequency.java b/Medium/Length of Longest Subarray With at Most K Frequency.java new file mode 100644 index 00000000..82d8f62d --- /dev/null +++ b/Medium/Length of Longest Subarray With at Most K Frequency.java @@ -0,0 +1,19 @@ +class Solution { + public int maxSubarrayLength(int[] nums, int k) { + int start = 0; + int end = 0; + int result = 0; + int n = nums.length; + Map map = new HashMap<>(); + while (end < n) { + map.put(nums[end], map.getOrDefault(nums[end], 0) + 1); + while (start < end && map.get(nums[end]) > k) { + map.put(nums[start], map.get(nums[start]) - 1); + start++; + } + end++; + result = Math.max(result, end - start); + } + return result; + } +} diff --git a/Medium/Length of the Longest Alphabetical Continuous Substring.java b/Medium/Length of the Longest Alphabetical Continuous Substring.java new file mode 100644 index 00000000..30426403 --- /dev/null +++ b/Medium/Length of the Longest Alphabetical Continuous Substring.java @@ -0,0 +1,14 @@ +class Solution { + public int longestContinuousSubstring(String s) { + int idx = 0; + int maxLength = 0; + while (idx < s.length()) { + int currIdx = idx++; + while (idx < s.length() && s.charAt(idx) - s.charAt(idx - 1) == 1) { + idx++; + } + maxLength = Math.max(maxLength, idx - currIdx); + } + return maxLength; + } +} diff --git a/Medium/Letter Combinations of a Phone Number.java b/Medium/Letter Combinations of a Phone Number.java index f3dc991a..b145954b 100644 --- a/Medium/Letter Combinations of a Phone Number.java +++ b/Medium/Letter Combinations of a Phone Number.java @@ -1,46 +1,32 @@ class Solution { - public List combinations; - public Map map; - - public List letterCombinations(String number) { - if (number.length() == 0) { - return new ArrayList<>(); - } - - combinations = new ArrayList<>(); - map = new HashMap<>(); - char[] chars = {'1', '2', '3', '4', '5', '6', '7', '8', '9'}; - String[] values = {"*", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; - - for (int i=0; i DIGIT_TO_CHAR_MAPPING = Map.of( + '2', "abc", + '3', "def", + '4', "ghi", + '5', "jkl", + '6', "mno", + '7', "pqrs", + '8', "tuv", + '9', "wxyz" + ); + + public List letterCombinations(String digits) { + List result = new ArrayList<>(); + letterCombinations(digits, 0, new StringBuilder(), result); + return result; } - private void helper(String num, StringBuilder sb, int start) { - if (sb.length() == num.length()) { - combinations.add(new StringBuilder(sb.toString()).toString()); + private void letterCombinations(String digits, int idx, StringBuilder sb, List result) { + if (idx == digits.length()) { + if (!sb.isEmpty()) { + result.add(sb.toString()); + } return; } - - for (int i=start; i lexicalOrder(int n) { + List result = new ArrayList<>(); + int curr = 1; + for (int i = 0; i < n; i++) { + result.add(curr); + if (curr * 10 <= n) { + curr *= 10; + } else { + while (curr % 10 == 9 || curr == n) { + curr /= 10; + } + curr++; + } + } + return result; + } +} diff --git a/Medium/Lexicographically Minimum String After Removing Stars.java b/Medium/Lexicographically Minimum String After Removing Stars.java new file mode 100644 index 00000000..794ee712 --- /dev/null +++ b/Medium/Lexicographically Minimum String After Removing Stars.java @@ -0,0 +1,28 @@ +class Solution { + public String clearStars(String s) { + Deque[] count = new Deque[26]; + for (int i = 0; i < 26; i++) { + count[i] = new ArrayDeque<>(); + } + char[] letters = s.toCharArray(); + for (int i = 0; i < letters.length; i++) { + if (letters[i] != '*') { + count[letters[i] - 'a'].push(i); + } else { + for (int j = 0; j < 26; j++) { + if (!count[j].isEmpty()) { + letters[count[j].pop()] = '*'; + break; + } + } + } + } + StringBuilder sb = new StringBuilder(); + for (char c : letters) { + if (c != '*') { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/Medium/Lexicographically Smallest Equivalent String.java b/Medium/Lexicographically Smallest Equivalent String.java new file mode 100644 index 00000000..f4d01c21 --- /dev/null +++ b/Medium/Lexicographically Smallest Equivalent String.java @@ -0,0 +1,46 @@ +class Solution { + public String smallestEquivalentString(String s1, String s2, String baseStr) { + UnionFind unionFind = new UnionFind(26); + for (int i = 0; i < s1.length(); i++) { + char c1 = s1.charAt(i); + char c2 = s2.charAt(i); + unionFind.union(c1 - 'a', c2 - 'a'); + } + StringBuilder result = new StringBuilder(); + for (char c : baseStr.toCharArray()) { + result.append((char) (unionFind.find(c - 'a') + 'a')); + } + return result.toString(); + } + + class UnionFind { + private int[] parent; + + public UnionFind(int n) { + parent = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + } + } + + public int find(int node) { + if (parent[node] == node) { + return node; + } + parent[node] = find(parent[node]); + return parent[node]; + } + + public void union(int nodeOne, int nodeTwo) { + int parentOne = find(nodeOne); + int parentTwo = find(nodeTwo); + if (parentOne != parentTwo) { + if (parentOne < parentTwo) { + parent[parentTwo] = parentOne; + } else { + parent[parentOne] = parentTwo; + } + } + } + } +} diff --git a/Medium/Lexicographically Smallest String After Substring Operation.java b/Medium/Lexicographically Smallest String After Substring Operation.java new file mode 100644 index 00000000..e55990b7 --- /dev/null +++ b/Medium/Lexicographically Smallest String After Substring Operation.java @@ -0,0 +1,20 @@ +class Solution { + public String smallestString(String s) { + StringBuilder sb = new StringBuilder(); + int idx = 0; + while (idx < s.length() && s.charAt(idx) == 'a') { + sb.append(s.charAt(idx++)); + } + if (idx == s.length()) { + return s.substring(0, s.length() - 1) + 'z'; + } + while (idx < s.length() && s.charAt(idx) != 'a') { + sb.append(getPreviousChar(s.charAt(idx++))); + } + return sb.append(s.substring(idx)).toString(); + } + + private char getPreviousChar(char c) { + return (char) (c - 1); + } +} diff --git a/Medium/Linked List Components.java b/Medium/Linked List Components.java index 1d32410d..62322281 100644 --- a/Medium/Linked List Components.java +++ b/Medium/Linked List Components.java @@ -3,30 +3,26 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public int numComponents(ListNode head, int[] G) { - int count = 0; - Set set = new HashSet<>(); - for (int g : G) { - set.add(g); + public int numComponents(ListNode head, int[] G) { + int numOfComponents = 0; + Set set = Arrays.stream(G).boxed().collect(Collectors.toSet()); + while (head != null && !set.isEmpty()) { + if (set.contains(head.val)) { + while (head != null && !set.isEmpty() && set.contains(head.val)) { + set.remove(head.val); + head = head.next; } - - while (head != null) { - if (set.contains(head.val)) { - while (head != null && set.contains(head.val)) { - head = head.next; - } - - count++; - } - else { - head = head.next; - } - } - - return count; + numOfComponents++; + } else { + head = head.next; + } } + return numOfComponents; + } } diff --git a/Medium/Linked List Cycle II.java b/Medium/Linked List Cycle II.java index ed568031..2a88b1b4 100644 --- a/Medium/Linked List Cycle II.java +++ b/Medium/Linked List Cycle II.java @@ -13,20 +13,21 @@ public class Solution { public ListNode detectCycle(ListNode head) { ListNode slow = head; ListNode fast = head; - - while (fast!=null && fast.next!=null){ - fast = fast.next.next; + while (fast != null && fast.next != null) { slow = slow.next; - - if (fast == slow){ - ListNode slow2 = head; - while (slow2 != slow){ - slow = slow.next; - slow2 = slow2.next; - } - return slow; + fast = fast.next.next; + if (slow == fast) { + break; } } - return null; + if (fast == null || fast.next == null) { + return null; + } + ListNode curr = head; + while (curr != slow) { + curr = curr.next; + slow = slow.next; + } + return curr; } } diff --git a/Medium/Linked List Frequency.java b/Medium/Linked List Frequency.java new file mode 100644 index 00000000..1c5a1739 --- /dev/null +++ b/Medium/Linked List Frequency.java @@ -0,0 +1,25 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode frequenciesOfElements(ListNode head) { + Map map = new HashMap<>(); + for (ListNode curr = head; curr != null; curr = curr.next) { + map.put(curr.val, map.getOrDefault(curr.val, 0) + 1); + } + ListNode dummy = new ListNode(-1); + ListNode curr = dummy; + for (Integer key : map.keySet()) { + curr.next = new ListNode(map.get(key)); + curr = curr.next; + } + return dummy.next; + } +} diff --git a/Medium/Linked List Random Node.java b/Medium/Linked List Random Node.java index f29d4831..2e89913a 100644 --- a/Medium/Linked List Random Node.java +++ b/Medium/Linked List Random Node.java @@ -3,47 +3,34 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - /** @param head The linked list's head. - Note that the head is guaranteed to be not null, so it contains at least one node. */ - ListNode head; - int length; - public Solution(ListNode head) { - this.head = head; - length = findLength(head); - } - - private int findLength(ListNode head) { - int count = 0; - - while (head != null) { - count++; - head = head.next; - } - - return count; - } - - /** Returns a random node's value. */ - public int getRandom() { - int idx = new Random().nextInt(((length - 1) - 0) + 1); - return getKthNode(head, idx); - } - - private int getKthNode(ListNode head, int k) { - int count = 0; - - while (count < k) { - count++; - head = head.next; - } - - return head.val; + /** @param head The linked list's head. + Note that the head is guaranteed to be not null, so it contains at least one node. */ + ListNode head; + Random rand; + public Solution(ListNode head) { + this.head = head; + rand = new Random(); + } + + /** Returns a random node's value. */ + public int getRandom() { + ListNode curr = head; + int val = curr.val; + for (int i = 1; curr.next != null; i++) { + curr = curr.next; + if (rand.nextInt(i + 1) == i) { + val = curr.val; + } } + return val; + } } /** diff --git a/Medium/Linked List in Binary Tree.java b/Medium/Linked List in Binary Tree.java new file mode 100644 index 00000000..9ba90a87 --- /dev/null +++ b/Medium/Linked List in Binary Tree.java @@ -0,0 +1,46 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean isSubPath(ListNode head, TreeNode root) { + if (head == null) { + return true; + } + if (root == null) { + return false; + } + return dfs(head, root) || isSubPath(head, root.left) || isSubPath(head, root.right); + } + + private boolean dfs(ListNode head, TreeNode root) { + if (head == null) { + return true; + } + if (root == null) { + return false; + } + return head.val == root.val && (dfs(head.next, root.left) || dfs(head.next, root.right)); + } +} diff --git a/Medium/Lonely Pixel I.java b/Medium/Lonely Pixel I.java index ae676662..42ae180d 100644 --- a/Medium/Lonely Pixel I.java +++ b/Medium/Lonely Pixel I.java @@ -1,37 +1,25 @@ class Solution { - public int findLonelyPixel(char[][] picture) { - int count = 0; - Map rowMap = new HashMap<>(); - - for (int i=0; i rowMap = new HashMap<>(); + Map colMap = new HashMap<>(); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (picture[i][j] == 'B') { + rowMap.put(i, rowMap.getOrDefault(i, 0) + 1); + colMap.put(j, colMap.getOrDefault(j, 0) + 1); } - - Map colMap = new HashMap<>(); - for (int i=0; i map = new HashMap<>(); - - // Base entry for 0th level - map.put(0, 0); - - int idx = 0; - int n = input.length(); - while (idx < n) { - // Keep increasing the level until we find a tab - while (idx < n && input.charAt(idx) == '\t') { - idx++; - currLevel++; - } - - // Keep increasing currLen for the characters in the name - while (idx < n && input.charAt(idx) != '\n') { - if (input.charAt(idx) == '.') { - isFile = true; - } - - currLen++; - idx++; - } - - // If isFile then update maxLen else update the value of level in map - if (isFile) { - maxLen = Math.max(maxLen, map.get(currLevel - 1) + currLen); - } - else { - map.put(currLevel, map.get(currLevel - 1) + 1 + currLen); - } - - // Reset variables - currLen = 0; - currLevel = 1; - isFile = false; - idx++; + public int lengthLongestPath(String input) { + int maxLen = 0; + int currLevel = 1; + boolean isFile = false; + int currLen = 0; + Map map = new HashMap<>(); + map.put(0, 0); + int idx = 0; + int n = input.length(); + while (idx < n) { + while (idx < n && input.charAt(idx) == '\t') { + idx++; + currLevel++; + } + while (idx < n && input.charAt(idx) != '\n') { + if (input.charAt(idx) == '.') { + isFile = true; } - - return maxLen; + currLen++; + idx++; + } + if (isFile) { + maxLen = Math.max(maxLen, map.get(currLevel - 1) + currLen); + } + else { + map.put(currLevel, map.get(currLevel - 1) + 1 + currLen); + } + currLen = 0; + currLevel = 1; + isFile = false; + idx++; } + return maxLen; + } } diff --git a/Medium/Longest Arithmetic Sequence.java b/Medium/Longest Arithmetic Sequence.java new file mode 100644 index 00000000..190f3d92 --- /dev/null +++ b/Medium/Longest Arithmetic Sequence.java @@ -0,0 +1,16 @@ +class Solution { + public int longestArithSeqLength(int[] A) { + int res = 2; + int n = A.length; + HashMap[] dp = new HashMap[n]; + for (int j = 0; j < A.length; j++) { + dp[j] = new HashMap<>(); + for (int i = 0; i < j; i++) { + int d = A[j] - A[i]; + dp[j].put(d, dp[i].getOrDefault(d, 1) + 1); + res = Math.max(res, dp[j].get(d)); + } + } + return res; + } +} diff --git a/Medium/Longest Arithmetic Subsequence of Given Difference.java b/Medium/Longest Arithmetic Subsequence of Given Difference.java new file mode 100644 index 00000000..ef48493e --- /dev/null +++ b/Medium/Longest Arithmetic Subsequence of Given Difference.java @@ -0,0 +1,12 @@ +class Solution { + public int longestSubsequence(int[] arr, int difference) { + Map map = new HashMap<>(); + int maxValue = 0; + for (int num : arr) { + int endingSubLength = map.getOrDefault(num - difference, 0); + map.put(num, endingSubLength + 1); + maxValue = Math.max(maxValue, map.get(num)); + } + return maxValue; + } +} diff --git a/Medium/Longest Arithmetic Subsequence.java b/Medium/Longest Arithmetic Subsequence.java new file mode 100644 index 00000000..67a7fbb6 --- /dev/null +++ b/Medium/Longest Arithmetic Subsequence.java @@ -0,0 +1,15 @@ +class Solution { + public int longestArithSeqLength(int[] nums) { + int result = 0; + Map[] dp = new HashMap[nums.length]; + for (int i = 0; i < nums.length; i++) { + dp[i] = new HashMap<>(); + for (int j = 0; j < i; j++) { + int diff = nums[j] - nums[i]; + dp[i].put(diff, dp[j].getOrDefault(diff, 1) + 1); + result = Math.max(result, dp[i].get(diff)); + } + } + return result; + } +} diff --git a/Medium/Longest Common Subsequence Between Sorted Arrays.java b/Medium/Longest Common Subsequence Between Sorted Arrays.java new file mode 100644 index 00000000..d050d3fd --- /dev/null +++ b/Medium/Longest Common Subsequence Between Sorted Arrays.java @@ -0,0 +1,15 @@ +class Solution { + public List longestCommonSubsequence(int[][] arrays) { + List result = new ArrayList<>(); + Map map = new HashMap<>(); + for (int[] arr : arrays) { + for (int num : arr) { + map.put(num, map.getOrDefault(num, 0) + 1); + if (map.get(num) == arrays.length) { + result.add(num); + } + } + } + return result; + } +} diff --git a/Medium/Longest Common Subsequence.java b/Medium/Longest Common Subsequence.java new file mode 100644 index 00000000..43fc5464 --- /dev/null +++ b/Medium/Longest Common Subsequence.java @@ -0,0 +1,17 @@ +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + int n = text1.length(); + int m = text2.length(); + int[][] dp = new int[n + 1][m + 1]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (text1.charAt(i) == text2.charAt(j)) { + dp[i + 1][j + 1] = 1 + dp[i][j]; + } else { + dp[i + 1][j + 1] = Math.max(dp[i + 1][j], dp[i][j + 1]); + } + } + } + return dp[n][m]; + } +} diff --git a/Medium/Longest Consecutive Sequence.java b/Medium/Longest Consecutive Sequence.java new file mode 100644 index 00000000..e977e86a --- /dev/null +++ b/Medium/Longest Consecutive Sequence.java @@ -0,0 +1,21 @@ +class Solution { + public int longestConsecutive(int[] nums) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + int maxLength = 0; + for (int num : set) { + if (!set.contains(num - 1)) { + int currNum = num; + int currentLength = 1; + while (set.contains(currNum + 1)) { + currNum++; + currentLength++; + } + maxLength = Math.max(currentLength, maxLength); + } + } + return maxLength; + } +} diff --git a/Medium/Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit.java b/Medium/Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit.java new file mode 100644 index 00000000..947954f3 --- /dev/null +++ b/Medium/Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit.java @@ -0,0 +1,29 @@ +class Solution { + public int longestSubarray(int[] nums, int limit) { + int maxSize = 0; + int start = 0; + Deque maxHeap = new ArrayDeque<>(); + Deque minHeap = new ArrayDeque<>(); + for (int i = 0; i < nums.length; i++) { + while (!maxHeap.isEmpty() && maxHeap.peekLast() < nums[i]) { + maxHeap.pollLast(); + } + while (!minHeap.isEmpty() && minHeap.peekLast() > nums[i]) { + minHeap.pollLast(); + } + minHeap.add(nums[i]); + maxHeap.add(nums[i]); + while (maxHeap.peek() - minHeap.peek() > limit) { + if (maxHeap.peek() == nums[start]) { + maxHeap.poll(); + } + if (minHeap.peek() == nums[start]) { + minHeap.poll(); + } + start++; + } + maxSize = Math.max(maxSize, i - start + 1); + } + return maxSize; + } +} diff --git a/Medium/Longest Happy String.java b/Medium/Longest Happy String.java new file mode 100644 index 00000000..4af8f747 --- /dev/null +++ b/Medium/Longest Happy String.java @@ -0,0 +1,42 @@ +class Solution { + public String longestDiverseString(int a, int b, int c) { + PriorityQueue pq = + new PriorityQueue<>((p, q) -> q.frequency() - p.frequency()); + if (a > 0) { + pq.add(new LetterFrequencyPair('a', a)); + } + if (b > 0) { + pq.add(new LetterFrequencyPair('b', b)); + } + if (c > 0) { + pq.add(new LetterFrequencyPair('c', c)); + } + StringBuilder sb = new StringBuilder(); + while (!pq.isEmpty()) { + LetterFrequencyPair removed = pq.remove(); + int frequency = removed.frequency(); + int resultLength = sb.length(); + if (resultLength >= 2 && + sb.charAt(resultLength - 1) == removed.letter() && + sb.charAt(resultLength - 2) == removed.letter()) { + if (pq.isEmpty()) { + break; + } + LetterFrequencyPair temp = pq.remove(); + sb.append(temp.letter()); + if (temp.frequency() - 1 > 0) { + pq.add(new LetterFrequencyPair(temp.letter(), temp.frequency() - 1)); + } + } else { + sb.append(removed.letter()); + frequency--; + } + if (frequency > 0) { + pq.add(new LetterFrequencyPair(removed.letter(), frequency)); + } + } + return sb.toString(); + } + + private record LetterFrequencyPair(char letter, int frequency) {} +} diff --git a/Medium/Longest Increasing Subsequence.java b/Medium/Longest Increasing Subsequence.java index fd5f299e..b56c14ef 100644 --- a/Medium/Longest Increasing Subsequence.java +++ b/Medium/Longest Increasing Subsequence.java @@ -1,21 +1,18 @@ class Solution { public int lengthOfLIS(int[] nums) { - int[] dp = new int[nums.length]; - Arrays.fill(dp, 1); - - for (int i = 1; i < nums.length; i ++) { - for (int j = 0; j < i; j++) { - if (nums[j] < nums[i]) { - dp[i] = Math.max(dp[i], dp[j] + 1); + List subsequence = new ArrayList<>(); + subsequence.add(nums[0]); + for (int i = 1; i < nums.length; i++) { + if (nums[i] > subsequence.get(subsequence.size() - 1)) { + subsequence.add(nums[i]); + } else { + int idx = 0; + while (nums[i] > subsequence.get(idx)) { + idx++; } + subsequence.set(idx, nums[i]); } } - - int max = Integer.MIN_VALUE; - for (int num : dp) { - max = Math.max(num, max); - } - - return max == Integer.MIN_VALUE ? 0 : max; + return subsequence.size(); } } diff --git a/Medium/Longest Line of Consecutive One in Matrix.java b/Medium/Longest Line of Consecutive One in Matrix.java index 70dcf736..a0fcebb2 100644 --- a/Medium/Longest Line of Consecutive One in Matrix.java +++ b/Medium/Longest Line of Consecutive One in Matrix.java @@ -1,139 +1,32 @@ class Solution { - public int longestLine(int[][] M) { - List> points = new ArrayList<>(); - for (int i=0; i point : points) { - int rowCount = rowLength(M, point.get(0), point.get(1), M[0].length); - int colCount = colLength(M, point.get(0), point.get(1), M.length); - int firstDiagonalCount = firstDiagnol(M, point.get(0), point.get(1), M.length, M[0].length); - int secondDiagonalCount = secondDiagnol(M, point.get(0), point.get(1), M.length, M[0].length); - - int maxOnes = Math.max(Math.max(rowCount, colCount), Math.max(firstDiagonalCount, secondDiagonalCount)); - - max = Math.max(max, maxOnes); - } - - return max; - } - - private int rowLength(int[][] M, int row, int col, int size) { - int count = 1; - int leftIdx = col - 1; - int rightIdx = col + 1; - - while (leftIdx >= 0) { - if (M[row][leftIdx] != 1) { - break; - } - - leftIdx--; - count++; - } - - while (rightIdx < size) { - if (M[row][rightIdx] != 1) { - break; - } - - rightIdx++; - count++; - } - - return count; - } - - private int colLength(int[][] M, int row, int col, int size) { - int count = 1; - int leftIdx = row - 1; - int rightIdx = row + 1; - - while (leftIdx >= 0) { - if (M[leftIdx][col] != 1) { - break; - } - - leftIdx--; - count++; - } - - while (rightIdx < size) { - if (M[rightIdx][col] != 1) { - break; - } - - rightIdx++; - count++; - } - - return count; + public int longestLine(int[][] M) { + if (M.length == 0 || M[0].length == 0) { + return 0; } - - private int firstDiagnol(int[][] M, int row, int col, int rows, int cols) { - int count = 1; - int rightRowIdx = row - 1; - int rightColIdx = col - 1; - int downRowIdx = row + 1; - int downColIdx = col + 1; - - while (rightRowIdx >= 0 && rightColIdx >= 0) { - if (M[rightRowIdx][rightColIdx] != 1) { - break; - } - - rightRowIdx--; - rightColIdx--; - count++; - } - - while (downRowIdx < rows && downColIdx < cols) { - if (M[downRowIdx][downColIdx] != 1) { - break; - } - - downRowIdx++; - downColIdx++; - count++; - } - - return count; - } - - private int secondDiagnol(int[][] M, int row, int col, int rows, int cols) { - int count = 1; - int rightRowIdx = row - 1; - int rightColIdx = col + 1; - int leftRowIdx = row + 1; - int leftColIdx = col - 1; - - while (rightRowIdx >= 0 && rightColIdx < cols) { - if (M[rightRowIdx][rightColIdx] != 1) { - break; - } - - rightRowIdx--; - rightColIdx++; - count++; - } - - while (leftRowIdx < rows && leftColIdx >= 0) { - if (M[leftRowIdx][leftColIdx] != 1) { - break; - } - - leftRowIdx++; - leftColIdx--; - count++; - } - - return count; + int maxLength = 0; + int rows = M.length; + int cols = M[0].length; + int[][] dirs = {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}}; + int[][][] dp = new int[rows][cols][4]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (M[i][j] == 1) { + for (int k = 0; k < 4; k++) { + dp[i][j][k] = 1; + int prevI = i + dirs[k][0]; + int prevJ = j + dirs[k][1]; + if (isValid(prevI, prevJ, rows, cols)) { + dp[i][j][k] += dp[prevI][prevJ][k]; + } + maxLength = Math.max(maxLength, dp[i][j][k]); + } + } + } } + return maxLength; + } + + private boolean isValid(int x, int y, int rows, int cols) { + return x >= 0 && x < rows && y >= 0 && y < cols; + } } diff --git a/Medium/Longest Palindromic Subsequence.java b/Medium/Longest Palindromic Subsequence.java index 5d9d4dfd..85c6c5e7 100644 --- a/Medium/Longest Palindromic Subsequence.java +++ b/Medium/Longest Palindromic Subsequence.java @@ -1,34 +1,25 @@ class Solution { public int longestPalindromeSubseq(String s) { - int[][] temp = new int[s.length()][s.length()]; - for(int i=0;i endIdx) { + return 0; } - - int j; - - for (int cl=2;cl <= s.length();cl++) { - for (int i=0;i uniqueNums = new HashSet<>(); + for (int num : nums) { + uniqueNums.add(num); + } + int result = 0; + for (int num : nums) { + int currStreak = 0; + long curr = num; + while (uniqueNums.contains((int) curr)) { + currStreak++; + if (curr * curr > LIMIT) { + break; + } + curr *= curr; + } + result = Math.max(result, currStreak); + } + return result < 2 ? -1 : result; + } +} diff --git a/Medium/Longest String Chain.java b/Medium/Longest String Chain.java new file mode 100644 index 00000000..5c36ef9d --- /dev/null +++ b/Medium/Longest String Chain.java @@ -0,0 +1,31 @@ +class Solution { + public int longestStrChain(String[] words) { + Set wordSet = Arrays.stream(words) + .collect(Collectors.toSet()); + Map memo = new HashMap<>(); + int result = 0; + for (String word : words) { + result = Math.max(result, dfs(wordSet, memo, word)); + } + return result; + } + + private int dfs(Set wordSet, Map memo, String word) { + if (memo.containsKey(word)) { + return memo.get(word); + } + int maxLength = 1; + StringBuilder sb = new StringBuilder(word); + for (int i = 0; i < word.length(); i++) { + sb.deleteCharAt(i); + String newWord = sb.toString(); + if (wordSet.contains(newWord)) { + int currLength = 1 + dfs(wordSet, memo, newWord); + maxLength = Math.max(maxLength, currLength); + } + sb.insert(i, word.charAt(i)); + } + memo.put(word, maxLength); + return maxLength; + } +} diff --git a/Medium/Longest Subarray With Maximum Bitwise AND.java b/Medium/Longest Subarray With Maximum Bitwise AND.java new file mode 100644 index 00000000..63c1ca55 --- /dev/null +++ b/Medium/Longest Subarray With Maximum Bitwise AND.java @@ -0,0 +1,20 @@ +class Solution { + public int longestSubarray(int[] nums) { + int result = 0; + int max = 0; + int count = 0; + for (int num : nums) { + if (max < num) { + max = num; + result = count = 0; + } + if (max == num) { + count++; + } else { + count = 0; + } + result = Math.max(result, count); + } + return result; + } +} diff --git a/Medium/Longest Subarray of 1's After Deleting One Element.java b/Medium/Longest Subarray of 1's After Deleting One Element.java new file mode 100644 index 00000000..b10a1675 --- /dev/null +++ b/Medium/Longest Subarray of 1's After Deleting One Element.java @@ -0,0 +1,15 @@ +class Solution { + public int longestSubarray(int[] nums) { + int zeroIdx = -1; + int windowSize = 0; + int startIdx = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] == 0) { + startIdx = zeroIdx + 1; + zeroIdx = i; + } + windowSize = Math.max(windowSize, i - startIdx); + } + return windowSize; + } +} diff --git a/Medium/Longest Substring Without Repeating Characters.java b/Medium/Longest Substring Without Repeating Characters.java index 47cd512b..2bef7542 100644 --- a/Medium/Longest Substring Without Repeating Characters.java +++ b/Medium/Longest Substring Without Repeating Characters.java @@ -1,21 +1,18 @@ class Solution { - public int lengthOfLongestSubstring(String s) { - int maxLen = 0; - int n = s.length(); - int start = 0; - int end = 0; - Set set = new HashSet<>(); - - while (end < n) { - if (!set.contains(s.charAt(end))) { - set.add(s.charAt(end++)); - maxLen = Math.max(maxLen, set.size()); - } - else { - set.remove(s.charAt(start++)); - } - } - - return maxLen; + public int lengthOfLongestSubstring(String s) { + int start = 0; + int end = 0; + int n = s.length(); + Map map = new HashMap<>(); + int maxLength = 0; + while (end < n) { + char c = s.charAt(end++); + map.put(c, map.getOrDefault(c, 0) + 1); + while (start <= end && map.get(c) > 1) { + map.put(s.charAt(start), map.getOrDefault(s.charAt(start++), 0) - 1); + } + maxLength = Math.max(maxLength, end - start); } + return maxLength; + } } diff --git a/Medium/Longest Substring with At Most K Distinct Characters.java b/Medium/Longest Substring with At Most K Distinct Characters.java new file mode 100644 index 00000000..a793b8c0 --- /dev/null +++ b/Medium/Longest Substring with At Most K Distinct Characters.java @@ -0,0 +1,21 @@ +class Solution { + public int lengthOfLongestSubstringKDistinct(String s, int k) { + Map map = new HashMap<>(); + int start = 0; + int end = 0; + int maxLength = 0; + while (end < s.length()) { + map.put(s.charAt(end), map.getOrDefault(s.charAt(end), 0) + 1); + while (start <= end && map.size() > k) { + map.put(s.charAt(start), map.get(s.charAt(start)) - 1); + if (map.get(s.charAt(start)) == 0) { + map.remove(s.charAt(start)); + } + start++; + } + end++; + maxLength = Math.max(maxLength, end - start); + } + return maxLength; + } +} diff --git a/Medium/Longest Substring with At Most Two Distinct Characters.java b/Medium/Longest Substring with At Most Two Distinct Characters.java new file mode 100644 index 00000000..04f60a83 --- /dev/null +++ b/Medium/Longest Substring with At Most Two Distinct Characters.java @@ -0,0 +1,22 @@ +class Solution { + public int lengthOfLongestSubstringTwoDistinct(String s) { + int max = 0; + int start = 0; + int end = 0; + int n = s.length(); + Map map = new HashMap<>(); + while (end < n) { + map.put(s.charAt(end), map.getOrDefault(s.charAt(end), 0) + 1); + end++; + while (start < end && map.size() > 2) { + map.put(s.charAt(start), map.getOrDefault(s.charAt(start), 0) - 1); + if (map.get(s.charAt(start)) == 0) { + map.remove(s.charAt(start)); + } + start++; + } + max = Math.max(max, end - start); + } + return max; + } +} diff --git a/Medium/Longest Uploaded Prefix.java b/Medium/Longest Uploaded Prefix.java new file mode 100644 index 00000000..f7d3f6f1 --- /dev/null +++ b/Medium/Longest Uploaded Prefix.java @@ -0,0 +1,28 @@ +class LUPrefix { + + private int longestPrefixIndex; + private boolean[] uploaded; + + public LUPrefix(int n) { + this.uploaded = new boolean[n]; + this.longestPrefixIndex = 0; + } + + public void upload(int video) { + uploaded[video - 1] = true; + while (longestPrefixIndex < uploaded.length && uploaded[longestPrefixIndex]) { + longestPrefixIndex++; + } + } + + public int longest() { + return longestPrefixIndex; + } +} + +/** + * Your LUPrefix object will be instantiated and called as such: + * LUPrefix obj = new LUPrefix(n); + * obj.upload(video); + * int param_2 = obj.longest(); + */ diff --git a/Medium/Longest Well-Performing Interval.java b/Medium/Longest Well-Performing Interval.java new file mode 100644 index 00000000..9940463a --- /dev/null +++ b/Medium/Longest Well-Performing Interval.java @@ -0,0 +1,20 @@ +class Solution { + public int longestWPI(int[] hours) { + int sum = 0; + int maxInterval = 0; + boolean greaterThanEightFound = false; + Map map = new HashMap<>(); + for (int i = 0; i < hours.length; i++) { + sum += hours[i] > 8 ? 1 : -1; + greaterThanEightFound = hours[i] > 8 ? true : greaterThanEightFound; + map.putIfAbsent(sum, i); + if (sum >= 1) { + maxInterval = Math.max(maxInterval, i + 1); + } + else if (map.containsKey(sum - 1)) { + maxInterval = Math.max(maxInterval, i - map.get(sum - 1)); + } + } + return maxInterval == 0 ? (greaterThanEightFound ? 1 : 0) : maxInterval; + } +} diff --git a/Medium/Longest Word With All Prefixes.java b/Medium/Longest Word With All Prefixes.java new file mode 100644 index 00000000..a2a69a0f --- /dev/null +++ b/Medium/Longest Word With All Prefixes.java @@ -0,0 +1,59 @@ +class Solution { + public String longestWord(String[] words) { + TrieNode root = new TrieNode(); + for (String word : words) { + root.insert(word); + } + String longestValidWord = ""; + for (String word : words) { + if (root.hasAllPrefixes(word)) { + if (word.length() > longestValidWord.length() || + (word.length() == longestValidWord.length() && word.compareTo(longestValidWord) < 0)) { + longestValidWord = word; + } + } + } + return longestValidWord; + } + + static class TrieNode { + private final Map children; + private boolean isWord; + + public TrieNode() { + this.children = new HashMap<>(); + } + + public void insert(String word) { + TrieNode curr = this; + for (char c : word.toCharArray()) { + curr = curr.getOrCreateChild(c); + } + curr.isWord = true; + } + + public boolean hasAllPrefixes(String word) { + TrieNode curr = this; + for (char c : word.toCharArray()) { + TrieNode child = curr.children.getOrDefault(c, null); + if (child == null) { + return false; + } + if (!child.isWord) { + return false; + } + curr = child; + } + return true; + } + + private TrieNode getOrCreateChild(char c) { + if (children.containsKey(c)) { + return children.get(c); + } + TrieNode node = new TrieNode(); + children.put(c, node); + return node; + } + } +} diff --git a/Medium/Longest Word in Dictionary through Deleting.java b/Medium/Longest Word in Dictionary through Deleting.java new file mode 100644 index 00000000..5f09bd58 --- /dev/null +++ b/Medium/Longest Word in Dictionary through Deleting.java @@ -0,0 +1,20 @@ +class Solution { + public String findLongestWord(String s, List d) { + d.sort((o1, o2) -> o1.length() != o2.length() ? Integer.compare(o2.length(), o1.length()) + : o1.compareTo(o2)); + for (String word : d) { + int wordIdx = 0; + int strIdx = 0; + while (strIdx < s.length() && wordIdx < word.length()) { + if (word.charAt(wordIdx) == s.charAt(strIdx)) { + wordIdx++; + } + strIdx++; + } + if (wordIdx == word.length()) { + return word; + } + } + return ""; + } +} diff --git a/Medium/Longest ZigZag Path in a Binary Tree.java b/Medium/Longest ZigZag Path in a Binary Tree.java new file mode 100644 index 00000000..71e32231 --- /dev/null +++ b/Medium/Longest ZigZag Path in a Binary Tree.java @@ -0,0 +1,42 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + + private enum DIRECTION { + LEFT, RIGHT; + } + + public int longestZigZag(TreeNode root) { + int[] pathLength = {0}; + dfs(root, DIRECTION.LEFT, 0, pathLength); + dfs(root, DIRECTION.RIGHT, 0, pathLength); + return pathLength[0]; + } + + private void dfs(TreeNode node, DIRECTION direction, int steps, int[] pathLength) { + if (node == null) { + return; + } + pathLength[0] = Math.max(pathLength[0], steps); + if (direction == DIRECTION.LEFT) { + dfs(node.left, DIRECTION.RIGHT, steps + 1, pathLength); + dfs(node.right, DIRECTION.LEFT, 1, pathLength); + } else { + dfs(node.left, DIRECTION.RIGHT, 1, pathLength); + dfs(node.right, DIRECTION.LEFT, steps + 1, pathLength); + } + } +} diff --git a/Medium/Lowest Common Ancestor of Deepest Leaves.java b/Medium/Lowest Common Ancestor of Deepest Leaves.java new file mode 100644 index 00000000..d1fdfc59 --- /dev/null +++ b/Medium/Lowest Common Ancestor of Deepest Leaves.java @@ -0,0 +1,45 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode lcaDeepestLeaves(TreeNode root) { + return dfs(root).node; + } + + private NodeResult dfs(TreeNode root) { + if (root == null) { + return new NodeResult(null, 0); + } + NodeResult leftResult = dfs(root.left); + NodeResult rightResult = dfs(root.right); + if (leftResult.distance > rightResult.distance) { + return new NodeResult(leftResult.node, leftResult.distance + 1); + } + if (leftResult.distance < rightResult.distance) { + return new NodeResult(rightResult.node, rightResult.distance + 1); + } + return new NodeResult(root, rightResult.distance + 1); + } + + private static class NodeResult { + TreeNode node; + int distance; + + public NodeResult(TreeNode node, int distance) { + this.node = node; + this.distance = distance; + } + } +} diff --git a/Medium/Lowest Common Ancestor of a Binary Tree II.java b/Medium/Lowest Common Ancestor of a Binary Tree II.java new file mode 100644 index 00000000..be4c28d2 --- /dev/null +++ b/Medium/Lowest Common Ancestor of a Binary Tree II.java @@ -0,0 +1,46 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + TreeNode result = lca(root, p, q); + if (result == p) { + return checkIfNodeExist(p, q) ? p : null; + } + if (result == q) { + return checkIfNodeExist(q, p) ? q : null; + } + return result; + } + + private boolean checkIfNodeExist(TreeNode root, TreeNode target) { + if (root == target) { + return true; + } + if (root == null) { + return false; + } + return checkIfNodeExist(root.left, target) || checkIfNodeExist(root.right, target); + } + + private TreeNode lca(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) { + return root; + } + if (root == p || root == q) { + return root; + } + TreeNode left = lca(root.left, p, q); + TreeNode right = lca(root.right, p, q); + if (left != null && right != null) { + return root; + } + return left != null ? left : right; + } +} diff --git a/Medium/Lowest Common Ancestor of a Binary Tree III.java b/Medium/Lowest Common Ancestor of a Binary Tree III.java new file mode 100644 index 00000000..098b0f86 --- /dev/null +++ b/Medium/Lowest Common Ancestor of a Binary Tree III.java @@ -0,0 +1,38 @@ +/* +// Definition for a Node. +class Node { + public int val; + public Node left; + public Node right; + public Node parent; +}; +*/ + +class Solution { + public Node lowestCommonAncestor(Node p, Node q) { + int pDepth = getDepth(p); + int qDepth = getDepth(q); + while (pDepth > qDepth) { + pDepth--; + p = p.parent; + } + while (qDepth > pDepth) { + qDepth--; + q = q.parent; + } + while (p != q) { + p = p.parent; + q = q.parent; + } + return p; + } + + private int getDepth(Node node) { + int depth = 0; + while (node != null) { + depth++; + node = node.parent; + } + return depth; + } +} diff --git a/Medium/Lowest Common Ancestor of a Binary Tree.java b/Medium/Lowest Common Ancestor of a Binary Tree.java index b83d0663..890c71e6 100644 --- a/Medium/Lowest Common Ancestor of a Binary Tree.java +++ b/Medium/Lowest Common Ancestor of a Binary Tree.java @@ -9,17 +9,20 @@ */ class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { - if (root == null || root == p || root == q) { + if (root == null) { + return null; + } + if (root == p || root == q) { return root; } - TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); - if (left != null && right != null) { return root; } - - return left != null ? left : right; + if (left != null || right != null) { + return left != null ? left : right; + } + return null; } } diff --git a/Medium/Magnetic Force Between Two Balls.java b/Medium/Magnetic Force Between Two Balls.java new file mode 100644 index 00000000..9ca9708b --- /dev/null +++ b/Medium/Magnetic Force Between Two Balls.java @@ -0,0 +1,32 @@ +class Solution { + public int maxDistance(int[] position, int m) { + int result = 0; + int n = position.length; + Arrays.sort(position); + int left = 1; + int right = (int) Math.ceil(position[n - 1] / (m - 1.0)); + while (left <= right) { + int mid = (left + right) / 2; + if (isPossible(position, mid, m)) { + result = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + return result; + } + + private boolean isPossible(int[] position, int distance, int m) { + int prevBall = position[0]; + int ballCount = 1; + for (int i = 1; i < position.length && ballCount < m; i++) { + int curr = position[i]; + if (curr - prevBall >= distance) { + ballCount++; + prevBall = curr; + } + } + return ballCount == m; + } +} diff --git a/Medium/Majority Element II.java b/Medium/Majority Element II.java new file mode 100644 index 00000000..5b59752e --- /dev/null +++ b/Medium/Majority Element II.java @@ -0,0 +1,43 @@ +class Solution { + public List majorityElement(int[] nums) { + Integer candidateOne = null; + Integer candidateTwo = null; + int countOne = 0; + int countTwo = 0; + for (int num : nums) { + if (candidateOne != null && candidateOne == num) { + countOne++; + } else if (candidateTwo != null && candidateTwo == num) { + countTwo++; + } else if (countOne == 0) { + candidateOne = num; + countOne++; + } else if (countTwo == 0) { + candidateTwo = num; + countTwo++; + } else { + countOne--; + countTwo--; + } + } + countOne = 0; + countTwo = 0; + for (int num : nums) { + if (candidateOne != null && candidateOne == num) { + countOne++; + } + if (candidateTwo != null && candidateTwo == num) { + countTwo++; + } + } + int n = nums.length; + List result = new ArrayList<>(); + if (countOne > n / 3) { + result.add(candidateOne); + } + if (countTwo > n / 3) { + result.add(candidateTwo); + } + return result; + } +} diff --git a/Medium/Make String a Subsequence Using Cyclic Increments.java b/Medium/Make String a Subsequence Using Cyclic Increments.java new file mode 100644 index 00000000..1247a755 --- /dev/null +++ b/Medium/Make String a Subsequence Using Cyclic Increments.java @@ -0,0 +1,18 @@ +class Solution { + public boolean canMakeSubsequence(String str1, String str2) { + int idxOne = 0; + int idxTwo = 0; + while (idxOne < str1.length() && idxTwo < str2.length()) { + if (str1.charAt(idxOne) == str2.charAt(idxTwo) || + nextCyclicChar(str1.charAt(idxOne)) == str2.charAt(idxTwo)) { + idxTwo++; + } + idxOne++; + } + return idxTwo == str2.length(); + } + + private static char nextCyclicChar(char c) { + return c == 'z' ? 'a' : (char) (c + 1); + } +} diff --git a/Medium/Make Sum Divisible by P.java b/Medium/Make Sum Divisible by P.java new file mode 100644 index 00000000..ee94817a --- /dev/null +++ b/Medium/Make Sum Divisible by P.java @@ -0,0 +1,26 @@ +class Solution { + public int minSubarray(int[] nums, int p) { + int n = nums.length; + int sum = 0; + for (int num : nums) { + sum = (sum + num) % p; + } + int target = sum % p; + if (target == 0) { + return 0; + } + Map map = new HashMap<>(); + map.put(0, -1); + int currSum = 0; + int result = n; + for (int i = 0; i < n; i++) { + currSum = (currSum + nums[i]) % p; + int needed = (currSum - target + p) % p; + if (map.containsKey(needed)) { + result = Math.min(result, i - map.get(needed)); + } + map.put(currSum, i); + } + return result == n ? -1 : result; + } +} diff --git a/Medium/Making File Names Unique.java b/Medium/Making File Names Unique.java new file mode 100644 index 00000000..5ec1113b --- /dev/null +++ b/Medium/Making File Names Unique.java @@ -0,0 +1,27 @@ +class Solution { + public String[] getFolderNames(String[] names) { + int n = names.length; + Map map = new HashMap<>(); + String[] ans = new String[n]; + for (int i = 0; i < n; i++) { + if (map.containsKey(names[i])) { + Integer val = map.get(names[i]); + StringBuilder sb = new StringBuilder(names[i]); + sb.append('(').append(val).append(')'); + while (map.containsKey(sb.toString())) { + val++; + sb = new StringBuilder(names[i]); + sb.append('(').append(val).append(')'); + } + ans[i] = sb.toString(); + map.put(sb.toString(), 1); + map.put(names[i], val + 1); + } + else { + ans[i] = names[i]; + map.put(names[i], 1); + } + } + return ans; + } +} diff --git a/Medium/Map Sum Pairs.java b/Medium/Map Sum Pairs.java index bc65aa1a..39eb3afe 100644 --- a/Medium/Map Sum Pairs.java +++ b/Medium/Map Sum Pairs.java @@ -1,26 +1,36 @@ class MapSum { - /** Initialize your data structure here. */ - Map map = new HashMap(); - public MapSum() { - - } - - public void insert(String key, int val) { - map.put(key, val); + /** Initialize your data structure here. */ + TrieNode root; + Map map; + public MapSum() { + root = new TrieNode('-'); + map = new HashMap<>(); + } + + public void insert(String key, int val) { + int delta = val - map.getOrDefault(key, 0); + map.put(key, val); + TrieNode curr = root; + for (int i = 0; i < key.length(); i++) { + if (!curr.map.containsKey(key.charAt(i))) { + curr.map.put(key.charAt(i), new TrieNode(key.charAt(i))); + } + curr = curr.map.get(key.charAt(i)); + curr.score += delta; } - - public int sum(String prefix) { - int sum = 0; - for (Map.Entry entry : map.entrySet()) { - String s = entry.getKey(); - if (s.length() >= prefix.length() && s.substring(0,prefix.length()).equals(prefix)) { - sum += entry.getValue(); - } - } - - return sum; + } + + public int sum(String prefix) { + TrieNode curr = root; + for (int i = 0; i < prefix.length(); i++) { + if (!curr.map.containsKey(prefix.charAt(i))) { + return 0; + } + curr = curr.map.get(prefix.charAt(i)); } + return curr.score; + } } /** @@ -29,3 +39,15 @@ public int sum(String prefix) { * obj.insert(key,val); * int param_2 = obj.sum(prefix); */ + +class TrieNode { + char c; + Map map; + int score; + + public TrieNode(char c) { + this.c = c; + map = new HashMap<>(); + score = 0; + } +} diff --git a/Medium/Masking Personal Information.java b/Medium/Masking Personal Information.java index 841240a6..1d0559dc 100644 --- a/Medium/Masking Personal Information.java +++ b/Medium/Masking Personal Information.java @@ -1,76 +1,34 @@ class Solution { - public static String maskPII(String S) { - if (S.length() == 0) { - return S; - } - - if (S.indexOf('@') != -1) { - return formatEmail(S); - } - else { - return formatNumber(S); - } - } - - private static String formatNumber(String s) { - StringBuilder sb = new StringBuilder(); - int digitCount = getDigitCount(s); - - if (digitCount > 10) { - sb.append("+"); - int extra = digitCount - 10; - while (extra-- > 0) { - sb.append("*"); - } - sb.append("-"); - } - sb.append("***-***-"); - - StringBuilder last4 = new StringBuilder(); - for (int i=s.length()-1; i>=0; i--) { - if (Character.isDigit(s.charAt(i))) { - last4.append(s.charAt(i)); - } - - if (last4.length() == 4) { - break; - } - } - - sb.append(last4.reverse().toString()); - - return sb.toString(); - } - - private static int getDigitCount(String s) { - char[] chars = s.toCharArray(); - int count = 0; - - for (char c : chars) { - if (Character.isDigit(c)) { - count++; - } - } - - return count; - } - - private static String formatEmail(String s) { - int idx = s.indexOf('@'); - int revStart = idx - 1; - while (revStart >= 0 && Character.isLetter(s.charAt(revStart))) { - revStart--; - } - - StringBuilder sb = new StringBuilder(); - - sb. - append(s.substring(0, revStart+1)). - append(Character.toLowerCase(s.charAt(revStart + 1))). - append("*****"). - append(Character.toLowerCase(s.charAt(s.indexOf('@') - 1))). - append(s.substring(s.indexOf('@'))); - - return sb.toString().toLowerCase(); + public String maskPII(String s) { + return s.indexOf('@') != -1 ? maskEmail(s) : maskPhoneNumber(s); + } + + private String maskPhoneNumber(String phoneNumber) { + StringBuilder digits = new StringBuilder(); + for (char c : phoneNumber.toCharArray()) { + if (Character.isDigit(c)) { + digits.append(c); + } } + return getMaskedAreaCode(digits.length()) + "***-***-" + digits.substring(digits.length() - 4); + } + + private String getMaskedAreaCode(int phoneNumberLength) { + return switch (phoneNumberLength) { + case 10 -> ""; + case 11 -> "+*-"; + case 12 -> "+**-"; + case 13 -> "+***-"; + default -> null; + }; + } + + private String maskEmail(String email) { + String[] split = email.split("@"); + String name = split[0]; + String domain = split[1].toLowerCase(); + String maskedName = Character.toLowerCase(name.charAt(0)) + String.join("", Collections.nCopies(5, "*")) + + Character.toLowerCase(name.charAt(name.length() - 1)); + return maskedName + "@" + domain; + } } diff --git a/Medium/Matchsticks to Square.java b/Medium/Matchsticks to Square.java new file mode 100644 index 00000000..b5de023b --- /dev/null +++ b/Medium/Matchsticks to Square.java @@ -0,0 +1,32 @@ +class Solution { + public boolean makesquare(int[] matchsticks) { + int n = matchsticks.length; + int sum = 0; + for (int stick : matchsticks) { + sum += stick; + } + int possibleSide = sum / 4; + if (possibleSide * 4 != sum) { + return false; + } + Arrays.sort(matchsticks); + return dfs(new int[4], matchsticks, possibleSide, matchsticks.length - 1); + } + + private boolean dfs(int[] sum, int[] sticks, int possibleSide, int idx) { + if (idx == -1) { + return sum[0] == sum[1] && sum[1] == sum[2] && sum[2] == sum[3]; + } + int stick = sticks[idx]; + for (int i = 0; i < 4; i++) { + if (sum[i] + stick <= possibleSide) { + sum[i] += stick; + if (dfs(sum, sticks, possibleSide, idx - 1)) { + return true; + } + sum[i] -= stick; + } + } + return false; + } +} diff --git a/Medium/Max Area of Island.java b/Medium/Max Area of Island.java new file mode 100644 index 00000000..b7fc94ba --- /dev/null +++ b/Medium/Max Area of Island.java @@ -0,0 +1,34 @@ +class Solution { + private final int[][] DIRS = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}}; + + public int maxAreaOfIsland(int[][] grid) { + int area = 0; + int rows = grid.length; + int cols = grid[0].length; + boolean[][] visited = new boolean[rows][cols]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (!visited[i][j] && grid[i][j] == 1) { + Queue queue = new LinkedList<>(); + int currArea = 0; + queue.add(new int[]{i, j}); + visited[i][j] = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + currArea++; + for (int[] dir : DIRS) { + int x = removed[0] + dir[0]; + int y = removed[1] + dir[1]; + if (x >= 0 && y >= 0 && x < rows && y < cols && !visited[x][y] && grid[x][y] == 1) { + queue.add(new int[]{x, y}); + visited[x][y] = true; + } + } + } + area = Math.max(area, currArea); + } + } + } + return area; + } +} diff --git a/Medium/Max Chunks To Make Sorted.java b/Medium/Max Chunks To Make Sorted.java new file mode 100644 index 00000000..fb401e54 --- /dev/null +++ b/Medium/Max Chunks To Make Sorted.java @@ -0,0 +1,18 @@ +class Solution { + public int maxChunksToSorted(int[] arr) { + int maxSplitCount = 0; + int maxVal = 0; + int idx = 0; + + while (idx < arr.length) { + maxVal = Math.max(maxVal, arr[idx]); + if (maxVal == idx) { + maxSplitCount++; + } + + idx++; + } + + return maxSplitCount; + } +} diff --git a/Medium/Max Consecutive Ones III.java b/Medium/Max Consecutive Ones III.java new file mode 100644 index 00000000..cec14a87 --- /dev/null +++ b/Medium/Max Consecutive Ones III.java @@ -0,0 +1,23 @@ +class Solution { + public int longestOnes(int[] nums, int k) { + int start = 0; + int end = 0; + int flipped = 0; + int n = nums.length; + int max = 0; + while (end < nums.length) { + if (nums[end] == 0) { + flipped++; + } + end++; + while (start < end && flipped > k) { + if (nums[start] == 0) { + flipped--; + } + start++; + } + max = Math.max(max, end - start); + } + return max; + } +} diff --git a/Medium/Max Increase to Keep City Skyline.java b/Medium/Max Increase to Keep City Skyline.java index 3e4a7f0b..fbcc1f27 100644 --- a/Medium/Max Increase to Keep City Skyline.java +++ b/Medium/Max Increase to Keep City Skyline.java @@ -1,36 +1,21 @@ class Solution { public int maxIncreaseKeepingSkyline(int[][] grid) { - int[] top = new int[grid.length]; - int[] left = new int[grid.length]; - int j = 0; - - for (int[] g : grid) { - int max = Integer.MIN_VALUE; - for (int i=0; i map = new HashMap<>(); + int count = 0; + for (int num : nums) { + if (map.getOrDefault(k - num, 0) > 0) { + count++; + map.put(k - num, map.getOrDefault(k - num, 0) - 1); + } else { + map.put(num, map.getOrDefault(num, 0) + 1); + } + } + return count; + } +} diff --git a/Medium/Max Sum of a Pair With Equal Sum of Digits.java b/Medium/Max Sum of a Pair With Equal Sum of Digits.java new file mode 100644 index 00000000..1d8d89ae --- /dev/null +++ b/Medium/Max Sum of a Pair With Equal Sum of Digits.java @@ -0,0 +1,25 @@ +class Solution { + public int maximumSum(int[] nums) { + Map map = new HashMap<>(); + int maxSum = -1; + for (int num : nums) { + int digitSum = calculateDigitSum(num); + if (map.containsKey(digitSum)) { + maxSum = Math.max(maxSum, map.get(digitSum) + num); + map.put(digitSum, Math.max(map.get(digitSum), num)); + } else { + map.put(digitSum, num); + } + } + return maxSum; + } + + private int calculateDigitSum(int num) { + int sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum; + } +} diff --git a/Medium/Maximal Network Rank.java b/Medium/Maximal Network Rank.java new file mode 100644 index 00000000..e5c3f20c --- /dev/null +++ b/Medium/Maximal Network Rank.java @@ -0,0 +1,21 @@ +class Solution { + public int maximalNetworkRank(int n, int[][] roads) { + Map> map = new HashMap<>(); + for (int[] road : roads) { + map.computeIfAbsent(road[0], k -> new HashSet<>()).add(road[1]); + map.computeIfAbsent(road[1], k -> new HashSet<>()).add(road[0]); + } + int maximumRank = 0; + for (int i = 0; i < n; i++) { + int iRank = map.getOrDefault(i, new HashSet<>()).size(); + for (int j = i + 1; j < n; j++) { + int combinedRank = iRank + map.getOrDefault(j, new HashSet<>()).size(); + if (map.getOrDefault(j, new HashSet<>()).contains(i)) { + combinedRank--; + } + maximumRank = Math.max(maximumRank, combinedRank); + } + } + return maximumRank; + } +} diff --git a/Medium/Maximal Score After Applying K Operations.java b/Medium/Maximal Score After Applying K Operations.java new file mode 100644 index 00000000..ca776caf --- /dev/null +++ b/Medium/Maximal Score After Applying K Operations.java @@ -0,0 +1,15 @@ +class Solution { + public long maxKelements(int[] nums, int k) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + for (int num : nums) { + pq.add(num); + } + long sum = 0; + while (!pq.isEmpty() && k-- > 0) { + int removed = pq.poll(); + sum += removed; + pq.add((int) Math.ceil(((double) removed) / 3)); + } + return sum; + } +} diff --git a/Medium/Maximize Distance to Closest Person.java b/Medium/Maximize Distance to Closest Person.java new file mode 100644 index 00000000..8816dda5 --- /dev/null +++ b/Medium/Maximize Distance to Closest Person.java @@ -0,0 +1,14 @@ +class Solution { + public int maxDistToClosest(int[] seats) { + int n = seats.length; + int maxDistance = 0; + int start = -1; + for (int i = 0; i < n; i++) { + if (seats[i] == 1) { + maxDistance = start == -1 ? i : Math.max(maxDistance, (i - start) / 2); + start = i; + } + } + return Math.max(maxDistance, n - 1 - start); + } +} diff --git a/Medium/Maximize Happiness of Selected Children.java b/Medium/Maximize Happiness of Selected Children.java new file mode 100644 index 00000000..01e3aeff --- /dev/null +++ b/Medium/Maximize Happiness of Selected Children.java @@ -0,0 +1,15 @@ +class Solution { + public long maximumHappinessSum(int[] happiness, int k) { + Arrays.sort(happiness); + int turnCount = 0; + long happinessSum = 0; + int idx = happiness.length - 1; + while (k-- > 0) { + int currentHappiness = Math.max(0, happiness[idx] - turnCount); + happinessSum += currentHappiness; + turnCount++; + idx--; + } + return happinessSum; + } +} diff --git a/Medium/Maximize Number of Subsequences in a String.java b/Medium/Maximize Number of Subsequences in a String.java new file mode 100644 index 00000000..c2c26208 --- /dev/null +++ b/Medium/Maximize Number of Subsequences in a String.java @@ -0,0 +1,17 @@ +class Solution { + public long maximumSubsequenceCount(String text, String pattern) { + long result = 0; + int countCharOne = 0; + int countCharTwo = 0; + for (char c : text.toCharArray()) { + if (c == pattern.charAt(1)) { + result += countCharOne; + countCharTwo++; + } + if (c == pattern.charAt(0)) { + countCharOne++; + } + } + return result + Math.max(countCharOne, countCharTwo); + } +} diff --git a/Medium/Maximize the Confusion of an Exam.java b/Medium/Maximize the Confusion of an Exam.java new file mode 100644 index 00000000..3e7e14d1 --- /dev/null +++ b/Medium/Maximize the Confusion of an Exam.java @@ -0,0 +1,19 @@ +class Solution { + public int maxConsecutiveAnswers(String answerKey, int k) { + int resultSize = k; + Map map = new HashMap<>(); + for (int i = 0; i < k; i++) { + map.put(answerKey.charAt(i), map.getOrDefault(answerKey.charAt(i), 0) + 1); + } + int start = 0; + for (int i = k; i < answerKey.length(); i++) { + map.put(answerKey.charAt(i), map.getOrDefault(answerKey.charAt(i), 0) + 1); + while (Math.min(map.getOrDefault('T', 0), map.getOrDefault('F', 0)) > k) { + map.put(answerKey.charAt(start), map.get(answerKey.charAt(start)) - 1); + start++; + } + resultSize = Math.max(resultSize, i - start + 1); + } + return resultSize; + } +} diff --git a/Medium/Maximize the Topmost Element After K Moves.java b/Medium/Maximize the Topmost Element After K Moves.java new file mode 100644 index 00000000..d8bb4948 --- /dev/null +++ b/Medium/Maximize the Topmost Element After K Moves.java @@ -0,0 +1,17 @@ +class Solution { + public int maximumTop(int[] nums, int k) { + if (nums.length == 1) { + return k % 2 == 1 ? -1 : nums[0]; + } + int maxTop = -1; + if (k < nums.length) { + maxTop = nums[k]; + } else if (k > nums.length) { + k = nums.length + 1; + } + for (int i = 0; i < k - 1; i++) { + maxTop = Math.max(maxTop, nums[i]); + } + return maxTop; + } +} diff --git a/Medium/Maximum Absolute Sum of Any Subarray.java b/Medium/Maximum Absolute Sum of Any Subarray.java new file mode 100644 index 00000000..0dbca0d6 --- /dev/null +++ b/Medium/Maximum Absolute Sum of Any Subarray.java @@ -0,0 +1,15 @@ +class Solution { + public int maxAbsoluteSum(int[] nums) { + int currMax = nums[0]; + int max = currMax; + int currMin = nums[0]; + int min = currMin; + for(int i = 1; i < nums.length; i++){ + currMax = Math.max(nums[i], currMax + nums[i]); + max = Math.max(max, currMax); + currMin = Math.min(nums[i], currMin + nums[i]); + min = Math.min(min, currMin); + } + return Math.max(max, Math.abs(min)); + } +} diff --git a/Medium/Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts.java b/Medium/Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts.java new file mode 100644 index 00000000..e723cd7e --- /dev/null +++ b/Medium/Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts.java @@ -0,0 +1,17 @@ +class Solution { + public int maxArea(int h, int w, int[] horizontalCuts, int[] verticalCuts) { + Arrays.sort(horizontalCuts); + Arrays.sort(verticalCuts); + int n = horizontalCuts.length; + int m = verticalCuts.length; + long maxHeight = Math.max(horizontalCuts[0], h - horizontalCuts[n - 1]); + for (int i = 1; i < n; i++) { + maxHeight = Math.max(maxHeight, horizontalCuts[i] - horizontalCuts[i - 1]); + } + long maxWidth = Math.max(verticalCuts[0], w - verticalCuts[m - 1]); + for (int i = 1; i < m; i++) { + maxWidth = Math.max(maxWidth, verticalCuts[i] - verticalCuts[i - 1]); + } + return (int) ((maxWidth * maxHeight) % (1000000007)); + } +} diff --git a/Medium/Maximum Average Subtree.java b/Medium/Maximum Average Subtree.java new file mode 100644 index 00000000..873f4f01 --- /dev/null +++ b/Medium/Maximum Average Subtree.java @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public double maximumAverageSubtree(TreeNode root) { + double[] result = {0.0}; + traverse(root, result); + return result[0]; + } + + private double[] traverse(TreeNode root, double[] result) { + if (root == null) { + return new double[]{0.0, 0.0}; + } + double[] leftValues = traverse(root.left, result); + double[] rightValues = traverse(root.right, result); + double sum = root.val + leftValues[0] + rightValues[0]; + double count = 1 + leftValues[1] + rightValues[1]; + double avg = sum / count; + result[0] = Math.max(result[0], avg); + return new double[]{sum, count}; + } +} diff --git a/Medium/Maximum Bags With Full Capacity of Rocks.java b/Medium/Maximum Bags With Full Capacity of Rocks.java new file mode 100644 index 00000000..e73a7826 --- /dev/null +++ b/Medium/Maximum Bags With Full Capacity of Rocks.java @@ -0,0 +1,15 @@ +class Solution { + public int maximumBags(int[] capacity, int[] rocks, int additionalRocks) { + PriorityQueue pq = new PriorityQueue<>(); + for (int i = 0; i < capacity.length; i++) { + pq.add(capacity[i] - rocks[i]); + } + while (!pq.isEmpty()) { + if (pq.peek() > additionalRocks) { + return capacity.length - pq.size(); + } + additionalRocks -= pq.poll(); + } + return capacity.length; + } +} diff --git a/Medium/Maximum Binary Tree.java b/Medium/Maximum Binary Tree.java index 93d7ac55..03cda51a 100644 --- a/Medium/Maximum Binary Tree.java +++ b/Medium/Maximum Binary Tree.java @@ -8,31 +8,35 @@ * } */ class Solution { - public TreeNode constructMaximumBinaryTree(int[] nums) { - if (nums.length == 0) { - return null; - } - - return constructTree(nums, 0, nums.length-1); + public TreeNode constructMaximumBinaryTree(int[] nums) { + if (nums.length == 0) { + return null; } - - private TreeNode constructTree(int[] nums, int start, int end) { - if (start > end) { - return null; - } - - int idx = start; - for (int i=start+1; i<=end; i++) { - if (nums[i] > nums[idx]) { - idx = i; - } - } - - TreeNode root = new TreeNode(nums[idx]); - - root.left = constructTree(nums, start, idx-1); - root.right = constructTree(nums, idx+1, end); - - return root; + TreeNode root = helper(nums, 0, nums.length - 1); + return root; + } + + private TreeNode helper(int[] nums, int start, int end) { + if (start > end) { + return null; } + int maxIdx = getMaxIdx(nums, start, end); + TreeNode root = new TreeNode(nums[maxIdx]); + root.left = helper(nums, start, maxIdx - 1); + root.right = helper(nums, maxIdx + 1, end); + return root; + } + + private int getMaxIdx(int[] nums, int start, int end) { + int maxVal = Integer.MIN_VALUE; + int maxIdx = -1; + while (start <= end) { + if (nums[start] > maxVal) { + maxVal = nums[start]; + maxIdx = start; + } + start++; + } + return maxIdx; + } } diff --git a/Medium/Maximum Coins Heroes Can Collect.java b/Medium/Maximum Coins Heroes Can Collect.java new file mode 100644 index 00000000..1e98abf9 --- /dev/null +++ b/Medium/Maximum Coins Heroes Can Collect.java @@ -0,0 +1,40 @@ +class Solution { + public long[] maximumCoins(int[] heroes, int[] monsters, int[] coins) { + List monsterEntities = new ArrayList<>(); + int n = monsters.length; + for (int i = 0; i < n; i++) { + monsterEntities.add(new MonsterEntity(monsters[i], coins[i])); + } + Collections.sort(monsterEntities, (a, b) -> (a.health() - b.health())); + long[] prefixCoinSum = new long[n]; + for (int i = 0; i < n; i++) { + prefixCoinSum[i] = i == 0 ? 0 : prefixCoinSum[i - 1]; + prefixCoinSum[i] += monsterEntities.get(i).coin(); + } + int m = heroes.length; + long[] result = new long[m]; + for (int i = 0; i < m; i++) { + int idx = binarySearch(monsterEntities, heroes[i]); + result[i] = idx != Integer.MIN_VALUE ? prefixCoinSum[idx] : 0; + } + return result; + } + + private int binarySearch(List monsterEntities, int heroHealth) { + int left = 0; + int right = monsterEntities.size() - 1; + int idx = Integer.MIN_VALUE; + while (left <= right) { + int mid = (left + right) / 2; + if (monsterEntities.get(mid).health() <= heroHealth) { + idx = Math.max(idx, mid); + left = mid + 1; + } else { + right = mid - 1; + } + } + return idx; + } + + private static record MonsterEntity(int health, int coin) {} +} diff --git a/Medium/Maximum Consecutive Floors Without Special Floors.java b/Medium/Maximum Consecutive Floors Without Special Floors.java new file mode 100644 index 00000000..8d33dc1e --- /dev/null +++ b/Medium/Maximum Consecutive Floors Without Special Floors.java @@ -0,0 +1,12 @@ +class Solution { + public int maxConsecutive(int bottom, int top, int[] special) { + Arrays.sort(special); + int maxConsecutiveFloors = Math.max(special[0] - bottom, top - special[special.length - 1]); + for (int specialFloor : special) { + int emptyFloors = specialFloor - bottom; + bottom = specialFloor + 1; + maxConsecutiveFloors = Math.max(maxConsecutiveFloors, emptyFloors); + } + return maxConsecutiveFloors; + } +} diff --git a/Medium/Maximum Difference Between Node and Ancestor.java b/Medium/Maximum Difference Between Node and Ancestor.java new file mode 100644 index 00000000..b623f146 --- /dev/null +++ b/Medium/Maximum Difference Between Node and Ancestor.java @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int maxAncestorDiff(TreeNode root) { + int maxDiff = 0; + Queue queue = new LinkedList<>(); + queue.add(new NodeValuePair(root, root.val, root.val)); + while (!queue.isEmpty()) { + NodeValuePair removed = queue.remove(); + TreeNode node = removed.node; + Integer minNodeValue = removed.minNodeValue; + Integer maxNodeValue = removed.maxNodeValue; + maxDiff = Math.max(maxDiff, Math.max(Math.abs(node.val - minNodeValue), Math.abs(node.val - maxNodeValue))); + Integer updatedMinNodeValue = Math.min(node.val, minNodeValue); + Integer updatedMaxNodeValue = Math.max(node.val, maxNodeValue); + if (node.left != null) { + queue.add(new NodeValuePair(node.left, updatedMinNodeValue, updatedMaxNodeValue)); + } + if (node.right != null) { + queue.add(new NodeValuePair(node.right, updatedMinNodeValue, updatedMaxNodeValue)); + } + } + return maxDiff; + } + + + private static class NodeValuePair { + private TreeNode node; + private Integer minNodeValue; + private Integer maxNodeValue; + + public NodeValuePair(TreeNode node, Integer minNodeValue, Integer maxNodeValue) { + this.node = node; + this.minNodeValue = minNodeValue; + this.maxNodeValue = maxNodeValue; + } + } +} diff --git a/Medium/Maximum Distance Between a Pair of Values.java b/Medium/Maximum Distance Between a Pair of Values.java new file mode 100644 index 00000000..f0388ec4 --- /dev/null +++ b/Medium/Maximum Distance Between a Pair of Values.java @@ -0,0 +1,26 @@ +class Solution { + public int maxDistance(int[] nums1, int[] nums2) { + int maxDistance = 0; + for (int i = 0; i < nums1.length; i++) { + int idx = getValidIdx(nums2, i, nums2.length - 1, nums1[i]); + if (idx != -1) { + maxDistance = Math.max(maxDistance, idx - i); + } + } + return maxDistance; + } + + private int getValidIdx(int[] nums, int start, int end, int limit) { + int idx = -1; + while (start <= end) { + int mid = (start + end) / 2; + if (nums[mid] >= limit) { + idx = Math.max(idx, mid); + start = mid + 1; + } else { + end = mid - 1; + } + } + return idx; + } +} diff --git a/Medium/Maximum Distance in Arrays.java b/Medium/Maximum Distance in Arrays.java new file mode 100644 index 00000000..8205803e --- /dev/null +++ b/Medium/Maximum Distance in Arrays.java @@ -0,0 +1,17 @@ +class Solution { + public int maxDistance(List> arrays) { + int result = 0; + int n = arrays.get(0).size(); + int min = arrays.get(0).get(0); + int max = arrays.get(0).get(n - 1); + for (int i = 1; i < arrays.size(); i++) { + n = arrays.get(i).size(); + result = Math.max(result, + Math.max(Math.abs(arrays.get(i).get(n - 1) - min), + Math.abs(max - arrays.get(i).get(0)))); + min = Math.min(min, arrays.get(i).get(0)); + max = Math.max(max, arrays.get(i).get(n - 1)); + } + return result; + } +} diff --git a/Medium/Maximum Erasure Value.java b/Medium/Maximum Erasure Value.java new file mode 100644 index 00000000..ff897923 --- /dev/null +++ b/Medium/Maximum Erasure Value.java @@ -0,0 +1,21 @@ +class Solution { + public int maximumUniqueSubarray(int[] nums) { + int maximumSum = 0; + int currSum = 0; + int start = 0; + int end = 0; + int n = nums.length; + Map map = new HashMap<>(); + while (end < n) { + int currNum = nums[end++]; + map.put(currNum, map.getOrDefault(currNum, 0) + 1); + currSum += currNum; + while (start < end && map.get(currNum) > 1) { + map.put(nums[start], map.getOrDefault(nums[start], 0) - 1); + currSum -= nums[start++]; + } + maximumSum = Math.max(maximumSum, currSum); + } + return maximumSum; + } +} diff --git a/Medium/Maximum Ice Cream Bars.java b/Medium/Maximum Ice Cream Bars.java new file mode 100644 index 00000000..d8faca38 --- /dev/null +++ b/Medium/Maximum Ice Cream Bars.java @@ -0,0 +1,18 @@ +class Solution { + public int maxIceCream(int[] costs, int coins) { + int[] costFrequency = new int[1000_01]; + for (int cost : costs) { + costFrequency[cost]++; + } + int numberOfIcecreams = 0; + for (int i = 1; i <= 1000_00 && coins >= i; i++) { + if (costFrequency[i] > 0) { + while (coins >= i && costFrequency[i]-- > 0) { + numberOfIcecreams++; + coins -= i; + } + } + } + return numberOfIcecreams; + } +} diff --git a/Medium/Maximum Length of Pair Chain.java b/Medium/Maximum Length of Pair Chain.java index 1ad30427..cb98b670 100644 --- a/Medium/Maximum Length of Pair Chain.java +++ b/Medium/Maximum Length of Pair Chain.java @@ -1,22 +1,14 @@ class Solution { public int findLongestChain(int[][] pairs) { - Arrays.sort(pairs, new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - return o1[0] - o2[0]; - } - }); - - int[] temp = new int[pairs.length]; - Arrays.fill(temp, 1); - for (int i=1; i a[1])); + int curr = Integer.MIN_VALUE; + int result = 0; + for (int[] pair : pairs) { + if (pair[0] > curr) { + result++; + curr = pair[1]; } } - - return Arrays.stream(temp).max().getAsInt(); + return result; } } diff --git a/Medium/Maximum Length of Repeated Subarray.java b/Medium/Maximum Length of Repeated Subarray.java new file mode 100644 index 00000000..af6696fb --- /dev/null +++ b/Medium/Maximum Length of Repeated Subarray.java @@ -0,0 +1,15 @@ +class Solution { + public int findLength(int[] nums1, int[] nums2) { + int result = 0; + int[][] dp = new int[nums1.length + 1][nums2.length + 1]; + for (int i = nums1.length - 1; i >= 0; i--) { + for (int j = nums2.length - 1; j >= 0; j--) { + if (nums1[i] == nums2[j]) { + dp[i][j] = dp[i + 1][j + 1] + 1; + result = Math.max(result, dp[i][j]); + } + } + } + return result; + } +} diff --git a/Medium/Maximum Length of Subarray With Positive Product.java b/Medium/Maximum Length of Subarray With Positive Product.java new file mode 100644 index 00000000..172d4d63 --- /dev/null +++ b/Medium/Maximum Length of Subarray With Positive Product.java @@ -0,0 +1,25 @@ +class Solution { + public int getMaxLen(int[] nums) { + int startIndex = -1; + int firstNegativeIndex = -1; + int negativeCount = 0; + int maxLen = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] < 0) { + negativeCount++; + if (firstNegativeIndex == -1) { + firstNegativeIndex = i; + } + } + else if (nums[i] == 0) { + negativeCount = 0; + firstNegativeIndex = -1; + startIndex = i; + } + maxLen = Math.max( + maxLen, (negativeCount % 2 == 0 ? i - startIndex : i - firstNegativeIndex) + ); + } + return maxLen; + } +} diff --git a/Medium/Maximum Length of a Concatenated String with Unique Characters.java b/Medium/Maximum Length of a Concatenated String with Unique Characters.java new file mode 100644 index 00000000..65ca06dc --- /dev/null +++ b/Medium/Maximum Length of a Concatenated String with Unique Characters.java @@ -0,0 +1,26 @@ +class Solution { + public int maxLength(List arr) { + return backtrack(arr, 0, new HashMap<>()); + } + + private int backtrack(List arr, int idx, Map map) { + if (map.values().stream().anyMatch(val -> val > 1)) { + return 0; + } + int result = map.size(); + for (int i = idx; i < arr.size(); i++) { + char[] chars = arr.get(i).toCharArray(); + for (char c : chars) { + map.put(c, map.getOrDefault(c, 0) + 1); + } + result = Math.max(result, backtrack(arr, i + 1, map)); + for (char c : chars) { + map.put(c, map.get(c) - 1); + if (map.get(c) == 0) { + map.remove(c); + } + } + } + return result; + } +} diff --git a/Medium/Maximum Level Sum of a Binary Tree.java b/Medium/Maximum Level Sum of a Binary Tree.java new file mode 100644 index 00000000..74c62767 --- /dev/null +++ b/Medium/Maximum Level Sum of a Binary Tree.java @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int maxLevelSum(TreeNode root) { + int maxSum = Integer.MIN_VALUE; + int maxSumLevel = 0; + int currLevel = 1; + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int levelSum = 0; + int size = queue.size(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + levelSum += removed.val; + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + if (levelSum > maxSum) { + maxSum = levelSum; + maxSumLevel = currLevel; + } + currLevel++; + } + return maxSumLevel; + } +} diff --git a/Medium/Maximum Matching of Players With Trainers.java b/Medium/Maximum Matching of Players With Trainers.java new file mode 100644 index 00000000..5334f4e5 --- /dev/null +++ b/Medium/Maximum Matching of Players With Trainers.java @@ -0,0 +1,15 @@ +class Solution { + public int matchPlayersAndTrainers(int[] players, int[] trainers) { + Arrays.sort(players); + Arrays.sort(trainers); + int playerIdx = 0; + int trainerIdx = 0; + while (playerIdx < players.length && trainerIdx < trainers.length) { + if (players[playerIdx] <= trainers[trainerIdx]) { + playerIdx++; + } + trainerIdx++; + } + return playerIdx; + } +} diff --git a/Medium/Maximum Nesting Depth of Two Valid Parentheses Strings.java b/Medium/Maximum Nesting Depth of Two Valid Parentheses Strings.java new file mode 100644 index 00000000..df70bcb7 --- /dev/null +++ b/Medium/Maximum Nesting Depth of Two Valid Parentheses Strings.java @@ -0,0 +1,11 @@ +class Solution { + public int[] maxDepthAfterSplit(String seq) { + int[] result = new int[seq.length()]; + int idx = 0; + int depth = 0; + for (char c : seq.toCharArray()) { + result[idx++] = c == '(' ? (depth++ % 2) : (--depth % 2); + } + return result; + } +} diff --git a/Medium/Maximum Number of Coins You Can Get.java b/Medium/Maximum Number of Coins You Can Get.java new file mode 100644 index 00000000..7642d7e2 --- /dev/null +++ b/Medium/Maximum Number of Coins You Can Get.java @@ -0,0 +1,11 @@ +class Solution { + public int maxCoins(int[] piles) { + Arrays.sort(piles); + int n = piles.length; + int maxCoinCount = 0; + for (int i = n / 3; i < n; i += 2) { + maxCoinCount += piles[i]; + } + return maxCoinCount; + } +} diff --git a/Medium/Maximum Number of Events That Can Be Attended.java b/Medium/Maximum Number of Events That Can Be Attended.java new file mode 100644 index 00000000..a69653b5 --- /dev/null +++ b/Medium/Maximum Number of Events That Can Be Attended.java @@ -0,0 +1,22 @@ +class Solution { + public int maxEvents(int[][] events) { + Arrays.sort(events, (a, b) -> a[0] - b[0]); + PriorityQueue pq = new PriorityQueue<>(); + int idx = 0; + int numOfEventsAttended = 0; + int n = events.length; + for (int currDay = 1; currDay <= 100000; currDay++) { + while (!pq.isEmpty() && pq.peek() < currDay) { + pq.poll(); + } + while (idx < n && events[idx][0] == currDay) { + pq.add(events[idx++][1]); + } + if (!pq.isEmpty()) { + pq.poll(); + numOfEventsAttended++; + } + } + return numOfEventsAttended; + } +} diff --git a/Medium/Maximum Number of Groups Entering a Competition.java b/Medium/Maximum Number of Groups Entering a Competition.java new file mode 100644 index 00000000..a1794f7a --- /dev/null +++ b/Medium/Maximum Number of Groups Entering a Competition.java @@ -0,0 +1,13 @@ +class Solution { + public int maximumGroups(int[] grades) { + int numOfGroups = 0; + int n = grades.length; + int groupSize = 1; + int totalGrades = 0; + while (totalGrades < n) { + totalGrades += ++groupSize; + numOfGroups++; + } + return numOfGroups; + } +} diff --git a/Medium/Maximum Number of Integers to Choose From a Range I.java b/Medium/Maximum Number of Integers to Choose From a Range I.java new file mode 100644 index 00000000..8f3ad2ee --- /dev/null +++ b/Medium/Maximum Number of Integers to Choose From a Range I.java @@ -0,0 +1,17 @@ +class Solution { + public int maxCount(int[] banned, int n, int maxSum) { + int count = 0; + Set bannedSet = Arrays.stream(banned).boxed().collect(Collectors.toSet()); + for (int i = 1; i <= n && count < n; i++) { + if (bannedSet.contains(i)) { + continue; + } + if (maxSum - i < 0) { + break; + } + count++; + maxSum -= i; + } + return count; + } +} diff --git a/Medium/Maximum Number of Moves in a Grid.java b/Medium/Maximum Number of Moves in a Grid.java new file mode 100644 index 00000000..014425f8 --- /dev/null +++ b/Medium/Maximum Number of Moves in a Grid.java @@ -0,0 +1,40 @@ +class Solution { + + private static final int[] DIRS = {-1, 0, 1}; + + public int maxMoves(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + Queue queue = new LinkedList<>(); + boolean[][] visited = new boolean[rows][cols]; + for (int i = 0; i < rows; i++) { + visited[i][0] = true; + queue.add(new int[]{i, 0, 0}); + } + int result = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + int row = removed[0]; + int col = removed[1]; + int count = removed[2]; + result = Math.max(result, count); + for (int dir : DIRS) { + int nextRow = row + dir; + int nextCol = col + 1; + if (nextRow >= 0 && + nextCol >= 0 && + nextRow < rows && + nextCol < cols && + !visited[nextRow][nextCol] && + grid[row][col] < grid[nextRow][nextCol]) { + visited[nextRow][nextCol] = true; + queue.add(new int[]{nextRow, nextCol, count + 1}); + } + } + } + } + return result; + } +} diff --git a/Medium/Maximum Number of Non-Overlapping Subarrays With Sum Equals Target.java b/Medium/Maximum Number of Non-Overlapping Subarrays With Sum Equals Target.java new file mode 100644 index 00000000..9cd5a000 --- /dev/null +++ b/Medium/Maximum Number of Non-Overlapping Subarrays With Sum Equals Target.java @@ -0,0 +1,18 @@ +class Solution { + public int maxNonOverlapping(int[] nums, int target) { + int sum = 0; + int count = 0; + Map map = new HashMap<>(); + map.put(0, -1); + int lastIdx = -1; + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + if (map.containsKey(sum - target) && map.get(sum - target) >= lastIdx) { + count++; + lastIdx = i; + } + map.put(sum, i); + } + return count; + } +} diff --git a/Medium/Maximum Number of Occurrences of a Substring.java b/Medium/Maximum Number of Occurrences of a Substring.java new file mode 100644 index 00000000..f0f56202 --- /dev/null +++ b/Medium/Maximum Number of Occurrences of a Substring.java @@ -0,0 +1,24 @@ +class Solution { + public int maxFreq(String s, int maxLetters, int minSize, int maxSize) { + Map letterFrequencyMap = new HashMap<>(); + Map substringFrequencyMap = new HashMap<>(); + int start = 0; + int maxCount = 0; + for (int i = 0; i < s.length(); i++) { + letterFrequencyMap.put(s.charAt(i), letterFrequencyMap.getOrDefault(s.charAt(i), 0) + 1); + while (i - start + 1 > minSize || letterFrequencyMap.size() > maxLetters) { + letterFrequencyMap.put(s.charAt(start), letterFrequencyMap.getOrDefault(s.charAt(start), 0) - 1); + if (letterFrequencyMap.get(s.charAt(start)) == 0) { + letterFrequencyMap.remove(s.charAt(start)); + } + start++; + } + if (i - start + 1 == minSize) { + String currSubstring = s.substring(start, i + 1); + substringFrequencyMap.put(currSubstring, substringFrequencyMap.getOrDefault(currSubstring, 0) + 1); + maxCount = Math.max(maxCount, substringFrequencyMap.get(currSubstring)); + } + } + return maxCount; + } +} diff --git a/Medium/Maximum Number of Vowels in a Substring of Given Length.java b/Medium/Maximum Number of Vowels in a Substring of Given Length.java new file mode 100644 index 00000000..0b27eda9 --- /dev/null +++ b/Medium/Maximum Number of Vowels in a Substring of Given Length.java @@ -0,0 +1,23 @@ +class Solution { + public int maxVowels(String s, int k) { + int currCount = 0; + Set vowels = Set.of('a', 'e', 'i', 'o', 'u'); + for (int i = 0; i < k - 1; i++) { + if (vowels.contains(s.charAt(i))) { + currCount++; + } + } + int maxCount = 0; + int start = 0; + for (int i = k - 1; i < s.length(); i++) { + if (vowels.contains(s.charAt(i))) { + currCount++; + } + maxCount = Math.max(maxCount, currCount); + if (vowels.contains(s.charAt(start++))) { + currCount--; + } + } + return maxCount; + } +} diff --git a/Medium/Maximum Points After Enemy Battles.java b/Medium/Maximum Points After Enemy Battles.java new file mode 100644 index 00000000..2358cd8f --- /dev/null +++ b/Medium/Maximum Points After Enemy Battles.java @@ -0,0 +1,16 @@ +class Solution { + public long maximumPoints(int[] enemyEnergies, int currentEnergy) { + long sum = 0; + int minimumEnergy = Integer.MAX_VALUE; + for (int energy : enemyEnergies) { + sum += energy; + minimumEnergy = Math.min(minimumEnergy, energy); + } + if (currentEnergy < minimumEnergy) { + return 0; + } + long totalEnergy = currentEnergy; + totalEnergy += sum - minimumEnergy; + return totalEnergy / minimumEnergy; + } +} diff --git a/Medium/Maximum Points You Can Obtain from Cards.java b/Medium/Maximum Points You Can Obtain from Cards.java new file mode 100644 index 00000000..b9648446 --- /dev/null +++ b/Medium/Maximum Points You Can Obtain from Cards.java @@ -0,0 +1,17 @@ +class Solution { + public int maxScore(int[] cardPoints, int k) { + int n = cardPoints.length; + int[] prefixSum = new int[k + 1]; + int[] suffixSum = new int[k + 1]; + for (int i = 0; i < k; i++) { + prefixSum[i + 1] = cardPoints[i] + prefixSum[i]; + suffixSum[i + 1] = cardPoints[n - i - 1] + suffixSum[i]; + } + int result = 0; + for (int i = 0; i <= k; i++) { + int currScore = prefixSum[i] + suffixSum[k - i]; + result = Math.max(result, currScore); + } + return result; + } +} diff --git a/Medium/Maximum Product Subarray.java b/Medium/Maximum Product Subarray.java index 770a69cf..a7f12091 100644 --- a/Medium/Maximum Product Subarray.java +++ b/Medium/Maximum Product Subarray.java @@ -1,17 +1,14 @@ class Solution { - public int maxProduct(int[] nums) { - int max = nums[0]; - int min = nums[0]; - int maxGlobal = max; - - for (int i = 1; i < nums.length; i++) { - int temp = max; - max = Math.max(Math.max(nums[i] * temp, nums[i] * min), nums[i]); - min = Math.min(Math.min(nums[i] * temp, nums[i] * min), nums[i]); - - maxGlobal = Math.max(max, maxGlobal); - } - - return maxGlobal; + public int maxProduct(int[] nums) { + int currMax = nums[0]; + int currMin = nums[0]; + int maxProd = currMax; + for (int i = 1; i < nums.length; i++) { + int temp = currMax; + currMax = Math.max(Math.max(temp * nums[i], currMin * nums[i]), nums[i]); + currMin = Math.min(Math.min(temp * nums[i], currMin * nums[i]), nums[i]); + maxProd = Math.max(maxProd, currMax); } + return maxProd; + } } diff --git a/Medium/Maximum Product of Splitted Binary Tree.java b/Medium/Maximum Product of Splitted Binary Tree.java new file mode 100644 index 00000000..72a36750 --- /dev/null +++ b/Medium/Maximum Product of Splitted Binary Tree.java @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int maxProduct(TreeNode root) { + List allNodeSums = new ArrayList<>(); + long totalSum = treeSum(root, allNodeSums); + long best = 0; + for (long sum : allNodeSums) { + best = Math.max(best, sum * (totalSum - sum)); + } + return (int) (best % 1000_000_007); + } + + private int treeSum(TreeNode root, List allNodeSums) { + if (root == null) { + return 0; + } + int leftSum = treeSum(root.left, allNodeSums); + int rightSum = treeSum(root.right, allNodeSums); + int totalSum = leftSum + rightSum + root.val; + allNodeSums.add(totalSum); + return totalSum; + } +} diff --git a/Medium/Maximum Product of Word Lengths.java b/Medium/Maximum Product of Word Lengths.java new file mode 100644 index 00000000..d98a03bb --- /dev/null +++ b/Medium/Maximum Product of Word Lengths.java @@ -0,0 +1,25 @@ +class Solution { + public int maxProduct(String[] words) { + int maxProd = 0; + for (int i = 0; i < words.length; i++) { + for (int j = i + 1; j < words.length; j++) { + if (noCommonLetters(words[i], words[j])) { + maxProd = Math.max(maxProd, words[i].length() * words[j].length()); + } + } + } + return maxProd; + } + + private boolean noCommonLetters(String s1, String s2) { + int bitMaskOne = 0; + int bitMaskTwo = 0; + for (char c : s1.toCharArray()) { + bitMaskOne |= 1 << ((int) c - (int) 'a'); + } + for (char c : s2.toCharArray()) { + bitMaskTwo |= 1 << ((int) c - (int) 'a'); + } + return (bitMaskOne & bitMaskTwo) == 0; + } +} diff --git a/Medium/Maximum Score From Removing Stones.java b/Medium/Maximum Score From Removing Stones.java new file mode 100644 index 00000000..bdc88bcb --- /dev/null +++ b/Medium/Maximum Score From Removing Stones.java @@ -0,0 +1,19 @@ +class Solution { + public int maximumScore(int a, int b, int c) { + PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder()); + pq.addAll(Arrays.asList(a, b, c)); + int score = 0; + while (pq.size() > 1) { + int firstStoneCount = pq.remove(); + int secondStoneCount = pq.remove(); + if (firstStoneCount > 1) { + pq.add(firstStoneCount - 1); + } + if (secondStoneCount > 1) { + pq.add(secondStoneCount - 1); + } + score++; + } + return score; + } +} diff --git a/Medium/Maximum Score From Removing Substrings.java b/Medium/Maximum Score From Removing Substrings.java new file mode 100644 index 00000000..0f7ccf87 --- /dev/null +++ b/Medium/Maximum Score From Removing Substrings.java @@ -0,0 +1,29 @@ +class Solution { + public int maximumGain(String s, int x, int y) { + int score = 0; + String firstPass = removeSubstring(s, x > y ? "ab" : "ba"); + int removeCount = (s.length() - firstPass.length()) / 2; + score += removeCount * Math.max(x, y); + String secondPass = removeSubstring(firstPass, x > y ? "ba" : "ab"); + removeCount = (firstPass.length() - secondPass.length()) / 2; + score += removeCount * Math.min(x, y); + return score; + } + + private String removeSubstring(String s, String target) { + Stack stack = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == target.charAt(1) && !stack.isEmpty() && stack.peek() == target.charAt(0)) { + stack.pop(); + } else { + stack.push(c); + } + } + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + sb.append(stack.pop()); + } + return sb.reverse().toString(); + } +} diff --git a/Medium/Maximum Score from Performing Multiplication Operations.java b/Medium/Maximum Score from Performing Multiplication Operations.java new file mode 100644 index 00000000..c197f348 --- /dev/null +++ b/Medium/Maximum Score from Performing Multiplication Operations.java @@ -0,0 +1,19 @@ +class Solution { + public int maximumScore(int[] nums, int[] multipliers) { + Integer[][] dp = new Integer[1001][1001]; + return helper(0, multipliers, nums, 0, dp); + } + + private int helper(int idx, int[] multipliers, int[] nums, int start, Integer[][] dp) { + if (idx == multipliers.length) { + return 0; + } + if (dp[idx][start] != null) { + return dp[idx][start]; + } + int end = nums.length - (idx - start) - 1; + int startOperation = multipliers[idx] * nums[start] + helper(idx + 1, multipliers, nums, start + 1, dp); + int endOperation = multipliers[idx] * nums[end] + helper(idx + 1, multipliers, nums, start, dp); + return dp[idx][start] = Math.max(startOperation, endOperation); + } +} diff --git a/Medium/Maximum Size Subarray Sum Equals k.java b/Medium/Maximum Size Subarray Sum Equals k.java index a8d97e05..dce7007a 100644 --- a/Medium/Maximum Size Subarray Sum Equals k.java +++ b/Medium/Maximum Size Subarray Sum Equals k.java @@ -1,23 +1,17 @@ class Solution { - public static int maxSubArrayLen(int[] nums, int k) { + public int maxSubArrayLen(int[] nums, int k) { Map map = new HashMap<>(); - int sum = 0; + int prefixSum = 0; int max = 0; - - map.put(0, -1); - - for (int i=0; i> graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], node -> new PriorityQueue<>(Comparator.reverseOrder())).add(vals[edge[1]]); + graph.computeIfAbsent(edge[1], node -> new PriorityQueue<>(Comparator.reverseOrder())).add(vals[edge[0]]); + } + int maxSum = Integer.MIN_VALUE; + for (int i = 0; i < vals.length; i++) { + int currSum = vals[i]; + PriorityQueue pq = graph.getOrDefault(i, new PriorityQueue<>()); + for (int j = 0; j < k && !pq.isEmpty(); j++){ + currSum += Math.max(pq.poll(), 0); + } + maxSum = Math.max(maxSum, currSum); + } + return maxSum; + } +} diff --git a/Medium/Maximum Subarray.java b/Medium/Maximum Subarray.java new file mode 100644 index 00000000..459a8733 --- /dev/null +++ b/Medium/Maximum Subarray.java @@ -0,0 +1,14 @@ +class Solution { + public int maxSubArray(int[] nums) { + int currSum = 0; + int maxSum = Integer.MIN_VALUE; + for (int num : nums) { + currSum += num; + if (currSum < num) { + currSum = num; + } + maxSum = Math.max(maxSum, currSum); + } + return maxSum; + } +} diff --git a/Medium/Maximum Subsequence Score.java b/Medium/Maximum Subsequence Score.java new file mode 100644 index 00000000..2598f5ed --- /dev/null +++ b/Medium/Maximum Subsequence Score.java @@ -0,0 +1,23 @@ +class Solution { + public long maxScore(int[] nums1, int[] nums2, int k) { + int[][] combined = new int[nums1.length][2]; + for (int i = 0; i < nums1.length; i++) { + combined[i] = new int[]{nums1[i], nums2[i]}; + } + Arrays.sort(combined, (o1, o2) -> o2[1] - o1[1]); + long result = 0; + long total = 0; + PriorityQueue pq = new PriorityQueue<>(); + for (int[] unit : combined) { + pq.add(unit[0]); + total += unit[0]; + if (pq.size() > k) { + total -= pq.poll(); + } + if (pq.size() == k) { + result = Math.max(result, total * unit[1]); + } + } + return result; + } +} diff --git a/Medium/Maximum Sum of Almost Unique Subarray.java b/Medium/Maximum Sum of Almost Unique Subarray.java new file mode 100644 index 00000000..1d9facff --- /dev/null +++ b/Medium/Maximum Sum of Almost Unique Subarray.java @@ -0,0 +1,28 @@ +class Solution { + public long maxSum(List nums, int m, int k) { + long result = 0; + long currSum = 0; + Map frequencyMap = new HashMap<>(); + int uniqueCount = 0; + for (int i = 0; i < nums.size(); i++) { + int curr = nums.get(i); + frequencyMap.put(curr, frequencyMap.getOrDefault(curr, 0) + 1); + if (frequencyMap.get(curr) == 1) { + uniqueCount++; + } + currSum += curr; + if (i >= k - 1) { + if (uniqueCount >= m) { + result = Math.max(result, currSum); + } + int temp = nums.get(i - k + 1); + frequencyMap.put(temp, frequencyMap.getOrDefault(temp, 0) - 1); + if (frequencyMap.get(temp) == 0) { + uniqueCount--; + } + currSum -= temp; + } + } + return result; + } +} diff --git a/Medium/Maximum Sum of Distinct Subarrays With Length K.java b/Medium/Maximum Sum of Distinct Subarrays With Length K.java new file mode 100644 index 00000000..044ad0bd --- /dev/null +++ b/Medium/Maximum Sum of Distinct Subarrays With Length K.java @@ -0,0 +1,26 @@ +class Solution { + public long maximumSubarraySum(int[] nums, int k) { + Map map = new HashMap<>(); + long currSum = 0; + long maxSum = 0; + for (int i = 0; i < k - 1; i++) { + map.put(nums[i], map.getOrDefault(nums[i], 0) + 1); + currSum += nums[i]; + } + int startIdx = 0; + for (int i = k - 1; i < nums.length; i++) { + map.put(nums[i], map.getOrDefault(nums[i], 0) + 1); + currSum += nums[i]; + if (map.size() == k) { + maxSum = Math.max(maxSum, currSum); + } + map.put(nums[startIdx], map.get(nums[startIdx]) - 1); + if (map.get(nums[startIdx]) == 0) { + map.remove(nums[startIdx]); + } + currSum -= nums[startIdx]; + startIdx++; + } + return maxSum; + } +} diff --git a/Medium/Maximum Sum of an Hourglass.java b/Medium/Maximum Sum of an Hourglass.java new file mode 100644 index 00000000..c819295a --- /dev/null +++ b/Medium/Maximum Sum of an Hourglass.java @@ -0,0 +1,22 @@ +class Solution { + + private static final int[][] coordinates = {{0, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, {2, 1}, {2, 2}}; + + public int maxSum(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + int highestHourglassSum = 0; + for (int i = 0; i < rows - 2; i++) { + for (int j = 0; j < cols - 2; j++) { + int currSum = 0; + for (int[] coordinate : coordinates) { + int x = i + coordinate[0]; + int y = j + coordinate[1]; + currSum += grid[x][y]; + } + highestHourglassSum = Math.max(highestHourglassSum, currSum); + } + } + return highestHourglassSum; + } +} diff --git a/Medium/Maximum Swap.java b/Medium/Maximum Swap.java new file mode 100644 index 00000000..c12fb12e --- /dev/null +++ b/Medium/Maximum Swap.java @@ -0,0 +1,20 @@ +class Solution { + public int maximumSwap(int num) { + char[] digits = String.valueOf(num).toCharArray(); + int n = digits.length; + int[] maxRightIdx = new int[n]; + maxRightIdx[n - 1] = n - 1; + for (int i = n - 2; i >= 0; i--) { + maxRightIdx[i] = (digits[i] > digits[maxRightIdx[i + 1]]) ? i : maxRightIdx[i + 1]; + } + for (int i = 0; i < n; i++) { + if (digits[i] < digits[maxRightIdx[i]]) { + char temp = digits[i]; + digits[i] = digits[maxRightIdx[i]]; + digits[maxRightIdx[i]] = temp; + return Integer.parseInt(String.valueOf(digits)); + } + } + return num; + } +} diff --git a/Medium/Maximum Total Importance of Roads.java b/Medium/Maximum Total Importance of Roads.java new file mode 100644 index 00000000..52e5eea7 --- /dev/null +++ b/Medium/Maximum Total Importance of Roads.java @@ -0,0 +1,17 @@ +class Solution { + public long maximumImportance(int n, int[][] roads) { + int[] outDegree = new int[n]; + for (int[] road : roads) { + outDegree[road[0]]++; + outDegree[road[1]]++; + } + Arrays.sort(outDegree); + long totalImportance = 0; + long importanceMultiple = 1L; + for (int count : outDegree) { + totalImportance += importanceMultiple * count; + importanceMultiple++; + } + return totalImportance; + } +} diff --git a/Medium/Maximum Twin Sum of a Linked List.java b/Medium/Maximum Twin Sum of a Linked List.java new file mode 100644 index 00000000..5f6b44bd --- /dev/null +++ b/Medium/Maximum Twin Sum of a Linked List.java @@ -0,0 +1,41 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public int pairSum(ListNode head) { + ListNode slow = head; + ListNode fast = head.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + fast = reverse(slow.next); + slow.next = null; + slow = head; + int maxSum = 0; + for (; slow != null && fast != null; slow = slow.next, fast = fast.next) { + maxSum = Math.max(maxSum, slow.val + fast.val); + } + return maxSum; + } + + private ListNode reverse(ListNode node) { + ListNode curr = node; + ListNode prev = null; + ListNode next = null; + while (curr != null) { + next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } +} diff --git a/Medium/Maximum Value after Insertion.java b/Medium/Maximum Value after Insertion.java new file mode 100644 index 00000000..78213f9b --- /dev/null +++ b/Medium/Maximum Value after Insertion.java @@ -0,0 +1,18 @@ +class Solution { + public String maxValue(String n, int x) { + if (n.charAt(0) == '-') { + for (int i = 1; i < n.length(); i++) { + if (Character.getNumericValue(n.charAt(i)) > x) { + return "-" + n.substring(1, i) + x + n.substring(i); + } + } + } else { + for (int i = 0; i < n.length(); i++) { + if (Character.getNumericValue(n.charAt(i)) < x) { + return n.substring(0, i) + x + n.substring(i); + } + } + } + return n + x; + } +} diff --git a/Medium/Maximum Value at a Given Index in a Bounded Array.java b/Medium/Maximum Value at a Given Index in a Bounded Array.java new file mode 100644 index 00000000..6a1a4966 --- /dev/null +++ b/Medium/Maximum Value at a Given Index in a Bounded Array.java @@ -0,0 +1,30 @@ +class Solution { + public int maxValue(int n, int index, int maxSum) { + int start = 1; + int end = maxSum; + while (start < end) { + int mid = (start + end + 1) / 2; + if (findSum(index, mid, n) <= maxSum) { + start = mid; + } else { + end = mid - 1; + } + } + return start; + } + + private long findSum(int index, int targetIndex, int n) { + long count = 0; + if (targetIndex > index) { + count += (long) (2 * targetIndex - index) * (index + 1) / 2; + } else { + count += (long) (targetIndex + 1) * targetIndex / 2 + index - targetIndex + 1; + } + if (targetIndex >= n - index) { + count += (long) (targetIndex + targetIndex - n + 1 + index) * (n - index) / 2; + } else { + count += (long) (targetIndex + 1) * targetIndex / 2 + n - index - targetIndex; + } + return count - targetIndex; + } +} diff --git a/Medium/Maximum Width Ramp.java b/Medium/Maximum Width Ramp.java index 37eb1862..2463f02b 100644 --- a/Medium/Maximum Width Ramp.java +++ b/Medium/Maximum Width Ramp.java @@ -1,21 +1,18 @@ class Solution { - public int maxWidthRamp(int[] A) { + public int maxWidthRamp(int[] nums) { + int n = nums.length; Stack stack = new Stack<>(); - int ans = 0; - int n = A.length; - - for (int i=0; i A[i]) { - stack.add(i); + for (int i = 0; i < n; i++) { + if (stack.isEmpty() || nums[stack.peek()] > nums[i]) { + stack.push(i); } } - - for (int i=n-1; i>=ans; i--) { - while (!stack.isEmpty() && A[stack.peek()] <= A[i]) { - ans = Math.max(ans, i - stack.pop()); + int result = 0; + for (int i = n - 1; i >= 0; i--) { + while (!stack.isEmpty() && nums[stack.peek()] <= nums[i]) { + result = Math.max(result, i - stack.pop()); } } - - return ans; + return result; } } diff --git a/Medium/Maximum Width of Binary Tree.java b/Medium/Maximum Width of Binary Tree.java index 0cccc71c..d5edef7e 100644 --- a/Medium/Maximum Width of Binary Tree.java +++ b/Medium/Maximum Width of Binary Tree.java @@ -4,42 +4,40 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { public int widthOfBinaryTree(TreeNode root) { if (root == null) { - return 1; + return 0; } - - int size = 0; - Queue queue = new LinkedList<>(); - Map map = new HashMap<>(); - map.put(root, 0); - queue.add(root); - + Queue queue = new LinkedList<>(); + queue.add(new NodeColIndex(root, 0)); + int maxWidth = 0; while (!queue.isEmpty()) { - int len = queue.size(); - int leftPos = map.get(queue.peek()); - - for (int i=0; i= 0; i--) { + int currBit = (num >>> i) & 1; + if (curr.children[currBit] == null) { + curr.children[currBit] = new Trie(); + } + curr = curr.children[currBit]; + } + } + int maxVal = Integer.MIN_VALUE; + for (int num : nums) { + Trie curr = root; + int currVal = 0; + for (int i = 31; i >= 0; i--) { + int currBit = (num >>> i) & 1; + if (curr.children[currBit ^ 1] != null) { + currVal += (1 << i); + curr = curr.children[currBit ^ 1]; + } + else { + curr = curr.children[currBit]; + } + } + maxVal = Math.max(maxVal, currVal); + } + return maxVal; + } +} + +class Trie { + Trie[] children; + public Trie() { + children = new Trie[2]; + } +} diff --git a/Medium/Maximum of Absolute Value Expression.java b/Medium/Maximum of Absolute Value Expression.java new file mode 100644 index 00000000..96291add --- /dev/null +++ b/Medium/Maximum of Absolute Value Expression.java @@ -0,0 +1,18 @@ +class Solution { + public int maxAbsValExpr(int[] arr1, int[] arr2) { + int res = 0; + int n = arr1.length; + int[] dirs = {-1,1}; + for (int dir1 : dirs) { + for (int dir2 : dirs) { + int closest = dir1 * arr1[0] + dir2 * arr2[0] + 0; + for (int i = 1; i < n; ++i) { + int cur = dir1 * arr1[i] + dir2 * arr2[i] + i; + res = Math.max(res, cur - closest); + closest = Math.min(closest, cur); + } + } + } + return res; + } +} diff --git a/Medium/Medium.md b/Medium/Medium.md new file mode 100644 index 00000000..6cea41be --- /dev/null +++ b/Medium/Medium.md @@ -0,0 +1,333 @@ +# Medium LeetCode-Java-Solutions +S.no | Coding Problem +--- | --- +1|[Range Sum Query 2D-Immutable](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRange Sum Query 2D-Immutable.java) +2|[Combination Sum III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCombination Sum III.java) +3|[Divide Two Integers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDivide Two Integers.java) +4|[Ugly Number II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumUgly Number II.java) +5|[Set Matrix Zeroes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSet Matrix Zeroes.java) +6|[Container With Most Water](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumContainer With Most Water.java) +7|[Spiral Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSpiral Matrix.java) +8|[Rabbits in Forest](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRabbits in Forest.java) +9|[Binary Tree Vertical Order Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Vertical Order Traversal.java) +10|[Basic Calculator II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBasic Calculator II.java) +11|[Corporate Flight Bookings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCorporate Flight Bookings.java) +12|[Custom Sort String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCustom Sort String.java) +13|[Minimum Moves to Equal Array Elements II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinimum Moves to Equal Array Elements II.java) +14|[Rotate List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRotate List.java) +15|[Flatten Nested List Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFlatten Nested List Iterator.java) +16|[Minimum Number of Arrows to Burst Balloons](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinimum Number of Arrows to Burst Balloons.java) +17|[Count Complete Tree Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCount Complete Tree Nodes.java) +18|[Search in Rotated Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSearch in Rotated Sorted Array.java) +19|[Subarray Product Less Than K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSubarray Product Less Than K.java) +20|[Unique Binary Search Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumUnique Binary Search Trees.java) +21|[Shuffle an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumShuffle an Array.java) +22|[Permutation in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPermutation in String.java) +23|[Flatten a Multilevel Doubly Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFlatten a Multilevel Doubly Linked List.java) +24|[Search in Rotated Sorted Array II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSearch in Rotated Sorted Array II.java) +25|[Pour Water](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPour Water.java) +26|[Find Leaves of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Leaves of Binary Tree.java) +27|[Majority Element II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMajority Element II.java) +28|[Course Schedule II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCourse Schedule II.java) +29|[Design Circular Queue](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Circular Queue.java) +30|[Battleships in a board](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBattleships in a board.java) +31|[Next Greater Element III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNext Greater Element III.java) +32|[Linked List Components](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLinked List Components.java) +33|[Multiply Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMultiply Strings.java) +34|[Convert Binary Search Tree to Sorted Doubly Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumConvert Binary Search Tree to Sorted Doubly Linked List.java) +35|[Add One Row to Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAdd One Row to Tree.java) +36|[Binary Tree Pruning](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Pruning.java) +37|[Word Break](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWord Break.java) +38|[Interval List Intersections](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInterval List Intersections.java) +39|[Pow](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPow.java) +40|[Daily Temperatures](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDaily Temperatures.java) +41|[Implement Rand10() Using Rand7()](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumImplement Rand10() Using Rand7().java) +42|[Palindromic Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPalindromic Substrings.java) +43|[Reverse Substrings Between Each Pair of Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReverse Substrings Between Each Pair of Parentheses.java) +44|[Design File System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign File System.java) +45|[Lowest Common Ancestor of Deepest Leaves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLowest Common Ancestor of Deepest Leaves.java) +46|[Grumpy Bookstore Owner](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumGrumpy Bookstore Owner.java) +47|[Remove Duplicates From Sorted Array II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRemove Duplicates From Sorted Array II.java) +48|[Validate IP Address](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumValidate IP Address.java) +49|[Boats to Save People](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBoats to Save People.java) +50|[Ternary Expression Parser](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTernary Expression Parser.java) +51|[Find Peak Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Peak Element.java) +52|[Design Tic-Tac-Toe](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Tic-Tac-Toe.java) +53|[Keys and Rooms](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumKeys and Rooms.java) +54|[Counting Bits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCounting Bits.java) +55|[Split Linked List into Parts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSplit Linked List into Parts.java) +56|[Number of Connected Components in an Undirected Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNumber of Connected Components in an Undirected Graph.java) +57|[Task Scheduler](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTask Scheduler.java) +58|[Online Election](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumOnline Election.java) +59|[Maximum Width Ramp](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Width Ramp.java) +60|[Time Based Key-Value Store](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTime Based Key-Value Store.java) +61|[Sum Root to Leaf Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSum Root to Leaf Numbers.java) +62|[Kth Largest Element in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumKth Largest Element in an Array.java) +63|[Bitwise AND of Numbers Range](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBitwise AND of Numbers Range.java) +64|[Binary Tree Longest Consecutive Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Longest Consecutive Sequence.java) +65|[Largest BST Subtree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLargest BST Subtree.java) +66|[Populating Next Right Pointers in Each Node II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPopulating Next Right Pointers in Each Node II.java) +67|[Online Stock Span](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumOnline Stock Span.java) +68|[Combination Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCombination Sum II.java) +69|[Insert Into a Cyclic Sorted List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInsert Into a Cyclic Sorted List.java) +70|[Reconstruct Itinerary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReconstruct Itinerary.java) +71|[Partition Labels](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPartition Labels.java) +72|[Distribute Coins in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDistribute Coins in Binary Tree.java) +73|[Longest Palindromic Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Palindromic Substring.java) +74|[Simplify Path](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSimplify Path.java) +75|[Zigzag Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumZigzag Iterator.java) +76|[Max Chunks To Make Sorted](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMax Chunks To Make Sorted.java) +77|[Is Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumIs Subsequence.java) +78|[Reverse Linked List II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReverse Linked List II.java) +79|[Complex Number Multiplication](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumComplex Number Multiplication.java) +80|[Maximum Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Binary Tree.java) +81|[Meeting Rooms II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMeeting Rooms II.java) +82|[Fraction to Recurring Decimal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFraction to Recurring Decimal.java) +83|[Add and Search Word - Data structure design](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAdd and Search Word - Data structure design.java) +84|[Super Ugly Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSuper Ugly Number.java) +85|[Escape The Ghosts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumEscape The Ghosts.java) +86|[Max Increase to Keep City Skyline](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMax Increase to Keep City Skyline.java) +87|[Minimum Path Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinimum Path Sum.java) +88|[Valid Tic-Tac-Toe State](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumValid Tic-Tac-Toe State.java) +89|[Shortest Completing Word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumShortest Completing Word.java) +90|[01 Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium01 Matrix.java) +91|[As Far from Land as Possible](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAs Far from Land as Possible.java) +92|[Number of Matching Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNumber of Matching Subsequence.java) +93|[Car Pooling](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCar Pooling.java) +94|[Generate Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumGenerate Parentheses.java) +95|[Exclusive Time of Functions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumExclusive Time of Functions.java) +96|[Sort Characters By Frequency](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSort Characters By Frequency.java) +97|[Max Consecutives Ones II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMax Consecutives Ones II.java) +98|[Number of Islands](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNumber of Islands.java) +99|[Reverse Words in a String II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReverse Words in a String II.java) +100|[Binary Tree Upside Down](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Upside Down.java) +101|[Count Univalue Subtrees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCount Univalue Subtrees.java) +102|[Split BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSplit BST.java) +103|[All Possible Full Binary Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAll Possible Full Binary Trees.java) +104|[Convert Sorted List to Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumConvert Sorted List to Binary Search Tree.java) +105|[Word Search](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWord Search.java) +106|[Add Two Numbers II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAdd Two Numbers II.java) +107|[Sort List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSort List.java) +108|[Gray Code](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumGray Code.java) +109|[Rotate Function](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRotate Function.java) +110|[Bulb Switcher](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBulb Switcher.java) +111|[Implement Trie (Prefix Tree)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumImplement Trie (Prefix Tree).java) +112|[Contains Duplicate III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumContains Duplicate III.java) +113|[Copy List with Random Pointer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCopy List with Random Pointer.java) +114|[Design Hit Counter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Hit Counter.java) +115|[Binary Tree Inorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Inorder Traversal.java) +116|[Maximum Product Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Product Subarray.java) +117|[Prison Cells After N Days](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPrison Cells After N Days.java) +118|[Evaluate Reverse Polish Notation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumEvaluate Reverse Polish Notation.java) +119|[H-Index](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumH-Index.java) +120|[Mini Parser](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMini Parser.java) +121|[Line Reflection](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLine Reflection.java) +122|[Linked List Cycle II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLinked List Cycle II.java) +123|[Minimum Size Subarray Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinimum Size Subarray Sum.java) +124|[Next Greater Element II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNext Greater Element II.java) +125|[Decode String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDecode String.java) +126|[Unique Paths II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumUnique Paths II.java) +127|[Shifting Letters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumShifting Letters.java) +128|[Subarray Sum Equals K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSubarray Sum Equals K.java) +129|[Graph Valid Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumGraph Valid Tree.java) +130|[Flatten Binary Tree to Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFlatten Binary Tree to Linked List.java) +131|[Top K Frequent Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTop K Frequent Elements.java) +132|[Find First and Last Position of Element in Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind First and Last Position of Element in Sorted Array.java) +133|[Broken Calculator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBroken Calculator.java) +134|[Design Twitter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Twitter.java) +135|[Nested List Weight Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNested List Weight Sum II.java) +136|[Permutations II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPermutations II.java) +137|[Sort An Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSort An Array.java) +138|[Construct Quad Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumConstruct Quad Tree.java) +139|[Game of Life](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumGame of Life.java) +140|[Remove Nth Node From End of List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRemove Nth Node From End of List.java) +141|[Random Pick Index](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRandom Pick Index.java) +142|[My Calendar II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMy Calendar II.java) +143|[Search for a range](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSearch for a range.java) +144|[Binary Tree Right Side View](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Right Side View.java) +145|[Longest Substring Without Repeating Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Substring Without Repeating Characters.java) +146|[Single Number III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSingle Number III.java) +147|[Candy Crush](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCandy Crush.java) +148|[Web Crawler](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWeb Crawler.java) +149|[Lonely Pixel I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLonely Pixel I.java) +150|[Reorganize String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReorganize String.java) +151|[Insertion Sort List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInsertion Sort List.java) +152|[Peeking Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPeeking Iterator.java) +153|[Reorder List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReorder List.java) +154|[Unique Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumUnique Paths.java) +155|[Reconstruct Original Digits from English](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReconstruct Original Digits from English.java) +156|[Walls and Gates](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWalls and Gates.java) +157|[Total Hamming Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTotal Hamming Distance.java) +158|[Rectangle Area](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRectangle Area.java) +159|[Binary Search Tree to Greater Sum Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Search Tree to Greater Sum Tree.java) +160|[Longest Absolute File Path](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Absolute File Path.java) +161|[Single Element in a Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSingle Element in a Sorted Array.java) +162|[Binary Search Tree Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Search Tree Iterator.java) +163|[Find K Closest Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind K Closest Elements.java) +164|[Rotate Image](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRotate Image.java) +165|[Next Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNext Permutation.java) +166|[Design Phone Directory](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Phone Directory.java) +167|[Jump Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumJump Game.java) +168|[H-Index II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumH-Index II.java) +169|[Subarray Sums Divisible by K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSubarray Sums Divisible by K.java) +170|[Kill Process](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumKill Process.java) +171|[Boundary of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBoundary of Binary Tree.java) +172|[Course Schedule](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCourse Schedule.java) +173|[Insert Delete GetRandom O(1)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInsert Delete GetRandom O(1).java) +174|[Coin Change 2](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCoin Change 2.java) +175|[Find Duplicate Subtrees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Duplicate Subtrees.java) +176|[Letter Tiles Possibilities](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLetter Tiles Possibilities.java) +177|[Palindrome Partitioning](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPalindrome Partitioning.java) +178|[Longest Palindromic Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Palindromic Subsequence.java) +179|[Expressive Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumExpressive Words.java) +180|[Linked List Random Node](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLinked List Random Node.java) +181|[Find Minimum in Rotated Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Minimum in Rotated Sorted Array.java) +182|[3Sum Closest](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium3Sum Closest.java) +183|[Permutations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPermutations.java) +184|[Next Greater Node In Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNext Greater Node In Linked List.java) +185|[Map Sum Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMap Sum Pairs.java) +186|[Minimum Genetic Mutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinimum Genetic Mutation.java) +187|[Maximum Binary Tree II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Binary Tree II.java) +188|[Delete Operation for Two Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDelete Operation for Two Strings.java) +189|[Inorder Successor in BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInorder Successor in BST.java) +190|[Array Nesting](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumArray Nesting.java) +191|[Output Contest Matches](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumOutput Contest Matches.java) +192|[Serialize and Deserialize BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSerialize and Deserialize BST.java) +193|[Find the duplicate number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind the duplicate number.java) +194|[Single Number II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSingle Number II.java) +195|[Statistics from a Large Sample](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumStatistics from a Large Sample.java) +196|[Accounts Merge](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAccounts Merge.java) +197|[Reverse Words in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReverse Words in a String.java) +198|[Find Duplicate File in System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Duplicate File in System.java) +199|[Delete Node in a BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDelete Node in a BST.java) +200|[Is Graph Bipartite](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumIs Graph Bipartite.java) +201|[Minesweeper](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinesweeper.java) +202|[Remove K Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRemove K Digits.java) +203|[Next Closest Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNext Closest Time.java) +204|[Self Dividing Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSelf Dividing Numbers.java) +205|[Replace Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReplace Words.java) +206|[Longest Increasing Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Increasing Subsequence.java) +207|[Find Right Interval](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Right Interval.java) +208|[Non Overlapping Intervals](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNon Overlapping Intervals.java) +209|[Range Addition](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRange Addition.java) +210|[3Sum Smaller](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium3Sum Smaller.java) +211|[Shortest Way to Form String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumShortest Way to Form String.java) +212|[Missing Element in Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMissing Element in Sorted Array.java) +213|[Insufficient Nodes in Root to Leaf Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInsufficient Nodes in Root to Leaf Paths.java) +214|[Maximum Width of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Width of Binary Tree.java) +215|[Product of Array Except self](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumProduct of Array Except self.java) +216|[Sort Colors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSort Colors.java) +217|[Arithmetic Slices](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumArithmetic Slices.java) +218|[Number of Dice Rolls With Target Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNumber of Dice Rolls With Target Sum.java) +219|[Perfect Squares](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPerfect Squares.java) +220|[Search a 2D Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSearch a 2D Matrix.java) +221|[Satisfisbility of Equality Equations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSatisfisbility of Equality Equations.java) +222|[Maximum Length of Pair Chain](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Length of Pair Chain.java) +223|[Queue Reconstruction By Height](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumQueue Reconstruction By Height.java) +224|[Bulls and Cows](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBulls and Cows.java) +225|[Unique Word Abbrevation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumUnique Word Abbrevation.java) +226|[Range Sum Query - Mutable](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRange Sum Query - Mutable.java) +227|[Delete Nodes And Return Forest](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDelete Nodes And Return Forest.java) +228|[4Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium4Sum.java) +229|[Missing Ranges](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMissing Ranges.java) +230|[Sentence Similarity II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSentence Similarity II.java) +231|[Evaluate Division](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumEvaluate Division.java) +232|[Find K Pairs with Smallest Sums](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind K Pairs with Smallest Sums.java) +233|[Partition List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPartition List.java) +234|[Encode and Decode Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumEncode and Decode Strings.java) +235|[Decrease Elements To Make Array Zigzag](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDecrease Elements To Make Array Zigzag.java) +236|[Maximum Level Sum of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Level Sum of a Binary Tree.java) +237|[All Nodes Distance K in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAll Nodes Distance K in Binary Tree.java) +238|[Design Circular Deque](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Circular Deque.java) +239|[Design Log Storage System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDesign Log Storage System.java) +240|[Decode Ways](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDecode Ways.java) +241|[Sort Transformed Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSort Transformed Array.java) +242|[Wiggle Sort](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWiggle Sort.java) +243|[Path Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPath Sum II.java) +244|[Subsets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSubsets.java) +245|[Increasing Subsequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumIncreasing Subsequences.java) +246|[Number of Distinct Islands](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNumber of Distinct Islands.java) +247|[Add Two Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAdd Two Numbers.java) +248|[Fruit Into Baskets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFruit Into Baskets.java) +249|[Lowest Common Ancestor of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLowest Common Ancestor of a Binary Tree.java) +250|[Complete Binary Tree Insertor](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumComplete Binary Tree Insertor.java) +251|[Clone Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumClone Graph.java) +252|[Binary Tree Preorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Preorder Traversal.java) +253|[Random Pick With Weight](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRandom Pick With Weight.java) +254|[Vertical Order Traversal Of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumVertical Order Traversal Of Binary Tree.java) +255|[Remove Duplicates from Sorted List II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRemove Duplicates from Sorted List II.java) +256|[Search in a Sorted Array of Unknown Size](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSearch in a Sorted Array of Unknown Size.java) +257|[Rectangle Overlap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRectangle Overlap.java) +258|[Analyze User Website Visit Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAnalyze User Website Visit Pattern.java) +259|[Combination Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCombination Sum.java) +260|[Solve the Equation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSolve the Equation.java) +261|[The Earliest Moment When Everyone Become Friends](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumThe Earliest Moment When Everyone Become Friends.java) +262|[Verify Preorder Serialization of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumVerify Preorder Serialization of a Binary Tree.java) +263|[Optimal Division](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumOptimal Division.java) +264|[Score of Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumScore of Parentheses.java) +265|[Merge Intervals](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMerge Intervals.java) +266|[Kth Smallest Element in a BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumKth Smallest Element in a BST.java) +267|[Coin Change](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCoin Change.java) +268|[Find the Celebrity](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind the Celebrity.java) +269|[Array Circular Loop](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumArray Circular Loop.java) +270|[Snapshot Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSnapshot Array.java) +271|[Top K Frequent Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTop K Frequent Words.java) +272|[Asteroid Collision](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAsteroid Collision.java) +273|[Encode and Decode TinyURL](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumEncode and Decode TinyURL.java) +274|[Insert into a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInsert into a Binary Search Tree.java) +275|[Word Ladder](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWord Ladder.java) +276|[Inorder Successor in BST II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInorder Successor in BST II.java) +277|[Find and Replace Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind and Replace Pattern.java) +278|[Number of Longest Increasing Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumNumber of Longest Increasing Subsequence.java) +279|[Remove Comments](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRemove Comments.java) +280|[Pancake Sorting](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPancake Sorting.java) +281|[Maximum Size Subarray Sum Equals k](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Size Subarray Sum Equals k.java) +282|[3Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium3Sum.java) +283|[Valid Triangle Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumValid Triangle Number.java) +284|[Kth Smallest Element in a Sorted Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumKth Smallest Element in a Sorted Matrix.java) +285|[String to Integer(atoi)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumString to Integer(atoi).java) +286|[All Paths From Source to Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAll Paths From Source to Target.java) +287|[Binary Tree Longest Consecutive Sequence II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumBinary Tree Longest Consecutive Sequence II.java) +288|[Friend Circles](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFriend Circles.java) +289|[Swap Nodes in Pair](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSwap Nodes in Pair.java) +290|[Plus One Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPlus One Linked List.java) +291|[Teemo Attacking](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumTeemo Attacking.java) +292|[Compare Version Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCompare Version Numbers.java) +293|[Smallest String Starting From Leaf](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSmallest String Starting From Leaf.java) +294|[Count Numbers With Unique Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCount Numbers With Unique Digits.java) +295|[Uncrossed Lines](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumUncrossed Lines.java) +296|[Vowel Spellchecker](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumVowel Spellchecker.java) +297|[Contiguous Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumContiguous Array.java) +298|[Longest Well-Performing Interval](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Well-Performing Interval.java) +299|[Find Bottom Left Tree Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Bottom Left Tree Value.java) +300|[Score After Flipping Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumScore After Flipping Matrix.java) +301|[4 Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium4 Sum II.java) +302|[Most Frequent Subtree Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMost Frequent Subtree Sum.java) +303|[Combinations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumCombinations.java) +304|[RLE Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRLE Iterator.java) +305|[Spiral Matrix II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSpiral Matrix II.java) +306|[Find Largest Value in Tree Row](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind Largest Value in Tree Row.java) +307|[Minimum Time Difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMinimum Time Difference.java) +308|[Find all Duplicates in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind all Duplicates in an Array.java) +309|[Diagonal Traverse](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumDiagonal Traverse.java) +310|[Print Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumPrint Binary Tree.java) +311|[Masking Personal Information](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMasking Personal Information.java) +312|[Summary Ranges](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumSummary Ranges.java) +313|[Letter Combinations of a Phone Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLetter Combinations of a Phone Number.java) +314|[Odd Even Linked Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumOdd Even Linked Lists.java) +315|[Find K-Length Substrings With No Repeated Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind K-Length Substrings With No Repeated Characters.java) +316|[ZigZag Conversion](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumZigZag Conversion.java) +317|[Water & Jug Problem](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumWater & Jug Problem.java) +318|[Find and Replace in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFind and Replace in String.java) +319|[Construct Binary Tree from Inorder and Postorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumConstruct Binary Tree from Inorder and Postorder Traversal.java) +320|[Flatten 2D Vector](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumFlatten 2D Vector.java) +321|[Hand of Straights](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumHand of Straights.java) +322|[Maximum Average Subtree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMaximum Average Subtree.java) +323|[Repeated DNA Sequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumRepeated DNA Sequences.java) +324|[Integer To Roman](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumInteger To Roman.java) +325|[My Calendar I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumMy Calendar I.java) +326|[Longest Line of Consecutive One in Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumLongest Line of Consecutive One in Matrix.java) +327|[Group Shifted Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumGroup Shifted Strings.java) +328|[Reverse Nodes in k-group](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumReverse Nodes in k-group.java) +329|[One Edit Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumOne Edit Distance.java) +330|[Add Bold Tag in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/MediumAdd Bold Tag in String.java) diff --git a/Medium/Meeting Rooms II.java b/Medium/Meeting Rooms II.java index 5dd2621a..ff594c8a 100644 --- a/Medium/Meeting Rooms II.java +++ b/Medium/Meeting Rooms II.java @@ -1,80 +1,15 @@ -/** - * Definition for an interval. - * public class Interval { - * int start; - * int end; - * Interval() { start = 0; end = 0; } - * Interval(int s, int e) { start = s; end = e; } - * } - */ class Solution { - public static int minMeetingRooms(Interval[] intervals) { - - if (intervals.length == 0) { - return 0; - } - - int[] start = new int[intervals.length]; - int[] end = new int[intervals.length]; - - int i = 0; - - for (Interval interval : intervals) { - start[i] = interval.start; - end[i] = interval.end; - - i++; - } - - Arrays.sort(start); - Arrays.sort(end); - - int slow = 0; - int fast = 0; - int count = 0; - - while (slow < intervals.length) { - if (start[slow] >= end[fast]) { - count--; - fast++; - } - - count++; - slow++; - } - - return count; - } - - public static int minMeetingRoomsQueue(Interval[] intervals) { - if (intervals.length == 0) { - return 0; - } - - PriorityQueue endTimes = new PriorityQueue<>(intervals.length, new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o1 - o2; - } - }); - - Arrays.sort(intervals, new Comparator() { - @Override - public int compare(Interval o1, Interval o2) { - return o1.start - o2.start; - } - }); - - endTimes.add(intervals[0].end); - - for (int i=1; i= endTimes.peek()) { - endTimes.poll(); - } - - endTimes.add(intervals[i].end); - } - - return endTimes.size(); + public int minMeetingRooms(int[][] intervals) { + Arrays.sort(intervals, Comparator.comparingInt((int[] o) -> o[0])); + PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1])); + int meetingRooms = 0; + for (int[] interval : intervals) { + while (!pq.isEmpty() && pq.peek()[1] <= interval[0]) { + pq.poll(); + } + pq.add(interval); + meetingRooms = Math.max(meetingRooms, pq.size()); + } + return meetingRooms; } } diff --git a/Medium/Meeting Scheduler.java b/Medium/Meeting Scheduler.java new file mode 100644 index 00000000..aeb5d8e9 --- /dev/null +++ b/Medium/Meeting Scheduler.java @@ -0,0 +1,22 @@ +class Solution { + public List minAvailableDuration(int[][] slots1, int[][] slots2, int duration) { + Arrays.sort(slots1, Comparator.comparingInt(o -> o[0])); + Arrays.sort(slots2, Comparator.comparingInt(o -> o[0])); + int idxOne = 0; + int idxTwo = 0; + while (idxOne < slots1.length && idxTwo < slots2.length) { + int maxStart = Math.max(slots1[idxOne][0], slots2[idxTwo][0]); + int minEnd = Math.min(slots1[idxOne][1], slots2[idxTwo][1]); + if (minEnd - maxStart >= duration) { + return List.of(maxStart, maxStart + duration); + } + if (minEnd == slots1[idxOne][1]) { + idxOne++; + } + if (minEnd == slots2[idxTwo][1]) { + idxTwo++; + } + } + return Collections.emptyList(); + } +} diff --git a/Medium/Merge In Between Linked Lists.java b/Medium/Merge In Between Linked Lists.java new file mode 100644 index 00000000..9f36b5a8 --- /dev/null +++ b/Medium/Merge In Between Linked Lists.java @@ -0,0 +1,30 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode mergeInBetween(ListNode list1, int a, int b, ListNode list2) { + ListNode curr = list1; + for (int i = 1; i < a; i++) { + curr = curr.next; + } + ListNode start = curr; + for (int i = a - 1; i <= b; i++) { + curr = curr.next; + } + ListNode end = curr; + start.next = list2; + curr = list2; + while (curr.next != null) { + curr = curr.next; + } + curr.next = end; + return list1; + } +} diff --git a/Medium/Merge Intervals.java b/Medium/Merge Intervals.java index fcef1675..cb0a90cf 100644 --- a/Medium/Merge Intervals.java +++ b/Medium/Merge Intervals.java @@ -1,55 +1,18 @@ -/** - * Definition for an interval. - * public class Interval { - * int start; - * int end; - * Interval() { start = 0; end = 0; } - * Interval(int s, int e) { start = s; end = e; } - * } - */ class Solution { - public static List merge(List intervals) { - - if (intervals.size() == 1) { - return intervals; - } - - List ans = new ArrayList<>(); - if (intervals.size() == 0) { - return ans; - } - - Collections.sort(intervals, new Comparator() { - @Override - public int compare(Interval o1, Interval o2) { - return o1.start - o2.start; - } - }); - - int i = 0; - Interval prevInterval = null; - - List temp = new ArrayList<>(intervals); - - for (Interval interval : temp) { - if (i == 0) { - prevInterval = interval; - i++; - continue; - } - - if (interval.start <= prevInterval.end) { - if (interval.end >= prevInterval.end) { - prevInterval.end = interval.end; - } - - intervals.remove(interval); - } - else { - prevInterval = interval; + public int[][] merge(int[][] intervals) { + Arrays.sort(intervals, Comparator.comparingInt((int[] o) -> o[0]) + .thenComparingInt(o -> o[1])); + int idx = 0; + List result = new ArrayList<>(); + while (idx < intervals.length) { + int start = intervals[idx][0]; + int end = intervals[idx][1]; + idx++; + while (idx < intervals.length && intervals[idx][0] <= end) { + end = Math.max(end, intervals[idx++][1]); } + result.add(new int[]{start, end}); } - - return intervals; + return result.toArray(new int[][]{}); } } diff --git a/Medium/Merge Nodes in Between Zeros.java b/Medium/Merge Nodes in Between Zeros.java new file mode 100644 index 00000000..e4cb4403 --- /dev/null +++ b/Medium/Merge Nodes in Between Zeros.java @@ -0,0 +1,32 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode mergeNodes(ListNode head) { + ListNode newHead = null; + ListNode prev = null; + ListNode curr = head.next; + while (curr != null) { + prev = curr; + if (newHead == null) { + newHead = prev; + } + int sum = 0; + while (curr != null && curr.val != 0) { + sum += curr.val; + curr = curr.next; + } + prev.val = sum; + curr = curr.next; + prev.next = curr; + } + return newHead; + } +} diff --git a/Medium/Min Cost to Connect All Points.java b/Medium/Min Cost to Connect All Points.java new file mode 100644 index 00000000..168142ca --- /dev/null +++ b/Medium/Min Cost to Connect All Points.java @@ -0,0 +1,64 @@ +class Solution { + public int minCostConnectPoints(int[][] points) { + int n = points.length; + List edges = new ArrayList<>(); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + int weight = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]); + int[] curr = {weight, i, j}; + edges.add(curr); + } + } + Collections.sort(edges, Comparator.comparingInt(a -> a[0])); + UnionFind unionFind = new UnionFind(n); + int minCost = 0; + int edgeUsedCount = 0; + for (int i = 0; i < edges.size() && edgeUsedCount < n - 1; i++) { + int nodeOne = edges.get(i)[1]; + int nodeTwo = edges.get(i)[2]; + int weight = edges.get(i)[0]; + if (unionFind.union(nodeOne, nodeTwo)) { + minCost += weight; + edgeUsedCount++; + } + } + return minCost; + } + + private static class UnionFind { + private final int[] group; + private final int[] rank; + + public UnionFind(int n) { + this.group = new int[n]; + this.rank = new int[n]; + for (int i = 0; i < n; i++) { + this.group[i] = i; + } + } + + public int find(int node) { + if (group[node] != node) { + group[node] = find(group[node]); + } + return group[node]; + } + + public boolean union(int nodeOne, int nodeTwo) { + int groupOne = find(nodeOne); + int groupTwo = find(nodeTwo); + if (groupOne == groupTwo) { + return false; + } + if (rank[groupOne] > rank[groupTwo]) { + group[groupTwo] = groupOne; + } else if (rank[groupOne] < rank[groupTwo]) { + group[groupOne] = groupTwo; + } else { + group[groupOne] = groupTwo; + rank[groupTwo]++; + } + return true; + } + } +} diff --git a/Medium/Min Stack.java b/Medium/Min Stack.java new file mode 100644 index 00000000..70d88780 --- /dev/null +++ b/Medium/Min Stack.java @@ -0,0 +1,33 @@ +class MinStack { + private final Stack stack; + + public MinStack() { + this.stack = new Stack<>(); + } + + public void push(int val) { + int min = stack.isEmpty() ? val : Math.min(val, stack.peek()[1]); + stack.push(new int[]{val, min}); + } + + public void pop() { + stack.pop(); + } + + public int top() { + return stack.peek()[0]; + } + + public int getMin() { + return stack.peek()[1]; + } +} + +/** + * Your MinStack object will be instantiated and called as such: + * MinStack obj = new MinStack(); + * obj.push(val); + * obj.pop(); + * int param_3 = obj.top(); + * int param_4 = obj.getMin(); + */ diff --git a/Medium/Mini Parser.java b/Medium/Mini Parser.java index 6be1808c..6fba4058 100644 --- a/Medium/Mini Parser.java +++ b/Medium/Mini Parser.java @@ -22,46 +22,47 @@ * public void add(NestedInteger ni); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ class Solution { - int idx = 0; - public NestedInteger deserialize(String s) { - int l = s.length(); - NestedInteger ans = new NestedInteger(); - - while (idx < l) { - if (s.charAt(idx) == '-' || s.charAt(idx) >= '0' && s.charAt(idx) <= '9') { - int num = 0; - int sign = 1; - - if (s.charAt(idx) == '-') { - sign = -1; - idx++; - } - - while (idx < l && s.charAt(idx) >= '0' && s.charAt(idx) <= '9') { - num = num * 10 + (s.charAt(idx) - '0'); - idx++; - } - - ans.add(new NestedInteger(num * sign)); - } - else if (s.charAt(idx) == '[') { - idx++; - ans.add(deserialize(s)); - } - else if (s.charAt(idx) == ']') { - idx++; - return ans; - } - else { - idx++; - } + public NestedInteger deserialize(String s) { + if (s.isEmpty()) { + return null; + } + if (s.charAt(0) != '[') { + return new NestedInteger(Integer.parseInt(s)); + } + Stack stack = new Stack<>(); + NestedInteger curr = null; + int leftIdx = 0; + for (int rightIdx = 0; rightIdx < s.length(); rightIdx++) { + if (s.charAt(rightIdx) == '[') { + if (curr != null) { + stack.push(curr); + } + curr = new NestedInteger(); + leftIdx = rightIdx + 1; + } else if (s.charAt(rightIdx) == ']') { + String number = s.substring(leftIdx, rightIdx); + if (!number.isEmpty()) { + curr.add(new NestedInteger(Integer.parseInt(number))); + } + if (!stack.isEmpty()) { + NestedInteger popped = stack.pop(); + popped.add(curr); + curr = popped; + } + leftIdx = rightIdx + 1; + } else if (s.charAt(rightIdx) == ',') { + if (s.charAt(rightIdx - 1) != ']') { + String number = s.substring(leftIdx, rightIdx); + curr.add(new NestedInteger(Integer.parseInt(number))); } - - return ans.getList().get(0); + leftIdx = rightIdx + 1; + } } + return curr; + } } diff --git a/Medium/Minimize Maximum Pair Sum in Array.java b/Medium/Minimize Maximum Pair Sum in Array.java new file mode 100644 index 00000000..4b555253 --- /dev/null +++ b/Medium/Minimize Maximum Pair Sum in Array.java @@ -0,0 +1,13 @@ +class Solution { + public int minPairSum(int[] nums) { + Arrays.sort(nums); + int start = 0; + int end = nums.length - 1; + int maxPairSum = -1; + while (start < end) { + int currSum = nums[start++] + nums[end--]; + maxPairSum = maxPairSum == -1 ? currSum : Math.max(maxPairSum, currSum); + } + return maxPairSum; + } +} diff --git a/Medium/Minimize Maximum of Array.java b/Medium/Minimize Maximum of Array.java new file mode 100644 index 00000000..79d5ee9b --- /dev/null +++ b/Medium/Minimize Maximum of Array.java @@ -0,0 +1,11 @@ +class Solution { + public int minimizeArrayValue(int[] nums) { + long prefixSum = 0L; + long result = 0L; + for (int i = 0; i < nums.length; i++) { + prefixSum += nums[i]; + result = Math.max(result, (prefixSum + i) / (i + 1)); + } + return (int) result; + } +} diff --git a/Medium/Minimize Product Sum of Two Arrays.java b/Medium/Minimize Product Sum of Two Arrays.java new file mode 100644 index 00000000..8302c68e --- /dev/null +++ b/Medium/Minimize Product Sum of Two Arrays.java @@ -0,0 +1,25 @@ +class Solution { + public int minProductSum(int[] nums1, int[] nums2) { + int[] frequencyOne = new int[101]; + int[] frequencyTwo = new int[101]; + for (int i = 0; i < nums1.length; i++) { + frequencyOne[nums1[i]]++; + frequencyTwo[nums2[i]]++; + } + int productSum = 0; + int idxOne = 1; + int idxTwo = 100; + while (idxOne < 101 && idxTwo > 0) { + if (frequencyOne[idxOne] == 0) { + idxOne++; + } else if (frequencyTwo[idxTwo] == 0) { + idxTwo--; + } else { + productSum += idxOne * idxTwo; + frequencyOne[idxOne]--; + frequencyTwo[idxTwo]--; + } + } + return productSum; + } +} diff --git a/Medium/Minimize XOR.java b/Medium/Minimize XOR.java new file mode 100644 index 00000000..cc5e87a3 --- /dev/null +++ b/Medium/Minimize XOR.java @@ -0,0 +1,24 @@ +class Solution { + public int minimizeXor(int num1, int num2) { + int result = 0; + int targetSetBitCount = Integer.bitCount(num2); + int setBitCount = 0; + int currBit = 31; + while (setBitCount < targetSetBitCount) { + if (isSet(num1, currBit) || (targetSetBitCount - setBitCount > currBit)) { + result = setBit(result, currBit); + setBitCount++; + } + currBit--; + } + return result; + } + + private boolean isSet(int x, int bit) { + return (x & (1 << bit)) != 0; + } + + private int setBit(int x, int bit) { + return x | (1 << bit); + } +} diff --git a/Medium/Minimize the Maximum Difference of Pairs.java b/Medium/Minimize the Maximum Difference of Pairs.java new file mode 100644 index 00000000..5ec67591 --- /dev/null +++ b/Medium/Minimize the Maximum Difference of Pairs.java @@ -0,0 +1,30 @@ +class Solution { + public int minimizeMax(int[] nums, int p) { + Arrays.sort(nums); + int n = nums.length; + int start = 0; + int end = nums[n - 1] - nums[0]; + while (start < end) { + int mid = (start + end) / 2; + if (countValidPairs(nums, mid) >= p) { + end = mid; + } else { + start = mid + 1; + } + } + return start; + } + + private static int countValidPairs(int[] nums, int limit) { + int idx = 0; + int count = 0; + while (idx < nums.length - 1) { + if (nums[idx + 1] - nums[idx] <= limit) { + count++; + idx++; + } + idx++; + } + return count; + } +} diff --git a/Medium/Minimized Maximum of Products Distributed to Any Store.java b/Medium/Minimized Maximum of Products Distributed to Any Store.java new file mode 100644 index 00000000..70a46016 --- /dev/null +++ b/Medium/Minimized Maximum of Products Distributed to Any Store.java @@ -0,0 +1,36 @@ +class Solution { + public int minimizedMaximum(int n, int[] quantities) { + int left = 0; + int right = 0; + for (int quantity : quantities) { + right = Math.max(right, quantity); + } + while (left < right) { + int mid = (left + right) / 2; + if (isPossible(n, mid, quantities)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } + + private boolean isPossible(int n, int min, int[] quantities) { + int idx = 0; + int remaining = quantities[idx]; + for (int i = 0; i < n; i++) { + if (remaining <= min) { + idx++; + if (idx == quantities.length) { + return true; + } else { + remaining = quantities[idx]; + } + } else { + remaining -= min; + } + } + return false; + } +} diff --git a/Medium/Minimum Add to Make Parentheses Valid.java b/Medium/Minimum Add to Make Parentheses Valid.java new file mode 100644 index 00000000..7fcfc88d --- /dev/null +++ b/Medium/Minimum Add to Make Parentheses Valid.java @@ -0,0 +1,14 @@ +class Solution { + public int minAddToMakeValid(String s) { + int open = 0; + int count = 0; + for (char c : s.toCharArray()) { + open += c == '(' ? 1 : -1; + if (open < 0) { + count += Math.abs(open); + open = 0; + } + } + return count + open; + } +} diff --git a/Medium/Minimum Amount of Time to Collect Garbage.java b/Medium/Minimum Amount of Time to Collect Garbage.java new file mode 100644 index 00000000..ace2125d --- /dev/null +++ b/Medium/Minimum Amount of Time to Collect Garbage.java @@ -0,0 +1,25 @@ +class Solution { + public int garbageCollection(String[] garbage, int[] travel) { + Map lastIdx = new HashMap<>(); + for (int i = garbage.length - 1; i >= 0; i--) { + if (garbage[i].indexOf('M') != -1) { + lastIdx.putIfAbsent('M', i); + } + if (garbage[i].indexOf('G') != -1) { + lastIdx.putIfAbsent('G', i); + } + if (garbage[i].indexOf('P') != -1) { + lastIdx.putIfAbsent('P', i); + } + } + int totalTime = 0; + for (int i = 0; i < garbage.length; i++) { + int travelTime = i == 0 ? 0 : travel[i - 1]; + totalTime += garbage[i].length(); + totalTime += lastIdx.getOrDefault('P', -1) >= i ? travelTime : 0; + totalTime += lastIdx.getOrDefault('M', -1) >= i ? travelTime : 0; + totalTime += lastIdx.getOrDefault('G', -1) >= i ? travelTime : 0; + } + return totalTime; + } +} diff --git a/Medium/Minimum Area Rectangle.java b/Medium/Minimum Area Rectangle.java new file mode 100644 index 00000000..bb5bdb8c --- /dev/null +++ b/Medium/Minimum Area Rectangle.java @@ -0,0 +1,29 @@ +class Solution { + public int minAreaRect(int[][] points) { + Map> rows = new TreeMap(); + // Map of key as x coordinate and value as list of y coordinates + for (int[] point: points) { + int x = point[0]; + int y = point[1]; + rows.computeIfAbsent(x, k -> new ArrayList()).add(y); + } + int ans = Integer.MAX_VALUE; + Map lastX = new HashMap(); + for (int x: rows.keySet()) { + List row = rows.get(x); + Collections.sort(row); + for (int i = 0; i < row.size(); ++i) { + for (int j = i + 1; j < row.size(); ++j) { + int y1 = row.get(i); + int y2 = row.get(j); + String code = y1 + ":" + y2; + if (lastX.containsKey(code)) { + ans = Math.min(ans, (x - lastX.get(code)) * (y2 - y1)); + } + lastX.put(code, x); + } + } + } + return ans < Integer.MAX_VALUE ? ans : 0; + } +} diff --git a/Medium/Minimum Average Difference.java b/Medium/Minimum Average Difference.java new file mode 100644 index 00000000..995bcd11 --- /dev/null +++ b/Medium/Minimum Average Difference.java @@ -0,0 +1,23 @@ +class Solution { + public int minimumAverageDifference(int[] nums) { + int n = nums.length; + long[] prefixSumArray = new long[n]; + long currSum = 0; + for (int i = 0; i < n; i++) { + currSum += nums[i]; + prefixSumArray[i] = currSum; + } + long minDifference = Integer.MAX_VALUE; + int minDifferenceIdx = -1; + for (int i = 0; i < n; i++) { + long leftAverage = prefixSumArray[i] / (i + 1); + long rightAverage = (i == n - 1) ? 0 : (prefixSumArray[n - 1] - prefixSumArray[i]) / (n - 1 - i); + long absoluteDiff = Math.abs(leftAverage - rightAverage); + if (minDifference > absoluteDiff) { + minDifference = absoluteDiff; + minDifferenceIdx = i; + } + } + return minDifferenceIdx; + } +} diff --git a/Medium/Minimum Consecutive Cards to Pick Up.java b/Medium/Minimum Consecutive Cards to Pick Up.java new file mode 100644 index 00000000..147cc54e --- /dev/null +++ b/Medium/Minimum Consecutive Cards to Pick Up.java @@ -0,0 +1,13 @@ +class Solution { + public int minimumCardPickup(int[] cards) { + int minCount = Integer.MAX_VALUE; + Map map = new HashMap<>(); + for (int i = 0; i < cards.length; i++) { + if (map.containsKey(cards[i])) { + minCount = Math.min(minCount, i - map.get(cards[i]) + 1); + } + map.put(cards[i], i); + } + return minCount == Integer.MAX_VALUE ? -1 : minCount; + } +} diff --git a/Medium/Minimum Cost For Tickets.java b/Medium/Minimum Cost For Tickets.java new file mode 100644 index 00000000..8867660b --- /dev/null +++ b/Medium/Minimum Cost For Tickets.java @@ -0,0 +1,29 @@ +class Solution { + public int mincostTickets(int[] days, int[] costs) { + Set daySet = new HashSet<>(); + for (int day : days) { + daySet.add(day); + } + int[] dp = new int[days[days.length - 1]]; + return helper(days[days.length - 1], daySet, costs, dp); + } + + private int helper(int currDay, Set daySet, int[] costs, int[] dp) { + if (currDay <= 0) { + return 0; + } + if (dp[currDay - 1] != 0) { + return dp[currDay - 1]; + } + int result = 0; + if (daySet.contains(currDay)) { + int one = helper(currDay - 1, daySet, costs, dp) + costs[0]; + int seven = helper(currDay - 7, daySet, costs, dp) + costs[1]; + int thirty = helper(currDay - 30, daySet, costs, dp) + costs[2]; + result = Math.min(one, Math.min(seven, thirty)); + } else { + result = helper(currDay - 1, daySet, costs, dp); + } + return dp[currDay - 1] = result; + } +} diff --git a/Medium/Minimum Cost to Connect Sticks.java b/Medium/Minimum Cost to Connect Sticks.java new file mode 100644 index 00000000..0bd1c1bf --- /dev/null +++ b/Medium/Minimum Cost to Connect Sticks.java @@ -0,0 +1,17 @@ +class Solution { + public int connectSticks(int[] sticks) { + int cost = 0; + PriorityQueue pq = new PriorityQueue<>(); + for (int stick : sticks) { + pq.add(stick); + } + while (pq.size() > 1) { + int first = pq.poll(); + int second = pq.poll(); + int joinSum = first + second; + cost += joinSum; + pq.add(joinSum); + } + return cost; + } +} diff --git a/Medium/Minimum Deletion Cost to Avoid Repeating Letters.java b/Medium/Minimum Deletion Cost to Avoid Repeating Letters.java new file mode 100644 index 00000000..cddb0210 --- /dev/null +++ b/Medium/Minimum Deletion Cost to Avoid Repeating Letters.java @@ -0,0 +1,21 @@ +class Solution { + public int minCost(String s, int[] cost) { + Stack stack = new Stack<>(); + int deletionCost = 0; + for (int i = 0; i < s.length(); i++) { + int insertionIndex = i; + if (!stack.isEmpty() && s.charAt(i) == s.charAt(stack.peek())) { + int poppedIdx = stack.pop(); + if (cost[i] > cost[poppedIdx]) { + deletionCost += cost[poppedIdx]; + } + else { + deletionCost += cost[i]; + insertionIndex = poppedIdx; + } + } + stack.push(insertionIndex); + } + return deletionCost; + } +} diff --git a/Medium/Minimum Deletions to Make Array Beautiful.java b/Medium/Minimum Deletions to Make Array Beautiful.java new file mode 100644 index 00000000..8567e813 --- /dev/null +++ b/Medium/Minimum Deletions to Make Array Beautiful.java @@ -0,0 +1,14 @@ +class Solution { + public int minDeletion(int[] nums) { + int numOfDeletions = 0; + int prevNum = -1; + for (int num : nums) { + if (num == prevNum) { + numOfDeletions++; + } else { + prevNum = prevNum == -1 ? num : -1; + } + } + return prevNum == -1 ? numOfDeletions : numOfDeletions + 1; + } +} diff --git a/Medium/Minimum Deletions to Make Character Frequencies Unique.java b/Medium/Minimum Deletions to Make Character Frequencies Unique.java new file mode 100644 index 00000000..2d57dc68 --- /dev/null +++ b/Medium/Minimum Deletions to Make Character Frequencies Unique.java @@ -0,0 +1,25 @@ +class Solution { + public int minDeletions(String s) { + int[] frequency = new int[26]; + for (char c : s.toCharArray()) { + frequency[c - 'a']++; + } + Arrays.sort(frequency); + int numOfDeletions = 0; + int expectedFrequency = frequency[25]; + for (int i = 25; i >= 0; i--) { + if (frequency[i] == 0) { + break; + } + if (frequency[i] > expectedFrequency) { + numOfDeletions += frequency[i] - expectedFrequency; + } else { + expectedFrequency = frequency[i]; + } + if (expectedFrequency > 0) { + expectedFrequency--; + } + } + return numOfDeletions; + } +} diff --git a/Medium/Minimum Difference Between Largest and Smallest Value in Three Moves.java b/Medium/Minimum Difference Between Largest and Smallest Value in Three Moves.java new file mode 100644 index 00000000..2722191a --- /dev/null +++ b/Medium/Minimum Difference Between Largest and Smallest Value in Three Moves.java @@ -0,0 +1,16 @@ +class Solution { + public int minDifference(int[] nums) { + int n = nums.length; + if (n <= 4) { + return 0; + } + Arrays.sort(nums); + int minDiff = Integer.MAX_VALUE; + int left = 0; + int right = n - 4; + while (left < 4) { + minDiff = Math.min(minDiff, nums[right++] - nums[left++]); + } + return minDiff; + } +} diff --git a/Medium/Minimum Domino Rotations For Equal Row.java b/Medium/Minimum Domino Rotations For Equal Row.java new file mode 100644 index 00000000..1ed001ae --- /dev/null +++ b/Medium/Minimum Domino Rotations For Equal Row.java @@ -0,0 +1,21 @@ +class Solution { + public int minDominoRotations(int[] A, int[] B) { + int[] counterA = new int[7]; + int[] counterB = new int[7]; + int[] same = new int[7]; + int n = A.length; + for (int i = 0; i < n; i++) { + counterA[A[i]]++; + counterB[B[i]]++; + if (A[i] == B[i]) { + same[A[i]]++; + } + } + for (int i = 1; i < 7; i++) { + if (counterA[i] + counterB[i] - same[i] == n) { + return n - Math.max(counterA[i], counterB[i]); + } + } + return -1; + } +} diff --git a/Medium/Minimum Falling Path Sum.java b/Medium/Minimum Falling Path Sum.java new file mode 100644 index 00000000..255081b9 --- /dev/null +++ b/Medium/Minimum Falling Path Sum.java @@ -0,0 +1,33 @@ +class Solution { + private static final int[][] DIRS = {{1, -1}, {1, 0}, {1, 1}}; + + public int minFallingPathSum(int[][] matrix) { + int rows = matrix.length; + int cols = matrix[0].length; + Integer[][] dp = new Integer[rows + 1][cols + 1]; + int result = Integer.MAX_VALUE; + for (int i = 0; i < cols; i++) { + result = Math.min(result, recurse(matrix, 0, i, rows, cols, dp)); + } + return result; + } + + private int recurse(int[][] matrix, int row, int col, int rows, int cols, Integer[][] dp) { + if (row == rows - 1) { + return matrix[row][col]; + } + if (dp[row][col] != null) { + return dp[row][col]; + } + int result = Integer.MAX_VALUE; + for (int[] dir : DIRS) { + int newRow = row + dir[0]; + int newCol = col + dir[1]; + if (newRow < 0 || newCol < 0 || newRow >= rows || newCol >= cols) { + continue; + } + result = Math.min(result, matrix[row][col] + recurse(matrix, newRow, newCol, rows, cols, dp)); + } + return dp[row][col] = result; + } +} diff --git a/Medium/Minimum Flips to Make a OR b Equal to c.java b/Medium/Minimum Flips to Make a OR b Equal to c.java new file mode 100644 index 00000000..91963256 --- /dev/null +++ b/Medium/Minimum Flips to Make a OR b Equal to c.java @@ -0,0 +1,5 @@ +class Solution { + public int minFlips(int a, int b, int c) { + return Integer.bitCount((a | b) ^ c) + Integer.bitCount(a & b & ((a | b) ^ c)); + } +} diff --git a/Medium/Minimum Fuel Cost to Report to the Capital.java b/Medium/Minimum Fuel Cost to Report to the Capital.java new file mode 100644 index 00000000..ee48239f --- /dev/null +++ b/Medium/Minimum Fuel Cost to Report to the Capital.java @@ -0,0 +1,28 @@ +class Solution { + public long minimumFuelCost(int[][] roads, int seats) { + Map> graph = new HashMap<>(); + for (int[] road : roads) { + graph.computeIfAbsent(road[0], k -> new ArrayList<>()).add(road[1]); + graph.computeIfAbsent(road[1], k -> new ArrayList<>()).add(road[0]); + } + long[] fuel = {0l}; + dfs(0, -1, graph, seats, fuel); + return fuel[0]; + } + + private long dfs(int node, int parent, Map> graph, int seats, long[] fuel) { + int representativeCount = 1; + if (!graph.containsKey(node)) { + return representativeCount; + } + for (int child : graph.get(node)) { + if (child != parent) { + representativeCount += dfs(child, node, graph, seats, fuel); + } + } + if (node != 0) { + fuel[0] += Math.ceil((double) representativeCount / seats); + } + return representativeCount; + } +} diff --git a/Medium/Minimum Health to Beat Game.java b/Medium/Minimum Health to Beat Game.java new file mode 100644 index 00000000..9b93099e --- /dev/null +++ b/Medium/Minimum Health to Beat Game.java @@ -0,0 +1,11 @@ +class Solution { + public long minimumHealth(int[] damage, int armor) { + int maxDamage = 0; + long totalDamage = 0; + for (int d : damage) { + totalDamage += d; + maxDamage = Math.max(maxDamage, d); + } + return totalDamage - Math.min(armor, maxDamage) + 1; + } +} diff --git a/Medium/Minimum Height Trees.java b/Medium/Minimum Height Trees.java new file mode 100644 index 00000000..a92f7494 --- /dev/null +++ b/Medium/Minimum Height Trees.java @@ -0,0 +1,35 @@ +class Solution { + public List findMinHeightTrees(int n, int[][] edges) { + if (n == 1) { + return Collections.singletonList(0); + } + Map> map = new HashMap<>(); + for (int[] edge : edges) { + map.computeIfAbsent(edge[0], k -> new HashSet<>()).add(edge[1]); + map.computeIfAbsent(edge[1], k -> new HashSet<>()).add(edge[0]); + } + List leaves = new ArrayList<>(); + for (int i = 0; i < n; i++) { + if (map.getOrDefault(i, new HashSet<>()).size() == 1) { + leaves.add(i); + } + } + int count = n; + while (count > 2) { + int size = leaves.size(); + count -= size; + List newLeaves = new ArrayList<>(); + for (int i = 0; i < size; i++) { + int leaf = leaves.get(i); + for (int toRemove : map.getOrDefault(leaf, new HashSet<>())) { + map.get(toRemove).remove(leaf); + if (map.get(toRemove).size() == 1) { + newLeaves.add(toRemove); + } + } + } + leaves = newLeaves; + } + return leaves; + } +} diff --git a/Medium/Minimum Increment to Make Array Unique.java b/Medium/Minimum Increment to Make Array Unique.java new file mode 100644 index 00000000..7be5a583 --- /dev/null +++ b/Medium/Minimum Increment to Make Array Unique.java @@ -0,0 +1,13 @@ +class Solution { + public int minIncrementForUnique(int[] nums) { + Arrays.sort(nums); + int increments = 0; + for (int i = 1; i < nums.length; i++) { + if (nums[i] <= nums[i - 1]) { + increments += nums[i - 1] + 1 - nums[i]; + nums[i] = nums[i - 1] + 1; + } + } + return increments; + } +} diff --git a/Medium/Minimum Knight Moves.java b/Medium/Minimum Knight Moves.java new file mode 100644 index 00000000..35759df8 --- /dev/null +++ b/Medium/Minimum Knight Moves.java @@ -0,0 +1,30 @@ +class Solution { + + private static final int[][] MOVES = {{1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}}; + + public int minKnightMoves(int x, int y) { + boolean[][] visited = new boolean[607][607]; + Queue queue = new LinkedList<>(); + queue.add(new int[]{0, 0}); + int steps = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + if (removed[0] == x && removed[1] == y) { + return steps; + } + for (int[] move : MOVES) { + int newX = removed[0] + move[0]; + int newY = removed[1] + move[1]; + if (!visited[newX + 302][newY + 302]) { + visited[newX + 302][newY + 302] = true; + queue.add(new int[]{newX, newY}); + } + } + } + steps++; + } + return steps; + } +} diff --git a/Medium/Minimum Length of String After Deleting Similar Ends.java b/Medium/Minimum Length of String After Deleting Similar Ends.java new file mode 100644 index 00000000..bc1c6c89 --- /dev/null +++ b/Medium/Minimum Length of String After Deleting Similar Ends.java @@ -0,0 +1,17 @@ +class Solution { + public int minimumLength(String s) { + int start = 0; + int end = s.length() - 1; + while (start < end && s.charAt(start) == s.charAt(end)) { + char startChar = s.charAt(start); + char endChar = s.charAt(end); + while (start <= end && s.charAt(start) == startChar) { + start++; + } + while (end > start && s.charAt(end) == endChar) { + end--; + } + } + return end - start + 1; + } +} diff --git a/Medium/Minimum Levels to Gain More Points.java b/Medium/Minimum Levels to Gain More Points.java new file mode 100644 index 00000000..c7fd7222 --- /dev/null +++ b/Medium/Minimum Levels to Gain More Points.java @@ -0,0 +1,17 @@ +class Solution { + public int minimumLevels(int[] possible) { + int n = possible.length; + int totalScore = 0; + for (int i = n - 1; i >= 0; i--) { + totalScore += possible[i] == 1 ? 1 : -1; + } + int score = 0; + for (int i = 0; i < n - 1; i++) { + score += possible[i] == 1 ? 1 : -1; + if (score > totalScore - score) { + return i + 1; + } + } + return -1; + } +} diff --git a/Medium/Minimum Moves to Equal Array Elements II.java b/Medium/Minimum Moves to Equal Array Elements II.java index 921078ed..1a0ac919 100644 --- a/Medium/Minimum Moves to Equal Array Elements II.java +++ b/Medium/Minimum Moves to Equal Array Elements II.java @@ -1,17 +1,12 @@ class Solution { - public int minMoves2(int[] nums) { - int i = 0; - int j = nums.length-1; - int c = 0; - - Arrays.sort(nums); - - while (i < j) { - c += nums[j] - nums[i]; - i++; - j--; - } - - return c; + public int minMoves2(int[] nums) { + Arrays.sort(nums); + int sum = 0; + int start = 0; + int end = nums.length - 1; + while (start < end) { + sum += nums[end--] - nums[start++]; } + return sum; + } } diff --git a/Medium/Minimum Moves to Equal Array Elements.java b/Medium/Minimum Moves to Equal Array Elements.java new file mode 100644 index 00000000..78d30c6f --- /dev/null +++ b/Medium/Minimum Moves to Equal Array Elements.java @@ -0,0 +1,12 @@ +class Solution { + public int minMoves(int[] nums) { + Arrays.sort(nums); + int moves = 0; + for (int i = 1; i < nums.length; i++) { + int diff = (moves + nums[i]) - nums[i - 1]; + nums[i] += moves; + moves += diff; + } + return moves; + } +} diff --git a/Medium/Minimum Moves to Reach Target Score.java b/Medium/Minimum Moves to Reach Target Score.java new file mode 100644 index 00000000..c9bfdfc0 --- /dev/null +++ b/Medium/Minimum Moves to Reach Target Score.java @@ -0,0 +1,15 @@ +class Solution { + public int minMoves(int target, int maxDoubles) { + int numOfSteps = 0; + while (target > 0 && maxDoubles > 0) { + if (target % 2 == 0) { + maxDoubles--; + target /= 2; + } else { + target--; + } + numOfSteps++; + } + return numOfSteps + target - 1; + } +} diff --git a/Medium/Minimum Number of Arrows to Burst Balloons.java b/Medium/Minimum Number of Arrows to Burst Balloons.java index 48740783..a00d9274 100644 --- a/Medium/Minimum Number of Arrows to Burst Balloons.java +++ b/Medium/Minimum Number of Arrows to Burst Balloons.java @@ -1,30 +1,15 @@ class Solution { - public static int findMinArrowShots(int[][] points) { - if (points.length == 0) { - return 0; - } - - Arrays.sort(points, new Comparator() { - @Override - public int compare(int[] o1, int[] o2) { - return o1[0] - o2[0]; - } - }); - - int[] start = points[0]; - int count = 1; - - for (int i=1; i o[1])); + int count = 0; + int idx = 0; + while (idx < points.length) { + int currEnd = points[idx][1]; + while (idx < points.length && points[idx][0] <= currEnd) { + idx++; + } + count++; } + return count; + } } diff --git a/Medium/Minimum Number of Days to Make m Bouquets.java b/Medium/Minimum Number of Days to Make m Bouquets.java new file mode 100644 index 00000000..83578712 --- /dev/null +++ b/Medium/Minimum Number of Days to Make m Bouquets.java @@ -0,0 +1,37 @@ +class Solution { + public int minDays(int[] bloomDay, int m, int k) { + int left = 0; + int right = 0; + for (int day : bloomDay) { + right = Math.max(right, day); + } + int days = -1; + while (left <= right) { + int mid = (left + right) / 2; + if (numberOfBouquet(bloomDay, mid, k) >= m) { + days = mid; + right = mid - 1; + } else { + left = mid + 1; + } + } + return days; + } + + private int numberOfBouquet(int[] bloomDay, int mid, int k) { + int bouquetCount = 0; + int count = 0; + for (int i = 0; i < bloomDay.length; i++) { + if (bloomDay[i] <= mid) { + count++; + } else { + count = 0; + } + if (count == k) { + bouquetCount++; + count = 0; + } + } + return bouquetCount; + } +} diff --git a/Medium/Minimum Number of Operations to Make Array Empty.java b/Medium/Minimum Number of Operations to Make Array Empty.java new file mode 100644 index 00000000..69754a8d --- /dev/null +++ b/Medium/Minimum Number of Operations to Make Array Empty.java @@ -0,0 +1,16 @@ +class Solution { + public int minOperations(int[] nums) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + int operations = 0; + for (Integer value : map.values()) { + if (value == 1) { + return -1; + } + operations += value / 3 + (value % 3 == 0 ? 0 : 1); + } + return operations; + } +} diff --git a/Medium/Minimum Number of Pushes to Type Word II.java b/Medium/Minimum Number of Pushes to Type Word II.java new file mode 100644 index 00000000..71ec90f6 --- /dev/null +++ b/Medium/Minimum Number of Pushes to Type Word II.java @@ -0,0 +1,23 @@ +class Solution { + public int minimumPushes(String word) { + Map map = new HashMap<>(); + for (char c : word.toCharArray()) { + map.put(c, map.getOrDefault(c, 0) + 1); + } + PriorityQueue pq = new PriorityQueue<>((a, b) -> map.get(b).compareTo(map.get(a))); + pq.addAll(map.keySet()); + int count = 0; + int typeMultiple = 1; + int counter = 0; + while (!pq.isEmpty()) { + char removed = pq.poll(); + count += typeMultiple * map.get(removed); + counter++; + if (counter == 8) { + counter = 0; + typeMultiple++; + } + } + return count; + } +} diff --git a/Medium/Minimum Number of Steps to Make Two Strings Anagram II.java b/Medium/Minimum Number of Steps to Make Two Strings Anagram II.java new file mode 100644 index 00000000..0c72d548 --- /dev/null +++ b/Medium/Minimum Number of Steps to Make Two Strings Anagram II.java @@ -0,0 +1,16 @@ +class Solution { + public int minSteps(String s, String t) { + int[] frequency = new int[26]; + for (char c : s.toCharArray()) { + frequency[c - 'a']++; + } + for (char c : t.toCharArray()) { + frequency[c - 'a']--; + } + int totalSteps = 0; + for (int i = 0; i < 26; i++) { + totalSteps += Math.abs(frequency[i]); + } + return totalSteps; + } +} diff --git a/Medium/Minimum Number of Steps to Make Two Strings Anagram.java b/Medium/Minimum Number of Steps to Make Two Strings Anagram.java new file mode 100644 index 00000000..55139382 --- /dev/null +++ b/Medium/Minimum Number of Steps to Make Two Strings Anagram.java @@ -0,0 +1,16 @@ +class Solution { + public int minSteps(String s, String t) { + int[] frequency = new int[26]; + for (int i = 0; i < s.length(); i++) { + frequency[s.charAt(i) - 'a']++; + frequency[t.charAt(i) - 'a']--; + } + int steps = 0; + for (int i = 0; i < 26; i++) { + if (frequency[i] > 0) { + steps += frequency[i]; + } + } + return steps; + } +} diff --git a/Medium/Minimum Number of Swaps to Make the String Balanced.java b/Medium/Minimum Number of Swaps to Make the String Balanced.java new file mode 100644 index 00000000..79935f13 --- /dev/null +++ b/Medium/Minimum Number of Swaps to Make the String Balanced.java @@ -0,0 +1,24 @@ +class Solution { + public int minSwaps(String s) { + char[] chars = s.toCharArray(); + Stack openBrackets = new Stack<>(); + for (int i = 0; i < chars.length; i++) { + if (chars[i] == '[') { + openBrackets.push(i); + } + } + int open = 0; + int swaps = 0; + for (int i = 0; i < chars.length; i++) { + open += chars[i] == '[' ? 1 : -1; + if (open < 0) { + swaps++; + int endIdx = openBrackets.pop(); + chars[endIdx] = ']'; + chars[i] = '['; + open += 2; + } + } + return swaps; + } +} diff --git a/Medium/Minimum Number of Vertices to Reach All Nodes.java b/Medium/Minimum Number of Vertices to Reach All Nodes.java new file mode 100644 index 00000000..6459877d --- /dev/null +++ b/Medium/Minimum Number of Vertices to Reach All Nodes.java @@ -0,0 +1,15 @@ +class Solution { + public List findSmallestSetOfVertices(int n, List> edges) { + int[] indegree = new int[n]; + for (List edge : edges) { + indegree[edge.get(1)]++; + } + List zeroIndegree = new ArrayList<>(); + for (int i = 0; i < n; i++) { + if (indegree[i] == 0) { + zeroIndegree.add(i); + } + } + return zeroIndegree; + } +} diff --git a/Medium/Minimum Operations to Exceed Threshold Value II.java b/Medium/Minimum Operations to Exceed Threshold Value II.java new file mode 100644 index 00000000..9a6c2b09 --- /dev/null +++ b/Medium/Minimum Operations to Exceed Threshold Value II.java @@ -0,0 +1,17 @@ +class Solution { + public int minOperations(int[] nums, int k) { + PriorityQueue pq = new PriorityQueue<>(); + for (int num : nums) { + pq.add((long) num); + } + int operations = 0; + while (pq.peek() < k) { + long smallest = pq.poll(); + long secondSmallest = pq.poll(); + long newValue = Math.min(smallest, secondSmallest) * 2 + Math.max(smallest, secondSmallest); + pq.add(newValue); + operations++; + } + return operations; + } +} diff --git a/Medium/Minimum Operations to Make Array Equal.java b/Medium/Minimum Operations to Make Array Equal.java new file mode 100644 index 00000000..fc570061 --- /dev/null +++ b/Medium/Minimum Operations to Make Array Equal.java @@ -0,0 +1,5 @@ +class Solution { + public int minOperations(int n) { + return (n / 2) * ((n / 2) + n % 2); + } +} diff --git a/Medium/Minimum Operations to Make Binary Array Elements Equal to One I.java b/Medium/Minimum Operations to Make Binary Array Elements Equal to One I.java new file mode 100644 index 00000000..4b5b20a1 --- /dev/null +++ b/Medium/Minimum Operations to Make Binary Array Elements Equal to One I.java @@ -0,0 +1,19 @@ +class Solution { + public int minOperations(int[] nums) { + int count = 0; + for (int i = 0; i <= nums.length - 3; i++) { + if (nums[i] == 0) { + nums[i] = nums[i] == 0 ? 1 : 0; + nums[i + 1] = nums[i + 1] == 0 ? 1 : 0; + nums[i + 2] = nums[i + 2] == 0 ? 1 : 0; + count++; + } + } + for (int i = nums.length - 3; i < nums.length; i++) { + if (nums[i] == 0) { + return -1; + } + } + return count; + } +} diff --git a/Medium/Minimum Operations to Make a Special Number.java b/Medium/Minimum Operations to Make a Special Number.java new file mode 100644 index 00000000..20f250fc --- /dev/null +++ b/Medium/Minimum Operations to Make a Special Number.java @@ -0,0 +1,25 @@ +class Solution { + + private final int NOT_FOUND_VALUE = 100_000; + + public int minimumOperations(String num) { + Integer[][] dp = new Integer[100][25]; + return helper(num, 0, 0, dp); + } + + private int helper(String num, int idx, int mod, Integer[][] dp) { + if (idx == num.length()) { + if (mod == 0) { + return 0; + } + return NOT_FOUND_VALUE; + } + if (dp[idx][mod] != null) { + return dp[idx][mod]; + } + int take = helper(num, idx + 1, (mod * 10 + (num.charAt(idx) - '0')) % 25, dp); + int remove = 1 + helper(num, idx + 1, mod, dp); + dp[idx][mod] = Math.min(take, remove); + return dp[idx][mod]; + } +} diff --git a/Medium/Minimum Operations to Reduce X to Zero.java b/Medium/Minimum Operations to Reduce X to Zero.java new file mode 100644 index 00000000..f2f2a99b --- /dev/null +++ b/Medium/Minimum Operations to Reduce X to Zero.java @@ -0,0 +1,22 @@ +class Solution { + public int minOperations(int[] nums, int x) { + int sum = 0; + for (int num : nums) { + sum += num; + } + int max = -1; + int left = 0; + int curr = 0; + int n = nums.length; + for (int right = 0; right < n; right++) { + curr += nums[right]; + while (curr > sum - x && left <= right) { + curr -= nums[left++]; + } + if (curr == sum - x) { + max = Math.max(max, right - left + 1); + } + } + return max != -1 ? n - max : -1; + } +} diff --git a/Medium/Minimum Path Sum.java b/Medium/Minimum Path Sum.java index 5a19e3ac..0565b7b0 100644 --- a/Medium/Minimum Path Sum.java +++ b/Medium/Minimum Path Sum.java @@ -1,22 +1,18 @@ class Solution { - public static int minPathSum(int[][] grid) { - int m = grid.length; - int n = grid[0].length; - - for (int i=0; i 0 && j > 0) { + dp[i][j] += Math.min(dp[i - 1][j], dp[i][j - 1]); + } else if (i > 0) { + dp[i][j] += dp[i - 1][j]; + } else if (j > 0) { + dp[i][j] += dp[i][j - 1]; } } } - - return grid[m-1][n-1]; + return dp[grid.length - 1][grid[0].length - 1]; } } diff --git a/Medium/Minimum Penalty for a Shop.java b/Medium/Minimum Penalty for a Shop.java new file mode 100644 index 00000000..e5c5eaa9 --- /dev/null +++ b/Medium/Minimum Penalty for a Shop.java @@ -0,0 +1,16 @@ +class Solution { + public int bestClosingTime(String customers) { + int n = customers.length(); + int minPenalty = 0; + int currPenalty = 0; + int minPenaltyHour = 0; + for (int i = 0; i < n; i++) { + currPenalty += customers.charAt(i) == 'Y' ? -1 : 1; + if (currPenalty < minPenalty) { + minPenaltyHour = i + 1; + minPenalty = currPenalty; + } + } + return minPenaltyHour; + } +} diff --git a/Medium/Minimum Processing Time.java b/Medium/Minimum Processing Time.java new file mode 100644 index 00000000..ec9b75e6 --- /dev/null +++ b/Medium/Minimum Processing Time.java @@ -0,0 +1,18 @@ +class Solution { + public int minProcessingTime(List processorTime, List tasks) { + PriorityQueue taskQueue = new PriorityQueue<>(); + PriorityQueue processorQueue = new PriorityQueue<>((a, b) -> b - a); + taskQueue.addAll(tasks); + processorQueue.addAll(processorTime); + int totalTime = Integer.MIN_VALUE; + while (!processorQueue.isEmpty()) { + int startTime = processorQueue.remove(); + int currTime = Integer.MIN_VALUE; + for (int i = 0; i < 4; i++) { + currTime = Math.max(currTime, startTime + taskQueue.remove()); + } + totalTime = Math.max(totalTime, currTime); + } + return totalTime; + } +} diff --git a/Medium/Minimum Remove to Make Valid Parentheses.java b/Medium/Minimum Remove to Make Valid Parentheses.java new file mode 100644 index 00000000..7d5be988 --- /dev/null +++ b/Medium/Minimum Remove to Make Valid Parentheses.java @@ -0,0 +1,28 @@ +class Solution { + public String minRemoveToMakeValid(String s) { + char[] letters = s.toCharArray(); + Stack stack = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '(') { + stack.push(i); + } else if (c == ')') { + if (stack.isEmpty()) { + letters[i] = '-'; + } else { + stack.pop(); + } + } + } + while (!stack.isEmpty()) { + letters[stack.pop()] = '-'; + } + StringBuilder sb = new StringBuilder(); + for (char c : letters) { + if (c != '-') { + sb.append(c); + } + } + return sb.toString(); + } +} diff --git a/Medium/Minimum Rounds to Complete All Tasks.java b/Medium/Minimum Rounds to Complete All Tasks.java new file mode 100644 index 00000000..309810a0 --- /dev/null +++ b/Medium/Minimum Rounds to Complete All Tasks.java @@ -0,0 +1,22 @@ +class Solution { + public int minimumRounds(int[] tasks) { + Map frequencyMap = Arrays.stream(tasks) + .boxed() + .collect(Collectors.groupingBy( + Function.identity(), + HashMap::new, + Collectors.counting())); + int rounds = 0; + for (Long occurrences : frequencyMap.values()) { + if (occurrences == 1) { + return -1; + } + if (occurrences % 3 == 0) { + rounds += (int) (occurrences / 3); + } else { + rounds += (int) (occurrences / 3 + 1); + } + } + return rounds; + } +} diff --git a/Medium/Minimum Score Triangulation of Polygon.java b/Medium/Minimum Score Triangulation of Polygon.java new file mode 100644 index 00000000..e94c16c2 --- /dev/null +++ b/Medium/Minimum Score Triangulation of Polygon.java @@ -0,0 +1,16 @@ +class Solution { + public int minScoreTriangulation(int[] A) { + int n = A.length; + int[][] dp = new int[n][n]; + for (int d = 2; d < n; ++d) { + for (int i = 0; i + d < n; ++i) { + int j = i + d; + dp[i][j] = Integer.MAX_VALUE; + for (int k = i + 1; k < j; ++k) { + dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k][j] + A[i] * A[j] * A[k]); + } + } + } + return dp[0][n - 1]; + } +} diff --git a/Medium/Minimum Score of a Path Between Two Cities.java b/Medium/Minimum Score of a Path Between Two Cities.java new file mode 100644 index 00000000..28b7ed1b --- /dev/null +++ b/Medium/Minimum Score of a Path Between Two Cities.java @@ -0,0 +1,31 @@ +class Solution { + public int minScore(int n, int[][] roads) { + Map>> graph = new HashMap<>(); + for (int[] road : roads) { + graph.computeIfAbsent(road[0], k -> new ArrayList<>()) + .add(List.of(road[1], road[2])); + graph.computeIfAbsent(road[1], k -> new ArrayList<>()) + .add(List.of(road[0], road[2])); + } + return bfs(n, graph); + } + + private int bfs(int n , Map>> graph) { + boolean[] visited = new boolean[n + 1]; + Queue queue = new LinkedList<>(); + int result = Integer.MAX_VALUE; + queue.add(1); + visited[1] = true; + while (!queue.isEmpty()) { + int node = queue.remove(); + for (List edge : graph.getOrDefault(node, new ArrayList<>())) { + result = Math.min(result, edge.get(1)); + if (!visited[edge.get(0)]) { + visited[edge.get(0)] = true; + queue.add(edge.get(0)); + } + } + } + return result; + } +} diff --git a/Medium/Minimum Size Subarray Sum.java b/Medium/Minimum Size Subarray Sum.java index 4d41780e..5bafe959 100644 --- a/Medium/Minimum Size Subarray Sum.java +++ b/Medium/Minimum Size Subarray Sum.java @@ -1,30 +1,18 @@ class Solution { - public int minSubArrayLen(int s, int[] nums) { - int sum = 0; - int slow = 0; - int fast = 0; - int n = nums.length; - int minLen = Integer.MAX_VALUE; - - while (fast < n) { - sum += nums[fast]; - - if (sum >= s) { - while (slow <= fast) { - minLen = Math.min(minLen, fast - slow + 1); - if (sum - nums[slow] >= s) { - sum -= nums[slow]; - slow++; - } - else { - break; - } - } + public int minSubArrayLen(int target, int[] nums) { + int start = 0; + int end = 0; + int currSum = 0; + int minLength = Integer.MAX_VALUE; + while (end < nums.length) { + currSum += nums[end++]; + while (start < end && currSum - nums[start] >= target) { + currSum -= nums[start++]; + } + if (currSum >= target) { + minLength = Math.min(minLength, end - start); } - - fast++; } - - return minLen == Integer.MAX_VALUE ? 0 : minLen; + return minLength == Integer.MAX_VALUE ? 0 : minLength; } } diff --git a/Medium/Minimum Speed to Arrive on Time.java b/Medium/Minimum Speed to Arrive on Time.java new file mode 100644 index 00000000..c5751902 --- /dev/null +++ b/Medium/Minimum Speed to Arrive on Time.java @@ -0,0 +1,26 @@ +class Solution { + public int minSpeedOnTime(int[] dist, double hour) { + int start = 1; + int end = 1000_000_0; + int minSpeed = -1; + while (start <= end) { + int mid = (start + end) / 2; + if (isPossible(dist, mid, hour)) { + minSpeed = mid; + end = mid - 1; + } else { + start = mid + 1; + } + } + return minSpeed; + } + + private boolean isPossible(int[] dist, int speed, double hour) { + double totalTime = 0.0; + for (int i = 0; i < dist.length; i++) { + double time = (double) dist[i] / (double) speed; + totalTime += (i == dist.length - 1 ? time : Math.ceil(time)); + } + return totalTime <= hour; + } +} diff --git a/Medium/Minimum Swaps to Group All 1's Together.java b/Medium/Minimum Swaps to Group All 1's Together.java new file mode 100644 index 00000000..ea3d82c8 --- /dev/null +++ b/Medium/Minimum Swaps to Group All 1's Together.java @@ -0,0 +1,20 @@ +class Solution { + public int minSwaps(int[] data) { + int totalOnes = 0; + for (int num : data) { + totalOnes += num; + } + int leftIdx = 0; + int rightIdx = 0; + int currOnes = 0; + int maxOnes = 0; + while (rightIdx < data.length) { + currOnes += data[rightIdx++]; + if (rightIdx - leftIdx > totalOnes) { + currOnes -= data[leftIdx++]; + } + maxOnes = Math.max(maxOnes, currOnes); + } + return totalOnes - maxOnes; + } +} diff --git a/Medium/Minimum Time Difference.java b/Medium/Minimum Time Difference.java index a330bbea..b8ba42a1 100644 --- a/Medium/Minimum Time Difference.java +++ b/Medium/Minimum Time Difference.java @@ -1,23 +1,21 @@ class Solution { - public int findMinDifference(List timePoints) { - int[] mins = new int[timePoints.size()]; - int i = 0; - for (String s : timePoints) { - int hr = Integer.parseInt(s.split(":")[0]); - int ms = Integer.parseInt(s.split(":")[1]); - - mins[i] = hr*60 + ms; - i++; - } - - Arrays.sort(mins); - - int minTime = Integer.MAX_VALUE; - - for(int j=1;j timePoints) { + List minutes = new ArrayList<>(); + for (String timePoint : timePoints) { + minutes.add( + Integer.parseInt(timePoint.split(":")[0]) * 60 + + Integer.parseInt(timePoint.split(":")[1])); } + Collections.sort(minutes); + int prev = Integer.MIN_VALUE; + int minDiff = Integer.MAX_VALUE; + for (int minute : minutes) { + if (prev != Integer.MIN_VALUE) { + minDiff = Math.min(minDiff, minute - prev); + } + prev = minute; + } + minDiff = Math.min(minDiff, (24 * 60 - minutes.get(minutes.size() - 1) + minutes.get(0))); + return minDiff; + } } diff --git a/Medium/Minimum Time to Collect All Apples in a Tree.java b/Medium/Minimum Time to Collect All Apples in a Tree.java new file mode 100644 index 00000000..0e54b3ec --- /dev/null +++ b/Medium/Minimum Time to Collect All Apples in a Tree.java @@ -0,0 +1,27 @@ +class Solution { + public int minTime(int n, int[][] edges, List hasApple) { + Map> map = new HashMap<>(); + for (int[] edge : edges) { + map.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]); + map.computeIfAbsent(edge[1], k -> new ArrayList<>()).add(edge[0]); + } + return recurse(0, -1, map, hasApple); + } + + private int recurse(int node, int parent, Map> graph, List hasApple) { + if (!graph.containsKey(node)) { + return 0; + } + int time = 0; + for (Integer conn: graph.get(node)) { + if (conn == parent) { + continue; + } + int connTime = recurse(conn, node, graph, hasApple); + if (connTime > 0 || hasApple.get(conn)) { + time += connTime + 2; + } + } + return time; + } +} diff --git a/Medium/Minimum Time to Complete Trips.java b/Medium/Minimum Time to Complete Trips.java new file mode 100644 index 00000000..f6fa3539 --- /dev/null +++ b/Medium/Minimum Time to Complete Trips.java @@ -0,0 +1,27 @@ +class Solution { + public long minimumTime(int[] time, int totalTrips) { + int maxTime = 1; + for (int t : time) { + maxTime = Math.max(maxTime, t); + } + long left = 1; + long right = (long) maxTime * totalTrips; + while (left < right) { + long mid = (left + right) / 2; + if (isPossible(time, mid, totalTrips)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } + + private boolean isPossible(int[] time, long totalTime, int totalTrips) { + long actualTrips = 0; + for (int t : time) { + actualTrips += totalTime / t; + } + return actualTrips >= totalTrips; + } +} diff --git a/Medium/Minimum Time to Make Rope Colorful.java b/Medium/Minimum Time to Make Rope Colorful.java new file mode 100644 index 00000000..3fdc7e26 --- /dev/null +++ b/Medium/Minimum Time to Make Rope Colorful.java @@ -0,0 +1,19 @@ +class Solution { + public int minCost(String colors, int[] neededTime) { + Stack stack = new Stack<>(); + int cost = 0; + for (int i = 0; i < colors.length(); i++) { + if (stack.isEmpty() || colors.charAt(i) != colors.charAt(stack.peek())) { + stack.push(i); + continue; + } + if (neededTime[i] > neededTime[stack.peek()]) { + cost += neededTime[stack.pop()]; + stack.push(i); + } else { + cost += neededTime[i]; + } + } + return cost; + } +} diff --git a/Medium/Mirror Reflection.java b/Medium/Mirror Reflection.java new file mode 100644 index 00000000..c5577abc --- /dev/null +++ b/Medium/Mirror Reflection.java @@ -0,0 +1,17 @@ +class Solution { + public int mirrorReflection(int p, int q) { + int extention = q; + int reflection = p; + while (extention % 2 == 0 && reflection % 2 == 0) { + extention /= 2; + reflection /= 2; + } + if (extention % 2 == 0 && reflection % 2 != 0) { + return 0; + } else if (extention % 2 != 0 && reflection % 2 == 0) { + return 2; + } else { + return 1; + } + } +} diff --git a/Medium/Missing Element in Sorted Array.java b/Medium/Missing Element in Sorted Array.java new file mode 100644 index 00000000..984822a7 --- /dev/null +++ b/Medium/Missing Element in Sorted Array.java @@ -0,0 +1,24 @@ +class Solution { + public int missingElement(int[] nums, int k) { + int n = nums.length; + if (k > missing(n - 1, nums)) { + return nums[n - 1] + k - missing(n - 1, nums); + } + int start = 0; + int end = n - 1; + while (start < end) { + int mid = start + (end - start) / 2; + if (missing(mid, nums) < k) { + start = mid + 1; + } + else { + end = mid; + } + } + return nums[start - 1] + k - missing(start - 1, nums); + } + + private int missing(int idx, int[] nums) { + return nums[idx] - nums[0] - idx; + } +} diff --git a/Medium/Missing Ranges.java b/Medium/Missing Ranges.java deleted file mode 100644 index bb57ffd0..00000000 --- a/Medium/Missing Ranges.java +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { - public List findMissingRanges(int[] nums, int lower, int upper) { - List list = new ArrayList<>(); - long next = lower; - - for (int i = 0; i < nums.length; i++) { - if (nums[i] < next) { - continue; - } - - if (nums[i] == next) { - next++; - continue; - } - - list.add(getRange(next, ((long) nums[i]) - 1)); - - next = ((long) nums[i]) + 1; - } - - if (next <= upper) { - list.add(getRange(next, (long) upper)); - } - - return list; - } - - private String getRange(long down, long up) { - return up == down ? String.valueOf(up) : String.format("%d->%d", down, up); - } -} diff --git a/Medium/Most Beautiful Item for Each Query.java b/Medium/Most Beautiful Item for Each Query.java new file mode 100644 index 00000000..5d2f75db --- /dev/null +++ b/Medium/Most Beautiful Item for Each Query.java @@ -0,0 +1,17 @@ +class Solution { + public int[] maximumBeauty(int[][] items, int[] queries) { + Arrays.sort(items, (a, b) -> (a[0] - b[0])); + TreeMap map = new TreeMap<>(); + map.put(0, 0); + int currMax = 0; + for (int[] item : items) { + currMax = Math.max(currMax, item[1]); + map.put(item[0], currMax); + } + int[] result = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + result[i] = map.floorEntry(queries[i]).getValue(); + } + return result; + } +} diff --git a/Medium/Most Frequent Subtree Sum.java b/Medium/Most Frequent Subtree Sum.java index a547b5ad..0d892dc1 100644 --- a/Medium/Most Frequent Subtree Sum.java +++ b/Medium/Most Frequent Subtree Sum.java @@ -4,53 +4,45 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - Map map = new HashMap<>(); - int max = 0; - public int[] findFrequentTreeSum(TreeNode root) { - populateSum(root); - - int count = 0; - - for (Map.Entry entry:map.entrySet()) { - if (entry.getValue() == max) { - count++; - } - } - - int[] ans = new int[count]; - int i = 0; - - for (Map.Entry entry:map.entrySet()) { - if (entry.getValue() == max) { - ans[i] = entry.getKey(); - i++; - } - } - - return ans; + public int[] findFrequentTreeSum(TreeNode root) { + Map subtreeSumFrequency = new HashMap<>(); + Map nodeToSum = new HashMap<>(); + dfsHelper(root, nodeToSum, subtreeSumFrequency); + int maxFrequency = subtreeSumFrequency.values().stream() + .max(Comparator.comparingInt(Integer::intValue)).orElseGet(() -> 0); + return subtreeSumFrequency + .keySet() + .stream() + .filter(e -> subtreeSumFrequency.get(e) == maxFrequency) + .collect(Collectors.toList()) + .stream() + .mapToInt(Integer::intValue) + .toArray(); + } + + private int dfsHelper(TreeNode node, Map nodeToSum, + Map subtreeSumFrequency) { + if (node == null) { + return 0; } - - public void populateSum(TreeNode root) { - - if (root == null) return; - int sum = getSum(root); - map.put(sum, map.getOrDefault(sum, 0) + 1); - - max = Math.max(max, map.get(sum)); - - populateSum(root.left); - populateSum(root.right); - - } - - public int getSum(TreeNode root) { - if (root == null) return 0; - - int sum = root.val; - return sum + getSum(root.left) + getSum(root.right); + if (nodeToSum.containsKey(node)) { + return nodeToSum.get(node); } + int leftSubtreeSum = dfsHelper(node.left, nodeToSum, subtreeSumFrequency); + int rightSubtreeSum = dfsHelper(node.right, nodeToSum, subtreeSumFrequency); + nodeToSum.put(node, node.val + leftSubtreeSum + rightSubtreeSum); + subtreeSumFrequency + .put(nodeToSum.get(node), subtreeSumFrequency.getOrDefault(nodeToSum.get(node), 0) + 1); + return nodeToSum.get(node); + } } diff --git a/Medium/Most Popular Video Creator.java b/Medium/Most Popular Video Creator.java new file mode 100644 index 00000000..d9e93554 --- /dev/null +++ b/Medium/Most Popular Video Creator.java @@ -0,0 +1,27 @@ +class Solution { + public List> mostPopularCreator(String[] creators, String[] ids, int[] views) { + Map creatorToViewCount = new HashMap<>(); + Map> creatorToIdWithMaxViews = new HashMap<>(); + long totalMaxViews = 0; + for (int i = 0; i < creators.length; i++) { + creatorToViewCount.put(creators[i], creatorToViewCount.getOrDefault(creators[i], 0L) + views[i]); + if (!creatorToIdWithMaxViews.containsKey(creators[i])) { + creatorToIdWithMaxViews.put(creators[i], new Pair<>(ids[i], (long) views[i])); + } else { + Pair currentIdToViewPair = creatorToIdWithMaxViews.get(creators[i]); + if (views[i] > currentIdToViewPair.getValue() || + (views[i] == currentIdToViewPair.getValue() && ids[i].compareTo(currentIdToViewPair.getKey()) < 0)) { + creatorToIdWithMaxViews.put(creators[i], new Pair<>(ids[i], (long) views[i])); + } + } + totalMaxViews = Math.max(totalMaxViews, creatorToViewCount.get(creators[i])); + } + List> result = new ArrayList<>(); + for (String key : creatorToViewCount.keySet()) { + if (creatorToViewCount.get(key) == totalMaxViews) { + result.add(Arrays.asList(key, creatorToIdWithMaxViews.get(key).getKey())); + } + } + return result; + } +} diff --git a/Medium/Most Profit Assigning Work.java b/Medium/Most Profit Assigning Work.java new file mode 100644 index 00000000..792530db --- /dev/null +++ b/Medium/Most Profit Assigning Work.java @@ -0,0 +1,31 @@ +class Solution { + public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) { + List tasks = new ArrayList<>(); + for (int i = 0; i < difficulty.length; i++) { + tasks.add(new Task(profit[i], difficulty[i])); + } + tasks.sort(Comparator.comparingInt(o -> o.difficulty)); + Arrays.sort(worker); + int idx = 0; + int maxProfit = 0; + int workerProfit = 0; + for (int ability : worker) { + while (idx < profit.length && ability >= tasks.get(idx).difficulty) { + workerProfit = Math.max(workerProfit, tasks.get(idx++).profit); + } + maxProfit += workerProfit; + } + return maxProfit; + } + + + class Task { + int profit; + int difficulty; + + public Task(int profit, int difficulty) { + this.profit = profit; + this.difficulty = difficulty; + } + } +} diff --git a/Medium/Most Stones Removed with Same Row or Column.java b/Medium/Most Stones Removed with Same Row or Column.java new file mode 100644 index 00000000..540efe34 --- /dev/null +++ b/Medium/Most Stones Removed with Same Row or Column.java @@ -0,0 +1,22 @@ +class Solution { + public int removeStones(int[][] stones) { + Set visited = new HashSet<>(); + int numOfIslands = 0; + for (int[] stone : stones) { + if (!visited.contains(stone)) { + dfs(stones, visited, stone); + numOfIslands++; + } + } + return stones.length - numOfIslands; + } + + private void dfs(int[][] stones, Set visited, int[] stone) { + visited.add(stone); + for (int[] st : stones) { + if ((st[0] == stone[0] || st[1] == stone[1]) && !visited.contains(st)) { + dfs(stones, visited, st); + } + } + } +} diff --git a/Medium/Multiply Strings.java b/Medium/Multiply Strings.java index 27238d18..7222ae47 100644 --- a/Medium/Multiply Strings.java +++ b/Medium/Multiply Strings.java @@ -1,68 +1,31 @@ class Solution { - public String multiply(String num1, String num2) { - // Initial array of n * m size - int n = num1.length(); - int m = num2.length(); - int[] ans = new int[n + m]; - - // Multiple both strings from end and store it in the array - // Keep decreasing end size by one for each iteration - int idx = ans.length - 1; - int carry = 0; - int tempIdx = idx; - - for (int i = n - 1; i >= 0; i--) { - tempIdx = idx; - for (int j = m - 1; j >= 0; j--) { - char a = num1.charAt(i); - char b = num2.charAt(j); - - int mul = ans[tempIdx] + multiplyChars(a, b) + carry; - if (mul > 9) { - carry = mul / 10; - mul = mul % 10; - } - else { - carry = 0; - } - - ans[tempIdx] = mul; - tempIdx--; - } - - // Continue adding carry if present else reset carry - while (carry > 0) { - int mul = ans[tempIdx] + carry; - if (mul > 9) { - carry = mul / 10; - mul = mul % 10; - } - else { - carry = 0; - } - - ans[tempIdx--] = mul; - } - - idx--; - } - - // Remove initial zeros - int zeroIdx = 0; - while (zeroIdx < ans.length && ans[zeroIdx] == 0 ) { - zeroIdx++; - } - - // Convert array to string and return - StringBuilder sb = new StringBuilder(); - for (int i = zeroIdx; i < ans.length; i++) { - sb.append(ans[i]); - } - - return sb.length() == 0 ? "0" : sb.toString(); + public String multiply(String num1, String num2) { + int m = num1.length(); + int n = num2.length(); + int[] result = new int[m + n]; + int endIdx = m + n - 1; + for (int i = m - 1; i >= 0; i--) { + int resultIdx = endIdx; + int carry = 0; + for (int j = n - 1; j >= 0; j--) { + int currValue = result[resultIdx] + carry + Character.getNumericValue(num1.charAt(i)) * Character.getNumericValue(num2.charAt(j)); + carry = currValue / 10; + result[resultIdx--] = currValue % 10; + } + while (carry > 0) { + result[resultIdx--] = carry % 10; + carry /= 10; + } + endIdx--; } - - private int multiplyChars(char a, char b) { - return Character.getNumericValue(a) * Character.getNumericValue(b); + int idx = 0; + while (idx < result.length && result[idx] == 0) { + idx++; } + StringBuilder sb = new StringBuilder(); + for (int i = idx; i < result.length; i++) { + sb.append(result[i]); + } + return sb.length() == 0 ? "0" : sb.toString(); + } } diff --git a/Medium/My Calendar I.java b/Medium/My Calendar I.java index c225f6b2..17064e87 100644 --- a/Medium/My Calendar I.java +++ b/Medium/My Calendar I.java @@ -1,21 +1,21 @@ class MyCalendar { - TreeMap map; - - public MyCalendar() { - map = new TreeMap<>(); - } - - public boolean book(int start, int end) { - Map.Entry entry = map.lowerEntry(end); - if (entry != null && entry.getValue() > start) { - return false; - } - - map.put(start, end); - return true; + + TreeMap events; + + public MyCalendar() { + events = new TreeMap<>(); + } + + public boolean book(int start, int end) { + Integer lower = events.floorKey(start); + Integer upper = events.ceilingKey(start); + if ((lower == null || events.get(lower) <= start) && (upper == null || end <= upper)) { + events.put(start, end); + return true; } + return false; + } } - /** * Your MyCalendar object will be instantiated and called as such: * MyCalendar obj = new MyCalendar(); diff --git a/Medium/My Calendar II.java b/Medium/My Calendar II.java index ece26a8f..5553a51c 100644 --- a/Medium/My Calendar II.java +++ b/Medium/My Calendar II.java @@ -1,25 +1,25 @@ class MyCalendarTwo { - private List books = new ArrayList<>(); - - public boolean book(int s, int e) { - - MyCalendar overlaps = new MyCalendar(); - for (int[] b : books) - if (Math.max(b[0], s) < Math.min(b[1], e)) - if (!overlaps.book(Math.max(b[0], s), Math.min(b[1], e))) return false; - books.add(new int[]{ s, e }); - return true; - } + + private TreeMap delta; + + public MyCalendarTwo() { + this.delta = new TreeMap<>(); + } - private static class MyCalendar { - List books = new ArrayList<>(); - public boolean book(int start, int end) { - for (int[] b : books) - if (Math.max(b[0], start) < Math.min(b[1], end)) return false; - books.add(new int[]{ start, end }); - return true; - } + public boolean book(int start, int end) { + delta.put(start, delta.getOrDefault(start, 0) + 1); + delta.put(end, delta.getOrDefault(end, 0) - 1); + int active = 0; + for (int d : delta.values()) { + active += d; + if (active >= 3) { + delta.put(start, delta.get(start) - 1); + delta.put(end, delta.get(end) + 1); + return false; + } } + return true; + } } /** diff --git a/Medium/N-ary Tree Level Order Traversal.java b/Medium/N-ary Tree Level Order Traversal.java new file mode 100644 index 00000000..7f3df2b3 --- /dev/null +++ b/Medium/N-ary Tree Level Order Traversal.java @@ -0,0 +1,40 @@ +/* +// Definition for a Node. +class Node { + public int val; + public List children; + + public Node() {} + + public Node(int _val) { + val = _val; + } + + public Node(int _val, List _children) { + val = _val; + children = _children; + } +}; +*/ + +class Solution { + public List> levelOrder(Node root) { + if (root == null) { + return new ArrayList<>(); + } + List> levels = new ArrayList<>(); + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + List currLevel = new ArrayList<>(); + while (size-- > 0) { + Node removed = queue.remove(); + currLevel.add(removed.val); + queue.addAll(removed.children); + } + levels.add(currLevel); + } + return levels; + } +} diff --git a/Medium/Nearest Exit from Entrance in Maze.java b/Medium/Nearest Exit from Entrance in Maze.java new file mode 100644 index 00000000..097d5aaa --- /dev/null +++ b/Medium/Nearest Exit from Entrance in Maze.java @@ -0,0 +1,45 @@ +class Solution { + private static final int[][] DIRS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + + public int nearestExit(char[][] maze, int[] entrance) { + int rows = maze.length; + int cols = maze[0].length; + Queue queue = new LinkedList<>(); + boolean[][] visited = new boolean[rows][cols]; + int entranceRow = entrance[0]; + int entranceCol = entrance[1]; + queue.add(new int[]{entranceRow, entranceCol}); + visited[entranceRow][entranceCol] = true; + int steps = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + int row = removed[0]; + int col = removed[1]; + if (!(row == entranceRow && col == entranceCol) && isExit(row, col, rows, cols)) { + return steps; + } + for (int[] dir : DIRS) { + int newRow = row + dir[0]; + int newCol = col + dir[1]; + if (newRow >= 0 && + newCol >= 0 && + newRow < rows && + newCol < cols && + !visited[newRow][newCol] && + maze[newRow][newCol] != '+') { + queue.add(new int[]{newRow, newCol}); + visited[newRow][newCol] = true; + } + } + } + steps++; + } + return -1; + } + + private boolean isExit(int row, int col, int rows, int cols) { + return (row + 1 == rows) || (row - 1 == -1) || (col + 1 == cols) || (col - 1 == -1); + } +} diff --git a/Medium/Neighboring Bitwise XOR.java b/Medium/Neighboring Bitwise XOR.java new file mode 100644 index 00000000..6e46025c --- /dev/null +++ b/Medium/Neighboring Bitwise XOR.java @@ -0,0 +1,16 @@ +class Solution { + public boolean doesValidArrayExist(int[] derived) { + int n = derived.length; + int[] original = new int[n + 1]; + for (int i = 0; i < derived.length; i++) { + original[i + 1] = derived[i] ^ original[i]; + } + boolean checkForZero = (original[0] == original[n]); + original[0] = 1; + for (int i = 0; i < n; i++) { + original[i + 1] = derived[i] ^ original[i]; + } + boolean checkForOne = (original[0] == original[n]); + return checkForZero || checkForOne; + } +} diff --git a/Medium/Nested List Weight Sum II.java b/Medium/Nested List Weight Sum II.java index d1ac07d2..f804c67b 100644 --- a/Medium/Nested List Weight Sum II.java +++ b/Medium/Nested List Weight Sum II.java @@ -22,41 +22,33 @@ * public void add(NestedInteger ni); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ +import java.util.Map.Entry; + + class Solution { - int maxDepth; - int sum; - public int depthSumInverse(List nestedList) { - maxDepth = 0; - maxDepthHelper(nestedList, 1); - - sum = 0; - helper(nestedList, maxDepth); - - return sum; - } - - private void helper(List nestedList, int level) { - for (NestedInteger nested : nestedList) { - if (nested.isInteger()) { - sum += nested.getInteger() * level; - } - else { - helper(nested.getList(), level - 1); - } - } - } - - private void maxDepthHelper(List nestedList, int currLevel) { - maxDepth = Math.max(maxDepth, currLevel); - - for (NestedInteger nestedInteger : nestedList) { - if (!nestedInteger.isInteger()) { - maxDepthHelper(nestedInteger.getList(), currLevel + 1); - } + public int depthSumInverse(List nestedList) { + Queue queue = new LinkedList<>(); + queue.addAll(nestedList); + int totalSum = 0; + int currSum = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + int levelSum = 0; + while (size-- > 0) { + NestedInteger nestedInteger = queue.remove(); + if (nestedInteger.isInteger()) { + levelSum += nestedInteger.getInteger(); + } else { + queue.addAll(nestedInteger.getList()); } + } + currSum += levelSum; + totalSum += currSum; } + return totalSum; + } } diff --git a/Medium/Network Delay Time.java b/Medium/Network Delay Time.java new file mode 100644 index 00000000..2ee2990a --- /dev/null +++ b/Medium/Network Delay Time.java @@ -0,0 +1,35 @@ +class Solution { + public int networkDelayTime(int[][] times, int n, int k) { + Map> map = new HashMap<>(); + for (int[] time : times) { + map.computeIfAbsent(time[0], j -> new ArrayList<>()).add(new TimeNode(time[1], time[2])); + } + PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(o -> o.time)); + pq.add(new TimeNode(k, 0)); + int maxTime = 0; + Set visited = new HashSet<>(); + visited.add(k); + while (!pq.isEmpty() && visited.size() < n) { + TimeNode removed = pq.remove(); + visited.add(removed.node); + maxTime = Math.max(maxTime, removed.time); + for (TimeNode conn : map.getOrDefault(removed.node, new ArrayList<>())) { + if (visited.contains(conn.node)) { + continue; + } + pq.add(new TimeNode(conn.node, removed.time + conn.time)); + } + } + return visited.size() == n ? maxTime : -1; + } + + class TimeNode { + int node; + int time; + + public TimeNode(int node, int time) { + this.node = node; + this.time = time; + } + } +} diff --git a/Medium/New 21 Game.java b/Medium/New 21 Game.java new file mode 100644 index 00000000..26c88d90 --- /dev/null +++ b/Medium/New 21 Game.java @@ -0,0 +1,21 @@ +class Solution { + public double new21Game(int n, int k, int maxPts) { + double[] dp = new double[n + 1]; + dp[0] = 1; + double s = k > 0 ? 1 : 0; + for (int i = 1; i <= n; i++) { + dp[i] = s / maxPts; + if (i < k) { + s += dp[i]; + } + if (i - maxPts >= 0 && i - maxPts < k) { + s -= dp[i - maxPts]; + } + } + double result = 0; + for (int i = k; i <= n; i++) { + result += dp[i]; + } + return result; + } +} diff --git a/Medium/Next Closest Time.java b/Medium/Next Closest Time.java index 0d1ef172..46e267f6 100644 --- a/Medium/Next Closest Time.java +++ b/Medium/Next Closest Time.java @@ -1,42 +1,23 @@ class Solution { - public String nextClosestTime(String time) { - char[] timeDigits = time.toCharArray(); - char[] sorted = time.toCharArray(); - Arrays.sort(sorted); - - timeDigits[4] = findNext(timeDigits[4], (char)('9' + 1), sorted); - if (timeDigits[4] > time.charAt(4)) { - return String.valueOf(timeDigits); - } - - timeDigits[3] = findNext(timeDigits[3], '5', sorted); - if (timeDigits[3] > time.charAt(3)) { - return String.valueOf(timeDigits); - } - - timeDigits[1] = timeDigits[0] == '2' ? - findNext(timeDigits[1], '3', sorted) : - findNext(timeDigits[1], (char)('9' + 1), sorted); - if (timeDigits[1] > time.charAt(1)) { - return String.valueOf(timeDigits); - } - - timeDigits[0] = findNext(timeDigits[0], '2', sorted); - - return String.valueOf(timeDigits); + public String nextClosestTime(String time) { + int minutes = Integer.parseInt(time.substring(0, 2)) * 60 + Integer.parseInt(time.substring(3)); + Set digits = new HashSet<>(); + for (char c : time.toCharArray()) { + digits.add(c - '0'); } - - private char findNext(char current, char limit, char[] sorted) { - if (current == limit) { - return sorted[0]; - } - - int pos = Arrays.binarySearch(sorted, current) + 1; - - while (pos < 4 && (sorted[pos] > limit || sorted[pos] == current)) { - pos++; + while (true) { + minutes = (minutes + 1) % (24 * 60); + int[] nextTime = {minutes / 60 / 10, minutes / 60 % 10, minutes % 60 / 10, minutes % 60 % 10}; + boolean found = true; + for (int unit : nextTime) { + if (!digits.contains(unit)) { + found = false; + break; } - - return pos == 4 ? sorted[0] : sorted[pos]; + } + if (found) { + return String.format("%02d:%02d", minutes / 60, minutes % 60); + } } + } } diff --git a/Medium/Next Greater Element II.java b/Medium/Next Greater Element II.java index 1da2f6a0..c392b087 100644 --- a/Medium/Next Greater Element II.java +++ b/Medium/Next Greater Element II.java @@ -1,25 +1,23 @@ class Solution { - public int[] nextGreaterElements(int[] nums) { - int[] ans = new int[nums.length]; - for (int i=0;i nums[i]) { - ans[i] = nums[j]; - break; - } - j++; - } + public int[] nextGreaterElements(int[] nums) { + int[] result = new int[nums.length]; + Stack stack = new Stack<>(); + for (int i = nums.length - 1; i >= 0; i--) { + while (!stack.isEmpty() && nums[stack.peek()] <= nums[i]) { + stack.pop(); + } + result[i] = stack.isEmpty() ? -1 : nums[stack.peek()]; + stack.push(i); + } + for (int i = nums.length - 1; i >= 0; i--) { + if (result[i] == -1) { + while (!stack.isEmpty() && nums[stack.peek()] <= nums[i]) { + stack.pop(); } - - return ans; + result[i] = stack.isEmpty() ? -1 : nums[stack.peek()]; + } + stack.push(i); } + return result; + } } diff --git a/Medium/Next Greater Element III.java b/Medium/Next Greater Element III.java index 0d0592ef..92d84436 100644 --- a/Medium/Next Greater Element III.java +++ b/Medium/Next Greater Element III.java @@ -1,53 +1,33 @@ class Solution { - public int nextGreaterElement(int n) { - int[] arr = getArr(n); - int i; - for (i=arr.length-1; i>0; i--) { - if (arr[i-1] < arr[i]) { - break; - } + public int nextGreaterElement(int n) { + char[] digits = String.valueOf(n).toCharArray(); + int idx = digits.length - 2; + while (idx >= 0) { + if (Character.getNumericValue(digits[idx]) < Character.getNumericValue(digits[idx + 1])) { + int secondIdx = digits.length - 1; + while (secondIdx >= idx && digits[secondIdx] <= digits[idx]) { + secondIdx--; + } + swap(digits, idx, secondIdx); + int start = idx + 1; + int end = digits.length - 1; + while (start < end) { + swap(digits, start++, end--); } - - if (i == 0) { - return -1; + try { + return Integer.parseInt(new String(digits)); + } catch (Exception e) { + return -1; } - - int num = arr[i-1]; - int small = i; - for (int j=i+1; j num && arr[j] <= arr[small]) { - small = j; - } - } - - int temp = arr[i-1]; - arr[i-1] = arr[small]; - arr[small] = temp; - - Arrays.sort(arr, i, arr.length); - long ans = getNumber(arr); - - return ans <= Integer.MAX_VALUE ? (int) ans : -1; - } - - private long getNumber(int[] arr) { - long num = 0; - for (int i=0; i= 0) { - arr[i] = n % 10; - n /= 10; - i--; - } - - return arr; + } + idx--; } + return -1; + } + + private void swap(char[] digits, int idxOne, int idxTwo) { + char temp = digits[idxOne]; + digits[idxOne] = digits[idxTwo]; + digits[idxTwo] = temp; + } } diff --git a/Medium/Next Greater Node In Linked List.java b/Medium/Next Greater Node In Linked List.java index 5b81f90e..871a6960 100644 --- a/Medium/Next Greater Node In Linked List.java +++ b/Medium/Next Greater Node In Linked List.java @@ -3,45 +3,38 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public int[] nextLargerNodes(ListNode head) { - ListNode rev = reverse(head); - Stack stack = new Stack<>(); - List list = new ArrayList<>(); - - while (rev != null) { - while (!stack.isEmpty() && stack.peek() <= rev.val) { - stack.pop(); - } - - list.add(stack.isEmpty() ? 0 : stack.peek()); - stack.push(rev.val); - rev = rev.next; - } - - int[] arr = new int[list.size()]; - for (int i = 0, j=list.size() - 1; i < list.size(); i++,j--) { - arr[i] = list.get(j); - } - - return arr; + public int[] nextLargerNodes(ListNode head) { + // Reverse the list + ListNode curr = head; + ListNode prev = null; + ListNode next = null; + int count = 0; + while (curr != null) { + next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + count++; } - - private ListNode reverse(ListNode head) { - ListNode curr = head; - ListNode prev = null; - ListNode next = null; - - while (curr != null) { - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - - return prev; + curr = prev; + Stack stack = new Stack<>(); + int[] ans = new int[count]; + int idx = count - 1; + while (curr != null) { + // Keep track of next greatest value node + while (!stack.isEmpty() && stack.peek() <= curr.val) { + stack.pop(); + } + ans[idx--] = stack.isEmpty() ? 0 : stack.peek(); + stack.push(curr.val); + curr = curr.next; } + return ans; + } } diff --git a/Medium/Next Greater Numerically Balanced Number.java b/Medium/Next Greater Numerically Balanced Number.java new file mode 100644 index 00000000..c5b399c5 --- /dev/null +++ b/Medium/Next Greater Numerically Balanced Number.java @@ -0,0 +1,6 @@ +class Solution { + public final int[] CANDIDATES = new int[] {1, 22, 122, 212, 221, 333, 1333, 3133, 3313, 3331, 4444, 14444, 22333, 23233, 23323, 23332, 32233, 32323, 32332, 33223, 33232, 33322, 41444, 44144, 44414, 44441, 55555, 122333, 123233, 123323, 123332, 132233, 132323, 132332, 133223, 133232, 133322, 155555, 212333, 213233, 213323, 213332, 221333, 223133, 223313, 223331, 224444, 231233, 231323, 231332, 232133, 232313, 232331, 233123, 233132, 233213, 233231, 233312, 233321, 242444, 244244, 244424, 244442, 312233, 312323, 312332, 313223, 313232, 313322, 321233, 321323, 321332, 322133, 322313, 322331, 323123, 323132, 323213, 323231, 323312, 323321, 331223, 331232, 331322, 332123, 332132, 332213, 332231, 332312, 332321, 333122, 333212, 333221, 422444, 424244, 424424, 424442, 442244, 442424, 442442, 444224, 444242, 444422, 515555, 551555, 555155, 555515, 555551, 666666}; + public int nextBeautifulNumber(int n) { + return Arrays.stream(CANDIDATES).filter(candidate -> candidate > n).findFirst().orElse(1224444); + } +} diff --git a/Medium/Next Permutation.java b/Medium/Next Permutation.java index f9c7c940..b08a0001 100644 --- a/Medium/Next Permutation.java +++ b/Medium/Next Permutation.java @@ -1,40 +1,31 @@ class Solution { public void nextPermutation(int[] nums) { - // Keep moving right to left until a down slope is found - boolean noChange = true; - int right = nums.length - 1; - int start = right; - while (start >= 1) { - // When found, swap the number with rightmost digit which is greater - // than the digit on the down slope - if (nums[start] > nums[start - 1]) { - int idx = right; - while (nums[idx] <= nums[start - 1]) { - idx--; - } - - int temp = nums[start - 1]; - nums[start - 1] = nums[idx]; - nums[idx] = temp; - noChange = false; - break; - } - - start--; + int n = nums.length; + int pivot = n - 1; + // Find the first value where decreasing order doesn't holds + while (pivot > 0 && nums[pivot] <= nums[pivot - 1]) { + pivot--; } - - if (noChange) { - Arrays.sort(nums); - return; + if (pivot != 0) { + int i = n - 1; + // Find the first value from right to left which is greater than element at + // pivot - 1 + while (nums[i] <= nums[pivot - 1]) { + i--; + } + swap(nums, pivot - 1, i); } - - // Reverse everything to the right of down slope - while (start < right) { - int temp = nums[start]; - nums[start] = nums[right]; - nums[right] = temp; - start++; - right--; + // Reverse the complete array + int left = pivot; + int right = n - 1; + while (left < right) { + swap(nums, left++, right--); } } + + private void swap(int[] nums, int idxOne, int idxTwo) { + int temp = nums[idxOne]; + nums[idxOne] = nums[idxTwo]; + nums[idxTwo] = temp; + } } diff --git a/Medium/Node With Highest Edge Score.java b/Medium/Node With Highest Edge Score.java new file mode 100644 index 00000000..9154bb2f --- /dev/null +++ b/Medium/Node With Highest Edge Score.java @@ -0,0 +1,19 @@ +class Solution { + public int edgeScore(int[] edges) { + Map map = new HashMap<>(); + int highestScore = 0; + int highestScoreCandidate = Integer.MAX_VALUE; + for (int i = 0; i < edges.length; i++) { + map.put(edges[i], map.getOrDefault(edges[i], 0) + i); + if (highestScore <= map.get(edges[i])) { + if (highestScore < map.get(edges[i])) { + highestScore = map.get(edges[i]); + highestScoreCandidate = edges[i]; + } else if (highestScore == map.get(edges[i]) && highestScoreCandidate > edges[i]) { + highestScoreCandidate = edges[i]; + } + } + } + return highestScoreCandidate; + } +} diff --git a/Medium/Non Overlapping Intervals.java b/Medium/Non Overlapping Intervals.java deleted file mode 100644 index 741adddd..00000000 --- a/Medium/Non Overlapping Intervals.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Definition for an interval. - * public class Interval { - * int start; - * int end; - * Interval() { start = 0; end = 0; } - * Interval(int s, int e) { start = s; end = e; } - * } - */ -class Solution { - public static int eraseOverlapIntervals(Interval[] intervals) { - if (intervals.length == 0) { - return 0; - } - - Arrays.sort(intervals, new Comparator() { - @Override - public int compare(Interval o1, Interval o2) { - return o1.end - o2.end; - } - }); - - int count = 1; - int end = intervals[0].end; - - for (int i=1; i= end) { - end = intervals[i].end; - count++; - } - } - - return intervals.length - count; - } -} diff --git a/Medium/Non-decreasing Array.java b/Medium/Non-decreasing Array.java new file mode 100644 index 00000000..489db551 --- /dev/null +++ b/Medium/Non-decreasing Array.java @@ -0,0 +1,19 @@ +class Solution { + public boolean checkPossibility(int[] nums) { + boolean mismatch = false; + for (int i = 1; i < nums.length; i++) { + if (nums[i - 1] > nums[i]) { + if (mismatch) { + return false; + } + if (i < 2 || nums[i - 2] <= nums[i]) { + nums[i - 1] = nums[i]; + } else { + nums[i] = nums[i - 1]; + } + mismatch = true; + } + } + return true; + } +} diff --git a/Medium/Non-overlapping Intervals.java b/Medium/Non-overlapping Intervals.java new file mode 100644 index 00000000..c403b5ed --- /dev/null +++ b/Medium/Non-overlapping Intervals.java @@ -0,0 +1,17 @@ +class Solution { + public int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, Comparator.comparingInt((int[] o) -> o[1])); + int result = 0; + int minEndTime = Integer.MIN_VALUE; + for (int i = 0; i < intervals.length; i++) { + int start = intervals[i][0]; + int end = intervals[i][1]; + if (start >= minEndTime) { + minEndTime = end; + } else { + result++; + } + } + return result; + } +} diff --git a/Medium/Number of Burgers with No Waste of Ingredients.java b/Medium/Number of Burgers with No Waste of Ingredients.java new file mode 100644 index 00000000..ebf00c37 --- /dev/null +++ b/Medium/Number of Burgers with No Waste of Ingredients.java @@ -0,0 +1,17 @@ +class Solution { + public List numOfBurgers(int tomatoSlices, int cheeseSlices) { + int twoX = tomatoSlices - 2 * cheeseSlices; + int x = twoX / 2; + int y = cheeseSlices - x; + return twoX >= 0 && twoX % 2 == 0 && y >= 0 ? Arrays.asList(x, y) : new ArrayList<>(); + } +} + +/* +4x + 2y = tomato +x + y = cheese +=> +2x = tomato - 2 * cheese +x = (tomato - 2 * cheese) / 2 +y = cheese - x +*/ diff --git a/Medium/Number of Closed Islands.java b/Medium/Number of Closed Islands.java new file mode 100644 index 00000000..bc8a9a9e --- /dev/null +++ b/Medium/Number of Closed Islands.java @@ -0,0 +1,38 @@ +class Solution { + + private static final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int closedIsland(int[][] grid) { + int count = 0; + boolean[][] visited = new boolean[grid.length][grid[0].length]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 0 && !visited[i][j] && isClosed(grid, i, j, visited)) { + count++; + } + } + } + return count; + } + + private boolean isClosed(int[][] grid, int i, int j, boolean[][] visited) { + Queue queue = new LinkedList<>(); + queue.add(new int[]{i, j}); + visited[i][j] = true; + boolean closed = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + for (int[] dir : DIRS) { + int newX = removed[0] + dir[0]; + int newY = removed[1] + dir[1]; + if (newX < 0 || newY < 0 || newX >= grid.length || newY >= grid[0].length) { + closed = false; + } else if (grid[newX][newY] == 0 && !visited[newX][newY]) { + queue.add(new int[]{newX, newY}); + visited[newX][newY] = true; + } + } + } + return closed; + } +} diff --git a/Medium/Number of Connected Components in an Undirected Graph.java b/Medium/Number of Connected Components in an Undirected Graph.java index 2c81b9ee..59e0be29 100644 --- a/Medium/Number of Connected Components in an Undirected Graph.java +++ b/Medium/Number of Connected Components in an Undirected Graph.java @@ -1,41 +1,29 @@ class Solution { public int countComponents(int n, int[][] edges) { - Map> map = new HashMap<>(); - + Map> graph = new HashMap<>(); for (int[] edge : edges) { - map.computeIfAbsent(edge[0], k -> new ArrayList()).add(edge[1]); - map.computeIfAbsent(edge[1], k -> new ArrayList()).add(edge[0]); + graph.computeIfAbsent(edge[0], k -> new HashSet<>()).add(edge[1]); + graph.computeIfAbsent(edge[1], k -> new HashSet<>()).add(edge[0]); } - - Set set = new HashSet<>(); - int count = 0; - - for (Map.Entry> entry : map.entrySet()) { - if (set.contains(entry.getKey())) { - continue; - } - - Queue queue = new LinkedList<>(); - queue.add(entry.getKey()); - set.add(entry.getKey()); - - while (!queue.isEmpty()) { - int popped = queue.remove(); - List connections = map.getOrDefault(popped, new ArrayList()); - - for (int connection : connections) { - if (set.contains(connection)) { - continue; + int connectedComponentCount = 0; + Set visited = new HashSet<>(); + for (int i = 0; i < n; i++) { + if (!visited.contains(i)) { + Queue queue = new LinkedList<>(); + visited.add(i); + queue.add(i); + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer neighbor : graph.getOrDefault(removed, new HashSet<>())) { + if (!visited.contains(neighbor)) { + queue.add(neighbor); + visited.add(neighbor); + } } - - set.add(connection); - queue.add(connection); } + connectedComponentCount++; } - - count++; } - - return count + (n - set.size()); + return connectedComponentCount; } } diff --git a/Medium/Number of Dice Rolls With Target Sum.java b/Medium/Number of Dice Rolls With Target Sum.java new file mode 100644 index 00000000..e192518a --- /dev/null +++ b/Medium/Number of Dice Rolls With Target Sum.java @@ -0,0 +1,31 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int numRollsToTarget(int n, int k, int target) { + Map map = new HashMap<>(); + return helper(n, k, target, map); + } + + private int helper(int n, int k, int target, Map map) { + if (n == 0 && target == 0) { + return 1; + } + if (n == 0 || target == 0) { + return 0; + } + int key = n * 1000 + target; + if (map.containsKey(key)) { + return map.get(key); + } + int result = 0; + for (int i = 1; i <= k; i++) { + if (target < i) { + break; + } + result = (result + helper(n - 1, k, target - i, map)) % MOD; + } + map.put(key, result); + return result; + } +} diff --git a/Medium/Number of Distinct Islands.java b/Medium/Number of Distinct Islands.java index f43442f3..e9ea1286 100644 --- a/Medium/Number of Distinct Islands.java +++ b/Medium/Number of Distinct Islands.java @@ -1,32 +1,35 @@ class Solution { - public int numDistinctIslands(int[][] grid) { - Set numOfIslands = new HashSet<>(); - - for (int i=0; i islands = new HashSet<>(); + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + StringBuilder currIsland = new StringBuilder(); + dfs(grid, row, col, visited, currIsland, '0'); + if (currIsland.length() == 0) { + continue; } - - return numOfIslands.size(); + islands.add(currIsland.toString()); + } } - - private String dfsHelper(int[][] grid, int row, int col, StringBuilder sb) { - if (row == grid.length || row < 0 || col == grid[row].length || col < 0 || grid[row][col] == 0) { - return sb.toString(); - } - - grid[row][col] = 0; - - sb.append(dfsHelper(grid, row - 1, col, new StringBuilder("u"))); - sb.append(dfsHelper(grid, row, col + 1, new StringBuilder("r"))); - sb.append(dfsHelper(grid, row + 1, col, new StringBuilder("d"))); - sb.append(dfsHelper(grid, row, col - 1, new StringBuilder("l"))); - - return sb.toString(); + return islands.size(); + } + + private void dfs(int[][] grid, int row, int col, boolean[][] visited, StringBuilder currIsland, char direction) { + if (row < 0 || row >= grid.length || col < 0 || col >= grid[0].length) { + return; + } + if (visited[row][col] || grid[row][col] == 0) { + return; } + visited[row][col] = true; + currIsland.append(direction); + dfs(grid, row + 1, col, visited, currIsland, 'D'); + dfs(grid, row - 1, col, visited, currIsland, 'U'); + dfs(grid, row, col + 1, visited, currIsland, 'R'); + dfs(grid, row, col - 1, visited, currIsland, 'L'); + currIsland.append('0'); + } } diff --git a/Medium/Number of Distinct Substrings in a String.java b/Medium/Number of Distinct Substrings in a String.java new file mode 100644 index 00000000..17d2a053 --- /dev/null +++ b/Medium/Number of Distinct Substrings in a String.java @@ -0,0 +1,26 @@ +class Solution { + public int countDistinct(String s) { + TrieNode root = new TrieNode(); + int n = s.length(); + int count = 0; + for (int i = 0; i < n; i++) { + TrieNode curr = root; + for (int j = i; j < n; j++) { + if (!curr.children.containsKey(s.charAt(j))) { + count++; + curr.children.put(s.charAt(j), new TrieNode()); + } + curr = curr.children.get(s.charAt(j)); + } + } + return count; + } + + private static class TrieNode { + Map children; + + public TrieNode() { + this.children = new HashMap<>(); + } + } +} diff --git a/Medium/Number of Enclaves.java b/Medium/Number of Enclaves.java new file mode 100644 index 00000000..afacc77a --- /dev/null +++ b/Medium/Number of Enclaves.java @@ -0,0 +1,40 @@ +class Solution { + + private static final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int numEnclaves(int[][] grid) { + int count = 0; + boolean[][] visited = new boolean[grid.length][grid[0].length]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == 1 && !visited[i][j]) { + count += getClosedEnclaveCount(grid, i, j, visited); + } + } + } + return count; + } + + private int getClosedEnclaveCount(int[][] grid, int i, int j, boolean[][] visited) { + boolean isClosed = true; + int enclaveCount = 0; + Queue queue = new LinkedList<>(); + queue.add(new int[]{i, j}); + visited[i][j] = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + enclaveCount++; + for (int[] dir : DIRS) { + int newX = removed[0] + dir[0]; + int newY = removed[1] + dir[1]; + if (newX < 0 || newY < 0 || newX >= grid.length || newY >= grid[0].length) { + isClosed = false; + } else if (grid[newX][newY] == 1 && !visited[newX][newY]) { + visited[newX][newY] = true; + queue.add(new int[]{newX, newY}); + } + } + } + return isClosed ? enclaveCount : 0; + } +} diff --git a/Medium/Number of Good Leaf Nodes Pairs.java b/Medium/Number of Good Leaf Nodes Pairs.java new file mode 100644 index 00000000..c54d967f --- /dev/null +++ b/Medium/Number of Good Leaf Nodes Pairs.java @@ -0,0 +1,59 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int countPairs(TreeNode root, int distance) { + Map> graph = new HashMap<>(); + Set leaves = new HashSet<>(); + traverse(root, null, graph, leaves); + int result = 0; + for (TreeNode leaf : leaves) { + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); + queue.add(leaf); + visited.add(leaf); + for (int i = 0; i <= distance; i++) { + int size = queue.size(); + while (size-- > 0) { + TreeNode curr = queue.remove(); + if (leaves.contains(curr) && curr != leaf) { + result++; + } + for (TreeNode neighbor : graph.getOrDefault(curr, new ArrayList<>())) { + if (visited.add(neighbor)) { + queue.add(neighbor); + } + } + } + } + } + return result / 2; + } + + private void traverse(TreeNode node, TreeNode parent, Map> graph, Set leaves) { + if (node == null) { + return; + } + if (node.left == null && node.right == null) { + leaves.add(node); + } + if (parent != null) { + graph.computeIfAbsent(parent, k -> new ArrayList<>()).add(node); + graph.computeIfAbsent(node, k -> new ArrayList<>()).add(parent); + } + traverse(node.left, node, graph, leaves); + traverse(node.right, node, graph, leaves); + } +} diff --git a/Medium/Number of Islands.java b/Medium/Number of Islands.java index 263dfdd1..ecf3afb7 100644 --- a/Medium/Number of Islands.java +++ b/Medium/Number of Islands.java @@ -1,29 +1,33 @@ class Solution { - public int numIslands(char[][] grid) { - int count = 0; - - for (int i=0; i queue = new LinkedList<>(); + queue.add(new int[]{i, j}); + visited[i][j] = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + for (int[] dir : DIRS) { + int newX = removed[0] + dir[0]; + int newY = removed[1] + dir[1]; + if (newX >= 0 && newY >= 0 && newX < rows && newY < cols && !visited[newX][newY] && grid[newX][newY] == '1') { + visited[newX][newY] = true; + queue.add(new int[]{newX, newY}); + } } + } + islandCount++; } - - return count; - } - - private void markArea(char[][] grid, int i, int j) { - if (i < 0 || j < 0 || i >= grid.length || j >= grid[i].length || grid[i][j] == '0') { - return; - } - - grid[i][j] = '0'; - markArea(grid, i-1, j); - markArea(grid, i, j-1); - markArea(grid, i, j+1); - markArea(grid, i+1, j); + } } + return islandCount; + } } diff --git a/Medium/Number of Laser Beams in a Bank.java b/Medium/Number of Laser Beams in a Bank.java new file mode 100644 index 00000000..ce39e8bd --- /dev/null +++ b/Medium/Number of Laser Beams in a Bank.java @@ -0,0 +1,17 @@ +class Solution { + public int numberOfBeams(String[] bank) { + int beamCount = 0; + int prevLaserCount = 0; + for (String row : bank) { + int count = 0; + for (char c : row.toCharArray()) { + count += c == '1' ? 1 : 0; + } + if (count > 0) { + beamCount += prevLaserCount * count; + prevLaserCount = count; + } + } + return beamCount; + } +} diff --git a/Medium/Number of Matching Subsequences.java b/Medium/Number of Matching Subsequences.java new file mode 100644 index 00000000..355527ee --- /dev/null +++ b/Medium/Number of Matching Subsequences.java @@ -0,0 +1,24 @@ +class Solution { + public int numMatchingSubseq(String s, String[] words) { + Map> map = new HashMap<>(); + for (int i = 0; i < words.length; i++) { + map.computeIfAbsent(words[i].charAt(0), k -> new ArrayList<>()).add(new int[]{0, i}); + } + int result = 0; + for (char c : s.toCharArray()) { + List values = map.getOrDefault(c, new ArrayList<>()); + map.put(c, new ArrayList<>()); + for (int[] val : values) { + int stringIdx = val[0]; + int wordIdx = val[1]; + if (stringIdx + 1 == words[wordIdx].length()) { + result++; + } else { + char nextChar = words[wordIdx].charAt(stringIdx + 1); + map.computeIfAbsent(nextChar, k -> new ArrayList<>()).add(new int[]{stringIdx + 1, wordIdx}); + } + } + } + return result; + } +} diff --git a/Medium/Number of Nodes in the Sub-Tree With the Same Label.java b/Medium/Number of Nodes in the Sub-Tree With the Same Label.java new file mode 100644 index 00000000..1798a058 --- /dev/null +++ b/Medium/Number of Nodes in the Sub-Tree With the Same Label.java @@ -0,0 +1,28 @@ +class Solution { + public int[] countSubTrees(int n, int[][] edges, String labels) { + Map> tree = new HashMap<>(); + for (int[] edge : edges) { + tree.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]); + tree.computeIfAbsent(edge[1], k -> new ArrayList<>()).add(edge[0]); + } + int[] result = new int[n]; + Set visited = new HashSet<>(); + bfs(tree, 0, labels, result, visited); + return result; + } + + private int[] bfs(Map> tree, int currNode, String labels, int[] result, Set visited) { + int[] labelCount = new int[26]; + if (visited.add(currNode)) { + labelCount[labels.charAt(currNode) - 'a']++; + for (Integer child : tree.getOrDefault(currNode, new ArrayList<>())) { + int[] childLabelCount = bfs(tree, child, labels, result, visited); + for (int i = 0; i < 26; i++) { + labelCount[i] += childLabelCount[i]; + } + } + result[currNode] += labelCount[labels.charAt(currNode) - 'a']; + } + return labelCount; + } +} diff --git a/Medium/Number of Operations to Make Network Connected.java b/Medium/Number of Operations to Make Network Connected.java new file mode 100644 index 00000000..c44c17d8 --- /dev/null +++ b/Medium/Number of Operations to Make Network Connected.java @@ -0,0 +1,36 @@ +class Solution { + public int makeConnected(int n, int[][] connections) { + if (connections.length < n - 1) { + return -1; + } + Map> graph = new HashMap<>(); + for (int[] conn : connections) { + graph.computeIfAbsent(conn[0], k -> new HashSet<>()).add(conn[1]); + graph.computeIfAbsent(conn[1], k -> new HashSet<>()).add(conn[0]); + } + int count = 0; + boolean[] visited = new boolean[n]; + for (int i = 0; i < n; i++) { + if (!visited[i]) { + bfs(graph, i, visited); + count++; + } + } + return count - 1; + } + + private void bfs(Map> graph, int start, boolean[] visited) { + Queue queue = new LinkedList<>(); + queue.add(start); + visited[start] = true; + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer node : graph.getOrDefault(removed, new HashSet<>())) { + if (!visited[node]) { + visited[node] = true; + queue.add(node); + } + } + } + } +} diff --git a/Medium/Number of Pairs of Interchangeable Rectangles.java b/Medium/Number of Pairs of Interchangeable Rectangles.java new file mode 100644 index 00000000..e8e6ef9f --- /dev/null +++ b/Medium/Number of Pairs of Interchangeable Rectangles.java @@ -0,0 +1,11 @@ +class Solution { + public long interchangeableRectangles(int[][] rectangles) { + return Arrays.stream(rectangles) + .collect(Collectors.groupingBy( + e -> ((double) e[0]) / e[1], HashMap::new, Collectors.counting())) + .values() + .stream() + .map(v -> (v * (v - 1)) / 2) + .reduce(0L, Long::sum); + } +} diff --git a/Medium/Number of Pairs of Strings With Concatenation Equal to Target.java b/Medium/Number of Pairs of Strings With Concatenation Equal to Target.java new file mode 100644 index 00000000..be6a6077 --- /dev/null +++ b/Medium/Number of Pairs of Strings With Concatenation Equal to Target.java @@ -0,0 +1,18 @@ +class Solution { + public int numOfPairs(String[] nums, String target) { + Map map = new HashMap<>(); + int count = 0; + for (String num : nums) { + if (target.startsWith(num)) { + String end = target.substring(num.length()); + count += map.getOrDefault(end, 0); + } + if (target.endsWith(num)) { + String start = target.substring(0, target.length() - num.length()); + count += map.getOrDefault(start, 0); + } + map.put(num, map.getOrDefault(num, 0) + 1); + } + return count; + } +} diff --git a/Medium/Number of Provinces.java b/Medium/Number of Provinces.java new file mode 100644 index 00000000..03338dd8 --- /dev/null +++ b/Medium/Number of Provinces.java @@ -0,0 +1,37 @@ +class Solution { + public int findCircleNum(int[][] isConnected) { + Map> graph = new HashMap<>(); + for (int i = 0; i < isConnected.length; i++) { + for (int j = 0; j < isConnected[i].length; j++) { + if (i != j && isConnected[i][j] == 1) { + graph.computeIfAbsent(i, k -> new HashSet<>()).add(j); + graph.computeIfAbsent(j, k -> new HashSet<>()).add(i); + } + } + } + Set visited = new HashSet<>(); + int provinces = 0; + for (int i = 0; i < isConnected.length; i++) { + if (!visited.contains(i)) { + traverse(graph, i, visited); + provinces++; + } + } + return provinces; + } + + private void traverse(Map> graph, int city, Set visited) { + Queue queue = new LinkedList<>(); + queue.add(city); + visited.add(city); + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer conn : graph.getOrDefault(removed, new HashSet<>())) { + if (!visited.contains(conn)) { + queue.add(conn); + visited.add(conn); + } + } + } + } +} diff --git a/Medium/Number of Same-End Substrings.java b/Medium/Number of Same-End Substrings.java new file mode 100644 index 00000000..4003737d --- /dev/null +++ b/Medium/Number of Same-End Substrings.java @@ -0,0 +1,28 @@ +class Solution { + public int[] sameEndSubstringCount(String s, int[][] queries) { + int n = s.length(); + int[][] prefixSum = new int[26][n]; + for (int i = 0; i < n; i++) { + prefixSum[s.charAt(i) - 'a'][i]++; + } + for (int i = 0; i < 26; i++) { + for (int j = 1; j < n; j++) { + prefixSum[i][j] += prefixSum[i][j - 1]; + } + } + int[] result = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int left = queries[i][0]; + int right = queries[i][1]; + int count = 0; + for (int c = 0; c < 26; c++) { + int leftFreq = left == 0 ? 0 : prefixSum[c][left - 1]; + int rightFreq = prefixSum[c][right]; + int freqInRange = rightFreq - leftFreq; + count += (freqInRange * (freqInRange + 1)) / 2; + } + result[i] = count; + } + return result; + } +} diff --git a/Medium/Number of Smooth Descent Periods of a Stock.java b/Medium/Number of Smooth Descent Periods of a Stock.java new file mode 100644 index 00000000..34f34227 --- /dev/null +++ b/Medium/Number of Smooth Descent Periods of a Stock.java @@ -0,0 +1,16 @@ +class Solution { + public long getDescentPeriods(int[] prices) { + long smoothDescentPeriods = 0; + int idx = 0; + while (idx < prices.length) { + long currentDescentPeriod = 1; + idx++; + while (idx < prices.length && prices[idx - 1] - prices[idx] == 1) { + currentDescentPeriod++; + idx++; + } + smoothDescentPeriods += currentDescentPeriod * (currentDescentPeriod + 1) / 2; + } + return smoothDescentPeriods; + } +} diff --git a/Medium/Number of Steps to Reduce a Number in Binary Representation to One.java b/Medium/Number of Steps to Reduce a Number in Binary Representation to One.java new file mode 100644 index 00000000..00a8296a --- /dev/null +++ b/Medium/Number of Steps to Reduce a Number in Binary Representation to One.java @@ -0,0 +1,27 @@ +class Solution { + public int numSteps(String s) { + int operations = 0; + StringBuilder sb = new StringBuilder(s); + while (sb.length() > 1) { + int n = sb.length(); + if (sb.charAt(n - 1) == '0') { + // divide by 2 + sb.deleteCharAt(n - 1); + } else { + // add 1 + int idx = n - 1; + while (idx >= 0 && sb.charAt(idx) != '0') { + sb.setCharAt(idx, '0'); + idx--; + } + if (idx < 0) { + sb.insert(0, '1'); + } else { + sb.setCharAt(idx, '1'); + } + } + operations++; + } + return operations; + } +} diff --git a/Medium/Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold.java b/Medium/Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold.java new file mode 100644 index 00000000..d2305c14 --- /dev/null +++ b/Medium/Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold.java @@ -0,0 +1,17 @@ +class Solution { + public int numOfSubarrays(int[] arr, int k, int threshold) { + int sum = 0; + int start = 0; + int count = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + if (i - start + 1 == k) { + if ((double) sum / k >= threshold) { + count++; + } + sum -= arr[start++]; + } + } + return count; + } +} diff --git a/Medium/Number of Subarrays with Bounded Maximum.java b/Medium/Number of Subarrays with Bounded Maximum.java new file mode 100644 index 00000000..a8c71df3 --- /dev/null +++ b/Medium/Number of Subarrays with Bounded Maximum.java @@ -0,0 +1,15 @@ +class Solution { + public int numSubarrayBoundedMax(int[] nums, int left, int right) { + return countHelper(nums, right) - countHelper(nums, left - 1); + } + + private int countHelper(int[] nums, int bound) { + int count = 0; + int curr = 0; + for (int num : nums) { + curr = num <= bound ? curr + 1 : 0; + count += curr; + } + return count; + } +} diff --git a/Medium/Number of Subsequences That Satisfy the Given Sum Condition.java b/Medium/Number of Subsequences That Satisfy the Given Sum Condition.java new file mode 100644 index 00000000..9a40ee6b --- /dev/null +++ b/Medium/Number of Subsequences That Satisfy the Given Sum Condition.java @@ -0,0 +1,26 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int numSubseq(int[] nums, int target) { + int n = nums.length; + Arrays.sort(nums); + int[] power = new int[n]; + power[0] = 1; + for (int i = 1; i < n; i++) { + power[i] = (power[i - 1] * 2) % MOD; + } + int result = 0; + int left = 0; + int right = n - 1; + while (left <= right) { + if (nums[left] + nums[right] <= target) { + result = (result + power[right - left]) % MOD; + left++; + } else { + right--; + } + } + return result; + } +} diff --git a/Medium/Number of Substrings Containing All Three Characters.java b/Medium/Number of Substrings Containing All Three Characters.java new file mode 100644 index 00000000..41f9141d --- /dev/null +++ b/Medium/Number of Substrings Containing All Three Characters.java @@ -0,0 +1,13 @@ +class Solution { + public int numberOfSubstrings(String s) { + int[] indexes = new int[]{-1, -1, -1}; + int count = 0; + for (int i = 0; i < s.length(); i++) { + indexes[s.charAt(i) - 'a'] = i; + if (indexes[0] != -1 && indexes[1] != -1 && indexes[2] != -1) { + count += Math.min(indexes[0], Math.min(indexes[1], indexes[2])) + 1; + } + } + return count; + } +} diff --git a/Medium/Number of Substrings With Only 1s.java b/Medium/Number of Substrings With Only 1s.java new file mode 100644 index 00000000..64febaeb --- /dev/null +++ b/Medium/Number of Substrings With Only 1s.java @@ -0,0 +1,14 @@ +class Solution { + public int numSub(String s) { + long ans = 0; + for (int i = 0; i < s.length(); i++) { + long count = 0; + while (i < s.length() && s.charAt(i) == '1') { + i++; + count++; + } + ans = (ans + (count * (count + 1)) / 2) % 1000000007; + } + return (int) ans; + } +} diff --git a/Medium/Number of Ways to Split Array.java b/Medium/Number of Ways to Split Array.java new file mode 100644 index 00000000..3cbaed3a --- /dev/null +++ b/Medium/Number of Ways to Split Array.java @@ -0,0 +1,17 @@ +class Solution { + public int waysToSplitArray(int[] nums) { + long arraySum = 0; + for (int i = 0; i < nums.length; i++) { + arraySum += nums[i]; + } + int ways = 0; + long prefixSum = 0; + for (int i = 0; i < nums.length - 1; i++) { + prefixSum += nums[i]; + if (prefixSum >= arraySum - prefixSum) { + ways++; + } + } + return ways; + } +} diff --git a/Medium/Number of Zero-Filled Subarrays.java b/Medium/Number of Zero-Filled Subarrays.java new file mode 100644 index 00000000..b7c17309 --- /dev/null +++ b/Medium/Number of Zero-Filled Subarrays.java @@ -0,0 +1,16 @@ +class Solution { + public long zeroFilledSubarray(int[] nums) { + long subarrayCount = 0L; + int idx = 0; + while (idx < nums.length) { + long count = 0L; + while (idx < nums.length && nums[idx] == 0) { + idx++; + count++; + } + subarrayCount += (count * (count + 1)) / 2; + idx++; + } + return subarrayCount; + } +} diff --git a/Medium/Numbers With Same Consecutive Differences.java b/Medium/Numbers With Same Consecutive Differences.java new file mode 100644 index 00000000..9c93c383 --- /dev/null +++ b/Medium/Numbers With Same Consecutive Differences.java @@ -0,0 +1,26 @@ +class Solution { + public int[] numsSameConsecDiff(int n, int k) { + List result = new ArrayList<>(); + helper(n, k, result, new StringBuilder()); + return result.stream().mapToInt(Integer::intValue).toArray(); + } + + private void helper(int n, int k, List result, StringBuilder sb) { + if (sb.length() == n) { + result.add(Integer.parseInt(sb.toString())); + return; + } + for (int i = 0; i <= 9; i++) { + if (sb.isEmpty() && i == 0) { + continue; + } + if (!sb.isEmpty() + && Math.abs(Character.getNumericValue(sb.charAt(sb.length() - 1)) - i) != k) { + continue; + } + sb.append(i); + helper(n, k, result, new StringBuilder(sb)); + sb.deleteCharAt(sb.length() - 1); + } + } +} diff --git a/Medium/Odd Even Linked Lists.java b/Medium/Odd Even Linked Lists.java index 4c4a1aae..2c8adf87 100644 --- a/Medium/Odd Even Linked Lists.java +++ b/Medium/Odd Even Linked Lists.java @@ -3,23 +3,26 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode oddEvenList(ListNode head) { - if(head == null || head.next == null) - return head; - ListNode odd = head; - ListNode even = head.next; - ListNode evenHead = even; - while(odd.next != null && even.next != null){ - odd.next = even.next; - odd = odd.next; - even.next = odd.next; - even = even.next; - } - odd.next = evenHead; - return head; + public ListNode oddEvenList(ListNode head) { + if (head == null || head.next == null) { + return head; } + ListNode oddIdxNode = head; + ListNode evenIdxNodeStart = head.next; + ListNode evenIdxNode = evenIdxNodeStart; + while (evenIdxNode != null && evenIdxNode.next != null) { + oddIdxNode.next = evenIdxNode.next; + oddIdxNode = oddIdxNode.next; + evenIdxNode.next = oddIdxNode.next; + evenIdxNode = evenIdxNode.next; + } + oddIdxNode.next = evenIdxNodeStart; + return head; + } } diff --git a/Medium/One Edit Distance.java b/Medium/One Edit Distance.java index 7a78e333..662a41d1 100644 --- a/Medium/One Edit Distance.java +++ b/Medium/One Edit Distance.java @@ -1,50 +1,28 @@ class Solution { - public static boolean isOneEditDistance(String s, String t) { - if (Math.abs(s.length() - t.length()) > 1) { + public boolean isOneEditDistance(String s, String t) { + int diff = Math.abs(s.length() - t.length()); + if (s.equals(t) || diff > 1) { return false; } - else if (s.length() - t.length() == 0) { - if (s.equals(t)) { - return false; - } - - boolean missed = false; - for (int i=0; i j) { - return false; + // Delete 1 character from t + if (s.substring(idx).equals(t.substring(idx + 1))) { + return true; } - i++; - continue; + return false; } - - i++; - j++; + idx++; } - return true; } } diff --git a/Medium/Ones and Zeroes.java b/Medium/Ones and Zeroes.java new file mode 100644 index 00000000..d4e6335f --- /dev/null +++ b/Medium/Ones and Zeroes.java @@ -0,0 +1,26 @@ +class Solution { + public int findMaxForm(String[] strs, int m, int n) { + int[][] dp = new int[m + 1][n + 1]; + for (String s : strs) { + int[] count = getCountForZeroAndOne(s); + for (int zeroes = m; zeroes >= count[0]; zeroes--) { + for (int ones = n; ones >= count[1]; ones--) { + dp[zeroes][ones] = Math.max(1 + dp[zeroes - count[0]][ones - count[1]], dp[zeroes][ones]); + } + } + } + return dp[m][n]; + } + + private int[] getCountForZeroAndOne(String s) { + int[] count = {0, 0}; + for (char c : s.toCharArray()) { + if (c == '0') { + count[0]++; + } else { + count[1]++; + } + } + return count; + } +} diff --git a/Medium/Online Election.java b/Medium/Online Election.java new file mode 100644 index 00000000..50dfc559 --- /dev/null +++ b/Medium/Online Election.java @@ -0,0 +1,29 @@ +class TopVotedCandidate { + + private TreeMap currWinner; + + public TopVotedCandidate(int[] persons, int[] times) { + this.currWinner = new TreeMap<>(); + Map candidateToVotecount = new HashMap<>(); + int currWinningCandidate = -1; + for (int i = 0; i < persons.length; i++) { + int person = persons[i]; + int newVoteCount = candidateToVotecount.getOrDefault(person, 0) + 1; + candidateToVotecount.put(person, newVoteCount); + if (currWinningCandidate == -1 || newVoteCount >= candidateToVotecount.get(currWinningCandidate)) { + currWinningCandidate = person; + } + currWinner.put(times[i], currWinningCandidate); + } + } + + public int q(int t) { + return this.currWinner.floorEntry(t).getValue(); + } +} + +/** + * Your TopVotedCandidate object will be instantiated and called as such: + * TopVotedCandidate obj = new TopVotedCandidate(persons, times); + * int param_1 = obj.q(t); + */ diff --git a/Medium/Online Stock Span.java b/Medium/Online Stock Span.java index caad4a18..ff50093d 100644 --- a/Medium/Online Stock Span.java +++ b/Medium/Online Stock Span.java @@ -1,23 +1,19 @@ class StockSpanner { - Stack prices; - Stack weights; - + + // Entry in stack is the current price and count of prices <= current price + private final Stack stack; + public StockSpanner() { - prices = new Stack(); - weights = new Stack(); + this.stack = new Stack<>(); } - + public int next(int price) { - int w = 1; - while (!prices.isEmpty() && prices.peek() <= price) { - prices.pop(); - w += weights.pop(); + int count = 1; + while (!stack.isEmpty() && stack.peek()[0] <= price) { + count += stack.pop()[1]; } - - prices.push(price); - weights.push(w); - - return w; + stack.push(new int[]{price, count}); + return count; } } diff --git a/Medium/Open The Lock.java b/Medium/Open The Lock.java new file mode 100644 index 00000000..f692f0ba --- /dev/null +++ b/Medium/Open The Lock.java @@ -0,0 +1,39 @@ +class Solution { + public int openLock(String[] deadends, String target) { + Set deadEndSet = new HashSet<>(Arrays.asList(deadends)); + String startingPoint = "0000"; + if (deadEndSet.contains(startingPoint)) { + return -1; + } + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); + queue.add(startingPoint); + visited.add(startingPoint); + int attempts = 0; + int[] rotations = {-1, 1}; + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + String removed = queue.remove(); + if (removed.equals(target)) { + return attempts; + } + if (deadEndSet.contains(removed)) { + continue; + } + for (int j = 0; j < 4; j++) { + for (int rotation : rotations) { + int newValue = ((removed.charAt(j) - '0') + rotation + 10) % 10; + String newRotation = removed.substring(0, j) + newValue + removed.substring(j + 1); + if (!visited.contains(newRotation)) { + visited.add(newRotation); + queue.add(newRotation); + } + } + } + } + attempts++; + } + return -1; + } +} diff --git a/Medium/Optimal Partition of String.java b/Medium/Optimal Partition of String.java new file mode 100644 index 00000000..68b01d59 --- /dev/null +++ b/Medium/Optimal Partition of String.java @@ -0,0 +1,14 @@ +class Solution { + public int partitionString(String s) { + int count = 0; + int idx = 0; + while (idx < s.length()) { + Set set = new HashSet<>(); + while (idx < s.length() && set.add(s.charAt(idx))) { + idx++; + } + count++; + } + return count; + } +} diff --git a/Medium/Out of Boundary Paths.java b/Medium/Out of Boundary Paths.java new file mode 100644 index 00000000..fc7e9a26 --- /dev/null +++ b/Medium/Out of Boundary Paths.java @@ -0,0 +1,26 @@ +class Solution { + + private static final int MOD = 1000_000_007; + + public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) { + Integer[][][] dp = new Integer[m][n][maxMove + 1]; + return findPaths(m, n, maxMove, startRow, startColumn, dp); + } + + public int findPaths(int m, int n, int maxMove, int startRow, int startColumn, Integer[][][] dp) { + if (startRow == m || startColumn == n || startRow < 0 || startColumn < 0) { + return 1; + } + if (maxMove == 0) { + return 0; + } + if (dp[startRow][startColumn][maxMove] != null) { + return dp[startRow][startColumn][maxMove]; + } + return dp[startRow][startColumn][maxMove] = ( + (findPaths(m, n, maxMove - 1, startRow - 1, startColumn, dp) + + findPaths(m, n, maxMove - 1, startRow + 1, startColumn, dp)) % MOD + + (findPaths(m, n, maxMove - 1, startRow, startColumn - 1, dp) + + findPaths(m, n, maxMove - 1, startRow, startColumn + 1, dp)) % MOD) % MOD; + } +} diff --git a/Medium/Pacific Atlantic Water Flow.java b/Medium/Pacific Atlantic Water Flow.java new file mode 100644 index 00000000..3c129529 --- /dev/null +++ b/Medium/Pacific Atlantic Water Flow.java @@ -0,0 +1,52 @@ +class Solution { + private final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public List> pacificAtlantic(int[][] heights) { + int numRows = heights.length; + int numCols = heights[0].length; + Queue pacificQueue = new LinkedList<>(); + Queue atlanticQueue = new LinkedList<>(); + for (int i = 0; i < numRows; i++) { + pacificQueue.add(new int[]{i, 0}); + atlanticQueue.add(new int[]{i, numCols - 1}); + } + for (int i = 0; i < numCols; i++) { + pacificQueue.add(new int[]{0, i}); + atlanticQueue.add(new int[]{numRows - 1, i}); + } + boolean[][] pacificReachable = bfs(pacificQueue, heights); + boolean[][] atlanticReachable = bfs(atlanticQueue, heights); + List> result = new ArrayList<>(); + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + if (pacificReachable[i][j] && atlanticReachable[i][j]) { + result.add(Arrays.asList(i, j)); + } + } + } + return result; + } + + private boolean[][] bfs(Queue queue, int[][] heights) { + int numRows = heights.length; + int numCols = heights[0].length; + boolean[][] reachable = new boolean[numRows][numCols]; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + reachable[x][y] = true; + for (int[] dir : DIRS) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX < 0 || newY < 0 || newX >= numRows || newY >= numCols || reachable[newX][newY]) { + continue; + } + if (heights[newX][newY] >= heights[x][y]) { + queue.add(new int[]{newX, newY}); + } + } + } + return reachable; + } +} diff --git a/Medium/Paint Fence.java b/Medium/Paint Fence.java new file mode 100644 index 00000000..39c72ffa --- /dev/null +++ b/Medium/Paint Fence.java @@ -0,0 +1,20 @@ +class Solution { + public int numWays(int n, int k) { + Map map = new HashMap<>(); + return numWays(n, k, map); + } + + private int numWays(int n, int k, Map map) { + if (n == 1) { + return k; + } + if (n == 2) { + return k * k; + } + if (map.containsKey(n)) { + return map.get(n); + } + map.put(n, (k - 1) * (numWays(n - 1, k, map) + numWays(n - 2, k, map))); + return map.get(n); + } +} diff --git a/Medium/Paint House.java b/Medium/Paint House.java new file mode 100644 index 00000000..27b1a502 --- /dev/null +++ b/Medium/Paint House.java @@ -0,0 +1,15 @@ +class Solution { + public int minCost(int[][] costs) { + int n = costs.length; + int[][] dp = new int[n][3]; + dp[0][0] = costs[0][0]; + dp[0][1] = costs[0][1]; + dp[0][2] = costs[0][2]; + for (int i = 1; i < n; i++) { + dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0]; + dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1]; + dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2]; + } + return Math.min(dp[n - 1][0], Math.min(dp[n - 1][1], dp[n - 1][2])); + } +} diff --git a/Medium/Palindrome Partitioning.java b/Medium/Palindrome Partitioning.java index 1171f009..de89ed16 100644 --- a/Medium/Palindrome Partitioning.java +++ b/Medium/Palindrome Partitioning.java @@ -1,27 +1,31 @@ class Solution { - public List> partition(String a) { - List> ans = new ArrayList<>(); - helper(ans, new ArrayList(), a, 0); - return ans; + public List> partition(String s) { + List> result = new ArrayList<>(); + backtrack(result, new ArrayList<>(), s, 0); + return result; } - - private void helper(List> ans, List temp, String a, int idx) { - if (idx == a.length()) { - ans.add(new ArrayList<>(temp)); + + private void backtrack(List> result, List currentList, + String s, int idx) { + if (idx == s.length()) { + result.add(new ArrayList<>(currentList)); return; } - for (int i=idx; i= 0 && rightIdx < s.length() && s.charAt(leftIdx) == s.charAt(rightIdx)) { + palindromeCount[0]++; + leftIdx--; + rightIdx++; } + } } diff --git a/Medium/Pancake Sorting.java b/Medium/Pancake Sorting.java new file mode 100644 index 00000000..b8606b27 --- /dev/null +++ b/Medium/Pancake Sorting.java @@ -0,0 +1,34 @@ +class Solution { + public List pancakeSort(int[] arr) { + List result = new ArrayList<>(); + for (int i = arr.length; i > 0; i--) { + int idx = findIdx(arr, i); + if (idx != i - 1) { + if (idx != 0) { + result.add(idx + 1); + flip(arr, idx + 1); + } + result.add(i); + flip(arr, i); + } + } + return result; + } + + private void flip(int[] arr, int k) { + for (int i = 0; i < k / 2; i++) { + int temp = arr[i]; + arr[i] = arr[k - i - 1]; + arr[k - i - 1] = temp; + } + } + + private int findIdx(int[] arr, int target) { + for (int i = 0; i < arr.length; i++) { + if (arr[i] == target) { + return i; + } + } + return -1; + } +} diff --git a/Medium/Parallel Courses.java b/Medium/Parallel Courses.java new file mode 100644 index 00000000..797e3b58 --- /dev/null +++ b/Medium/Parallel Courses.java @@ -0,0 +1,35 @@ +class Solution { + public int minimumSemesters(int n, int[][] relations) { + Map> graph = new HashMap<>(); + int[] indegree = new int[n]; + for (int[] relation : relations) { + int course = relation[0]; + int dependency = relation[1]; + indegree[course - 1]++; + graph.computeIfAbsent(dependency, k -> new HashSet<>()).add(course); + } + Queue queue = new LinkedList<>(); + int numOfSemesters = 0; + int coursesTaken = 0; + for (int i = 0; i < n; i++) { + if (indegree[i] == 0) { + queue.add(i + 1); + } + } + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int removed = queue.remove(); + coursesTaken++; + for (Integer dependent : graph.getOrDefault(removed, new HashSet<>())) { + indegree[dependent - 1]--; + if (indegree[dependent - 1] == 0) { + queue.add(dependent); + } + } + } + numOfSemesters++; + } + return coursesTaken == n ? numOfSemesters : -1; + } +} diff --git a/Medium/Partition Array According to Given Pivot.java b/Medium/Partition Array According to Given Pivot.java new file mode 100644 index 00000000..740b1707 --- /dev/null +++ b/Medium/Partition Array According to Given Pivot.java @@ -0,0 +1,20 @@ +class Solution { + public int[] pivotArray(int[] nums, int pivot) { + int[] result = new int[nums.length]; + int leftIdx = 0; + int rightIdx = nums.length - 1; + for (int i = 0; i < nums.length; i++) { + if (nums[i] < pivot) { + result[leftIdx++] = nums[i]; + } + int tempIdx = nums.length - 1 - i; + if (nums[tempIdx] > pivot) { + result[rightIdx--] = nums[tempIdx]; + } + } + while (leftIdx <= rightIdx) { + result[leftIdx++] = pivot; + } + return result; + } +} diff --git a/Medium/Partition Array for Maximum Sum.java b/Medium/Partition Array for Maximum Sum.java new file mode 100644 index 00000000..4868c1c3 --- /dev/null +++ b/Medium/Partition Array for Maximum Sum.java @@ -0,0 +1,25 @@ +class Solution { + public int maxSumAfterPartitioning(int[] arr, int k) { + Integer[] dp = new Integer[arr.length]; + return maxSum(arr, k, dp, 0); + } + + private int maxSum(int[] arr, int k, Integer[] dp, int start) { + int n = arr.length; + if (start >= n) { + return 0; + } + if (dp[start] != null) { + return dp[start]; + } + int currMax = 0; + int result = 0; + int end = Math.min(n, start + k); + for (int i = start; i < end; i++) { + currMax = Math.max(currMax, arr[i]); + result = Math.max(result, + currMax * (i - start + 1) + maxSum(arr, k, dp, i + 1)); + } + return dp[start] = result; + } +} diff --git a/Medium/Partition Equal Subset Sum.java b/Medium/Partition Equal Subset Sum.java new file mode 100644 index 00000000..41c71f7e --- /dev/null +++ b/Medium/Partition Equal Subset Sum.java @@ -0,0 +1,23 @@ +class Solution { + public boolean canPartition(int[] nums) { + int sum = 0; + for (int num : nums) { + sum += num; + } + if (sum % 2 == 1) { + return false; + } + sum /= 2; + int n = nums.length; + boolean[] dp = new boolean[sum + 1]; + dp[0] = true; + for (int num : nums) { + for (int i = sum; i > 0; i--) { + if (i >= num) { + dp[i] = dp[i] || dp[i - num]; + } + } + } + return dp[sum]; + } +} diff --git a/Medium/Partition Labels.java b/Medium/Partition Labels.java index 7608fcb5..e3157703 100644 --- a/Medium/Partition Labels.java +++ b/Medium/Partition Labels.java @@ -1,27 +1,19 @@ class Solution { - public List partitionLabels(String S) { - - if (S == null || S.length() == 0) return null; - - int[] map = new int[26]; - - for (int i=0;i partitionLabels(String s) { + Map map = new HashMap<>(); + for (int i = 0; i < s.length(); i++) { + map.put(s.charAt(i), i); } - - List ans = new ArrayList(); - - int end = 0; - int start = -1; - - for (int i=0;i result = new ArrayList<>(); + int start = 0; + int maxIdx = Integer.MIN_VALUE; + for (int i = 0; i < s.length(); i++) { + maxIdx = Math.max(map.get(s.charAt(i)), maxIdx); + if (maxIdx == i) { + result.add(i - start + 1); + start = i + 1; } } - - return ans; + return result; } } diff --git a/Medium/Partition List.java b/Medium/Partition List.java index 400a58f4..a807608c 100644 --- a/Medium/Partition List.java +++ b/Medium/Partition List.java @@ -3,35 +3,41 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode partition(ListNode head, int x) { - Queue small = new LinkedList<>(); - Queue bigOrEqual = new LinkedList<>(); - ListNode curr = head; - while (curr != null){ - if (curr.val < x) { - small.add(curr.val); + ListNode lessHead = null; + ListNode lessCurr = null; + ListNode greaterHead = null; + ListNode greaterCurr = null; + while (head != null) { + if (head.val < x) { + if (lessCurr == null) { + lessCurr = new ListNode(head.val); + lessHead = lessCurr; + } else { + lessCurr.next = new ListNode(head.val); + lessCurr = lessCurr.next; + } + } else { + if (greaterCurr == null) { + greaterCurr = new ListNode(head.val); + greaterHead = greaterCurr; + } else { + greaterCurr.next = new ListNode(head.val); + greaterCurr = greaterCurr.next; + } } - else { - bigOrEqual.add(curr.val); - } - curr = curr.next; + head = head.next; } - - curr = head; - while (curr != null) { - if (!small.isEmpty()) { - curr.val = small.remove(); - } - else { - curr.val = bigOrEqual.remove(); - } - curr = curr.next; + if (lessHead == null) { + return greaterHead; } - - return head; + lessCurr.next = greaterHead; + return lessHead; } } diff --git a/Medium/Partitioning Into Minimum Number Of Deci-Binary Numbers.java b/Medium/Partitioning Into Minimum Number Of Deci-Binary Numbers.java new file mode 100644 index 00000000..4bd5953a --- /dev/null +++ b/Medium/Partitioning Into Minimum Number Of Deci-Binary Numbers.java @@ -0,0 +1,9 @@ +class Solution { + public int minPartitions(String n) { + int maxDigit = Character.getNumericValue(n.charAt(0)); + for (char c : n.toCharArray()) { + maxDigit = Math.max(maxDigit, Character.getNumericValue(c)); + } + return maxDigit; + } +} diff --git a/Medium/Path Sum II.java b/Medium/Path Sum II.java index e90b2004..776676f7 100644 --- a/Medium/Path Sum II.java +++ b/Medium/Path Sum II.java @@ -4,36 +4,67 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - List> list = new ArrayList<>(); - public List> pathSum(TreeNode root, int sum) { - if (root == null) return list; - - Stack path = new Stack<>(); - - pathSumImpl(root, sum, path); - return list; + public List> pathSum(TreeNode root, int targetSum) { + List> result = new ArrayList<>(); + if (root == null) { + return result; } - - private void pathSumImpl(TreeNode root, int sum, Stack path) { - path.push(root.val); - if (root.left == null && root.right == null) { - if (sum == root.val) { - list.add(new ArrayList(path)); - } - } - - if (root.left != null) { - pathSumImpl(root.left, sum-root.val, path); + Queue queue = new LinkedList<>(); + NodePathSumWrapper currNode = new NodePathSumWrapper(root, 0); + currNode.addToPath(root.val); + queue.add(currNode); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + NodePathSumWrapper removed = queue.remove(); + TreeNode node = removed.node; + if (node.left == null && node.right == null) { + if (removed.currSum == targetSum) { + result.add(new ArrayList<>(removed.path)); + } + } else { + if (node.left != null) { + NodePathSumWrapper leftNodeWrapper = new NodePathSumWrapper(node.left, removed.currSum); + leftNodeWrapper.path.addAll(removed.path); + leftNodeWrapper.addToPath(node.left.val); + queue.add(leftNodeWrapper); + } + if (node.right != null) { + NodePathSumWrapper rightNodeWrapper = new NodePathSumWrapper(node.right, removed.currSum); + rightNodeWrapper.path.addAll(removed.path); + rightNodeWrapper.addToPath(node.right.val); + queue.add(rightNodeWrapper); + } } - - if (root.right != null) { - pathSumImpl(root.right, sum-root.val, path); - } - - path.pop(); + } + } + return result; + } + + private static class NodePathSumWrapper { + TreeNode node; + int currSum; + List path; + + public NodePathSumWrapper(TreeNode node, int currSum) { + this.node = node; + this.currSum = currSum; + this.path = new ArrayList<>(); + } + + public void addToPath(int value) { + this.path.add(value); + this.currSum += value; } + } } diff --git a/Medium/Path Sum III.java b/Medium/Path Sum III.java new file mode 100644 index 00000000..69badada --- /dev/null +++ b/Medium/Path Sum III.java @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int pathSum(TreeNode root, int targetSum) { + Map map = new HashMap<>(); + map.put(0L, 1); + int[] count = {0}; + preorder(root, 0L, map, count, targetSum); + return count[0]; + } + + private void preorder(TreeNode root, long currSum, Map map, int[] count, int targetSum) { + if (root == null) { + return; + } + currSum += root.val; + count[0] += map.getOrDefault(currSum - targetSum, 0); + map.put(currSum, map.getOrDefault(currSum, 0) + 1); + preorder(root.left, currSum, map, count, targetSum); + preorder(root.right, currSum, map, count, targetSum); + map.put(currSum, map.get(currSum) - 1); + } +} diff --git a/Medium/Path With Maximum Minimum Value.java b/Medium/Path With Maximum Minimum Value.java new file mode 100644 index 00000000..31942850 --- /dev/null +++ b/Medium/Path With Maximum Minimum Value.java @@ -0,0 +1,27 @@ +class Solution { + + private static final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int maximumMinimumPath(int[][] grid) { + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> o2[2] - o1[2]); + pq.add(new int[]{0, 0, grid[0][0]}); + int numRows = grid.length; + int numCols = grid[0].length; + boolean[][] visited = new boolean[numRows][numCols]; + while (!pq.isEmpty()) { + int[] removed = pq.poll(); + if (removed[0] == numRows - 1 && removed[1] == numCols - 1) { + return removed[2]; + } + visited[removed[0]][removed[1]] = true; + for (int[] dir : DIRS) { + int newX = removed[0] + dir[0]; + int newY = removed[1] + dir[1]; + if (newX >= 0 && newY >= 0 && newX < numRows && newY < numCols && !visited[newX][newY]) { + pq.add(new int[]{newX, newY, Math.min(removed[2], grid[newX][newY])}); + } + } + } + return -1; + } +} diff --git a/Medium/Path With Minimum Effort.java b/Medium/Path With Minimum Effort.java new file mode 100644 index 00000000..b9c33606 --- /dev/null +++ b/Medium/Path With Minimum Effort.java @@ -0,0 +1,47 @@ +class Solution { + + private final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int minimumEffortPath(int[][] heights) { + if (heights.length == 1 && heights[0].length == 1) { + return 0; + } + int leftBound = 0; + int rightBound = 1000000; + while (leftBound < rightBound) { + int mid = (leftBound + rightBound) / 2; + if (connected(heights, mid)) { + rightBound = mid; + } else { + leftBound = mid + 1; + } + } + return leftBound; + } + + private boolean connected(int[][] heights, int targetEffort) { + int numRows = heights.length; + int numCols = heights[0].length; + Queue queue = new LinkedList<>(); + boolean[][] seen = new boolean[numRows][numCols]; + queue.add(new int[]{0, 0}); + seen[0][0] = true; + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + if (x == numRows - 1 && y == numCols - 1) { + return true; + } + for (int[] dir : DIRS) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newY >= 0 && newX < numRows && newY < numCols && !seen[newX][newY] && Math.abs(heights[x][y] - heights[newX][newY]) <= targetEffort) { + queue.add(new int[]{newX, newY}); + seen[newX][newY] = true; + } + } + } + return false; + } +} diff --git a/Medium/Path with Maximum Gold.java b/Medium/Path with Maximum Gold.java new file mode 100644 index 00000000..3869c0c4 --- /dev/null +++ b/Medium/Path with Maximum Gold.java @@ -0,0 +1,30 @@ +class Solution { + int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + public int getMaximumGold(int[][] grid) { + int maxGold = 0; + int rows = grid.length; + int cols = grid[0].length; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + int currGold = getMaxGold(grid, i, j, rows, cols, new boolean[rows][cols]); + maxGold = Math.max(maxGold, currGold); + } + } + return maxGold; + } + + private int getMaxGold(int[][] grid, int x, int y, int rows, int cols, boolean[][] visited) { + if (x < 0 || x >= rows || y < 0 || y >= cols || visited[x][y] || grid[x][y] == 0) { + return 0; + } + int curr = 0; + visited[x][y] = true; + for (int[] dir : dirs) { + int newX = x + dir[0]; + int newY = y + dir[1]; + curr = Math.max(curr, getMaxGold(grid, newX, newY, rows, cols, visited)); + } + visited[x][y] = false; + return grid[x][y] + curr; + } +} diff --git a/Medium/Path with Maximum Probability.java b/Medium/Path with Maximum Probability.java new file mode 100644 index 00000000..d104e576 --- /dev/null +++ b/Medium/Path with Maximum Probability.java @@ -0,0 +1,38 @@ +class Solution { + public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { + Map> graph = new HashMap<>(); + for (int i = 0; i < edges.length; i++) { + Node node1 = new Node(edges[i][1], succProb[i]); + Node node2 = new Node(edges[i][0], succProb[i]); + graph.computeIfAbsent(edges[i][0], k -> new ArrayList<>()).add(node1); + graph.computeIfAbsent(edges[i][1], k -> new ArrayList<>()).add(node2); + } + double[] probs = new double[n]; + Queue queue = new LinkedList<>(); + queue.add(new Node(start, 1.0)); + while (!queue.isEmpty()) { + Node node = queue.remove(); + int parent = node.val; + double prob = node.prob; + for (Node child : graph.getOrDefault(parent, new ArrayList<>())) { + if (probs[child.val] >= prob * child.prob) { + continue; + } + queue.add(new Node(child.val, prob * child.prob)); + probs[child.val] = prob * child.prob; + } + } + return probs[end]; + } +} + + +class Node { + int val; + double prob; + + public Node(int val, double prob) { + this.val = val; + this.prob = prob; + } +} diff --git a/Medium/Peak Index in a Mountain Array.java b/Medium/Peak Index in a Mountain Array.java new file mode 100644 index 00000000..d496f7c4 --- /dev/null +++ b/Medium/Peak Index in a Mountain Array.java @@ -0,0 +1,15 @@ +class Solution { + public int peakIndexInMountainArray(int[] arr) { + int start = 0; + int end = arr.length - 1; + while (start < end) { + int mid = (start + end) / 2; + if (arr[mid] < arr[mid + 1]) { + start = mid + 1; + } else { + end = mid; + } + } + return start; + } +} diff --git a/Medium/Peeking Iterator.java b/Medium/Peeking Iterator.java index 44edad63..4a1c6782 100644 --- a/Medium/Peeking Iterator.java +++ b/Medium/Peeking Iterator.java @@ -1,47 +1,36 @@ // Java Iterator interface reference: // https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html -import java.util.NoSuchElementException; class PeekingIterator implements Iterator { + private Iterator iterator; + private Integer topElement; - private Integer next; - private Iterator iter; - private boolean noNextElement = false; - - public PeekingIterator(Iterator iterator) { - // initialize any member here. - iter = iterator; - moveIterator(); - } + public PeekingIterator(Iterator iterator) { + // initialize any member here. + this.iterator = iterator; + populateTopElement(); + } - // Returns the next element in the iteration without advancing the iterator. - public Integer peek() { - return next; - } + // Returns the next element in the iteration without advancing the iterator. + public Integer peek() { + return this.topElement; + } - // hasNext() and next() should behave the same as in the Iterator interface. - // Override them if needed. - @Override - public Integer next() { - if (noNextElement) { - throw new NoSuchElementException(); - } - Integer val = next; - moveIterator(); - return val; - } + // hasNext() and next() should behave the same as in the Iterator interface. + // Override them if needed. + @Override + public Integer next() { + Integer nextValue = this.topElement; + populateTopElement(); + return nextValue; + } - @Override - public boolean hasNext() { - return !noNextElement; - } - - public void moveIterator() { - if (iter.hasNext()) { - next = iter.next(); - } - else { - noNextElement = true; - } - } + @Override + public boolean hasNext() { + return this.topElement != null; + } + + private void populateTopElement() { + this.topElement = this.iterator.hasNext() ? this.iterator.next() : null; + } } diff --git a/Medium/People Whose List of Favorite Companies Is Not a Subset of Another List.java b/Medium/People Whose List of Favorite Companies Is Not a Subset of Another List.java new file mode 100644 index 00000000..bb29bc53 --- /dev/null +++ b/Medium/People Whose List of Favorite Companies Is Not a Subset of Another List.java @@ -0,0 +1,47 @@ +class Solution { + public List peopleIndexes(List> favoriteCompanies) { + Map map = new HashMap<>(); + List> hashedList = new ArrayList<>(); + int count = 1; + for (List companies : favoriteCompanies) { + List temp = new ArrayList<>(); + for (String company : companies) { + if (!map.containsKey(company)) { + map.put(company, count++); + } + temp.add(map.get(company)); + } + Collections.sort(temp); + hashedList.add(temp); + } + List foundList = new ArrayList<>(); + int n = hashedList.size(); + for (int i = 0; i < n; i++) { + boolean found = false; + for (int j = 0; j < n && !found; j++) { + if (i != j) { + List curr = hashedList.get(j); + List target = hashedList.get(i); + int idxCurr = 0; + int idxTarget = 0; + int sizeCurr = curr.size(); + int sizeTarget = target.size(); + while (idxCurr < sizeCurr && idxTarget < sizeTarget) { + if (curr.get(idxCurr) == target.get(idxTarget)) { + idxTarget++; + } + idxCurr++; + } + if (idxTarget == sizeTarget) { + found = true; + break; + } + } + } + if (!found) { + foundList.add(i); + } + } + return foundList; + } +} diff --git a/Medium/Perfect Squares.java b/Medium/Perfect Squares.java index 510a9c57..4f61d351 100644 --- a/Medium/Perfect Squares.java +++ b/Medium/Perfect Squares.java @@ -1,20 +1,15 @@ class Solution { - public int numSquares(int n) { - int[] dp = new int[n + 1]; - dp[0] = 0; - - for (int i = 1; i <= n; i++) { - int min = Integer.MAX_VALUE; - int j = 1; - - while (i - j*j >= 0) { - min = Math.min(min, dp[i - j*j] + 1); - j++; - } - - dp[i] = min; - } - - return dp[n]; + public int numSquares(int n) { + int[] dp = new int[n + 1]; + Arrays.fill(dp, Integer.MAX_VALUE); + dp[0] = 0; + for(int i = 1; i <= n; i++) { + int min = Integer.MAX_VALUE; + for (int j = 1; i - j * j >= 0; j++) { + min = Math.min(min, dp[i - j * j] + 1); + } + dp[i] = min; } + return dp[n]; + } } diff --git a/Medium/Permutation in String.java b/Medium/Permutation in String.java index ca89a82f..dd255290 100644 --- a/Medium/Permutation in String.java +++ b/Medium/Permutation in String.java @@ -1,31 +1,38 @@ class Solution { public boolean checkInclusion(String s1, String s2) { - int l1 = s1.length(); - int l2 = s2.length(); - if (l1 > l2) return false; - - int[] check = new int[26]; - - for (int i=0;i s2.length()) { + return false; } - - if (zeroArr(check)) return true; - - for (int i = l1; i < l2; i++) { - check[s2.charAt(i) - 'a']--; - check[s2.charAt(i - l1) - 'a']++; - if (zeroArr(check)) return true; + Map map = new HashMap<>(); + for (char c : s1.toCharArray()) { + map.put(c, map.getOrDefault(c, 0) + 1); + } + int n = s1.length(); + int[] count = {map.size()}; + for (int i = 0; i < n - 1; i++) { + updateMap(map, s2.charAt(i), count, true); + } + int start = 0; + for (int i = n - 1; i < s2.length(); i++) { + updateMap(map, s2.charAt(i), count, true); + if (count[0] == 0) { + return true; + } + updateMap(map, s2.charAt(start++), count, false); } - return false; } - boolean zeroArr(int[] arr) { - for (int i=0;i<26;i++) { - if (arr[i] != 0) return false; + private void updateMap(Map map, char c, int[] count, boolean decrement) { + if (map.containsKey(c)) { + int diff = decrement ? -1 : 1; + map.put(c, map.get(c) + diff); + if (decrement && map.get(c) == 0) { + count[0]--; + } + if (!decrement && map.get(c) == 1) { + count[0]++; + } } - return true; } } diff --git a/Medium/Permutations II.java b/Medium/Permutations II.java index 74ca2f6f..2469a285 100644 --- a/Medium/Permutations II.java +++ b/Medium/Permutations II.java @@ -1,32 +1,25 @@ class Solution { - public static List> permuteUnique(int[] nums) { - List> ans = new ArrayList<>(); - Arrays.sort(nums); - permuteHelper(nums, new ArrayList<>(), ans, new boolean[nums.length]); - return new ArrayList<>(ans); + public List> permuteUnique(int[] nums) { + List> result = new ArrayList<>(); + Arrays.sort(nums); + helper(nums, result, new ArrayList<>(), new boolean[nums.length]); + return result; + } + + private void helper(int[] nums, List> result, List curr, boolean[] visited) { + if (curr.size() == nums.length) { + result.add(new ArrayList<>(curr)); + return; } - - private static void permuteHelper(int[] nums, List list, List> ans, boolean[] used) { - if (list.size() == nums.length) { - ans.add(new ArrayList<>(list)); - } - else { - for (int i=0; i 0 && nums[i] == nums[i-1] && !used[i-1])) { - continue; - } - - used[i] = true; - list.add(nums[i]); - - // Explore - permuteHelper(nums, list, ans, used); - - // Un-choose - used[i] = false; - list.remove(list.size()-1); - } - } + for (int i = 0; i < nums.length; i++) { + if (visited[i] || (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1])) { + continue; + } + curr.add(nums[i]); + visited[i] = true; + helper(nums, result, curr, visited); + curr.remove(curr.size() - 1); + visited[i] = false; } + } } diff --git a/Medium/Permutations.java b/Medium/Permutations.java index 0d40a3f9..61c86f42 100644 --- a/Medium/Permutations.java +++ b/Medium/Permutations.java @@ -1,30 +1,25 @@ class Solution { - public List> ans = new ArrayList<>(); - public List> permute(int[] nums) { - List list = new ArrayList<>(); - permuteHelper(nums, list, 0); - return ans; + List> result = new ArrayList<>(); + Set visited = new HashSet<>(); + permute(nums, result, new ArrayList<>(), visited); + return result; } - - private void permuteHelper(int[] nums, List list, int idx) { - if (list.size() == nums.length) { - ans.add(new ArrayList<>(list)); + + private void permute(int[] nums, List> result, List curr, Set visited) { + if (curr.size() == nums.length) { + result.add(new ArrayList<>(curr)); + return; } - else { - for (int i=0; i 9) { - carry = 1; - temp = temp - 10; - } - else { - carry = 0; - } - - prev = curr; - - curr.val = temp; - curr = curr.next; - } - - if (carry != 0) { - prev.next = new ListNode(carry); - } - - ListNode ans = reverse(rev); - - return ans; + public ListNode plusOne(ListNode head) { + ListNode dummy = new ListNode(0); + dummy.next = head; + ListNode notNine = dummy; + while (head != null) { + if (head.val != 9) { + notNine = head; + } + head = head.next; } - - private ListNode reverse(ListNode node) { - ListNode curr = node; - ListNode prev = null; - ListNode next = null; - - while (curr != null) { - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - - return prev; + notNine.val++; + notNine = notNine.next; + while (notNine != null) { + notNine.val = 0; + notNine = notNine.next; } + return dummy.val != 0 ? dummy : dummy.next; + } } diff --git a/Medium/Populating Next Right Pointers in Each Node II.java b/Medium/Populating Next Right Pointers in Each Node II.java index d4cf5639..42c9e387 100644 --- a/Medium/Populating Next Right Pointers in Each Node II.java +++ b/Medium/Populating Next Right Pointers in Each Node II.java @@ -7,8 +7,12 @@ class Node { public Node next; public Node() {} + + public Node(int _val) { + val = _val; + } - public Node(int _val,Node _left,Node _right,Node _next) { + public Node(int _val, Node _left, Node _right, Node _next) { val = _val; left = _left; right = _right; @@ -16,33 +20,27 @@ public Node(int _val,Node _left,Node _right,Node _next) { } }; */ + class Solution { - public Node connect(Node root) { - Queue queue = new LinkedList<>(); - - queue.add(root); - queue.add(null); - - while (queue.peek() != null) { - int size = queue.size() - 1; - - while (size-- > 0) { - Node removed = queue.remove(); - removed.next = queue.peek(); - - if (removed.left != null) { - queue.add(removed.left); - } - - if (removed.right != null) { - queue.add(removed.right); - } - } - - queue.remove(); - queue.add(null); + public Node connect(Node root) { + Queue queue = new LinkedList<>(); + queue.add(root); + queue.add(null); + while (queue.peek() != null) { + int size = queue.size() - 1; + while (size-- > 0) { + Node removed = queue.remove(); + removed.next = queue.peek(); + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); } - - return root; + } + queue.remove(); + queue.add(null); } + return root; + } } diff --git a/Medium/Populating Next Right Pointers in Each Node.java b/Medium/Populating Next Right Pointers in Each Node.java new file mode 100644 index 00000000..176deb77 --- /dev/null +++ b/Medium/Populating Next Right Pointers in Each Node.java @@ -0,0 +1,41 @@ +/* +// Definition for a Node. +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; + } +}; +*/ + +class Solution { + public Node connect(Node root) { + Node prev = root; + Node curr = null; + while (prev != null && prev.left != null) { + curr = prev; + while (curr != null) { + curr.left.next = curr.right; + if (curr.next != null) { + curr.right.next = curr.next.left; + } + curr = curr.next; + } + prev = prev.left; + } + return root; + } +} diff --git a/Medium/Possible Bipartition.java b/Medium/Possible Bipartition.java new file mode 100644 index 00000000..4d2a0500 --- /dev/null +++ b/Medium/Possible Bipartition.java @@ -0,0 +1,38 @@ +class Solution { + public boolean possibleBipartition(int n, int[][] dislikes) { + Map> map = new HashMap<>(); + for (int[] dislike : dislikes) { + map.computeIfAbsent(dislike[0], k -> new ArrayList<>()).add(dislike[1]); + map.computeIfAbsent(dislike[1], k -> new ArrayList<>()).add(dislike[0]); + } + int[] color = new int[n + 1]; + Arrays.fill(color, -1); + for (int i = 1; i <= n; i++) { + if (color[i] == -1) { + if (!bfs(i, map, color)) { + return false; + } + } + } + return true; + } + + private boolean bfs(int node, Map> map, int[] color) { + Queue queue = new LinkedList<>(); + queue.add(node); + color[node] = 0; + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (Integer neighbor : map.getOrDefault(removed, new ArrayList<>())) { + if (color[neighbor] == color[removed]) { + return false; + } + if (color[neighbor] == -1) { + color[neighbor] = 1 - color[removed]; + queue.add(neighbor); + } + } + } + return true; + } +} diff --git a/Medium/Pow(x, n).java b/Medium/Pow(x, n).java new file mode 100644 index 00000000..541772af --- /dev/null +++ b/Medium/Pow(x, n).java @@ -0,0 +1,11 @@ +class Solution { + public double myPow(double x, int n) { + if (n == 0) { + return 1; + } + if (n < 0) { + return 1 / x * myPow(1 / x, -1 * (n + 1)); + } + return n % 2 == 0 ? myPow(x * x, n / 2) : x * myPow(x * x, n / 2); + } +} diff --git a/Medium/Pow.java b/Medium/Pow.java index d27486cf..8278dc37 100644 --- a/Medium/Pow.java +++ b/Medium/Pow.java @@ -1,5 +1,18 @@ class Solution { - public double myPow(double x, int n) { - return Math.pow(x,n); + public double myPow(double x, int n) { + long N = n; + if (N < 0) { + x = 1 / x; + N = -N; } + double ans = 1; + double currProd = x; + for (long i = N; i > 0; i /= 2) { + if ((i % 2) == 1) { + ans = ans * currProd; + } + currProd = currProd * currProd; + } + return ans; + } } diff --git a/Medium/Prime Palindrome.java b/Medium/Prime Palindrome.java new file mode 100644 index 00000000..afb50361 --- /dev/null +++ b/Medium/Prime Palindrome.java @@ -0,0 +1,39 @@ +class Solution { + public int primePalindrome(int N) { + for (int i = 1; i <= 5; i++) { + for (int root = (int)Math.pow(10, i - 1); root < (int)Math.pow(10, i); root++) { + StringBuilder sb = new StringBuilder(Integer.toString(root)); + for (int j = i - 2; j >= 0; j--) { + sb.append(sb.charAt(j)); + } + int num = Integer.valueOf(sb.toString()); + if (num >= N && isPrime(num)) { + return num; + } + } + for (int root = (int)Math.pow(10, i - 1); root < (int)Math.pow(10, i); root++) { + StringBuilder sb = new StringBuilder(Integer.toString(root)); + for (int j = i - 1; j >= 0; j--) { + sb.append(sb.charAt(j)); + } + int num = Integer.parseInt(sb.toString()); + if (num >= N && isPrime(num)) { + return num; + } + } + } + return -1; + } + + private boolean isPrime(int n) { + if (n < 2) { + return false; + } + for (int j = 2; j <= (int) Math.sqrt(n); j++) { + if (n % j == 0) { + return false; + } + } + return true; + } +} diff --git a/Medium/Print Binary Tree.java b/Medium/Print Binary Tree.java index 3b211d02..ad19e97b 100644 --- a/Medium/Print Binary Tree.java +++ b/Medium/Print Binary Tree.java @@ -8,45 +8,43 @@ * } */ class Solution { - - List> ans = new ArrayList<>(); - public List> printTree(TreeNode root) { - int row = height(root); - int col = (int)(Math.pow(2, row) - 1); - - List oneRow = new ArrayList<>(); - - for (int i=0;i(oneRow)); + int height = getHeight(root); + int numOfNodes = (int) Math.pow(2, height) - 1; + + List> ans = new ArrayList<>(); + + for (int i = 0; i < height; i++) { + List temp = new ArrayList<>(); + for (int j = 0; j < numOfNodes; j++) { + temp.add(""); + } + + ans.add(temp); } - - helper(0, 0, col, root); - + + updateList(ans, root, 0, 0, numOfNodes); + return ans; } - - public void helper(int rowNum, int start, int end, TreeNode root) { - - if (root == null) return; - - int mid = (start + end)/2; - - List temp = ans.get(rowNum); - temp.set(mid, String.valueOf(root.val)); - - ans.set(rowNum, temp); - - helper(rowNum+1, start, mid-1, root.left); - helper(rowNum+1, mid+1, end, root.right); + + private void updateList (List> ans, TreeNode root, int idx, int start, int end) { + if (root == null) { + return; + } + + int mid = (start + end) / 2; + + ans.get(idx).set(mid, String.valueOf(root.val)); + updateList(ans, root.left, idx + 1, start, mid - 1); + updateList(ans, root.right, idx + 1, mid + 1, end); } - - public int height(TreeNode root) { - if (root == null) return 0; - return 1 + Math.max(height(root.left), height(root.right)); + + private int getHeight (TreeNode root) { + if (root == null) { + return 0; + } + + return 1 + Math.max(getHeight(root.left), getHeight(root.right)); } } diff --git a/Medium/Print Immutable Linked List in Reverse.java b/Medium/Print Immutable Linked List in Reverse.java new file mode 100644 index 00000000..d571d18e --- /dev/null +++ b/Medium/Print Immutable Linked List in Reverse.java @@ -0,0 +1,21 @@ +/** + * // This is the ImmutableListNode's API interface. + * // You should not implement it, or speculate about its implementation. + * interface ImmutableListNode { + * public void printValue(); // print the value of this node. + * public ImmutableListNode getNext(); // return the next node. + * }; + */ + +class Solution { + public void printLinkedListInReverse(ImmutableListNode head) { + Stack stack = new Stack<>(); + while (head != null) { + stack.push(head); + head = head.getNext(); + } + while (!stack.isEmpty()) { + stack.pop().printValue(); + } + } +} diff --git a/Medium/Print Words Vertically.java b/Medium/Print Words Vertically.java new file mode 100644 index 00000000..722c9430 --- /dev/null +++ b/Medium/Print Words Vertically.java @@ -0,0 +1,23 @@ +class Solution { + public List printVertically(String s) { + String[] words = s.split("\\s+"); + int longestWordLength = 0; + for (String word : words) { + longestWordLength = Math.max(longestWordLength, word.length()); + } + List ans = new ArrayList<>(); + for (int i = 0; i < longestWordLength; i++) { + StringBuilder sb = new StringBuilder(); + for (String word : words) { + sb.append(i < word.length() ? word.charAt(i) : " "); + } + while (sb.charAt(sb.length() - 1) == ' ') { + sb.deleteCharAt(sb.length() - 1); + } + if (sb.length() > 0) { + ans.add(sb.toString()); + } + } + return ans; + } +} diff --git a/Medium/Prison Cells After N Days.java b/Medium/Prison Cells After N Days.java index a793b51c..6010b774 100644 --- a/Medium/Prison Cells After N Days.java +++ b/Medium/Prison Cells After N Days.java @@ -1,20 +1,17 @@ class Solution { - public int[] prisonAfterNDays(int[] cells, int N) { - Map map = new HashMap<>(); - while (N > 0) { - int[] temp = new int[8]; - map.put(Arrays.toString(cells), N--); - for (int i = 1; i < 7; i++) { - temp[i] = cells[i - 1] == cells[i + 1] ? 1 : 0; - } - - cells = temp; - - if (map.containsKey(Arrays.toString(cells))) { - N %= map.get(Arrays.toString(cells)) - N; - } - } - - return cells; + public int[] prisonAfterNDays(int[] cells, int N) { + Map seen = new HashMap<>(); + while (N > 0) { + int[] cells2 = new int[8]; + seen.put(Arrays.toString(cells), N--); + for (int i = 1; i < 7; ++i) { + cells2[i] = cells[i - 1] == cells[i + 1] ? 1 : 0; + } + cells = cells2; + if (seen.containsKey(Arrays.toString(cells))) { + N %= seen.get(Arrays.toString(cells)) - N; + } } + return cells; + } } diff --git a/Medium/Product of Array Except self.java b/Medium/Product of Array Except self.java index 8bf5e870..44306f8b 100644 --- a/Medium/Product of Array Except self.java +++ b/Medium/Product of Array Except self.java @@ -1,19 +1,16 @@ class Solution { - public int[] productExceptSelf(int[] nums) { - - int[] ans = new int[nums.length]; - - for (int i = 0, tmp = 1; i < nums.length; i++) { - ans[i] = tmp; - tmp *= nums[i]; - } - - for (int i = nums.length - 1, tmp = 1; i >= 0; i--) { - ans[i] *= tmp; - tmp *= nums[i]; - } - - return ans; - + public int[] productExceptSelf(int[] nums) { + int[] ans = new int[nums.length]; + int mul = 1; + for (int i = 0; i < nums.length; i++) { + ans[i] = mul; + mul *= nums[i]; } + mul = 1; + for (int i = nums.length - 1; i >= 0; i--) { + ans[i] *= mul; + mul *= nums[i]; + } + return ans; + } } diff --git a/Medium/Product of Two Run-Length Encoded Arrays.java b/Medium/Product of Two Run-Length Encoded Arrays.java new file mode 100644 index 00000000..4aab9bc8 --- /dev/null +++ b/Medium/Product of Two Run-Length Encoded Arrays.java @@ -0,0 +1,31 @@ +class Solution { + public List> findRLEArray(int[][] encoded1, int[][] encoded2) { + int idxOne = 0; + int idxTwo = 0; + List> result = new ArrayList<>(); + while (idxOne < encoded1.length && idxTwo < encoded2.length) { + int valOne = encoded1[idxOne][0]; + int valTwo = encoded2[idxTwo][0]; + int countOne = encoded1[idxOne][1]; + int countTwo = encoded2[idxTwo][1]; + int value = valOne * valTwo; + int count = Math.min(countOne, countTwo); + encoded1[idxOne][1] -= count; + encoded2[idxTwo][1] -= count; + if (encoded1[idxOne][1] == 0) { + idxOne++; + } + if (encoded2[idxTwo][1] == 0) { + idxTwo++; + } + if (!result.isEmpty() && result.get(result.size() - 1).get(0) == value) { + int existingCount = result.get(result.size() - 1).get(1); + int newCount = existingCount + count; + result.get(result.size() - 1).set(1, newCount); + } else { + result.add(Arrays.asList(value, count)); + } + } + return result; + } +} diff --git a/Medium/Product of the Last K Numbers.java b/Medium/Product of the Last K Numbers.java new file mode 100644 index 00000000..acfc5bae --- /dev/null +++ b/Medium/Product of the Last K Numbers.java @@ -0,0 +1,30 @@ +class ProductOfNumbers { + + private List list; + + public ProductOfNumbers() { + this.list = new ArrayList<>(); + add(0); + } + + public void add(int num) { + if (num > 0) { + list.add(list.get(list.size() - 1) * num); + } else { + list = new ArrayList<>(); + list.add(1); + } + } + + public int getProduct(int k) { + int n = list.size(); + return k < n ? list.get(n - 1) / list.get(n - k - 1) : 0; + } +} + +/** + * Your ProductOfNumbers object will be instantiated and called as such: + * ProductOfNumbers obj = new ProductOfNumbers(); + * obj.add(num); + * int param_2 = obj.getProduct(k); + */ diff --git a/Medium/Pseudo-Palindromic Paths in a Binary Tree.java b/Medium/Pseudo-Palindromic Paths in a Binary Tree.java new file mode 100644 index 00000000..87acbbf4 --- /dev/null +++ b/Medium/Pseudo-Palindromic Paths in a Binary Tree.java @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int pseudoPalindromicPaths (TreeNode root) { + int[] result = {0}; + Map map = new HashMap<>(); + helper(root, map, result); + return result[0]; + } + + private void helper(TreeNode root, Map map, int[] result) { + if (root == null) { + return; + } + map.put(root.val, map.getOrDefault(root.val, 0) + 1); + if (root.left == null && root.right == null) { + if (isPseudoPalindromic(map)) { + result[0]++; + } + } + helper(root.left, map, result); + helper(root.right, map, result); + map.put(root.val, map.getOrDefault(root.val, 0) - 1); + } + + private static boolean isPseudoPalindromic(Map map) { + boolean oddFound = false; + for (Integer key : map.keySet()) { + if (map.get(key) % 2 != 0) { + if (oddFound) { + return false; + } + oddFound = true; + } + } + return true; + } +} diff --git a/Medium/Push Dominoes.java b/Medium/Push Dominoes.java new file mode 100644 index 00000000..16753989 --- /dev/null +++ b/Medium/Push Dominoes.java @@ -0,0 +1,32 @@ +class Solution { + public String pushDominoes(String dominoes) { + int[] forces = new int[dominoes.length()]; + int force = 0; + for (int i = 0; i < dominoes.length(); i++) { + if (dominoes.charAt(i) == 'R') { + force = dominoes.length(); + } else if (dominoes.charAt(i) == 'L') { + force = 0; + } else { + force = Math.max(force - 1, 0); + } + forces[i] += force; + } + force = 0; + for (int i = dominoes.length() - 1; i >= 0; i--) { + if (dominoes.charAt(i) == 'L') { + force = dominoes.length(); + } else if (dominoes.charAt(i) == 'R') { + force = 0; + } else { + force = Math.max(force - 1, 0); + } + forces[i] -= force; + } + StringBuilder result = new StringBuilder(); + for (int i = 0; i < forces.length; i++) { + result.append(forces[i] > 0 ? 'R' : (forces[i] < 0 ? 'L' : '.')); + } + return result.toString(); + } +} diff --git a/Medium/Put Boxes Into the Warehouse I.java b/Medium/Put Boxes Into the Warehouse I.java new file mode 100644 index 00000000..3d8b4a59 --- /dev/null +++ b/Medium/Put Boxes Into the Warehouse I.java @@ -0,0 +1,15 @@ +class Solution { + public int maxBoxesInWarehouse(int[] boxes, int[] warehouse) { + Arrays.sort(boxes); + for (int i = 1; i < warehouse.length; i++) { + warehouse[i] = Math.min(warehouse[i - 1], warehouse[i]); + } + int count = 0; + for (int i = warehouse.length - 1; i >= 0; i--) { + if (count < boxes.length && boxes[count] <= warehouse[i]) { + count++; + } + } + return count; + } +} diff --git a/Medium/Queries on a Permutation With Key.java b/Medium/Queries on a Permutation With Key.java new file mode 100644 index 00000000..5738ab0c --- /dev/null +++ b/Medium/Queries on a Permutation With Key.java @@ -0,0 +1,16 @@ +class Solution { + public int[] processQueries(int[] queries, int m) { + LinkedList list = new LinkedList<>(); + for (int i = 1; i <= m; i++) { + list.add(i); + } + int[] result = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int idx = list.indexOf(queries[i]); + result[i] = idx; + list.remove(idx); + list.addFirst(queries[i]); + } + return result; + } +} diff --git a/Medium/Queue Reconstruction By Height.java b/Medium/Queue Reconstruction By Height.java index 79279acf..4f422303 100644 --- a/Medium/Queue Reconstruction By Height.java +++ b/Medium/Queue Reconstruction By Height.java @@ -1,19 +1,11 @@ class Solution { - public int[][] reconstructQueue(int[][] people) { - - Arrays.sort(people,new Comparator(){ - @Override - public int compare(int[] o1, int[] o2){ - return o1[0]!=o2[0]?-o1[0]+o2[0]:o1[1]-o2[1]; - } - }); - - List res = new LinkedList<>(); - for(int[] cur : people){ - res.add(cur[1],cur); - } - - return res.toArray(new int[people.length][]); - + public int[][] reconstructQueue(int[][] people) { + Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]); + List result = new ArrayList<>(); + for (int[] p : people) { + result.add(p[1], p); } + int n = people.length; + return result.toArray(new int[n][2]); + } } diff --git a/Medium/README.md b/Medium/README.md new file mode 100644 index 00000000..cb496742 --- /dev/null +++ b/Medium/README.md @@ -0,0 +1,795 @@ +# Medium LeetCode-Java-Solutions +S.no | Coding Problem +--- | --- +1|[Jump Game II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Jump%20Game%20II.java) +2|[Unique Paths II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Unique%20Paths%20II.java) +3|[Search a 2D Matrix II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20a%202D%20Matrix%20II.java) +4|[First Unique Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/First%20Unique%20Number.java) +5|[Minimum Number of Vertices to Reach All Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Number%20of%20Vertices%20to%20Reach%20All%20Nodes.java) +6|[Inorder Successor in BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Inorder%20Successor%20in%20BST.java) +7|[3Sum Closest](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/3Sum%20Closest.java) +8|[Binary Tree Zigzag Level Order Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Zigzag%20Level%20Order%20Traversal.java) +9|[Successful Pairs of Spells and Potions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Successful%20Pairs%20of%20Spells%20and%20Potions.java) +10|[Sort the Jumbled Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20the%20Jumbled%20Numbers.java) +11|[Closest Nodes Queries in a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Closest%20Nodes%20Queries%20in%20a%20Binary%20Search%20Tree.java) +12|[House Robber III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/House%20Robber%20III.java) +13|[Out of Boundary Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Out%20of%20Boundary%20Paths.java) +14|[Campus Bikes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Campus%20Bikes.java) +15|[Arithmetic Subarrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Arithmetic%20Subarrays.java) +16|[Binary Tree Level Order Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Level%20Order%20Traversal.java) +17|[Vowels of All Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Vowels%20of%20All%20Substrings.java) +18|[Grumpy Bookstore Owner](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Grumpy%20Bookstore%20Owner.java) +19|[Minimize the Maximum Difference of Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimize%20the%20Maximum%20Difference%20of%20Pairs.java) +20|[Linked List Cycle II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Linked%20List%20Cycle%20II.java) +21|[Dota2 Senate](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Dota2%20Senate.java) +22|[Largest Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Largest%20Number.java) +23|[Stone Game II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Stone%20Game%20II.java) +24|[Web Crawler](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Web%20Crawler.java) +25|[Champagne Tower](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Champagne%20Tower.java) +26|[Candy Crush](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Candy%20Crush.java) +27|[Bold Words in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Bold%20Words%20in%20String.java) +28|[Diagonal Traverse](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Diagonal%20Traverse.java) +29|[Shortest Way to Form String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Way%20to%20Form%20String.java) +30|[Maximum Number of Coins You Can Get](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Coins%20You%20Can%20Get.java) +31|[Masking Personal Information](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Masking%20Personal%20Information.java) +32|[The Earliest Moment When Everyone Become Friends](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/The%20Earliest%20Moment%20When%20Everyone%20Become%20Friends.java) +33|[Divide Two Integers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Divide%20Two%20Integers.java) +34|[Minimum Cost to Connect Sticks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Cost%20to%20Connect%20Sticks.java) +35|[Lowest Common Ancestor of Deepest Leaves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lowest%20Common%20Ancestor%20of%20Deepest%20Leaves.java) +36|[Single Number III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Single%20Number%20III.java) +37|[Next Greater Element III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Next%20Greater%20Element%20III.java) +38|[Making File Names Unique](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Making%20File%20Names%20Unique.java) +39|[Validate Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Validate%20Binary%20Search%20Tree.java) +40|[Sparse Matrix Multiplication](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sparse%20Matrix%20Multiplication.java) +41|[Uncrossed Lines](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Uncrossed%20Lines.java) +42|[Capacity To Ship Packages Within D Days](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Capacity%20To%20Ship%20Packages%20Within%20D%20Days.java) +43|[Count Vowel Strings in Ranges](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Vowel%20Strings%20in%20Ranges.java) +44|[Set Matrix Zeroes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Set%20Matrix%20Zeroes.java) +45|[Flatten a Multilevel Doubly Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Flatten%20a%20Multilevel%20Doubly%20Linked%20List.java) +46|[Word Subsets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Word%20Subsets.java) +47|[Find Smallest Common Element in All Rows](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Smallest%20Common%20Element%20in%20All%20Rows.java) +48|[Reverse Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Integer.java) +49|[Most Popular Video Creator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Most%20Popular%20Video%20Creator.java) +50|[Most Stones Removed with Same Row or Column](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Most%20Stones%20Removed%20with%20Same%20Row%20or%20Column.java) +51|[Shortest Word Distance II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Word%20Distance%20II.java) +52|[Total Hamming Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Total%20Hamming%20Distance.java) +53|[Sort Linked List Already Sorted Using Absolute Values](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20Linked%20List%20Already%20Sorted%20Using%20Absolute%20Values.java) +54|[Count Number of Homogenous Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Number%20of%20Homogenous%20Substrings.java) +55|[Score of Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Score%20of%20Parentheses.java) +56|[Gas Station](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Gas%20Station.java) +57|[Number of Subarrays with Bounded Maximum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Subarrays%20with%20Bounded%20Maximum.java) +58|[Kth Largest Sum in a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Kth%20Largest%20Sum%20in%20a%20Binary%20Tree.java) +59|[Smallest Number in Infinite Set](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20Number%20in%20Infinite%20Set.java) +60|[All Divisions With the Highest Score of a Binary Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Divisions%20With%20the%20Highest%20Score%20of%20a%20Binary%20Array.java) +61|[Non-decreasing Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Non-decreasing%20Array.java) +62|[Palindrome Partitioning](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Palindrome%20Partitioning.java) +63|[Find all Duplicates in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20all%20Duplicates%20in%20an%20Array.java) +64|[Find Largest Value in Each Tree Row](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Largest%20Value%20in%20Each%20Tree%20Row.java) +65|[Flatten 2D Vector](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Flatten%202D%20Vector.java) +66|[Find All Lonely Numbers in the Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20All%20Lonely%20Numbers%20in%20the%20Array.java) +67|[Furthest Building You Can Reach](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Furthest%20Building%20You%20Can%20Reach.java) +68|[Convert Binary Search Tree to Sorted Doubly Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Convert%20Binary%20Search%20Tree%20to%20Sorted%20Doubly%20Linked%20List.java) +69|[Design a File Sharing System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20a%20File%20Sharing%20System.java) +70|[Watering Plants](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Watering%20Plants.java) +71|[Smallest String Starting From Leaf](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20String%20Starting%20From%20Leaf.java) +72|[Throne Inheritence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Throne%20Inheritence.java) +73|[Minimum Remove to Make Valid Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Remove%20to%20Make%20Valid%20Parentheses.java) +74|[Implement Trie II (Prefix Tree)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Implement%20Trie%20II%20(Prefix%20Tree).java) +75|[Remove Covered Intervals](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Covered%20Intervals.java) +76|[Minimum Add to Make Parentheses Valid](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Add%20to%20Make%20Parentheses%20Valid.java) +77|[Arithmetic Slices](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Arithmetic%20Slices.java) +78|[Binary Tree Preorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Preorder%20Traversal.java) +79|[Time Needed to Inform All Employees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Time%20Needed%20to%20Inform%20All%20Employees.java) +80|[Kill Process](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Kill%20Process.java) +81|[Maximum Twin Sum of a Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Twin%20Sum%20of%20a%20Linked%20List.java) +82|[Line Reflection](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Line%20Reflection.java) +83|[Maximum Number of Occurrences of a Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Occurrences%20of%20a%20Substring.java) +84|[Frequency Tracker](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Frequency%20Tracker.java) +85|[Diameter of N-ary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Diameter%20of%20N-ary%20Tree.java) +86|[Maximum Number of Non-Overlapping Subarrays With Sum Equals Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Non-Overlapping%20Subarrays%20With%20Sum%20Equals%20Target.java) +87|[Majority Element II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Majority%20Element%20II.java) +88|[Number of Ways to Split Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Ways%20to%20Split%20Array.java) +89|[Plus One Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Plus%20One%20Linked%20List.java) +90|[Append Characters to String to Make Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Append%20Characters%20to%20String%20to%20Make%20Subsequence.java) +91|[Longest Consecutive Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Consecutive%20Sequence.java) +92|[Find Minimum in Rotated Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Minimum%20in%20Rotated%20Sorted%20Array.java) +93|[Decrease Elements To Make Array Zigzag](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Decrease%20Elements%20To%20Make%20Array%20Zigzag.java) +94|[Binary Tree Longest Consecutive Sequence II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Longest%20Consecutive%20Sequence%20II.java) +95|[Concatenation of Consecutive Binary Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Concatenation%20of%20Consecutive%20Binary%20Numbers.java) +96|[Bitwise AND of Numbers Range](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Bitwise%20AND%20of%20Numbers%20Range.java) +97|[Maximum Points You Can Obtain from Cards](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Points%20You%20Can%20Obtain%20from%20Cards.java) +98|[Count Number of Teams](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Number%20of%20Teams.java) +99|[Sum of Subarray Minimums](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20of%20Subarray%20Minimums.java) +100|[Binary Trees With Factors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Trees%20With%20Factors.java) +101|[Prime Palindrome](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Prime%20Palindrome.java) +102|[Minimum Path Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Path%20Sum.java) +103|[Friend Circles](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Friend%20Circles.java) +104|[Matchsticks to Square](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Matchsticks%20to%20Square.java) +105|[Valid Sudoku](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Valid%20Sudoku.java) +106|[Four Divisors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Four%20Divisors.java) +107|[As Far from Land as Possible](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/As%20Far%20from%20Land%20as%20Possible.java) +108|[Count Square Submatrices with All Ones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Square%20Submatrices%20with%20All%20Ones.java) +109|[Linked List in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Linked%20List%20in%20Binary%20Tree.java) +110|[Number of Nodes in the Sub-Tree With the Same Label](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Nodes%20in%20the%20Sub-Tree%20With%20the%20Same%20Label.java) +111|[Pseudo-Palindromic Paths in a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Pseudo-Palindromic%20Paths%20in%20a%20Binary%20Tree.java) +112|[Pancake Sorting](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Pancake%20Sorting.java) +113|[Walls and Gates](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Walls%20and%20Gates.java) +114|[Decode String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Decode%20String.java) +115|[Combination Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Combination%20Sum%20II.java) +116|[Complete Binary Tree Insertor](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Complete%20Binary%20Tree%20Insertor.java) +117|[Minimum Moves to Equal Array Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Moves%20to%20Equal%20Array%20Elements.java) +118|[Design an ATM Machine](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20an%20ATM%20Machine.java) +119|[Split Linked List in Parts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Split%20Linked%20List%20in%20Parts.java) +120|[Longest Word With All Prefixes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Word%20With%20All%20Prefixes.java) +121|[Binary Tree Pruning](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Pruning.java) +122|[Escape The Ghosts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Escape%20The%20Ghosts.java) +123|[Longest Arithmetic Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Arithmetic%20Sequence.java) +124|[Longest Arithmetic Subsequence of Given Difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Arithmetic%20Subsequence%20of%20Given%20Difference.java) +125|[Equal Row and Column Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Equal%20Row%20and%20Column%20Pairs.java) +126|[Count Numbers With Unique Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Numbers%20With%20Unique%20Digits.java) +127|[Maximum Average Subtree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Average%20Subtree.java) +128|[Product of Array Except self](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Product%20of%20Array%20Except%20self.java) +129|[Find Bottom Left Tree Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Bottom%20Left%20Tree%20Value.java) +130|[Shifting Letters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shifting%20Letters.java) +131|[Maximum Product of Splitted Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Product%20of%20Splitted%20Binary%20Tree.java) +132|[Minimum Knight Moves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Knight%20Moves.java) +133|[3Sum With Multiplicity](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/3Sum%20With%20Multiplicity.java) +134|[Rotting Oranges](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rotting%20Oranges.java) +135|[Palindromic Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Palindromic%20Substrings.java) +136|[Maximum of Absolute Value Expression](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20of%20Absolute%20Value%20Expression.java) +137|[Insert Interval](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insert%20Interval.java) +138|[Is Graph Bipartite](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Is%20Graph%20Bipartite.java) +139|[Add Two Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Add%20Two%20Numbers.java) +140|[Find Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Permutation.java) +141|[Number of Burgers with No Waste of Ingredients](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Burgers%20with%20No%20Waste%20of%20Ingredients.java) +142|[Finding the Users Active Minutes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Finding%20the%20Users%20Active%20Minutes.java) +143|[Validate Stack Sequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Validate%20Stack%20Sequences.java) +144|[Number of Substrings Containing All Three Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Substrings%20Containing%20All%20Three%20Characters.java) +145|[Next Greater Element II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Next%20Greater%20Element%20II.java) +146|[Count and Say](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20and%20Say.java) +147|[Design Add and Search Words Data Structure](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Add%20and%20Search%20Words%20Data%20Structure.java) +148|[Maximum Score From Removing Stones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Score%20From%20Removing%20Stones.java) +149|[Minimum Consecutive Cards to Pick Up](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Consecutive%20Cards%20to%20Pick%20Up.java) +150|[Score After Flipping Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Score%20After%20Flipping%20Matrix.java) +151|[Jump Game VI](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Jump%20Game%20VI.java) +152|[Design Browser History](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Browser%20History.java) +153|[Cheapest Flights Within K Stops](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Cheapest%20Flights%20Within%20K%20Stops.java) +154|[Meeting Scheduler](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Meeting%20Scheduler.java) +155|[Perfect Squares](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Perfect%20Squares.java) +156|[Maximum Matching of Players With Trainers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Matching%20of%20Players%20With%20Trainers.java) +157|[Word Search](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Word%20Search.java) +158|[Find Triangular Sum of an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Triangular%20Sum%20of%20an%20Array.java) +159|[Knight Dialer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Knight%20Dialer.java) +160|[3Sum Smaller](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/3Sum%20Smaller.java) +161|[Repeated DNA Sequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Repeated%20DNA%20Sequences.java) +162|[Lowest Common Ancestor of a Binary Tree III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree%20III.java) +163|[Partition Array According to Given Pivot](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Partition%20Array%20According%20to%20Given%20Pivot.java) +164|[Construct K Palindrome Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Construct%20K%20Palindrome%20Strings.java) +165|[Solve the Equation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Solve%20the%20Equation.java) +166|[Average Waiting Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Average%20Waiting%20Time.java) +167|[Time Needed to Rearrange a Binary String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Time%20Needed%20to%20Rearrange%20a%20Binary%20String.java) +168|[Sort Integers by The Power Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20Integers%20by%20The%20Power%20Value.java) +169|[Sum in a Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20in%20a%20Matrix.java) +170|[Combination Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Combination%20Sum.java) +171|[Make String a Subsequence Using Cyclic Increments](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Make%20String%20a%20Subsequence%20Using%20Cyclic%20Increments.java) +172|[Merge Intervals](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Merge%20Intervals.java) +173|[4 Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/4%20Sum%20II.java) +174|[Advantage Shuffle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Advantage%20Shuffle.java) +175|[Number of Dice Rolls With Target Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Dice%20Rolls%20With%20Target%20Sum.java) +176|[Minimum Flips to Make a OR b Equal to c](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Flips%20to%20Make%20a%20OR%20b%20Equal%20to%20c.java) +177|[Basic Calculator II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Basic%20Calculator%20II.java) +178|[Find Original Array From Doubled Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Original%20Array%20From%20Doubled%20Array.java) +179|[Maximum Length of Repeated Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Length%20of%20Repeated%20Subarray.java) +180|[Lonely Pixel I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lonely%20Pixel%20I.java) +181|[Guess Number Higher or Lower II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Guess%20Number%20Higher%20or%20Lower%20II.java) +182|[Remove Duplicate Letters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Duplicate%20Letters.java) +183|[Construct Binary Tree from Preorder and Inorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Construct%20Binary%20Tree%20from%20Preorder%20and%20Inorder%20Traversal.java) +184|[Group the People Given the Group Size They Belong To](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Group%20the%20People%20Given%20the%20Group%20Size%20They%20Belong%20To.java) +185|[House Robber II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/House%20Robber%20II.java) +186|[Find the Winner of an Array Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Winner%20of%20an%20Array%20Game.java) +187|[Check if Strings Can be Made Equal With Operations II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20if%20Strings%20Can%20be%20Made%20Equal%20With%20Operations%20II.java) +188|[Letter Combinations of a Phone Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Letter%20Combinations%20of%20a%20Phone%20Number.java) +189|[Implement Magic Dictionary](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Implement%20Magic%20Dictionary.java) +190|[Task Scheduler](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Task%20Scheduler.java) +191|[Minimum Size Subarray Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Size%20Subarray%20Sum.java) +192|[Max Chunks To Make Sorted](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Max%20Chunks%20To%20Make%20Sorted.java) +193|[Max Number of K-Sum Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Max%20Number%20of%20K-Sum%20Pairs.java) +194|[Longest Word in Dictionary through Deleting](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Word%20in%20Dictionary%20through%20Deleting.java) +195|[Maximum Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Binary%20Tree.java) +196|[Find and Replace in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20and%20Replace%20in%20String.java) +197|[Sort Characters By Frequency](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20Characters%20By%20Frequency.java) +198|[Maximum Erasure Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Erasure%20Value.java) +199|[Number of Matching Subsequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Matching%20Subsequences.java) +200|[Simple Bank System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Simple%20Bank%20System.java) +201|[Camelcase Matching](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Camelcase%20Matching.java) +202|[Split Array into Consecutive Subsequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Split%20Array%20into%20Consecutive%20Subsequences.java) +203|[Integer To Roman](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Integer%20To%20Roman.java) +204|[Smallest Value of the Rearranged Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20Value%20of%20the%20Rearranged%20Number.java) +205|[Count Servers That Communicate](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Servers%20That%20Communicate.java) +206|[Execution of All Suffix Instructions Staying in a Grid](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Execution%20of%20All%20Suffix%20Instructions%20Staying%20in%20a%20Grid.java) +207|[Number of Laser Beams in a Bank](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Laser%20Beams%20in%20a%20Bank.java) +208|[Minimize Maximum Pair Sum in Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimize%20Maximum%20Pair%20Sum%20in%20Array.java) +209|[Lowest Common Ancestor of a Binary Tree II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree%20II.java) +210|[Image Overlap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Image%20Overlap.java) +211|[Balance a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Balance%20a%20Binary%20Search%20Tree.java) +212|[Insert Greatest Common Divisors in Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insert%20Greatest%20Common%20Divisors%20in%20Linked%20List.java) +213|[Reordered Power of 2](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reordered%20Power%20of%202.java) +214|[Construct Binary Tree from Inorder and Postorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Construct%20Binary%20Tree%20from%20Inorder%20and%20Postorder%20Traversal.java) +215|[Multiply Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Multiply%20Strings.java) +216|[K Radius Subarray Averages](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/K%20Radius%20Subarray%20Averages.java) +217|[Minimum Health to Beat Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Health%20to%20Beat%20Game.java) +218|[Path With Minimum Effort](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Path%20With%20Minimum%20Effort.java) +219|[Append K Integers With Minimal Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Append%20K%20Integers%20With%20Minimal%20Sum.java) +220|[Minimum Moves to Equal Array Elements II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Moves%20to%20Equal%20Array%20Elements%20II.java) +221|[Parallel Courses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Parallel%20Courses.java) +222|[Put Boxes Into the Warehouse I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Put%20Boxes%20Into%20the%20Warehouse%20I.java) +223|[Adding Two Negabinary Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Adding%20Two%20Negabinary%20Numbers.java) +224|[Minimum Rounds to Complete All Tasks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Rounds%20to%20Complete%20All%20Tasks.java) +225|[Longest Happy String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Happy%20String.java) +226|[Nested List Weight Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Nested%20List%20Weight%20Sum%20II.java) +227|[Range Sum Query 2D-Immutable](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Range%20Sum%20Query%202D-Immutable.java) +228|[Remove Nth Node From End of List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Nth%20Node%20From%20End%20of%20List.java) +229|[Peeking Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Peeking%20Iterator.java) +230|[Subsets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subsets.java) +231|[Design Circular Queue](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Circular%20Queue.java) +232|[4 Keys Keyboard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/4%20Keys%20Keyboard.java) +233|[Single Element in a Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Single%20Element%20in%20a%20Sorted%20Array.java) +234|[Permutations II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Permutations%20II.java) +235|[Knight Probability in Chessboard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Knight%20Probability%20in%20Chessboard.java) +236|[Reachable Nodes With Restrictions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reachable%20Nodes%20With%20Restrictions.java) +237|[Longest ZigZag Path in a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20ZigZag%20Path%20in%20a%20Binary%20Tree.java) +238|[Reduce Array Size to The Half](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reduce%20Array%20Size%20to%20The%20Half.java) +239|[Maximum Length of Pair Chain](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Length%20of%20Pair%20Chain.java) +240|[Binary Tree Vertical Order Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Vertical%20Order%20Traversal.java) +241|[Reorder Data in Log Files](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reorder%20Data%20in%20Log%20Files.java) +242|[Maximum Product Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Product%20Subarray.java) +243|[Rotate List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rotate%20List.java) +244|[Find the Celebrity](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Celebrity.java) +245|[Swap Nodes in Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Swap%20Nodes%20in%20Pairs.java) +246|[Filter Restaurants by Vegan-Friendly, Price and Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Filter%20Restaurants%20by%20Vegan-Friendly,%20Price%20and%20Distance.java) +247|[Evaluate Division](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Evaluate%20Division.java) +248|[Minimum Operations to Make Array Equal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Operations%20to%20Make%20Array%20Equal.java) +249|[Combinations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Combinations.java) +250|[Max Area of Island](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Max%20Area%20of%20Island.java) +251|[Sort List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20List.java) +252|[Most Frequent Subtree Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Most%20Frequent%20Subtree%20Sum.java) +253|[Find Peak Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Peak%20Element.java) +254|[Open The Lock](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Open%20The%20Lock.java) +255|[Fruit Into Baskets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Fruit%20Into%20Baskets.java) +256|[Maximum Sum of Almost Unique Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Sum%20of%20Almost%20Unique%20Subarray.java) +257|[Remove K Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20K%20Digits.java) +258|[Minimum Number of Steps to Make Two Strings Anagram](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Number%20of%20Steps%20to%20Make%20Two%20Strings%20Anagram.java) +259|[Connecting Cities With Minimum Cost](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Connecting%20Cities%20With%20Minimum%20Cost.java) +260|[Decoded String at Index](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Decoded%20String%20at%20Index.java) +261|[Satisfisbility of Equality Equations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Satisfisbility%20of%20Equality%20Equations.java) +262|[Maximum Product of Word Lengths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Product%20of%20Word%20Lengths.java) +263|[Maximum Number of Integers to Choose From a Range I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Integers%20to%20Choose%20From%20a%20Range%20I.java) +264|[Pour Water](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Pour%20Water.java) +265|[Gray Code](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Gray%20Code.java) +266|[Minimum Moves to Reach Target Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Moves%20to%20Reach%20Target%20Score.java) +267|[Encode and Decode TinyURL](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Encode%20and%20Decode%20TinyURL.java) +268|[Game of Life](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Game%20of%20Life.java) +269|[Number of Pairs of Strings With Concatenation Equal to Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Pairs%20of%20Strings%20With%20Concatenation%20Equal%20to%20Target.java) +270|[Maximum Swap](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Swap.java) +271|[Time Based Key-Value Store](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Time%20Based%20Key-Value%20Store.java) +272|[Compare Version Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Compare%20Version%20Numbers.java) +273|[Reverse Nodes in Even Length Groups](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Nodes%20in%20Even%20Length%20Groups.java) +274|[Maximum Number of Vowels in a Substring of Given Length](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Vowels%20in%20a%20Substring%20of%20Given%20Length.java) +275|[Graph Valid Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Graph%20Valid%20Tree.java) +276|[Minimum Operations to Reduce X to Zero](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Operations%20to%20Reduce%20X%20to%20Zero.java) +277|[Group Anagrams](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Group%20Anagrams.java) +278|[Delete the Middle Node of a Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Delete%20the%20Middle%20Node%20of%20a%20Linked%20List.java) +279|[Lowest Common Ancestor of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree.java) +280|[Deepest Leaves Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Deepest%20Leaves%20Sum.java) +281|[Minimize Maximum of Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimize%20Maximum%20of%20Array.java) +282|[Boundary of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Boundary%20of%20Binary%20Tree.java) +283|[Clone N-ary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Clone%20N-ary%20Tree.java) +284|[Rotate Image](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rotate%20Image.java) +285|[Self Dividing Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Self%20Dividing%20Numbers.java) +286|[Remove Nodes From Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Nodes%20From%20Linked%20List.java) +287|[Map Sum Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Map%20Sum%20Pairs.java) +288|[Restore the Array From Adjacent Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Restore%20the%20Array%20From%20Adjacent%20Pairs.java) +289|[Find the Index of the Large Integer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Index%20of%20the%20Large%20Integer.java) +290|[Combination Sum IV](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Combination%20Sum%20IV.java) +291|[Pacific Atlantic Water Flow](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Pacific%20Atlantic%20Water%20Flow.java) +292|[Delete Leaves With a Given Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Delete%20Leaves%20With%20a%20Given%20Value.java) +293|[Pow](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Pow.java) +294|[Remove Comments](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Comments.java) +295|[Longest Uploaded Prefix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Uploaded%20Prefix.java) +296|[Rotated Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rotated%20Digits.java) +297|[Next Permutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Next%20Permutation.java) +298|[Find the Substring With Maximum Cost](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Substring%20With%20Maximum%20Cost.java) +299|[Design Log Storage System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Log%20Storage%20System.java) +300|[Decode Ways](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Decode%20Ways.java) +301|[Number of Longest Increasing Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Longest%20Increasing%20Subsequence.java) +302|[Triangle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Triangle.java) +303|[Non-overlapping Intervals](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Non-overlapping%20Intervals.java) +304|[Broken Calculator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Broken%20Calculator.java) +305|[Maximum Score from Performing Multiplication Operations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Score%20from%20Performing%20Multiplication%20Operations.java) +306|[Vowel Spellchecker](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Vowel%20Spellchecker.java) +307|[Maximum Sum of Distinct Subarrays With Length K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Sum%20of%20Distinct%20Subarrays%20With%20Length%20K.java) +308|[4Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/4Sum.java) +309|[House Robber](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/House%20Robber.java) +310|[Find Root of N-Ary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Root%20of%20N-Ary%20Tree.java) +311|[Rotate Function](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rotate%20Function.java) +312|[Can Make Palindrome from Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Can%20Make%20Palindrome%20from%20Substring.java) +313|[Find Distance in a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Distance%20in%20a%20Binary%20Tree.java) +314|[Possible Bipartition](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Possible%20Bipartition.java) +315|[Design Hit Counter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Hit%20Counter.java) +316|[Insert into a Sorted Circular Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insert%20into%20a%20Sorted%20Circular%20Linked%20List.java) +317|[Online Stock Span](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Online%20Stock%20Span.java) +318|[Min Cost to Connect All Points](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Min%20Cost%20to%20Connect%20All%20Points.java) +319|[Minimum Time to Collect All Apples in a Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Time%20to%20Collect%20All%20Apples%20in%20a%20Tree.java) +320|[Minimum Area Rectangle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Area%20Rectangle.java) +321|[Invalid Transactions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Invalid%20Transactions.java) +322|[Remove All Occurrences of a Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20All%20Occurrences%20of%20a%20Substring.java) +323|[Minimum Average Difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Average%20Difference.java) +324|[Maximal Score After Applying K Operations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximal%20Score%20After%20Applying%20K%20Operations.java) +325|[Minimum Amount of Time to Collect Garbage](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Amount%20of%20Time%20to%20Collect%20Garbage.java) +326|[Search in Rotated Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20in%20Rotated%20Sorted%20Array.java) +327|[Letter Tiles Possibilities](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Letter%20Tiles%20Possibilities.java) +328|[Divide Players Into Teams of Equal Skill](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Divide%20Players%20Into%20Teams%20of%20Equal%20Skill.java) +329|[Path with Maximum Gold](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Path%20with%20Maximum%20Gold.java) +330|[Copy List with Random Pointer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Copy%20List%20with%20Random%20Pointer.java) +331|[Number of Islands](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Islands.java) +332|[Total Cost to Hire K Workers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Total%20Cost%20to%20Hire%20K%20Workers.java) +333|[Sum Multiples](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20Multiples.java) +334|[Custom Sort String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Custom%20Sort%20String.java) +335|[Populating Next Right Pointers in Each Node](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Populating%20Next%20Right%20Pointers%20in%20Each%20Node.java) +336|[Mirror Reflection](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Mirror%20Reflection.java) +337|[All Possible Full Binary Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Possible%20Full%20Binary%20Trees.java) +338|[Maximum Total Importance of Roads](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Total%20Importance%20of%20Roads.java) +339|[Sum Root to Leaf Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20Root%20to%20Leaf%20Numbers.java) +340|[Contiguous Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Contiguous%20Array.java) +341|[Large Divisble Subset](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Large%20Divisble%20Subset.java) +342|[Minimum Height Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Height%20Trees.java) +343|[Analyze User Website Visit Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Analyze%20User%20Website%20Visit%20Pattern.java) +344|[Partitioning Into Minimum Number Of Deci-Binary Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Partitioning%20Into%20Minimum%20Number%20Of%20Deci-Binary%20Numbers.java) +345|[Permutations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Permutations.java) +346|[Maximum Sum of an Hourglass](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Sum%20of%20an%20Hourglass.java) +347|[Minimum Fuel Cost to Report to the Capital](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Fuel%20Cost%20to%20Report%20to%20the%20Capital.java) +348|[Find the Prefix Common Array of Two Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Prefix%20Common%20Array%20of%20Two%20Arrays.java) +349|[Coin Change 2](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Coin%20Change%202.java) +350|[Construct Quad Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Construct%20Quad%20Tree.java) +351|[Valid Parenthesis String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Valid%20Parenthesis%20String.java) +352|[Apply Discount Every n Orders](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Apply%20Discount%20Every%20n%20Orders.java) +353|[All Elements in Two Binary Search Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Elements%20in%20Two%20Binary%20Search%20Trees.java) +354|[Longest Substring Without Repeating Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Substring%20Without%20Repeating%20Characters.java) +355|[Fraction to Recurring Decimal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Fraction%20to%20Recurring%20Decimal.java) +356|[Extra Characters in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Extra%20Characters%20in%20a%20String.java) +357|[Product of the Last K Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Product%20of%20the%20Last%20K%20Numbers.java) +358|[Wiggle Sort](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Wiggle%20Sort.java) +359|[Peak Index in a Mountain Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Peak%20Index%20in%20a%20Mountain%20Array.java) +360|[Accounts Merge](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Accounts%20Merge.java) +361|[K Closest Points to Origin](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/K%20Closest%20Points%20to%20Origin.java) +362|[Largest Time for Given Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Largest%20Time%20for%20Given%20Digits.java) +363|[Fair Distribution of Cookies](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Fair%20Distribution%20of%20Cookies.java) +364|[Count Sub Islands](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Sub%20Islands.java) +365|[Reverse Words in a String II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Words%20in%20a%20String%20II.java) +366|[Find Leaves of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Leaves%20of%20Binary%20Tree.java) +367|[Partition Labels](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Partition%20Labels.java) +368|[Apply Discount to Prices](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Apply%20Discount%20to%20Prices.java) +369|[Sort An Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20An%20Array.java) +370|[Hand of Straights](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Hand%20of%20Straights.java) +371|[Angle Between Hands of a Clock](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Angle%20Between%20Hands%20of%20a%20Clock.java) +372|[Maximum Star Sum of a Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Star%20Sum%20of%20a%20Graph.java) +373|[Reorder List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reorder%20List.java) +374|[Find a Corresponding Node of a Binary Tree in a Clone of That Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20a%20Corresponding%20Node%20of%20a%20Binary%20Tree%20in%20a%20Clone%20of%20That%20Tree.java) +375|[Remove Colored Pieces if Both Neighbors are the Same Color](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Colored%20Pieces%20if%20Both%20Neighbors%20are%20the%20Same%20Color.java) +376|[Find Consecutive Integers from a Data Stream](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Consecutive%20Integers%20from%20a%20Data%20Stream.java) +377|[Find Eventual Safe States](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Eventual%20Safe%20States.java) +378|[Odd Even Linked Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Odd%20Even%20Linked%20Lists.java) +379|[Find Right Interval](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Right%20Interval.java) +380|[Dot Product of Two Sparse Vectors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Dot%20Product%20of%20Two%20Sparse%20Vectors.java) +381|[Minimum Number of Arrows to Burst Balloons](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Number%20of%20Arrows%20to%20Burst%20Balloons.java) +382|[Product of Two Run-Length Encoded Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Product%20of%20Two%20Run-Length%20Encoded%20Arrays.java) +383|[HTML Entity Parser](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/HTML%20Entity%20Parser.java) +384|[Find All Anagrams in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20All%20Anagrams%20in%20a%20String.java) +385|[Boats to Save People](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Boats%20to%20Save%20People.java) +386|[Print Words Vertically](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Print%20Words%20Vertically.java) +387|[Minimum Falling Path Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Falling%20Path%20Sum.java) +388|[Strictly Palindromic Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Strictly%20Palindromic%20Number.java) +389|[Sentence Similarity III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sentence%20Similarity%20III.java) +390|[Minimum Genetic Mutation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Genetic%20Mutation.java) +391|[Split BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Split%20BST.java) +392|[Iterator for Combination](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Iterator%20for%20Combination.java) +393|[Valid Triangle Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Valid%20Triangle%20Number.java) +394|[Keys and Rooms](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Keys%20and%20Rooms.java) +395|[Interval List Intersections](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Interval%20List%20Intersections.java) +396|[Subarray Sums Divisible by K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subarray%20Sums%20Divisible%20by%20K.java) +397|[Merge Nodes in Between Zeros](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Merge%20Nodes%20in%20Between%20Zeros.java) +398|[Maximum Level Sum of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Level%20Sum%20of%20a%20Binary%20Tree.java) +399|[Expressive Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Expressive%20Words.java) +400|[Friends Of Appropriate Ages](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Friends%20Of%20Appropriate%20Ages.java) +401|[Flatten Nested List Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Flatten%20Nested%20List%20Iterator.java) +402|[Corporate Flight Bookings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Corporate%20Flight%20Bookings.java) +403|[Unique Binary Search Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Unique%20Binary%20Search%20Trees.java) +404|[Longest Increasing Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Increasing%20Subsequence.java) +405|[Design Front Middle Back Queue](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Front%20Middle%20Back%20Queue.java) +406|[Design A Leaderboard](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20A%20Leaderboard.java) +407|[Search in Rotated Sorted Array II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20in%20Rotated%20Sorted%20Array%20II.java) +408|[Tuple With Same Product](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Tuple%20With%20Same%20Product.java) +409|[Delete Nodes And Return Forest](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Delete%20Nodes%20And%20Return%20Forest.java) +410|[The kth Factor of n](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/The%20kth%20Factor%20of%20n.java) +411|[Minimum Time Difference](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Time%20Difference.java) +412|[Maximum Length of Subarray With Positive Product](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Length%20of%20Subarray%20With%20Positive%20Product.java) +413|[Smallest Integer Divisible by K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20Integer%20Divisible%20by%20K.java) +414|[Find Players With Zero or One Losses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Players%20With%20Zero%20or%20One%20Losses.java) +415|[Min Stack](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Min%20Stack.java) +416|[Remove Zero Sum Consecutive Nodes from Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Zero%20Sum%20Consecutive%20Nodes%20from%20Linked%20List.java) +417|[Validate IP Address](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Validate%20IP%20Address.java) +418|[Reduction Operations to Make the Array Elements Equal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reduction%20Operations%20to%20Make%20the%20Array%20Elements%20Equal.java) +419|[Nearest Exit from Entrance in Maze](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Nearest%20Exit%20from%20Entrance%20in%20Maze.java) +420|[Cinema Seat Allocation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Cinema%20Seat%20Allocation.java) +421|[Delete Operation for Two Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Delete%20Operation%20for%20Two%20Strings.java) +422|[Path with Maximum Probability](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Path%20with%20Maximum%20Probability.java) +423|[Minimum Time to Complete Trips](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Time%20to%20Complete%20Trips.java) +424|[Check If All 1's Are at Least Length K Places Away](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20If%20All%201's%20Are%20at%20Least%20Length%20K%20Places%20Away.java) +425|[RLE Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/RLE%20Iterator.java) +426|[Increasing Subsequences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Increasing%20Subsequences.java) +427|[Number of Closed Islands](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Closed%20Islands.java) +428|[Number of Substrings With Only 1s](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Substrings%20With%20Only%201s.java) +429|[Delete Tree Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Delete%20Tree%20Nodes.java) +430|[Exclusive Time of Functions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Exclusive%20Time%20of%20Functions.java) +431|[Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20If%20a%20String%20Is%20a%20Valid%20Sequence%20from%20Root%20to%20Leaves%20Path%20in%20a%20Binary%20Tree.java) +432|[Count Ways To Build Good Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Ways%20To%20Build%20Good%20Strings.java) +433|[Minimum Score of a Path Between Two Cities](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Score%20of%20a%20Path%20Between%20Two%20Cities.java) +434|[Leftmost Column with at Least a One](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Leftmost%20Column%20with%20at%20Least%20a%20One.java) +435|[Subsets II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subsets%20II.java) +436|[One Edit Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/One%20Edit%20Distance.java) +437|[N-ary Tree Level Order Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/N-ary%20Tree%20Level%20Order%20Traversal.java) +438|[Design Snake Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Snake%20Game.java) +439|[Swap For Longest Repeated Character Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Swap%20For%20Longest%20Repeated%20Character%20Substring.java) +440|[Find the Student that Will Replace the Chalk](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Student%20that%20Will%20Replace%20the%20Chalk.java) +441|[LRU Cache](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/LRU%20Cache.java) +442|[Maximum Number of Groups Entering a Competition](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Groups%20Entering%20a%20Competition.java) +443|[Container With Most Water](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Container%20With%20Most%20Water.java) +444|[Subdomain Visit Count](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subdomain%20Visit%20Count.java) +445|[4Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/4Sum%20II.java) +446|[Word Ladder](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Word%20Ladder.java) +447|[Delete Node in a BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Delete%20Node%20in%20a%20BST.java) +448|[Longest Well-Performing Interval](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Well-Performing%20Interval.java) +449|[Reconstruct Original Digits from English](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reconstruct%20Original%20Digits%20from%20English.java) +450|[Single Number II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Single%20Number%20II.java) +451|[Maximum Value after Insertion](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Value%20after%20Insertion.java) +452|[Optimal Division](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Optimal%20Division.java) +453|[Continuous Subarray Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Continuous%20Subarray%20Sum.java) +454|[Number of Operations to Make Network Connected](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Operations%20to%20Make%20Network%20Connected.java) +455|[Network Delay Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Network%20Delay%20Time.java) +456|[Flip Equivalent Binary Trees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Flip%20Equivalent%20Binary%20Trees.java) +457|[String to Integer (atoi)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/String%20to%20Integer%20(atoi).java) +458|[Coin Change](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Coin%20Change.java) +459|[Max Consecutives Ones II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Max%20Consecutives%20Ones%20II.java) +460|[Kth Smallest Element in a BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Kth%20Smallest%20Element%20in%20a%20BST.java) +461|[UTF-8 Validation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/UTF-8%20Validation.java) +462|[Remove Interval](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Interval.java) +463|[Find Nearest Right Node in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Nearest%20Right%20Node%20in%20Binary%20Tree.java) +464|[Create Binary Tree From Descriptions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Create%20Binary%20Tree%20From%20Descriptions.java) +465|[Evaluate the Bracket Pairs of a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Evaluate%20the%20Bracket%20Pairs%20of%20a%20String.java) +466|[Wiggle Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Wiggle%20Subsequence.java) +467|[Random Pick Index](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Random%20Pick%20Index.java) +468|[Distribute Coins in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Distribute%20Coins%20in%20Binary%20Tree.java) +469|[Sum of Even Numbers After Queries](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20of%20Even%20Numbers%20After%20Queries.java) +470|[Path With Maximum Minimum Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Path%20With%20Maximum%20Minimum%20Value.java) +471|[Most Profit Assigning Work](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Most%20Profit%20Assigning%20Work.java) +472|[The Number of Weak Characters in the Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/The%20Number%20of%20Weak%20Characters%20in%20the%20Game.java) +473|[Partition List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Partition%20List.java) +474|[Number of Distinct Islands](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Distinct%20Islands.java) +475|[Design Circular Deque](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Circular%20Deque.java) +476|[Implement Trie (Prefix Tree)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Implement%20Trie%20(Prefix%20Tree).java) +477|[Maximize Number of Subsequences in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximize%20Number%20of%20Subsequences%20in%20a%20String.java) +478|[Max Sum of a Pair With Equal Sum of Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Max%20Sum%20of%20a%20Pair%20With%20Equal%20Sum%20of%20Digits.java) +479|[Number of Provinces](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Provinces.java) +480|[Largest BST Subtree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Largest%20BST%20Subtree.java) +481|[Range Sum Query - Mutable](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Range%20Sum%20Query%20-%20Mutable.java) +482|[Mini Parser](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Mini%20Parser.java) +483|[Number of Smooth Descent Periods of a Stock](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Smooth%20Descent%20Periods%20of%20a%20Stock.java) +484|[Maximum Distance Between a Pair of Values](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Distance%20Between%20a%20Pair%20of%20Values.java) +485|[Alert Using Same Key-Card Three or More Times in a One Hour Period](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Alert%20Using%20Same%20Key-Card%20Three%20or%20More%20Times%20in%20a%20One%20Hour%20Period.java) +486|[Linked List Components](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Linked%20List%20Components.java) +487|[Binary Tree Upside Down](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Upside%20Down.java) +488|[New 21 Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/New%2021%20Game.java) +489|[Max Increase to Keep City Skyline](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Max%20Increase%20to%20Keep%20City%20Skyline.java) +490|[Daily Temperatures](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Daily%20Temperatures.java) +491|[Binary Search Tree to Greater Sum Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Search%20Tree%20to%20Greater%20Sum%20Tree.java) +492|[Subarray Product Less Than K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subarray%20Product%20Less%20Than%20K.java) +493|[Design a Stack With Increment Operation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20a%20Stack%20With%20Increment%20Operation.java) +494|[Break a Palindrome](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Break%20a%20Palindrome.java) +495|[Maximum Size Subarray Sum Equals k](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Size%20Subarray%20Sum%20Equals%20k.java) +496|[Minimum Number of Steps to Make Two Strings Anagram II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Number%20of%20Steps%20to%20Make%20Two%20Strings%20Anagram%20II.java) +497|[Subarray Sum Equals K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subarray%20Sum%20Equals%20K.java) +498|[Car Pooling](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Car%20Pooling.java) +499|[Remove Sub-Folders from the Filesystem](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Sub-Folders%20from%20the%20Filesystem.java) +500|[Sum of Nodes with Even-Valued Grandparent](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20of%20Nodes%20with%20Even-Valued%20Grandparent.java) +501|[Check If a String Can Break Another String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20If%20a%20String%20Can%20Break%20Another%20String.java) +502|[Ternary Expression Parser](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Ternary%20Expression%20Parser.java) +503|[Generate Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Generate%20Parentheses.java) +504|[Minimum Penalty for a Shop](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Penalty%20for%20a%20Shop.java) +505|[Encode and Decode Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Encode%20and%20Decode%20Strings.java) +506|[Asteroid Collision](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Asteroid%20Collision.java) +507|[Minimum Deletion Cost to Avoid Repeating Letters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Deletion%20Cost%20to%20Avoid%20Repeating%20Letters.java) +508|[Design Phone Directory](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Phone%20Directory.java) +509|[Remove Duplicates from Sorted List II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Duplicates%20from%20Sorted%20List%20II.java) +510|[Count Nodes Equal to Sum of Descendants](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Nodes%20Equal%20to%20Sum%20of%20Descendants.java) +511|[Random Pick With Weight](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Random%20Pick%20With%20Weight.java) +512|[Maximize the Topmost Element After K Moves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximize%20the%20Topmost%20Element%20After%20K%20Moves.java) +513|[Swapping Nodes in a Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Swapping%20Nodes%20in%20a%20Linked%20List.java) +514|[Number of Subsequences That Satisfy the Given Sum Condition](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Subsequences%20That%20Satisfy%20the%20Given%20Sum%20Condition.java) +515|[Ones and Zeroes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Ones%20and%20Zeroes.java) +516|[Number of Connected Components in an Undirected Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Connected%20Components%20in%20an%20Undirected%20Graph.java) +517|[Display Table of Food Orders in a Restaurant](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Display%20Table%20of%20Food%20Orders%20in%20a%20Restaurant.java) +518|[Campus Bikes II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Campus%20Bikes%20II.java) +519|[Longest Line of Consecutive One in Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Line%20of%20Consecutive%20One%20in%20Matrix.java) +520|[Zigzag Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Zigzag%20Iterator.java) +521|[Merge In Between Linked Lists](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Merge%20In%20Between%20Linked%20Lists.java) +522|[Surrounded Regions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Surrounded%20Regions.java) +523|[Seat Reservation Manager](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Seat%20Reservation%20Manager.java) +524|[Print Immutable Linked List in Reverse](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Print%20Immutable%20Linked%20List%20in%20Reverse.java) +525|[Tree Diameter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Tree%20Diameter.java) +526|[Incremental Memory Leak](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Incremental%20Memory%20Leak.java) +527|[Lexicographically Smallest Equivalent String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lexicographically%20Smallest%20Equivalent%20String.java) +528|[Reverse Words in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Words%20in%20a%20String.java) +529|[Simplify Path](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Simplify%20Path.java) +530|[Design Underground System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Underground%20System.java) +531|[Sequential Digits](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sequential%20Digits.java) +532|[Longest Substring with At Most Two Distinct Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Substring%20with%20At%20Most%20Two%20Distinct%20Characters.java) +533|[Smallest String With Swaps](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20String%20With%20Swaps.java) +534|[Jump Game III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Jump%20Game%20III.java) +535|[Adding Spaces to a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Adding%20Spaces%20to%20a%20String.java) +536|[Shortest Path with Alternating Colors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Path%20with%20Alternating%20Colors.java) +537|[Maximum Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Subarray.java) +538|[Removing Stars From a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Removing%20Stars%20From%20a%20String.java) +539|[Find K Pairs with Smallest Sums](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20K%20Pairs%20with%20Smallest%20Sums.java) +540|[Check if There is a Valid Path in a Grid](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20if%20There%20is%20a%20Valid%20Path%20in%20a%20Grid.java) +541|[Tweet Counts Per Frequency](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Tweet%20Counts%20Per%20Frequency.java) +542|[Ugly Number II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Ugly%20Number%20II.java) +543|[Find First and Last Position of Element in Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20First%20and%20Last%20Position%20of%20Element%20in%20Sorted%20Array.java) +544|[Longest Subarray of 1's After Deleting One Element](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Subarray%20of%201's%20After%20Deleting%20One%20Element.java) +545|[Clone Binary Tree With Random Pointer](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Clone%20Binary%20Tree%20With%20Random%20Pointer.java) +546|[Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Continuous%20Subarray%20With%20Absolute%20Diff%20Less%20Than%20or%20Equal%20to%20Limit.java) +547|[Count Number of Bad Pairs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Number%20of%20Bad%20Pairs.java) +548|[Super Ugly Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Super%20Ugly%20Number.java) +549|[Add Two Numbers II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Add%20Two%20Numbers%20II.java) +550|[Implement Rand10() Using Rand7()](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Implement%20Rand10()%20Using%20Rand7().java) +551|[Minimum Deletions to Make Character Frequencies Unique](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Deletions%20to%20Make%20Character%20Frequencies%20Unique.java) +552|[Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Area%20of%20a%20Piece%20of%20Cake%20After%20Horizontal%20and%20Vertical%20Cuts.java) +553|[Array Nesting](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Array%20Nesting.java) +554|[Valid Square](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Valid%20Square.java) +555|[Find Closest Node to Given Two Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Closest%20Node%20to%20Given%20Two%20Nodes.java) +556|[Course Schedule](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Course%20Schedule.java) +557|[The k Strongest Values in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/The%20k%20Strongest%20Values%20in%20an%20Array.java) +558|[Longest Arithmetic Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Arithmetic%20Subsequence.java) +559|[Optimal Partition of String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Optimal%20Partition%20of%20String.java) +560|[Maximum Bags With Full Capacity of Rocks](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Bags%20With%20Full%20Capacity%20of%20Rocks.java) +561|[Path Sum II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Path%20Sum%20II.java) +562|[Unique Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Unique%20Paths.java) +563|[Replace Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Replace%20Words.java) +564|[Rank Teams by Votes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rank%20Teams%20by%20Votes.java) +565|[Determine if a Cell Is Reachable at a Given Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Determine%20if%20a%20Cell%20Is%20Reachable%20at%20a%20Given%20Time.java) +566|[Jump Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Jump%20Game.java) +567|[Can Convert String in K Moves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Can%20Convert%20String%20in%20K%20Moves.java) +568|[Least Number of Unique Integers after K Removals](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Least%20Number%20of%20Unique%20Integers%20after%20K%20Removals.java) +569|[Sum of Absolute Differences in a Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20of%20Absolute%20Differences%20in%20a%20Sorted%20Array.java) +570|[Determine the Minimum Sum of a k-avoiding Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Determine%20the%20Minimum%20Sum%20of%20a%20k-avoiding%20Array.java) +571|[Linked List Random Node](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Linked%20List%20Random%20Node.java) +572|[Valid Tic-Tac-Toe State](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Valid%20Tic-Tac-Toe%20State.java) +573|[Increasing Triplet Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Increasing%20Triplet%20Subsequence.java) +574|[Partition Equal Subset Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Partition%20Equal%20Subset%20Sum.java) +575|[Range Addition](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Range%20Addition.java) +576|[Next Greater Numerically Balanced Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Next%20Greater%20Numerically%20Balanced%20Number.java) +577|[Interleaving String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Interleaving%20String.java) +578|[String Compression](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/String%20Compression.java) +579|[Insert Into a Cyclic Sorted List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insert%20Into%20a%20Cyclic%20Sorted%20List.java) +580|[Count Submatrices With All Ones](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Submatrices%20With%20All%20Ones.java) +581|[Shuffle an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shuffle%20an%20Array.java) +582|[Battleships in a board](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Battleships%20in%20a%20board.java) +583|[Shortest Path in Binary Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Path%20in%20Binary%20Matrix.java) +584|[Brace Expansion](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Brace%20Expansion.java) +585|[Complex Number Multiplication](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Complex%20Number%20Multiplication.java) +586|[Queries on a Permutation With Key](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Queries%20on%20a%20Permutation%20With%20Key.java) +587|[Find Duplicate Subtrees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Duplicate%20Subtrees.java) +588|[Maximum Ice Cream Bars](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Ice%20Cream%20Bars.java) +589|[Recover Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Recover%20Binary%20Search%20Tree.java) +590|[My Calendar I](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/My%20Calendar%20I.java) +591|[Reorder Routes to Make All Paths Lead to the City Zero](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reorder%20Routes%20to%20Make%20All%20Paths%20Lead%20to%20the%20City%20Zero.java) +592|[Maximize the Confusion of an Exam](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximize%20the%20Confusion%20of%20an%20Exam.java) +593|[Evaluate Reverse Polish Notation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Evaluate%20Reverse%20Polish%20Notation.java) +594|[Maximum Width Ramp](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Width%20Ramp.java) +595|[Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Sub-arrays%20of%20Size%20K%20and%20Average%20Greater%20than%20or%20Equal%20to%20Threshold.java) +596|[Range Sum of Sorted Subarray Sums](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Range%20Sum%20of%20Sorted%20Subarray%20Sums.java) +597|[Find The Original Array of Prefix Xor](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20The%20Original%20Array%20of%20Prefix%20Xor.java) +598|[Bomb Enemy](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Bomb%20Enemy.java) +599|[Find Center of Star Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Center%20of%20Star%20Graph.java) +600|[Add Bold Tag in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Add%20Bold%20Tag%20in%20String.java) +601|[Reverse Linked List II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Linked%20List%20II.java) +602|[Permutation in String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Permutation%20in%20String.java) +603|[Sum of Numbers With Units Digit K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20of%20Numbers%20With%20Units%20Digit%20K.java) +604|[Two Sum II - Input Array Is Sorted](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Two%20Sum%20II%20-%20Input%20Array%20Is%20Sorted.java) +605|[Maximum Number of Events That Can Be Attended](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Number%20of%20Events%20That%20Can%20Be%20Attended.java) +606|[Shortest Word Distance III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Word%20Distance%20III.java) +607|[Sender With Largest Word Count](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sender%20With%20Largest%20Word%20Count.java) +608|[Short Encoding of Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Short%20Encoding%20of%20Words.java) +609|[Serialize and Deserialize BST](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Serialize%20and%20Deserialize%20BST.java) +610|[Remove All Ones With Row and Column Flips II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20All%20Ones%20With%20Row%20and%20Column%20Flips%20II.java) +611|[Minimum Domino Rotations For Equal Row](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Domino%20Rotations%20For%20Equal%20Row.java) +612|[132 Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/132%20Pattern.java) +613|[Remove All Adjacent Duplicates in String II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20All%20Adjacent%20Duplicates%20in%20String%20II.java) +614|[Insertion Sort List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insertion%20Sort%20List.java) +615|[Length of the Longest Alphabetical Continuous Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Length%20of%20the%20Longest%20Alphabetical%20Continuous%20Substring.java) +616|[Find the Duplicate Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Duplicate%20Number.java) +617|[Replace Elements in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Replace%20Elements%20in%20an%20Array.java) +618|[Design Twitter](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Twitter.java) +619|[Last Moment Before All Ants Fall Out of a Plank](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Last%20Moment%20Before%20All%20Ants%20Fall%20Out%20of%20a%20Plank.java) +620|[Sentence Similarity II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sentence%20Similarity%20II.java) +621|[Count Number of Distinct Integers After Reverse Operations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Number%20of%20Distinct%20Integers%20After%20Reverse%20Operations.java) +622|[Find the Index of the First Occurrence in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Index%20of%20the%20First%20Occurrence%20in%20a%20String.java) +623|[Last Stone Weight II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Last%20Stone%20Weight%20II.java) +624|[Rectangle Area](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rectangle%20Area.java) +625|[My Calendar II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/My%20Calendar%20II.java) +626|[Find All Possible Recipes from Given Supplies](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20All%20Possible%20Recipes%20from%20Given%20Supplies.java) +627|[Maximum Value at a Given Index in a Bounded Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Value%20at%20a%20Given%20Index%20in%20a%20Bounded%20Array.java) +628|[Number of Distinct Substrings in a String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Distinct%20Substrings%20in%20a%20String.java) +629|[Search Suggestions System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20Suggestions%20System.java) +630|[Subrectangle Queries](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Subrectangle%20Queries.java) +631|[Sort the Matrix Diagonally](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20the%20Matrix%20Diagonally.java) +632|[Convert Sorted List to Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Convert%20Sorted%20List%20to%20Binary%20Search%20Tree.java) +633|[Count Nodes Equal to Average of Subtree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Nodes%20Equal%20to%20Average%20of%20Subtree.java) +634|[Bulb Switcher](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Bulb%20Switcher.java) +635|[Verify Preorder Serialization of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Verify%20Preorder%20Serialization%20of%20a%20Binary%20Tree.java) +636|[Minimum Speed to Arrive on Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Speed%20to%20Arrive%20on%20Time.java) +637|[Inorder Successor in BST II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Inorder%20Successor%20in%20BST%20II.java) +638|[Detonate the Maximum Bombs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Detonate%20the%20Maximum%20Bombs.java) +639|[Add Minimum Number of Rungs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Add%20Minimum%20Number%20of%20Rungs.java) +640|[Lexicographically Smallest String After Substring Operation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lexicographically%20Smallest%20String%20After%20Substring%20Operation.java) +641|[Find the City With the Smallest Number of Neighbors at a Threshold Distance](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20City%20With%20the%20Smallest%20Number%20of%20Neighbors%20at%20a%20Threshold%20Distance.java) +642|[Node With Highest Edge Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Node%20With%20Highest%20Edge%20Score.java) +643|[Output Contest Matches](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Output%20Contest%20Matches.java) +644|[Design an Expression Tree With Evaluate Function](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20an%20Expression%20Tree%20With%20Evaluate%20Function.java) +645|[H-Index](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/H-Index.java) +646|[Best Time to Buy and Sell Stock with Cooldown](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20with%20Cooldown.java) +647|[Rabbits in Forest](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rabbits%20in%20Forest.java) +648|[Count Univalue Subtrees](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Univalue%20Subtrees.java) +649|[Find Elements in a Contaminated Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Elements%20in%20a%20Contaminated%20Binary%20Tree.java) +650|[Next Greater Node In Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Next%20Greater%20Node%20In%20Linked%20List.java) +651|[Maximum Nesting Depth of Two Valid Parentheses Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Nesting%20Depth%20of%20Two%20Valid%20Parentheses%20Strings.java) +652|[Find and Replace Pattern](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20and%20Replace%20Pattern.java) +653|[Design File System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20File%20System.java) +654|[Determine if Two Strings Are Close](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Determine%20if%20Two%20Strings%20Are%20Close.java) +655|[Maximum Absolute Sum of Any Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Absolute%20Sum%20of%20Any%20Subarray.java) +656|[Number of Pairs of Interchangeable Rectangles](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Pairs%20of%20Interchangeable%20Rectangles.java) +657|[Kth Largest Element in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Kth%20Largest%20Element%20in%20an%20Array.java) +658|[The Number of Full Rounds You Have Played](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/The%20Number%20of%20Full%20Rounds%20You%20Have%20Played.java) +659|[Snapshot Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Snapshot%20Array.java) +660|[Top K Frequent Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Top%20K%20Frequent%20Elements.java) +661|[Smallest Subtree with all the Deepest Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20Subtree%20with%20all%20the%20Deepest%20Nodes.java) +662|[Maximal Network Rank](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximal%20Network%20Rank.java) +663|[Rearrange Array Elements by Sign](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rearrange%20Array%20Elements%20by%20Sign.java) +664|[Kth Smallest Element in a Sorted Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Kth%20Smallest%20Element%20in%20a%20Sorted%20Matrix.java) +665|[Two City Scheduling](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Two%20City%20Scheduling.java) +666|[Minimum Score Triangulation of Polygon](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Score%20Triangulation%20of%20Polygon.java) +667|[Binary Tree Coloring Game](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Coloring%20Game.java) +668|[Maximum Difference Between Node and Ancestor](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Difference%20Between%20Node%20and%20Ancestor.java) +669|[Sum of Beauty of All Substrings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sum%20of%20Beauty%20of%20All%20Substrings.java) +670|[Push Dominoes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Push%20Dominoes.java) +671|[Combination Sum III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Combination%20Sum%20III.java) +672|[Find K Closest Elements](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20K%20Closest%20Elements.java) +673|[01 Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/01%20Matrix.java) +674|[Clone Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Clone%20Graph.java) +675|[Longest Palindromic Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Palindromic%20Substring.java) +676|[Robot Bounded In Circle](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Robot%20Bounded%20In%20Circle.java) +677|[Minimum Deletions to Make Array Beautiful](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Deletions%20to%20Make%20Array%20Beautiful.java) +678|[Koko Eating Bananas](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Koko%20Eating%20Bananas.java) +679|[Statistics from a Large Sample](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Statistics%20from%20a%20Large%20Sample.java) +680|[Insert Delete GetRandom O(1)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insert%20Delete%20GetRandom%20O(1).java) +681|[Longest Substring with At Most K Distinct Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Substring%20with%20At%20Most%20K%20Distinct%20Characters.java) +682|[Minimum Swaps to Group All 1's Together](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Swaps%20to%20Group%20All%201's%20Together.java) +683|[Path Sum III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Path%20Sum%20III.java) +684|[Snakes and Ladders](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Snakes%20and%20Ladders.java) +685|[Longest Palindromic Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Palindromic%20Subsequence.java) +686|[Longest String Chain](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20String%20Chain.java) +687|[Buildings With an Ocean View](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Buildings%20With%20an%20Ocean%20View.java) +688|[Sort Transformed Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20Transformed%20Array.java) +689|[Search in a Sorted Array of Unknown Size](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20in%20a%20Sorted%20Array%20of%20Unknown%20Size.java) +690|[Minimize Product Sum of Two Arrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimize%20Product%20Sum%20of%20Two%20Arrays.java) +691|[Count Complete Tree Nodes](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Complete%20Tree%20Nodes.java) +692|[Minesweeper](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minesweeper.java) +693|[Best Time to Buy and Sell Stock with Transaction Fee](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20with%20Transaction%20Fee.java) +694|[Online Election](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Online%20Election.java) +695|[Minimum Cost For Tickets](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Cost%20For%20Tickets.java) +696|[Find K-Length Substrings With No Repeated Characters](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20K-Length%20Substrings%20With%20No%20Repeated%20Characters.java) +697|[Pow(x, n)](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Pow(x,%20n).java) +698|[Construct String With Repeat Limit](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Construct%20String%20With%20Repeat%20Limit.java) +699|[Word Break](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Word%20Break.java) +700|[Reverse Odd Levels of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Odd%20Levels%20of%20Binary%20Tree.java) +701|[Design SQL](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20SQL.java) +702|[Find the Kth Largest Integer in the Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Kth%20Largest%20Integer%20in%20the%20Array.java) +703|[Flatten Binary Tree to Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Flatten%20Binary%20Tree%20to%20Linked%20List.java) +704|[Sort Colors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20Colors.java) +705|[Best Time to Buy and Sell Stock II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20II.java) +706|[Longest Absolute File Path](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Longest%20Absolute%20File%20Path.java) +707|[Count Unreachable Pairs of Nodes in an Undirected Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Unreachable%20Pairs%20of%20Nodes%20in%20an%20Undirected%20Graph.java) +708|[Prison Cells After N Days](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Prison%20Cells%20After%20N%20Days.java) +709|[Insert into a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insert%20into%20a%20Binary%20Search%20Tree.java) +710|[Binary Search Tree Iterator II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Search%20Tree%20Iterator%20II.java) +711|[Course Schedule II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Course%20Schedule%20II.java) +712|[Remove Duplicates From Sorted Array II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Duplicates%20From%20Sorted%20Array%20II.java) +713|[Shortest Bridge](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Bridge.java) +714|[Binary Search Tree Iterator](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Search%20Tree%20Iterator.java) +715|[Find Duplicate File in System](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Duplicate%20File%20in%20System.java) +716|[Insufficient Nodes in Root to Leaf Paths](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Insufficient%20Nodes%20in%20Root%20to%20Leaf%20Paths.java) +717|[Divide Array in Sets of K Consecutive Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Divide%20Array%20in%20Sets%20of%20K%20Consecutive%20Numbers.java) +718|[Check Completeness of a Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20Completeness%20of%20a%20Binary%20Tree.java) +719|[Two Sum BSTs](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Two%20Sum%20BSTs.java) +720|[Count Sorted Vowel Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Sorted%20Vowel%20Strings.java) +721|[Check If a String Contains All Binary Codes of Size K](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Check%20If%20a%20String%20Contains%20All%20Binary%20Codes%20of%20Size%20K.java) +722|[Contains Duplicate III](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Contains%20Duplicate%20III.java) +723|[Stock Price Fluctuation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Stock%20Price%20Fluctuation.java) +724|[Spiral Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Spiral%20Matrix.java) +725|[Next Closest Time](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Next%20Closest%20Time.java) +726|[Find the Maximum Divisibility Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Maximum%20Divisibility%20Score.java) +727|[Group Shifted Strings](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Group%20Shifted%20Strings.java) +728|[Array Circular Loop](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Array%20Circular%20Loop.java) +729|[ZigZag Conversion](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/ZigZag%20Conversion.java) +730|[Find the Score of All Prefixes of an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Score%20of%20All%20Prefixes%20of%20an%20Array.java) +731|[Number of Matching Subsequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Matching%20Subsequence.java) +732|[All Paths From Source to Target](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Paths%20From%20Source%20to%20Target.java) +733|[Spiral Matrix II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Spiral%20Matrix%20II.java) +734|[Design Authentication Manager](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Authentication%20Manager.java) +735|[Minimum Operations to Make a Special Number](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Operations%20to%20Make%20a%20Special%20Number.java) +736|[People Whose List of Favorite Companies Is Not a Subset of Another List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/People%20Whose%20List%20of%20Favorite%20Companies%20Is%20Not%20a%20Subset%20of%20Another%20List.java) +737|[Number of Enclaves](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Enclaves.java) +738|[Sort the Students by Their Kth Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Sort%20the%20Students%20by%20Their%20Kth%20Score.java) +739|[Number of Zero-Filled Subarrays](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Number%20of%20Zero-Filled%20Subarrays.java) +740|[Bag of Tokens](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Bag%20of%20Tokens.java) +741|[Binary Tree Longest Consecutive Sequence](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Longest%20Consecutive%20Sequence.java) +742|[All Paths from Source Lead to Destination](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Paths%20from%20Source%20Lead%20to%20Destination.java) +743|[Trim a Binary Search Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Trim%20a%20Binary%20Search%20Tree.java) +744|[Lexicographical Numbers](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Lexicographical%20Numbers.java) +745|[Minimum Time to Make Rope Colorful](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Minimum%20Time%20to%20Make%20Rope%20Colorful.java) +746|[Rotate Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rotate%20Array.java) +747|[Unique Word Abbrevation](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Unique%20Word%20Abbrevation.java) +748|[Binary Tree Right Side View](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Binary%20Tree%20Right%20Side%20View.java) +749|[Solving Questions With Brainpower](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Solving%20Questions%20With%20Brainpower.java) +750|[All Nodes Distance K in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Nodes%20Distance%20K%20in%20Binary%20Tree.java) +751|[Queue Reconstruction By Height](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Queue%20Reconstruction%20By%20Height.java) +752|[Step-By-Step Directions From a Binary Tree Node to Another](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Step-By-Step%20Directions%20From%20a%20Binary%20Tree%20Node%20to%20Another.java) +753|[Medium](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Medium.md) +754|[Meeting Rooms II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Meeting%20Rooms%20II.java) +755|[Maximum Binary Tree II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Binary%20Tree%20II.java) +756|[Maximum Subsequence Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Subsequence%20Score.java) +757|[Smallest String With A Given Numeric Value](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Smallest%20String%20With%20A%20Given%20Numeric%20Value.java) +758|[Print Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Print%20Binary%20Tree.java) +759|[Find Missing Observations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20Missing%20Observations.java) +760|[Restore IP Address](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Restore%20IP%20Address.java) +761|[Water & Jug Problem](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Water%20&%20Jug%20Problem.java) +762|[Maximum Width of Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Width%20of%20Binary%20Tree.java) +763|[Target Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Target%20Sum.java) +764|[Find the Longest Semi-Repetitive Substring](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Longest%20Semi-Repetitive%20Substring.java) +765|[Synonymous Sentences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Synonymous%20Sentences.java) +766|[Top K Frequent Words](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Top%20K%20Frequent%20Words.java) +767|[Convert an Array Into a 2D Array With Conditions](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Convert%20an%20Array%20Into%20a%202D%20Array%20With%20Conditions.java) +768|[Shortest Unsorted Continuous Subarray](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Unsorted%20Continuous%20Subarray.java) +769|[Satisfiability of Equality Equations](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Satisfiability%20of%20Equality%20Equations.java) +770|[All Ancestors of a Node in a Directed Acyclic Graph](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/All%20Ancestors%20of%20a%20Node%20in%20a%20Directed%20Acyclic%20Graph.java) +771|[Maximize Distance to Closest Person](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximize%20Distance%20to%20Closest%20Person.java) +772|[Design Tic-Tac-Toe](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Design%20Tic-Tac-Toe.java) +773|[H-Index II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/H-Index%20II.java) +774|[3Sum](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/3Sum.java) +775|[Maximum Consecutive Floors Without Special Floors](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20Consecutive%20Floors%20Without%20Special%20Floors.java) +776|[Reorganize String](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reorganize%20String.java) +777|[Reverse Substrings Between Each Pair of Parentheses](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Reverse%20Substrings%20Between%20Each%20Pair%20of%20Parentheses.java) +778|[Maximum XOR of Two Numbers in an Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Maximum%20XOR%20of%20Two%20Numbers%20in%20an%20Array.java) +779|[Count Good Nodes in Binary Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Good%20Nodes%20in%20Binary%20Tree.java) +780|[Find the Minimum and Maximum Number of Nodes Between Critical Points](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Find%20the%20Minimum%20and%20Maximum%20Number%20of%20Nodes%20Between%20Critical%20Points.java) +781|[Missing Element in Sorted Array](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Missing%20Element%20in%20Sorted%20Array.java) +782|[Even Odd Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Even%20Odd%20Tree.java) +783|[Rearrange Array to Maximize Prefix Score](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Rearrange%20Array%20to%20Maximize%20Prefix%20Score.java) +784|[Search for a range](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20for%20a%20range.java) +785|[Count Collisions on a Road](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Count%20Collisions%20on%20a%20Road.java) +786|[Numbers With Same Consecutive Differences](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Numbers%20With%20Same%20Consecutive%20Differences.java) +787|[Remove Duplicates From an Unsorted Linked List](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Remove%20Duplicates%20From%20an%20Unsorted%20Linked%20List.java) +788|[Populating Next Right Pointers in Each Node II](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Populating%20Next%20Right%20Pointers%20in%20Each%20Node%20II.java) +789|[Construct Binary Search Tree from Preorder Traversal](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Construct%20Binary%20Search%20Tree%20from%20Preorder%20Traversal.java) +790|[Shortest Completing Word](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Shortest%20Completing%20Word.java) +791|[Search a 2D Matrix](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Search%20a%202D%20Matrix.java) +792|[Add One Row to Tree](https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/Medium/Add%20One%20Row%20to%20Tree.java) diff --git a/Medium/RLE Iterator.java b/Medium/RLE Iterator.java index 2c1f7683..7baf4e97 100644 --- a/Medium/RLE Iterator.java +++ b/Medium/RLE Iterator.java @@ -1,42 +1,31 @@ class RLEIterator { - int[] arr; - int idx; - int len; - public RLEIterator(int[] A) { - arr = A; - idx = 0; - len = A.length; - } - - public int next(int n) { - while (idx < len - 1 && (arr[idx] - n) < 0) { - n -= arr[idx] > 0 ? arr[idx] : 0; - updateIdx(); - - if (idx >= len - 1) { - return -1; - } - } - - if (idx < len - 1 && arr[idx] > 0) { - if (arr[idx] - n >= 0) { - int temp = arr[idx+1]; - arr[idx] -= n; - - return temp; - } - } - + + int[] encoding; + int currCounterIdx; + + public RLEIterator(int[] encoding) { + this.encoding = encoding; + this.currCounterIdx = 0; + } + + public int next(int n) { + while (n > 0) { + while (this.encoding[this.currCounterIdx] == 0 && this.currCounterIdx + 2 < this.encoding.length) { + this.currCounterIdx += 2; + } + if (this.encoding[this.currCounterIdx] == 0) { return -1; + } + int diff = Math.min(this.encoding[this.currCounterIdx], n); + this.encoding[this.currCounterIdx] -= diff; + n -= diff; } - - private void updateIdx() { - idx += 2; - } + return this.encoding[this.currCounterIdx + 1]; + } } /** * Your RLEIterator object will be instantiated and called as such: - * RLEIterator obj = new RLEIterator(A); + * RLEIterator obj = new RLEIterator(encoding); * int param_1 = obj.next(n); */ diff --git a/Medium/Random Pick Index.java b/Medium/Random Pick Index.java new file mode 100644 index 00000000..e6ac8299 --- /dev/null +++ b/Medium/Random Pick Index.java @@ -0,0 +1,27 @@ +class Solution { + int[] nums; + Random rand; + public Solution(int[] nums) { + this.nums = nums; + rand = new Random(); + } + + public int pick(int target) { + int count = 0; + int res = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] == target) { + if (rand.nextInt(++count) == 0) { + res = i; + } + } + } + return res; + } +} + +/** + * Your Solution object will be instantiated and called as such: + * Solution obj = new Solution(nums); + * int param_1 = obj.pick(target); + */ diff --git a/Medium/Random Pick With Weight.java b/Medium/Random Pick With Weight.java index f5924c0c..e620ec63 100644 --- a/Medium/Random Pick With Weight.java +++ b/Medium/Random Pick With Weight.java @@ -1,34 +1,31 @@ class Solution { - - List prefixSum; - int total; - Random rand; - public Solution(int[] w) { - prefixSum = new ArrayList<>(); - total = 0; - for (int i=0; i= prefixSum.get(mid)) { - i = mid + 1; - } - else { - j = mid; - } - } - - return j; + this.totalPrefixSum = currPrefixSum; + } + + public int pickIndex() { + double randomTarget = this.totalPrefixSum * Math.random(); + int left = 0; + int right = this.prefixSum.length; + while (left < right) { + int mid = left + (right - left) / 2; + if (randomTarget > this.prefixSum[mid]) { + left = mid + 1; + } else { + right = mid; + } } + return left; + } } /** diff --git a/Medium/Range Sum Query - Mutable.java b/Medium/Range Sum Query - Mutable.java new file mode 100644 index 00000000..d57769f2 --- /dev/null +++ b/Medium/Range Sum Query - Mutable.java @@ -0,0 +1,55 @@ +class NumArray { + + private BIT bit; + private int[] nums; + + public NumArray(int[] nums) { + this.bit = new BIT(nums.length); + this.nums = nums; + for (int i = 0; i < nums.length; i++) { + this.bit.update(i + 1, nums[i]); + } + } + + public void update(int index, int val) { + int delta = val - nums[index]; + this.bit.update(index + 1, delta); + this.nums[index] = val; + } + + public int sumRange(int left, int right) { + return this.bit.query(right + 1) - this.bit.query(left); + } + + private static class BIT { + + private int[] sum; + + public BIT(int n) { + this.sum = new int[n + 1]; + } + + private void update(int idx, int delta) { + while (idx < sum.length) { + sum[idx] += delta; + idx += (idx & -idx); + } + } + + private int query(int idx) { + int result = 0; + while (idx > 0) { + result += sum[idx]; + idx -= (idx & -idx); + } + return result; + } + } +} + +/** + * Your NumArray object will be instantiated and called as such: + * NumArray obj = new NumArray(nums); + * obj.update(index,val); + * int param_2 = obj.sumRange(left,right); + */ diff --git a/Medium/Range Sum Query 2D-Immutable.java b/Medium/Range Sum Query 2D-Immutable.java index ad98e625..bd30c3e1 100644 --- a/Medium/Range Sum Query 2D-Immutable.java +++ b/Medium/Range Sum Query 2D-Immutable.java @@ -1,45 +1,31 @@ class NumMatrix { - int[][] dp; - int[][] matrix; - public NumMatrix(int[][] matrix) { - this.matrix = matrix; - if (matrix.length == 0) { - dp = new int[0][0]; - return; - } - - dp = new int[matrix.length][matrix[0].length]; - fillDpArray(); - - for (int[] arr : dp) { - System.out.println(Arrays.toString(arr)); - } - } - - private void fillDpArray() { - int row = matrix.length; - int col = matrix[0].length; - - for (int i = 0; i < row; i++) { - int sum = 0; - for (int j = 0; j < col; j++) { - sum += this.matrix[i][j]; - dp[i][j] = sum; - } - } + + int rows; + int cols; + int[][] rowLevelSum; + public NumMatrix(int[][] matrix) { + this.rows = matrix.length; + this.cols = matrix[0].length; + this.rowLevelSum = new int[rows][cols]; + for (int i = 0; i < rows; i++) { + int sum = 0; + for (int j = 0; j < cols; j++) { + sum += matrix[i][j]; + this.rowLevelSum[i][j] = sum; + } } - - public int sumRegion(int row1, int col1, int row2, int col2) { - int currSum = 0; - for (int i = row1; i <= row2; i++) { - currSum += dp[i][col2]; - if (col1 != 0) { - currSum -= dp[i][col1 - 1]; - } - } - - return currSum; + } + + public int sumRegion(int row1, int col1, int row2, int col2) { + int sum = 0; + for (int i = row1; i <= row2; i++) { + sum += rowLevelSum[i][col2]; + if (col1 > 0) { + sum -= rowLevelSum[i][col1 - 1]; + } } + return sum; + } } /** diff --git a/Medium/Range Sum of Sorted Subarray Sums.java b/Medium/Range Sum of Sorted Subarray Sums.java new file mode 100644 index 00000000..9b7504b7 --- /dev/null +++ b/Medium/Range Sum of Sorted Subarray Sums.java @@ -0,0 +1,23 @@ +class Solution { + private static final int MOD = 1000_000_007; + + public int rangeSum(int[] nums, int n, int left, int right) { + Queue pq = new PriorityQueue<>(Comparator.comparingInt(o -> o[0])); + for (int i = 0; i < n; i++) { + pq.add(new int[]{nums[i], i + 1}); + } + int sum = 0; + for (int i = 1; i <= right; i++) { + int[] removed = pq.poll(); + if (i >= left) { + sum = (sum + removed[0]) % MOD; + } + if (removed[1] < n) { + removed[0] = removed[0] + nums[removed[1]]; + removed[1]++; + pq.add(removed); + } + } + return sum; + } +} diff --git a/Medium/Rank Teams by Votes.java b/Medium/Rank Teams by Votes.java new file mode 100644 index 00000000..e3cf32af --- /dev/null +++ b/Medium/Rank Teams by Votes.java @@ -0,0 +1,28 @@ +class Solution { + public String rankTeams(String[] votes) { + Map> map = new HashMap<>(); + int positionCount = votes[0].length(); + for (String vote : votes) { + for (int i = 0; i < vote.length(); i++) { + char c = vote.charAt(i); + map.computeIfAbsent(c, k -> new HashMap<>()); + map.get(c).put(i, map.get(c).getOrDefault(i, 0) + 1); + } + } + PriorityQueue priorityQueue = new PriorityQueue<>((o1, o2) -> { + for (int i = 0; i < positionCount; i++) { + int c = map.get(o2).getOrDefault(i, 0) - map.get(o1).getOrDefault(i, 0); + if (c != 0) { + return c; + } + } + return o1 - o2; + }); + priorityQueue.addAll(map.keySet()); + StringBuilder sb = new StringBuilder(); + while (!priorityQueue.isEmpty()) { + sb.append(priorityQueue.poll()); + } + return sb.toString(); + } +} diff --git a/Medium/Reachable Nodes With Restrictions.java b/Medium/Reachable Nodes With Restrictions.java new file mode 100644 index 00000000..2a9b6f85 --- /dev/null +++ b/Medium/Reachable Nodes With Restrictions.java @@ -0,0 +1,28 @@ +class Solution { + public int reachableNodes(int n, int[][] edges, int[] restricted) { + Map> graph = new HashMap<>(); + for (int[] edge : edges) { + graph.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(edge[1]); + graph.computeIfAbsent(edge[1], k -> new ArrayList<>()).add(edge[0]); + } + Set restrictedSet = Arrays.stream(restricted).boxed().collect(Collectors.toSet()); + Set visited = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add(0); + visited.add(0); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int node = queue.remove(); + for (Integer neighbor : graph.getOrDefault(node, new ArrayList<>())) { + if (restrictedSet.contains(neighbor) || visited.contains(neighbor)) { + continue; + } + queue.add(neighbor); + visited.add(neighbor); + } + } + } + return visited.size(); + } +} diff --git a/Medium/Rearrange Array Elements by Sign.java b/Medium/Rearrange Array Elements by Sign.java new file mode 100644 index 00000000..83857f13 --- /dev/null +++ b/Medium/Rearrange Array Elements by Sign.java @@ -0,0 +1,18 @@ +class Solution { + public int[] rearrangeArray(int[] nums) { + int n = nums.length; + int[] result = new int[n]; + int posIndex = 0; + int negIndex = 1; + for (int i = 0; i < n; i++) { + if (nums[i] > 0) { + result[posIndex] = nums[i]; + posIndex += 2; + } else { + result[negIndex] = nums[i]; + negIndex += 2; + } + } + return result; + } +} diff --git a/Medium/Rearrange Array to Maximize Prefix Score.java b/Medium/Rearrange Array to Maximize Prefix Score.java new file mode 100644 index 00000000..6f52eda8 --- /dev/null +++ b/Medium/Rearrange Array to Maximize Prefix Score.java @@ -0,0 +1,15 @@ +class Solution { + public int maxScore(int[] nums) { + Arrays.sort(nums); + long currPrefixSum = 0; + int prefixScore = 0; + for (int i = nums.length - 1; i >= 0; i--) { + currPrefixSum += nums[i]; + if (currPrefixSum <= 0) { + break; + } + prefixScore++; + } + return prefixScore; + } +} diff --git a/Medium/Reconstruct Original Digits from English.java b/Medium/Reconstruct Original Digits from English.java index 77f44e20..606452a6 100644 --- a/Medium/Reconstruct Original Digits from English.java +++ b/Medium/Reconstruct Original Digits from English.java @@ -1,31 +1,30 @@ class Solution { - public String originalDigits(String s) { - int[] count = new int[26]; - for (char c : s.toCharArray()) { - count[c - 'a']++; - } - - int[] out = new int[10]; - - out[0] = count['z' - 'a']; - out[2] = count['w' - 'a']; - out[4] = count['u' - 'a']; - out[6] = count['x' - 'a']; - out[8] = count['g' - 'a']; - out[3] = count['h' - 'a'] - out[8]; - out[5] = count['f' - 'a'] - out[4]; - out[7] = count['s' - 'a'] - out[6]; - out[9] = count['i' - 'a'] - out[5] - out[6] - out[8]; - out[1] = count['n' - 'a'] - out[7] - 2 * out[9]; - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < 10; i++) { - for (int j = 0; j < out[i]; j++) { - sb.append(i); - } - } - - return sb.toString(); + public String originalDigits(String s) { + int[] count = new int[10]; + for (int i = 0; i < s.length(); i++){ + char c = s.charAt(i); + if (c == 'z') count[0]++; + if (c == 'w') count[2]++; + if (c == 'x') count[6]++; + if (c == 's') count[7]++; //7-6 + if (c == 'g') count[8]++; + if (c == 'u') count[4]++; + if (c == 'f') count[5]++; //5-4 + if (c == 'h') count[3]++; //3-8 + if (c == 'i') count[9]++; //9-8-5-6 + if (c == 'o') count[1]++; //1-0-2-4 } + count[7] -= count[6]; + count[5] -= count[4]; + count[3] -= count[8]; + count[9] = count[9] - count[8] - count[5] - count[6]; + count[1] = count[1] - count[0] - count[2] - count[4]; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i <= 9; i++){ + for (int j = 0; j < count[i]; j++){ + sb.append(i); + } + } + return sb.toString(); + } } diff --git a/Medium/Recover Binary Search Tree.java b/Medium/Recover Binary Search Tree.java new file mode 100644 index 00000000..8a3a133f --- /dev/null +++ b/Medium/Recover Binary Search Tree.java @@ -0,0 +1,43 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public void recoverTree(TreeNode root) { + TreeNode nodeOne = null; + TreeNode nodeTwo = null; + TreeNode prevNode = null; + Stack stack = new Stack<>(); + while (root != null || !stack.isEmpty()) { + while (root != null) { + stack.push(root); + root = root.left; + } + if (!stack.isEmpty()) { + root = stack.pop(); + if (nodeOne == null && prevNode != null && prevNode.val > root.val) { + nodeOne = prevNode; + } + if (nodeOne != null && prevNode.val > root.val) { + nodeTwo = root; + } + prevNode = root; + root = root.right; + } + } + int tempValue = nodeOne.val; + nodeOne.val = nodeTwo.val; + nodeTwo.val = tempValue; + } +} diff --git a/Medium/Rectangle Area.java b/Medium/Rectangle Area.java new file mode 100644 index 00000000..fbf0ca5f --- /dev/null +++ b/Medium/Rectangle Area.java @@ -0,0 +1,15 @@ +class Solution { + public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) { + int areaOfSqrA = (C - A) * (D - B); + int areaOfSqrB = (G - E) * (H - F); + int left = Math.max(A, E); + int right = Math.min(G, C); + int bottom = Math.max(F, B); + int top = Math.min(D, H); + int overlap = 0; + if(right > left && top > bottom) { + overlap = (right - left) * (top - bottom); + } + return areaOfSqrA + areaOfSqrB - overlap; + } +} diff --git a/Medium/Rectangle Overlap.java b/Medium/Rectangle Overlap.java deleted file mode 100644 index 26b038d2..00000000 --- a/Medium/Rectangle Overlap.java +++ /dev/null @@ -1,20 +0,0 @@ -class Solution { - public boolean isRectangleOverlap(int[] rec1, int[] rec2) { - int rec1X1 = rec1[0]; - int rec1X2 = rec1[2]; - int rec1Y1 = rec1[1]; - int rec1Y2 = rec1[3]; - - int rec2X1 = rec2[0]; - int rec2X2 = rec2[2]; - int rec2Y1 = rec2[1]; - int rec2Y2 = rec2[3]; - - return !( - rec1X1 >= rec2X2 || - rec1X2 <= rec2X1 || - rec1Y2 <= rec2Y1 || - rec1Y1 >= rec2Y2 - ); - } -} diff --git a/Medium/Reduce Array Size to The Half.java b/Medium/Reduce Array Size to The Half.java new file mode 100644 index 00000000..82572571 --- /dev/null +++ b/Medium/Reduce Array Size to The Half.java @@ -0,0 +1,27 @@ +class Solution { + public int minSetSize(int[] arr) { + Map map = new HashMap<>(); + int maxCount = 0; + for (int num : arr) { + map.put(num, map.getOrDefault(num, 0) + 1); + maxCount = Math.max(maxCount, map.get(num)); + } + int[] bucket = new int[maxCount + 1]; + for (int count : map.values()) { + bucket[count]++; + } + int n = arr.length; + int setSize = 0; + int bucketIdx = bucket.length - 1; + while (n > arr.length / 2) { + if (bucket[bucketIdx] > 0) { + setSize++; + n -= bucketIdx; + bucket[bucketIdx]--; + } else { + bucketIdx--; + } + } + return setSize; + } +} diff --git a/Medium/Reduction Operations to Make the Array Elements Equal.java b/Medium/Reduction Operations to Make the Array Elements Equal.java new file mode 100644 index 00000000..bb55c50e --- /dev/null +++ b/Medium/Reduction Operations to Make the Array Elements Equal.java @@ -0,0 +1,35 @@ +class Solution { + public int reductionOperations(int[] nums) { + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.put(nums[i], map.getOrDefault(nums[i], 0) + 1); + } + PriorityQueue pq = new PriorityQueue<>(new Comparator<>(){ + public int compare(KeyEntry k1, KeyEntry k2) { + return k2.key - k1.key; + } + }); + for (Integer key : map.keySet()) { + pq.add(new KeyEntry(key, map.get(key))); + } + int numOfSteps = 0; + while (pq.size() > 1) { + KeyEntry largest = pq.poll(); + KeyEntry secondLargest = pq.poll(); + secondLargest.val += largest.val; + pq.add(secondLargest); + numOfSteps += largest.val; + } + return numOfSteps; + } +} + +class KeyEntry { + int key; + int val; + + public KeyEntry(int key, int val) { + this.key = key; + this.val = val; + } +} diff --git a/Medium/Remove Adjacent Almost-Equal Characters.java b/Medium/Remove Adjacent Almost-Equal Characters.java new file mode 100644 index 00000000..46bdf2ab --- /dev/null +++ b/Medium/Remove Adjacent Almost-Equal Characters.java @@ -0,0 +1,14 @@ +class Solution { + public int removeAlmostEqualCharacters(String word) { + int count = 0; + for (int i = 0; i < word.length() - 1; i++) { + char curr = word.charAt(i); + char next = word.charAt(i + 1); + if (Math.abs(curr - next) <= 1) { + count++; + i++; + } + } + return count; + } +} diff --git a/Medium/Remove All Adjacent Duplicates in String II.java b/Medium/Remove All Adjacent Duplicates in String II.java new file mode 100644 index 00000000..0cf6d3ac --- /dev/null +++ b/Medium/Remove All Adjacent Duplicates in String II.java @@ -0,0 +1,33 @@ +class Solution { + public String removeDuplicates(String s, int k) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (!stack.isEmpty() && stack.peek().c == c) { + stack.peek().count++; + } else { + stack.push(new CharPair(c)); + } + if (stack.peek().count == k) { + stack.pop(); + } + } + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + CharPair pair = stack.pop(); + for (int i = 0; i < pair.count; i++) { + sb.append(pair.c); + } + } + return sb.reverse().toString(); + } + + private static class CharPair { + char c; + int count; + + public CharPair(char c) { + this.c = c; + this.count = 1; + } + } +} diff --git a/Medium/Remove All Occurrences of a Substring.java b/Medium/Remove All Occurrences of a Substring.java new file mode 100644 index 00000000..e46ad3f2 --- /dev/null +++ b/Medium/Remove All Occurrences of a Substring.java @@ -0,0 +1,32 @@ +class Solution { + public String removeOccurrences(String s, String part) { + Stack stack = new Stack<>(); + int n = s.length(); + int partLength = part.length(); + for (int i = 0; i < n; i++) { + stack.push(s.charAt(i)); + if (stack.size() >= partLength && check(stack, part, partLength)) { + for (int j = 0; j < partLength; j++) { + stack.pop(); + } + } + } + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + sb.append(stack.pop()); + } + return sb.reverse().toString(); + } + + private boolean check(Stack stack, String part, int partLength) { + Stack temp = new Stack<>(); + temp.addAll(stack); + for (int i = partLength - 1; i >= 0; i--) { + if (temp.isEmpty() || temp.peek() != part.charAt(i)) { + return false; + } + temp.pop(); + } + return true; + } +} diff --git a/Medium/Remove All Ones With Row and Column Flips II.java b/Medium/Remove All Ones With Row and Column Flips II.java new file mode 100644 index 00000000..aeeeab2f --- /dev/null +++ b/Medium/Remove All Ones With Row and Column Flips II.java @@ -0,0 +1,23 @@ +class Solution { + public int removeOnes(int[][] grid) { + return removeOnesHelper(grid, 0, 0); + } + + private int removeOnesHelper(int[][] grid, int x, int y) { + int rows = grid.length; + int cols = grid[0].length; + int result = Integer.MAX_VALUE; + int ones = 0; + for (int i = 0; i < rows; i++) { + if ((x & (1 << i)) == 0) { + for (int j = 0; j < cols; j++) { + if ((y & (1 << j)) == 0 && grid[i][j] == 1) { + ones++; + result = Math.min(result, 1 + removeOnesHelper(grid, x + (1 << i), y + (1 << j))); + } + } + } + } + return ones == 0 ? 0 : result; + } +} diff --git a/Medium/Remove Colored Pieces if Both Neighbors are the Same Color.java b/Medium/Remove Colored Pieces if Both Neighbors are the Same Color.java new file mode 100644 index 00000000..950afa6f --- /dev/null +++ b/Medium/Remove Colored Pieces if Both Neighbors are the Same Color.java @@ -0,0 +1,16 @@ +class Solution { + public boolean winnerOfGame(String colors) { + int alice = 0; + int bob = 0; + for (int i = 1; i < colors.length() - 1; i++) { + if (colors.charAt(i - 1) == colors.charAt(i) && colors.charAt(i + 1) == colors.charAt(i)) { + if (colors.charAt(i) == 'A') { + alice++; + } else { + bob++; + } + } + } + return alice - bob > 0; + } +} diff --git a/Medium/Remove Comments.java b/Medium/Remove Comments.java index 3a9d0bca..e9daac5c 100644 --- a/Medium/Remove Comments.java +++ b/Medium/Remove Comments.java @@ -1,41 +1,34 @@ class Solution { - public List removeComments(String[] source) { - List ans = new ArrayList<>(); - int i = 0; - int n = source.length; - boolean blockComment = false; - StringBuilder sb = new StringBuilder(); - - for (i = 0; i < n; i++) { - String line = source[i]; - - for (int j = 0; j < line.length(); j++) { - if (!blockComment) { - if (j + 1 < line.length() && line.charAt(j) == '/' && line.charAt(j + 1) == '/') { - break; - } - else if (j + 1 < line.length() && line.charAt(j) == '/' && line.charAt(j+1) == '*') { - blockComment = true; - j++; - } - else { - sb.append(line.charAt(j)); - } - } - else { - if (j + 1 < line.length() && line.charAt(j) == '*' && line.charAt(j + 1) == '/') { - blockComment = false; - j++; - } - } - } - - if (sb.length() > 0 && !blockComment) { - ans.add(sb.toString()); - sb = new StringBuilder(); - } + public List removeComments(String[] source) { + StringBuilder sb = new StringBuilder(); + List list = new ArrayList<>(); + boolean blockComment = false; + for (String word : source) { + for (int i = 0; i < word.length(); i++) { + if (!blockComment) { + if ((i + 1) < word.length() && word.charAt(i) == '/' && word.charAt(i + 1) == '/') { + break; + } + else if ((i + 1) < word.length() && word.charAt(i) == '/' && word.charAt(i + 1) == '*') { + blockComment = true; + i++; + } + else { + sb.append(word.charAt(i)); + } } - - return ans; + else { + if ((i + 1) < word.length() && word.charAt(i) == '*' && word.charAt(i + 1) == '/') { + blockComment = false; + i++; + } + } + } + if (!blockComment && sb.length() > 0) { + list.add(sb.toString()); + sb.setLength(0); + } } + return list; + } } diff --git a/Medium/Remove Covered Intervals.java b/Medium/Remove Covered Intervals.java new file mode 100644 index 00000000..03fdf662 --- /dev/null +++ b/Medium/Remove Covered Intervals.java @@ -0,0 +1,27 @@ +class Solution { + public int removeCoveredIntervals(int[][] intervals) { + Arrays.sort(intervals, (o1, o2) -> { + int c = o1[0] - o2[0]; + if (c != 0) { + return c; + } + return o2[1] - o1[1]; + }); + int currIdx = 0; + int n = intervals.length; + int intervalCount = 0; + while (currIdx < n) { + int[] currInterval = intervals[currIdx]; + int currIntervalStart = currInterval[0]; + int currIntervalEnd = currInterval[1]; + currIdx++; + while (currIdx < n && + intervals[currIdx][0] >= currIntervalStart && + intervals[currIdx][1] <= currIntervalEnd) { + currIdx++; + } + intervalCount++; + } + return intervalCount; + } +} diff --git a/Medium/Remove Duplicate Letters.java b/Medium/Remove Duplicate Letters.java new file mode 100644 index 00000000..19bd928d --- /dev/null +++ b/Medium/Remove Duplicate Letters.java @@ -0,0 +1,25 @@ +class Solution { + public String removeDuplicateLetters(String s) { + Map lastIndexMap = new HashMap<>(); + for (int i = 0; i < s.length(); i++) { + lastIndexMap.put(s.charAt(i), i); + } + Stack stack = new Stack<>(); + Set visited = new HashSet<>(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (!visited.contains(c)) { + while (!stack.isEmpty() && c < stack.peek() && lastIndexMap.get(stack.peek()) > i) { + visited.remove(stack.pop()); + } + visited.add(c); + stack.push(c); + } + } + StringBuilder sb = new StringBuilder(); + for (Character c : stack) { + sb.append(c); + } + return sb.toString(); + } +} diff --git a/Medium/Remove Duplicates From Sorted Array II.java b/Medium/Remove Duplicates From Sorted Array II.java index 2ed32e65..63879666 100644 --- a/Medium/Remove Duplicates From Sorted Array II.java +++ b/Medium/Remove Duplicates From Sorted Array II.java @@ -1,29 +1,19 @@ class Solution { - public int removeDuplicates(int[] nums) { - return removeDuplicatesUtil(nums, nums.length, 2); - } - - private int removeDuplicatesUtil(int[] nums, int n, int k) { - if (n <= k) return n; - - int i = 1; - int j = 1; - int cnt = 1; - - while (j < n) { - if (nums[j] != nums[j-1]) { - cnt = 1; - nums[i++] = nums[j]; - } - else { - if (cnt < k) { - nums[i++] = nums[j]; - cnt++; - } - } - ++j; - } - - return i; + public int removeDuplicates(int[] nums) { + int startIdx = 0; + int n = nums.length; + int currIdx = 0; + while (currIdx < n) { + int currValue = nums[currIdx]; + int count = 0; + while (currIdx < n && nums[currIdx] == currValue) { + currIdx++; + count++; + } + for (int i = 0; i < Math.min(2, count); i++) { + nums[startIdx++] = currValue; + } } + return startIdx; + } } diff --git a/Medium/Remove Duplicates From an Unsorted Linked List.java b/Medium/Remove Duplicates From an Unsorted Linked List.java new file mode 100644 index 00000000..18308224 --- /dev/null +++ b/Medium/Remove Duplicates From an Unsorted Linked List.java @@ -0,0 +1,37 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode deleteDuplicatesUnsorted(ListNode head) { + Map map = new HashMap<>(); + ListNode curr = head; + while (curr != null) { + map.put(curr.val, map.getOrDefault(curr.val, 0) + 1); + curr = curr.next; + } + curr = head; + ListNode prev = null; + ListNode newHead = null; + while (curr != null) { + if (map.get(curr.val) > 1) { + if (prev != null) { + prev.next = curr.next; + } + } else { + prev = curr; + if (newHead == null) { + newHead = curr; + } + } + curr = curr.next; + } + return newHead; + } +} diff --git a/Medium/Remove Duplicates from Sorted List II.java b/Medium/Remove Duplicates from Sorted List II.java index 007ecd17..edb287cc 100644 --- a/Medium/Remove Duplicates from Sorted List II.java +++ b/Medium/Remove Duplicates from Sorted List II.java @@ -3,30 +3,31 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode deleteDuplicates(ListNode head) { - if(head==null) return null; - - ListNode FakeHead=new ListNode(0); - FakeHead.next=head; - ListNode pre=FakeHead; - ListNode cur=head; - - while(cur!=null){ - while(cur.next!=null&&cur.val==cur.next.val){ - cur=cur.next; - } - if(pre.next==cur){ - pre=pre.next; - } - else{ - pre.next=cur.next; - } - cur=cur.next; + public ListNode deleteDuplicates(ListNode head) { + ListNode prev = null; + ListNode curr = head; + while (curr != null) { + if (curr.next != null && curr.next.val == curr.val) { + int currVal = curr.val; + while (curr != null && curr.val == currVal) { + curr = curr.next; } - return FakeHead.next; + if (prev == null) { + head = curr; + } else { + prev.next = curr; + } + } else { + prev = curr; + curr = curr.next; + } } + return head; + } } diff --git a/Medium/Remove Interval.java b/Medium/Remove Interval.java new file mode 100644 index 00000000..e64370e0 --- /dev/null +++ b/Medium/Remove Interval.java @@ -0,0 +1,37 @@ +class Solution { + public List> removeInterval(int[][] intervals, int[] toBeRemoved) { + List> result = new ArrayList<>(); + int n = intervals.length; + int removeStart = toBeRemoved[0]; + int removeEnd = toBeRemoved[1]; + for (int i = 0; i < n; i++) { + int currStart = intervals[i][0]; + int currEnd = intervals[i][1]; + // complete overlap hence skipping complete interval + if (currStart >= removeStart && currEnd <= removeEnd) { + continue; + } + // no overlap hence adding complete interval + if ((currStart <= removeStart && currEnd <= removeStart) || (currStart >= removeEnd && currEnd >= removeEnd)) { + result.add(List.of(currStart, currEnd)); + continue; + } + // partial overlaps + if (currStart <= removeStart) { + int newStart = Math.min(currStart, removeStart); + int newEnd = Math.max(currStart, removeStart); + if (newStart != newEnd) { + result.add(List.of(newStart, newEnd)); + } + } + if (currEnd >= removeEnd) { + int newStart = Math.min(currEnd, removeEnd); + int newEnd = Math.max(currEnd, removeEnd); + if (newStart != newEnd) { + result.add(List.of(newStart, newEnd)); + } + } + } + return result; + } +} diff --git a/Medium/Remove K Digits.java b/Medium/Remove K Digits.java index 6166b173..f42a2575 100644 --- a/Medium/Remove K Digits.java +++ b/Medium/Remove K Digits.java @@ -1,35 +1,25 @@ class Solution { - public String removeKdigits(String num, int k) { - Stack stack = new Stack<>(); - int idx = 0; - int n = num.length(); - while (idx < n) { - while (k > 0 && !stack.isEmpty()) { - if (stack.peek() <= Character.getNumericValue(num.charAt(idx))) { - break; - } - stack.pop(); - k--; - } - - stack.push(Character.getNumericValue(num.charAt(idx++))); - } - - while (k-- > 0) { - stack.pop(); - } - - StringBuilder sb = new StringBuilder(); - while (!stack.isEmpty()) { - sb.append(stack.pop()); - } - - String ans = sb.reverse().toString(); - idx = -1; - while (idx + 1 < ans.length() && ans.charAt(idx + 1) == '0') { - idx++; - } - - return ans.substring(idx + 1).length() == 0 ? "0" : ans.substring(idx + 1); + public String removeKdigits(String num, int k) { + LinkedList stack = new LinkedList<>(); + for (char c : num.toCharArray()) { + while (!stack.isEmpty() && k > 0 && stack.peekLast() > c) { + stack.removeLast(); + k--; + } + stack.addLast(c); } + while (k-- > 0) { + stack.removeLast(); + } + StringBuilder sb = new StringBuilder(); + boolean currZero = true; + for (char c : stack) { + if (currZero && c == '0') { + continue; + } + currZero = false; + sb.append(c); + } + return sb.length() == 0 ? "0" : sb.toString(); + } } diff --git a/Medium/Remove Nodes From Linked List.java b/Medium/Remove Nodes From Linked List.java new file mode 100644 index 00000000..850e4da0 --- /dev/null +++ b/Medium/Remove Nodes From Linked List.java @@ -0,0 +1,40 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode removeNodes(ListNode head) { + ListNode revNode = reverse(head); + ListNode curr = revNode; + ListNode prev = null; + int maxValue = Integer.MIN_VALUE; + while (curr != null) { + if (curr.val < maxValue) { + prev.next = curr.next; + } else { + prev = curr; + maxValue = Math.max(curr.val, maxValue); + } + curr = curr.next; + } + return reverse(revNode); + } + + private ListNode reverse(ListNode node) { + ListNode curr = node; + ListNode prev = null; + while (curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } +} diff --git a/Medium/Remove Nth Node From End of List.java b/Medium/Remove Nth Node From End of List.java index ae91da94..f6f741f8 100644 --- a/Medium/Remove Nth Node From End of List.java +++ b/Medium/Remove Nth Node From End of List.java @@ -3,36 +3,26 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode removeNthFromEnd(ListNode head, int n) { - - if (head == null || head.next == null) return null; - - ListNode curr = head; - int i = 0; - - while (curr != null) { - curr = curr.next; - i++; - } - - if (i == n) { - return head.next; - } - - n = i - n; - i = 1; - curr = head; - - while (i != n) { - curr = curr.next; - i++; - } - curr.next = curr.next.next; - - return head; + public ListNode removeNthFromEnd(ListNode head, int n) { + ListNode curr = head; + while (n-- > 0) { + curr = curr.next; } + if (curr == null) { + return head.next; + } + ListNode slowNode = head; + while (curr.next != null) { + slowNode = slowNode.next; + curr = curr.next; + } + slowNode.next = slowNode.next.next; + return head; + } } diff --git a/Medium/Remove Sub-Folders from the Filesystem.java b/Medium/Remove Sub-Folders from the Filesystem.java new file mode 100644 index 00000000..62f67bcd --- /dev/null +++ b/Medium/Remove Sub-Folders from the Filesystem.java @@ -0,0 +1,67 @@ +class Solution { + public List removeSubfolders(String[] folder) { + TrieNode root = new TrieNode(); + for (String file : folder) { + TrieNode curr = root; + String[] splits = file.split("/"); + for (int i = 1; i < splits.length; i++) { + Optional nextNode = curr.getChild(splits[i]); + if (nextNode.isEmpty()) { + TrieNode newNode = curr.addChild(splits[i]); + curr = newNode; + } else { + curr = nextNode.get(); + } + } + curr.markIsFolder(); + } + List result = new ArrayList<>(); + for (String file : folder) { + TrieNode curr = root; + String[] splits = file.split("/"); + boolean isSubfolder = false; + for (int i = 1; i < splits.length; i++) { + TrieNode nextNode = curr.getChild(splits[i]).get(); + if (nextNode.isFolder() && i != splits.length - 1) { + isSubfolder = true; + break; + } + curr = nextNode; + } + if (!isSubfolder) { + result.add(file); + } + } + return result; + } + + class TrieNode { + private boolean isFolder; + private Map children; + + public TrieNode() { + this.children = new HashMap<>(); + } + + public TrieNode addChild(String childKey) { + TrieNode node = new TrieNode(); + children.put(childKey, node); + return node; + } + + public Optional getChild(String childKey) { + if (!children.containsKey(childKey)) { + return Optional.empty(); + } + return Optional.of(children.get(childKey)); + } + + public void markIsFolder() { + isFolder = true; + } + + public boolean isFolder() { + return isFolder; + } + } +} diff --git a/Medium/Remove Zero Sum Consecutive Nodes from Linked List.java b/Medium/Remove Zero Sum Consecutive Nodes from Linked List.java new file mode 100644 index 00000000..6f55accd --- /dev/null +++ b/Medium/Remove Zero Sum Consecutive Nodes from Linked List.java @@ -0,0 +1,32 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode removeZeroSumSublists(ListNode head) { + ListNode dummy = new ListNode(0, head); + ListNode curr = dummy; + int prefixSum = 0; + Map map = new HashMap<>(); + map.put(0, curr); + while (curr != null) { + prefixSum += curr.val; + map.put(prefixSum, curr); + curr = curr.next; + } + prefixSum = 0; + curr = dummy; + while (curr != null) { + prefixSum += curr.val; + curr.next = map.get(prefixSum).next; + curr = curr.next; + } + return dummy.next; + } +} diff --git a/Medium/Removing Stars From a String.java b/Medium/Removing Stars From a String.java new file mode 100644 index 00000000..9278128a --- /dev/null +++ b/Medium/Removing Stars From a String.java @@ -0,0 +1,17 @@ +class Solution { + public String removeStars(String s) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (c == '*') { + stack.pop(); + } else { + stack.push(c); + } + } + StringBuilder sb = new StringBuilder(); + while (!stack.isEmpty()) { + sb.append(stack.pop()); + } + return sb.reverse().toString(); + } +} diff --git a/Medium/Reorder Data in Log Files.java b/Medium/Reorder Data in Log Files.java new file mode 100644 index 00000000..cc14332b --- /dev/null +++ b/Medium/Reorder Data in Log Files.java @@ -0,0 +1,17 @@ +class Solution { + public String[] reorderLogFiles(String[] logs) { + List letterLogs = new ArrayList<>(); + List digitLogs = new ArrayList<>(); + for (String log : logs) { + if (Character.isDigit(log.split("\\s+")[1].charAt(0))) { + digitLogs.add(log); + } else { + letterLogs.add(log); + } + } + letterLogs.sort(Comparator.comparing((String o) -> o.substring(o.indexOf(' ') + 1)) + .thenComparing(o -> o.split("\\s+")[0])); + letterLogs.addAll(digitLogs); + return letterLogs.toArray(new String[0]); + } +} diff --git a/Medium/Reorder List.java b/Medium/Reorder List.java index 73a7ebe7..99b9ea19 100644 --- a/Medium/Reorder List.java +++ b/Medium/Reorder List.java @@ -3,86 +3,41 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - - public static void reorderList(ListNode head) { - if (head == null || head.next == null) return; - int midLength = getLength(head)/2; - ListNode curr = head; - int count = 1; - - while (count < midLength) { - curr = curr.next; - count++; + public void reorderList(ListNode head) { + ListNode slow = head; + ListNode fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; } - - ListNode rev = reverse(curr.next); - curr = head; - - while (midLength-- > 1) { - curr = curr.next; + ListNode secondHalf = reverse(slow.next); + slow.next = null; + ListNode firstHalf = head; + while (firstHalf != null && secondHalf != null) { + ListNode firstNext = firstHalf.next; + ListNode secondNext = secondHalf.next; + firstHalf.next = secondHalf; + secondHalf.next = firstNext; + firstHalf = firstNext; + secondHalf = secondNext; } - - curr.next = null; - curr = head; - - head = merge(curr, rev); } - private static ListNode merge(ListNode head1, ListNode head2) { - ListNode ans = head1; - ListNode pCurr = head1; - ListNode qCurr = head2; - - ListNode pNext = null; - ListNode qNext = null; - ListNode pPrev = null; - - while (pCurr != null && qCurr != null) { - pNext = pCurr.next; - qNext = qCurr.next; - - qCurr.next = pNext; - pCurr.next = qCurr; - - if (pNext == null) { - pPrev = qCurr; - } - - pCurr = pNext; - qCurr = qNext; - } - - pPrev.next = qCurr; - - return ans; - } - - private static ListNode reverse(ListNode root) { + private ListNode reverse(ListNode node) { + ListNode curr = node; ListNode prev = null; - ListNode curr = root; - ListNode next = null; - while (curr != null) { - next = curr.next; + ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } - return prev; } - - private static int getLength(ListNode head) { - int count = 0; - while (head != null) { - count++; - head = head.next; - } - - return count; - } } diff --git a/Medium/Reorder Routes to Make All Paths Lead to the City Zero.java b/Medium/Reorder Routes to Make All Paths Lead to the City Zero.java new file mode 100644 index 00000000..78f7e54f --- /dev/null +++ b/Medium/Reorder Routes to Make All Paths Lead to the City Zero.java @@ -0,0 +1,31 @@ +class Solution { + public int minReorder(int n, int[][] connections) { + Map>> graph = new HashMap<>(); + for (int[] conn : connections) { + graph.computeIfAbsent(conn[0], k -> new ArrayList<>()).add(List.of(conn[1], 1)); + graph.computeIfAbsent(conn[1], k -> new ArrayList<>()).add(List.of(conn[0], 0)); + } + int[] count = {0}; + bfs(0, n, graph, count); + return count[0]; + } + + private void bfs(int node, int n, Map>> graph, int[] count) { + Queue queue = new LinkedList<>(); + boolean[] visited = new boolean[n]; + visited[node] = true; + queue.add(node); + while (!queue.isEmpty()) { + int removed = queue.remove(); + for (List conn : graph.getOrDefault(removed, new ArrayList<>())) { + int neighbor = conn.get(0); + int direction = conn.get(1); + if (!visited[neighbor]) { + count[0] += direction; + visited[neighbor] = true; + queue.add(neighbor); + } + } + } + } +} diff --git a/Medium/Reordered Power of 2.java b/Medium/Reordered Power of 2.java new file mode 100644 index 00000000..09c9fe1b --- /dev/null +++ b/Medium/Reordered Power of 2.java @@ -0,0 +1,20 @@ +class Solution { + public boolean reorderedPowerOf2(int n) { + int[] digitCount = count(n); + for (int i = 0; i < 31; i++) { + if (Arrays.equals(digitCount, count(1 << i))) { + return true; + } + } + return false; + } + + private int[] count(int n) { + int[] result = new int[10]; + while (n > 0) { + result[n % 10]++; + n /= 10; + } + return result; + } +} diff --git a/Medium/Reorganize String.java b/Medium/Reorganize String.java index 824bc88b..9dd20760 100644 --- a/Medium/Reorganize String.java +++ b/Medium/Reorganize String.java @@ -1,44 +1,38 @@ class Solution { - public String reorganizeString(String S) { - int buffer = S.length()%2 == 0 ? S.length()/2 : S.length()/2 + 1; + public String reorganizeString(String s) { Map map = new HashMap<>(); - char[] chars = S.toCharArray(); - - for (char c : chars) { + int maxFrequency = 0; + char maxFrequencyLetter = ' '; + int n = s.length(); + for (char c : s.toCharArray()) { map.put(c, map.getOrDefault(c, 0) + 1); - if (map.get(c) > buffer) { - return ""; + if (maxFrequency < map.get(c)) { + maxFrequency = map.get(c); + maxFrequencyLetter = c; } } - - return createString(map); - } - - private String createString(Map map) { - PriorityQueue pq = new PriorityQueue<>((a, b) -> b[1] - a[1]); - for (char c : map.keySet()) { - pq.add(new int[] {c, map.get(c)}); + if (maxFrequency > (n + 1) / 2) { + return ""; } + char[] letters = new char[s.length()]; + int idx = 0; + idx = insertLetter(n, map, maxFrequencyLetter, letters, idx); + map.remove(maxFrequencyLetter); + for (Character key : map.keySet()) { + idx = insertLetter(n, map, key, letters, idx); + } + return String.valueOf(letters); + } - StringBuilder sb = new StringBuilder(); - while (!pq.isEmpty()) { - int[] first = pq.poll(); - if (sb.length() == 0 || first[0] != sb.charAt(sb.length() - 1)) { - sb.append((char) first[0]); - if (--first[1] > 0) { - pq.add(first); - } - } - else { - int[] second = pq.poll(); - sb.append((char) second[0]); - if (--second[1] > 0) { - pq.add(second); - } - pq.add(first); + private static int insertLetter(int n, Map map, char maxFrequencyLetter, char[] letters, int idx) { + while (map.get(maxFrequencyLetter) > 0) { + if (idx >= n) { + idx = 1; } + letters[idx] = maxFrequencyLetter; + idx += 2; + map.put(maxFrequencyLetter, map.get(maxFrequencyLetter) - 1); } - - return sb.toString(); + return idx; } } diff --git a/Medium/Repeated DNA Sequences.java b/Medium/Repeated DNA Sequences.java index ec329cfd..c764a92c 100644 --- a/Medium/Repeated DNA Sequences.java +++ b/Medium/Repeated DNA Sequences.java @@ -1,19 +1,13 @@ class Solution { - public List findRepeatedDnaSequences(String s) { - Map map = new HashMap<>(); - - for (int i=0; i<=s.length() - 10; i++) { - map.put(s.substring(i, i+10), map.getOrDefault(s.substring(i, i+10), 0) + 1); - } - - List ans = new ArrayList<>(); - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() > 1) { - ans.add(entry.getKey()); - } - } - - return ans; + public List findRepeatedDnaSequences(String s) { + Set seenSequences = new HashSet<>(); + Set duplicateSequences = new HashSet<>(); + for (int idx = 0; idx <= s.length() - 10; idx++) { + String currentSequence = s.substring(idx, idx + 10); + if (!seenSequences.add(currentSequence)) { + duplicateSequences.add(currentSequence); + } } + return new ArrayList<>(duplicateSequences); + } } diff --git a/Medium/Replace Elements in an Array.java b/Medium/Replace Elements in an Array.java new file mode 100644 index 00000000..77140194 --- /dev/null +++ b/Medium/Replace Elements in an Array.java @@ -0,0 +1,14 @@ +class Solution { + public int[] arrayChange(int[] nums, int[][] operations) { + Map indexMap = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + indexMap.put(nums[i], i); + } + for (int[] operation : operations) { + int prevElementIdx = indexMap.get(operation[0]); + indexMap.put(operation[1], prevElementIdx); + nums[prevElementIdx] = operation[1]; + } + return nums; + } +} diff --git a/Medium/Replace Words.java b/Medium/Replace Words.java index 3e8c6e14..0fd7e0e6 100644 --- a/Medium/Replace Words.java +++ b/Medium/Replace Words.java @@ -1,63 +1,56 @@ class Solution { - - public String replaceWords(List dict, String sentence) { - - Map map = new HashMap<>(); - - for (String s: dict) { - map.put(s, s.length()); - } - - Map sortedMap = sortByValue(map); - - String[] arr = sentence.split("\\s"); - String[] ans = new String[arr.length]; - int j = 0; - - for (String s : arr) { - boolean gotIt = false; - for (Map.Entry entry : sortedMap.entrySet()) { - if (s.startsWith(entry.getKey())) { - ans[j] = entry.getKey(); - gotIt = true; - break; - } - } - - if (!gotIt) { - ans[j] = s; - } - - j++; - } - - StringBuilder ansString = new StringBuilder(""); - - for (String s : ans) { - ansString.append(s + " "); - } - - return ansString.toString().trim(); + public String replaceWords(List dict, String sentence) { + Node root = new Node('-'); + for (String word : dict) { + addWord(word, 0, root); } - - private Map sortByValue(Map unsortMap) { - - List> list = - new LinkedList>(unsortMap.entrySet()); - - Collections.sort(list, new Comparator>() { - public int compare(Map.Entry o1, - Map.Entry o2) { - return (o1.getValue()).compareTo(o2.getValue()); - } - }); - - Map sortedMap = new LinkedHashMap(); - for (Map.Entry entry : list) { - sortedMap.put(entry.getKey(), entry.getValue()); - } - - return sortedMap; + String[] words = sentence.split("\\s+"); + for (int i = 0; i < words.length; i++) { + String prefix = getPrefix(words[i], root); + if (prefix != null) { + words[i] = prefix; + } + } + return String.join(" ", words); + } + + private String getPrefix(String word, Node root) { + for (int i = 0; i < word.length(); i++) { + if (!root.children.containsKey(word.charAt(i))) { + return null; + } + root = root.children.get(word.charAt(i)); + if (root.word != null) { + return root.word; + } } + return null; + } + + private void addWord(String word, int idx, Node root) { + if (idx == word.length()) { + return; + } + if (!root.children.containsKey(word.charAt(idx))) { + root.children.put(word.charAt(idx), new Node(word.charAt(idx))); + } + root = root.children.get(word.charAt(idx)); + if (idx == word.length() - 1) { + root.word = word; + } + addWord(word, idx + 1, root); + } +} + +class Node { + char c; + Map children; + String word; + + public Node(char c) { + this.c = c; + children = new HashMap<>(); + word = null; + } } diff --git a/Medium/Restore IP Address.java b/Medium/Restore IP Address.java new file mode 100644 index 00000000..635e87e4 --- /dev/null +++ b/Medium/Restore IP Address.java @@ -0,0 +1,42 @@ +class Solution { + public List restoreIpAddresses(String s) { + int n = s.length(); + LinkedList segments = new LinkedList(); + List output = new ArrayList(); + backtrack(s, -1, 3, output, segments, n); + return output; + } + + private void backtrack(String s, int prevPos, int dots, List output, LinkedList segments, int n) { + int maxPos = Math.min(n - 1, prevPos + 4); + for (int i = prevPos + 1; i < maxPos; i++) { + String segment = s.substring(prevPos + 1, i + 1); + if (isValid(segment)) { + segments.add(segment); + if (dots - 1 == 0) { + updateOutput(s, i, n, segments, output); + } + else { + backtrack(s, i, dots - 1, output, segments, n); + } + segments.removeLast(); + } + } + } + + public void updateOutput(String s, int currPos, int n, LinkedList segments, List output) { + String segment = s.substring(currPos + 1, n); + if (isValid(segment)) { + segments.add(segment); + output.add(String.join(".", segments)); + segments.removeLast(); + } + } + + public boolean isValid(String segment) { + int m = segment.length(); + if (m > 3) + return false; + return (segment.charAt(0) != '0') ? (Integer.parseInt(segment) <= 255) : (m == 1); + } +} diff --git a/Medium/Restore the Array From Adjacent Pairs.java b/Medium/Restore the Array From Adjacent Pairs.java new file mode 100644 index 00000000..041f727d --- /dev/null +++ b/Medium/Restore the Array From Adjacent Pairs.java @@ -0,0 +1,31 @@ +class Solution { + public int[] restoreArray(int[][] adjacentPairs) { + int n = adjacentPairs.length + 1; + Map> map = new HashMap<>(); + for (int[] pair : adjacentPairs) { + map.computeIfAbsent(pair[0], k -> new ArrayList<>()).add(pair[1]); + map.computeIfAbsent(pair[1], k -> new ArrayList<>()).add(pair[0]); + } + Queue queue = new LinkedList<>(); + int firstElement = map.entrySet() + .stream() + .filter(entry -> entry.getValue().size() == 1) + .map(Map.Entry::getKey) + .findFirst() + .orElse(-1); + queue.add(firstElement); + Set set = new HashSet<>(); + int[] result = new int[n]; + int idx = 0; + while (!queue.isEmpty()) { + int removed = queue.remove(); + if (set.contains(removed)) { + continue; + } + result[idx++] = removed; + set.add(removed); + queue.addAll(map.get(removed)); + } + return result; + } +} diff --git a/Medium/Resulting String After Adjacent Removals.java b/Medium/Resulting String After Adjacent Removals.java new file mode 100644 index 00000000..efa43bf6 --- /dev/null +++ b/Medium/Resulting String After Adjacent Removals.java @@ -0,0 +1,21 @@ +class Solution { + public String resultingString(String s) { + Stack stack = new Stack<>(); + for (char c : s.toCharArray()) { + if (!stack.isEmpty() && isAdjacent(stack.peek(), c)) { + stack.pop(); + } else { + stack.push(c); + } + } + StringBuilder result = new StringBuilder(); + for (char c : stack) { + result.append(c); + } + return result.toString(); + } + + private static boolean isAdjacent(char first, char second) { + return Math.abs(first - second) == 1 || (first == 'a' && second == 'z') || (first == 'z' && second == 'a'); + } +} diff --git a/Medium/Reverse Integer.java b/Medium/Reverse Integer.java new file mode 100644 index 00000000..6acc2d42 --- /dev/null +++ b/Medium/Reverse Integer.java @@ -0,0 +1,17 @@ +class Solution { + public int reverse(int x) { + int reverse = 0; + while (x != 0) { + int rem = x % 10; + x /= 10; + if (reverse > Integer.MAX_VALUE / 10 || (reverse == Integer.MAX_VALUE / 10 && rem > 7)) { + return 0; + } + if (reverse < Integer.MIN_VALUE / 10 || (reverse == Integer.MIN_VALUE / 10 && rem < -8)) { + return 0; + } + reverse = reverse * 10 + rem; + } + return reverse; + } +} diff --git a/Medium/Reverse Linked List II.java b/Medium/Reverse Linked List II.java index ca17dc02..3835dbcd 100644 --- a/Medium/Reverse Linked List II.java +++ b/Medium/Reverse Linked List II.java @@ -3,37 +3,49 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode reverseBetween(ListNode head, int m, int n) { - if (head == null || m == n || m > n) { - return head; + public ListNode reverseBetween(ListNode head, int left, int right) { + ListNode curr = head; + ListNode prevToLeft = null; + for (int i = 1; i < left; i++) { + prevToLeft = curr; + curr = curr.next; + } + ListNode nextToLeft = prevToLeft == null ? head : prevToLeft.next; + for (int i = left; i < right; i++) { + curr = curr.next; } - - ListNode dummy = new ListNode(0); - dummy.next = head; - ListNode pre = dummy; - ListNode curr = dummy.next; - - for (int i = 1; i < m; i++) { - pre = curr; + ListNode nextToRight = curr.next; + curr.next = null; + if (prevToLeft != null) { + prevToLeft.next = null; + } + ListNode reversedStart = reverse(nextToLeft); + if (prevToLeft != null) { + prevToLeft.next = reversedStart; + } + curr = reversedStart; + while (curr.next != null) { curr = curr.next; } - - ListNode node = pre; - - for (int i = m; i <= n; i++) { - ListNode tmp = curr.next; - curr.next = pre; - pre = curr; - curr = tmp; + curr.next = nextToRight; + return prevToLeft == null ? reversedStart : head; + } + + private ListNode reverse(ListNode head) { + ListNode prev = null; + ListNode curr = head; + while (curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; } - - node.next.next = curr; - node.next = pre; - - return dummy.next; + return prev; } } diff --git a/Medium/Reverse Nodes in Even Length Groups.java b/Medium/Reverse Nodes in Even Length Groups.java new file mode 100644 index 00000000..5b723f6a --- /dev/null +++ b/Medium/Reverse Nodes in Even Length Groups.java @@ -0,0 +1,57 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode reverseEvenLengthGroups(ListNode head) { + if (head == null) { + return head; + } + int numOfNodes = 1; + ListNode prev = null; + ListNode curr = head; + int totalNumOfNodes = 0; + while (curr != null) { + totalNumOfNodes++; + curr = curr.next; + } + curr = head; + while (curr != null) { + numOfNodes = Math.min(numOfNodes, totalNumOfNodes); + totalNumOfNodes -= numOfNodes; + if (numOfNodes % 2 == 0) { + ListNode[] res = reverseList(curr, numOfNodes); + prev.next = res[0]; + prev = curr; + curr = res[1]; + } else { + for (int i = 0; i < numOfNodes && curr != null; i++) { + prev = curr; + curr = curr.next; + } + } + numOfNodes++; + } + return head; + } + + private ListNode[] reverseList(ListNode node, int n) { + ListNode prev = null; + ListNode curr = node; + ListNode post = null; + while (n-- > 0) { + post = curr.next; + curr.next = prev; + prev = curr; + curr = post; + } + node.next = curr; + return new ListNode[]{prev, post}; + } +} diff --git a/Medium/Reverse Nodes in k-group.java b/Medium/Reverse Nodes in k-group.java deleted file mode 100644 index d565c37c..00000000 --- a/Medium/Reverse Nodes in k-group.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public ListNode reverseKGroup(ListNode head, int k) { - ArrayList arr = new ArrayList<>(); - ListNode curr = head; - while (curr != null) { - arr.add(curr.val); - curr = curr.next; - } - - curr = head; - int i = 0; - int n = k; - while(i+k <= arr.size()) { - while(n != 0) { - curr.val = arr.get(i+n-1); - curr = curr.next; - n--; - } - i += k; - n = k; - } - return head; - } -} diff --git a/Medium/Reverse Odd Levels of Binary Tree.java b/Medium/Reverse Odd Levels of Binary Tree.java new file mode 100644 index 00000000..72fc142a --- /dev/null +++ b/Medium/Reverse Odd Levels of Binary Tree.java @@ -0,0 +1,55 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode reverseOddLevels(TreeNode root) { + int level = 0; + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + List currLevel = new ArrayList<>(); + int size = queue.size(); + while (size-- > 0) { + TreeNode removed = queue.remove(); + if (level % 2 != 0) { + currLevel.add(removed); + } + if (removed.left != null) { + queue.add(removed.left); + } + if (removed.right != null) { + queue.add(removed.right); + } + } + if (level % 2 != 0) { + reverseLevel(currLevel); + } + level++; + } + return root; + } + + private void reverseLevel(List currLevel) { + int start = 0; + int end = currLevel.size() - 1; + while (start < end) { + TreeNode startNode = currLevel.get(start++); + TreeNode endNode = currLevel.get(end--); + int temp = startNode.val; + startNode.val = endNode.val; + endNode.val = temp; + } + } +} diff --git a/Medium/Reverse Substrings Between Each Pair of Parentheses.java b/Medium/Reverse Substrings Between Each Pair of Parentheses.java new file mode 100644 index 00000000..b2ecb320 --- /dev/null +++ b/Medium/Reverse Substrings Between Each Pair of Parentheses.java @@ -0,0 +1,29 @@ +class Solution { + public String reverseParentheses(String s) { + char[] letters = s.toCharArray(); + Stack stack = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '(') { + stack.push(i); + } else if (s.charAt(i) == ')') { + reverse(letters, stack.pop(), i); + } + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < letters.length; i++) { + if (letters[i] == '(' || letters[i] == ')') { + continue; + } + sb.append(letters[i]); + } + return sb.toString(); + } + + private void reverse(char[] letters, int start, int end) { + while (start < end) { + char temp = letters[start]; + letters[start++] = letters[end]; + letters[end--] = temp; + } + } +} diff --git a/Medium/Reverse Words in a String II.java b/Medium/Reverse Words in a String II.java index 1931ba7d..c3ce706c 100644 --- a/Medium/Reverse Words in a String II.java +++ b/Medium/Reverse Words in a String II.java @@ -1,27 +1,22 @@ class Solution { - public static void reverseWords(char[] str) { - reverse(str, 0, str.length); - - int start = 0; - for (int i=0; i= 0) { - if (s.charAt(i) != ' ') { - while (i >= 0 && s.charAt(i) != ' ') { - temp.append(s.charAt(i)); - i--; - } - - sb.append(temp.reverse().toString()).append(" "); - temp = new StringBuilder(); + StringBuilder result = new StringBuilder(); + int idx = s.length() - 1; + while (idx >= 0) { + if (s.charAt(idx) == ' ') { + idx--; + continue; } - - i--; - } - - if (temp.length() > 0) { - sb.append(temp.reverse().toString()); + StringBuilder sb = new StringBuilder(); + while (idx >= 0 && Character.isLetterOrDigit(s.charAt(idx))) { + sb.append(s.charAt(idx--)); + } + result.append(sb.reverse().toString()).append(" "); } - - return sb.toString().trim(); + return result.toString().trim(); } } diff --git a/Medium/Right Triangles.java b/Medium/Right Triangles.java new file mode 100644 index 00000000..d94804b3 --- /dev/null +++ b/Medium/Right Triangles.java @@ -0,0 +1,25 @@ +class Solution { + public long numberOfRightTriangles(int[][] grid) { + int rows = grid.length; + int cols = grid[0].length; + int[] rowCount = new int[rows]; + int[] colCount = new int[cols]; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + rowCount[i]++; + colCount[j]++; + } + } + } + long triangles = 0; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + triangles += (rowCount[i] - 1) * (colCount[j] - 1); + } + } + } + return triangles; + } +} diff --git a/Medium/Robot Bounded In Circle.java b/Medium/Robot Bounded In Circle.java new file mode 100644 index 00000000..f3942994 --- /dev/null +++ b/Medium/Robot Bounded In Circle.java @@ -0,0 +1,21 @@ +class Solution { + public boolean isRobotBounded(String instructions) { + int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + int x = 0; + int y = 0; + int idx = 0; + for (char c : instructions.toCharArray()) { + if (c == 'L') { + idx = (idx + 3) % 4; + } + else if (c == 'R') { + idx = (idx + 1) % 4; + } + else { + x += directions[idx][0]; + y += directions[idx][1]; + } + } + return (x == 0 && y == 0) || idx != 0; + } +} diff --git a/Medium/Rotate Array.java b/Medium/Rotate Array.java new file mode 100644 index 00000000..1090cd86 --- /dev/null +++ b/Medium/Rotate Array.java @@ -0,0 +1,19 @@ +class Solution { + public void rotate(int[] nums, int k) { + int n = nums.length; + k %= n; + int count = 0; + for (int i = 0; count < n; i++) { + int currIdx = i; + int prevValue = nums[i]; + do { + int nextIdx = (currIdx + k) % n; + int tempValue = nums[nextIdx]; + nums[nextIdx] = prevValue; + prevValue = tempValue; + currIdx = nextIdx; + count++; + } while (i != currIdx); + } + } +} diff --git a/Medium/Rotate Image.java b/Medium/Rotate Image.java index f90d06ac..ad3e759d 100644 --- a/Medium/Rotate Image.java +++ b/Medium/Rotate Image.java @@ -1,19 +1,14 @@ class Solution { - public void rotate(int[][] matrix) { - for (int i=0;i 0) { - rotateArr(arr); - k--; - } - - curr = head; - int j = 0; - while (curr != null) { - curr.val = arr[j]; - j++; - curr = curr.next; - } - - return head; + int n = 0; + ListNode curr = head; + while (curr != null) { + n++; + curr = curr.next; } + k = k % n; + if (k == 0) { + return head; + } + k = n - k; + curr = head; + while (k-- > 1) { + curr = curr.next; + } + ListNode newHead = curr.next; + curr.next = null; + curr = newHead; + while (curr != null && curr.next != null) { + curr = curr.next; + } + curr.next = head; + return newHead; + } } diff --git a/Medium/Rotated Digits.java b/Medium/Rotated Digits.java new file mode 100644 index 00000000..5d0104e8 --- /dev/null +++ b/Medium/Rotated Digits.java @@ -0,0 +1,25 @@ +class Solution { + public int rotatedDigits(int n) { + int[] dp = new int[n + 1]; + int result = 0; + for (int i = 0; i <= Math.min(n, 9); i++) { + if (i == 0 || i == 1 || i == 8) { + dp[i] = 1; + } else if (i == 2 || i == 5 || i == 6 || i == 9) { + dp[i] = 2; + result++; + } + } + for (int i = 10; i <= n; i++) { + int factor = dp[i / 10]; + int remainder = dp[i % 10]; + if (factor == 1 && remainder == 1) { + dp[i] = 1; + } else if (factor >= 1 && remainder >= 1) { + dp[i] = 2; + result++; + } + } + return result; + } +} diff --git a/Medium/Rotting Oranges.java b/Medium/Rotting Oranges.java new file mode 100644 index 00000000..dd9a1be5 --- /dev/null +++ b/Medium/Rotting Oranges.java @@ -0,0 +1,37 @@ +class Solution { + private final int[][] DIRS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + public int orangesRotting(int[][] grid) { + Queue queue = new LinkedList<>(); + int nonRottenCount = 0; + int numRows = grid.length; + int numCols = grid[0].length; + for (int i = 0; i < numRows; i++) { + for (int j = 0; j < numCols; j++) { + if (grid[i][j] == 2) { + queue.add(new int[]{i, j}); + } else if (grid[i][j] == 1) { + nonRottenCount++; + } + } + } + int totalTime = 0; + while (!queue.isEmpty() && nonRottenCount > 0) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + for (int[] dir : DIRS) { + int newX = removed[0] + dir[0]; + int newY = removed[1] + dir[1]; + if (newX >= 0 && newY >= 0 && newX < numRows && newY < numCols && grid[newX][newY] == 1) { + grid[newX][newY] = 2; + nonRottenCount--; + queue.add(new int[]{newX, newY}); + } + } + } + totalTime++; + } + return nonRottenCount == 0 ? totalTime : -1; + } +} diff --git a/Medium/Satisfiability of Equality Equations.java b/Medium/Satisfiability of Equality Equations.java new file mode 100644 index 00000000..cba2bf2a --- /dev/null +++ b/Medium/Satisfiability of Equality Equations.java @@ -0,0 +1,42 @@ +class Solution { + public boolean equationsPossible(String[] equations) { + List[] graph = new ArrayList[26]; + for (int i = 0; i < 26; i++) { + graph[i] = new ArrayList<>(); + } + for (String equation : equations) { + if (equation.charAt(1) == '=') { + int first = equation.charAt(0) - 'a'; + int second = equation.charAt(3) - 'a'; + graph[first].add(second); + graph[second].add(first); + } + } + int[] color = new int[26]; + Arrays.fill(color, -1); + for (int i = 0; i < 26; i++) { + if (color[i] == -1) { + dfs(i, i, color, graph); + } + } + for (String equation : equations) { + if (equation.charAt(1) == '!') { + int first = equation.charAt(0) - 'a'; + int second = equation.charAt(3) - 'a'; + if (color[first] == color[second]) { + return false; + } + } + } + return true; + } + + private static void dfs(int node, int nodeColor, int[] color, List[] graph) { + if (color[node] == -1) { + color[node] = nodeColor; + for (int neighbor : graph[node]) { + dfs(neighbor, nodeColor, color, graph); + } + } + } +} diff --git a/Medium/Score After Flipping Matrix.java b/Medium/Score After Flipping Matrix.java index c369309d..54c3f3ac 100644 --- a/Medium/Score After Flipping Matrix.java +++ b/Medium/Score After Flipping Matrix.java @@ -1,59 +1,33 @@ class Solution { - public int matrixScore(int[][] A) { - for (int i=0; i actualSum) { - for (int j=0; j numOnes) { - for (int j=0; j rows-countZero) { + for(int i = 0; i < rows; i++) { + grid[i][j] = 1 - grid[i][j]; } } } - - int maxSum = 0; - for (int[] arr : A) { - maxSum += getDecimalValue(arr, false); - } - - return maxSum; - } - - private int getDecimalValue(int[] arr, boolean isToggled) { - int sum = 0; - int pow = 0; - - for (int i=arr.length-1; i>=0; i--) { - if (isToggled) { - sum += Math.pow(2, pow) * (arr[i] ^ 1); - } - else { - sum += Math.pow(2, pow) * arr[i]; + int score = 0; + for (int[] row : grid) { + for (int j = 0; j < cols; j++) { + score += row[j] << (cols - j - 1); } - - pow++; } - - return sum; + return score; } } diff --git a/Medium/Score of Parentheses.java b/Medium/Score of Parentheses.java index 0366b58d..43851423 100644 --- a/Medium/Score of Parentheses.java +++ b/Medium/Score of Parentheses.java @@ -1,25 +1,15 @@ class Solution { - public static int scoreOfParentheses(String S) { - Stack st = new Stack<>(); - for (int i=0; i stack = new Stack<>(); + int currMultiplier = 0; + for (char c : S.toCharArray()) { + if (c == '(') { + stack.push(currMultiplier); + currMultiplier = 0; + } else { + currMultiplier = stack.pop() + Math.max(2 * currMultiplier, 1); + } } + return currMultiplier; + } } diff --git a/Medium/Search Suggestions System.java b/Medium/Search Suggestions System.java new file mode 100644 index 00000000..47458964 --- /dev/null +++ b/Medium/Search Suggestions System.java @@ -0,0 +1,46 @@ +class Solution { + public List> suggestedProducts(String[] products, String searchWord) { + TrieNode root = new TrieNode(); + for (String prod : products) { + TrieNode curr = root; + for (char c : prod.toCharArray()) { + if (curr.children[c - 'a'] == null) { + curr.children[c - 'a'] = new TrieNode(); + } + curr = curr.children[c - 'a']; + curr.matchingProducts.add(prod); + } + } + List> result = new ArrayList<>(); + TrieNode curr = root; + for (char c : searchWord.toCharArray()) { + if (curr == null) { + result.add(new ArrayList<>()); + } else { + if (curr.children[c - 'a'] == null) { + curr = null; + result.add(new ArrayList<>()); + } else { + curr = curr.children[c - 'a']; + PriorityQueue currMatchingProductsQueue = new PriorityQueue<>(curr.matchingProducts); + List currMatchingProducts = new ArrayList<>(); + while (!currMatchingProductsQueue.isEmpty() && currMatchingProducts.size() < 3) { + currMatchingProducts.add(currMatchingProductsQueue.poll()); + } + result.add(currMatchingProducts); + } + } + } + return result; + } + + private class TrieNode { + TrieNode[] children; + PriorityQueue matchingProducts; + + public TrieNode() { + this.children = new TrieNode[26]; + this.matchingProducts = new PriorityQueue<>(); + } + } +} diff --git a/Medium/Search a 2D Matrix II.java b/Medium/Search a 2D Matrix II.java new file mode 100644 index 00000000..c409ef25 --- /dev/null +++ b/Medium/Search a 2D Matrix II.java @@ -0,0 +1,18 @@ +class Solution { + public boolean searchMatrix(int[][] matrix, int target) { + int rows = matrix.length; + int cols = matrix[0].length; + int rowIdx = rows - 1; + int colIdx = 0; + while (rowIdx >= 0 && colIdx < cols) { + if (matrix[rowIdx][colIdx] > target) { + rowIdx--; + } else if (matrix[rowIdx][colIdx] < target) { + colIdx++; + } else { + return true; + } + } + return false; + } +} diff --git a/Medium/Search a 2D Matrix.java b/Medium/Search a 2D Matrix.java index 1c8b5722..086454e0 100644 --- a/Medium/Search a 2D Matrix.java +++ b/Medium/Search a 2D Matrix.java @@ -1,37 +1,21 @@ class Solution { public boolean searchMatrix(int[][] matrix, int target) { - if (matrix.length == 0 || matrix[0].length == 0) { - return false; - } - - if (target < matrix[0][0] || target > matrix[matrix.length-1][matrix[matrix.length-1].length - 1]) { - return false; - } - - int i=0; - for (i=0; i= matrix[i][0] && target < matrix[i+1][0]) { - return binarySearch(matrix[i], 0, matrix[i].length-1, target); - } - } - - return binarySearch(matrix[i], 0, matrix[i].length-1, target); - } - - private boolean binarySearch(int[] arr, int start, int end, int target) { - while (start <= end) { - int mid = (start + end)/2; - if (arr[mid] == target) { + int row = matrix.length - 1; + int col = matrix[0].length - 1; + while (row >= 0 && col >= 0) { + if (matrix[row][col] == target) { return true; } - else if (arr[mid] > target) { - end = mid - 1; - } - else { - start = mid + 1; + if (matrix[row][col] > target) { + col--; + if (col < 0) { + col = matrix[0].length - 1; + row--; + } + } else { + row--; } } - return false; } } diff --git a/Medium/Search in Rotated Sorted Array II.java b/Medium/Search in Rotated Sorted Array II.java index 46baafb6..bcb34f99 100644 --- a/Medium/Search in Rotated Sorted Array II.java +++ b/Medium/Search in Rotated Sorted Array II.java @@ -1,11 +1,28 @@ class Solution { public boolean search(int[] nums, int target) { - for(int i=0;i nums[mid] && target <= nums[end]) { + start = mid + 1; + } else { + end = mid - 1; + } + } else if (nums[mid] > nums[start] || nums[mid] > nums[end]) { + if (target < nums[mid] && target >= nums[start]) { + end = mid - 1; + } else { + start = mid + 1; + } + } else { + end--; + } } - return false; } } diff --git a/Medium/Search in Rotated Sorted Array.java b/Medium/Search in Rotated Sorted Array.java index e078af3f..43104bf9 100644 --- a/Medium/Search in Rotated Sorted Array.java +++ b/Medium/Search in Rotated Sorted Array.java @@ -1,32 +1,29 @@ class Solution { - public int search(int[] nums, int target) { - int start = 0; - int end = nums.length - 1; - - while (start <= end) { - int mid = (start + end)/2; - if (nums[mid] == target) { - return mid; - } - if (nums[start] <= nums[mid]){ - if (target < nums[mid] && target >= nums[start]) { - end = mid - 1; - } - else { - start = mid + 1; - } - } - - else if (nums[mid] <= nums[end]){ - if (target > nums[mid] && target <= nums[end]) { - start = mid + 1; - } - else { - end = mid - 1; - } - } + public int search(int[] nums, int target) { + int start = 0; + int end = nums.length - 1; + while (start <= end) { + int mid = (start + end) / 2; + if (nums[mid] == target) { + return mid; + } + if (nums[mid] >= nums[start]) { + if (nums[start] <= target && nums[mid] > target) { + end = mid - 1; } - - return -1; + else { + start = mid + 1; + } + } + else { + if (nums[end] >= target && nums[mid] < target) { + start = mid + 1; + } + else { + end = mid - 1; + } + } } + return -1; + } } diff --git a/Medium/Seat Reservation Manager.java b/Medium/Seat Reservation Manager.java new file mode 100644 index 00000000..8a7e8edb --- /dev/null +++ b/Medium/Seat Reservation Manager.java @@ -0,0 +1,26 @@ +class SeatManager { + + private PriorityQueue seats; + + public SeatManager(int n) { + this.seats = new PriorityQueue<>(); + for (int i = 1; i <= n; i++) { + this.seats.add(i); + } + } + + public int reserve() { + return this.seats.poll(); + } + + public void unreserve(int seatNumber) { + this.seats.add(seatNumber); + } +} + +/** + * Your SeatManager object will be instantiated and called as such: + * SeatManager obj = new SeatManager(n); + * int param_1 = obj.reserve(); + * obj.unreserve(seatNumber); + */ diff --git a/Medium/Sender With Largest Word Count.java b/Medium/Sender With Largest Word Count.java new file mode 100644 index 00000000..6bb1bf25 --- /dev/null +++ b/Medium/Sender With Largest Word Count.java @@ -0,0 +1,22 @@ +import java.util.Map.Entry; + + +class Solution { + public String largestWordCount(String[] messages, String[] senders) { + Map map = new HashMap<>(); + for (int i = 0; i < messages.length; i++) { + int wordCount = messages[i].split("\\s+").length; + map.put(senders[i], map.getOrDefault(senders[i], 0) + wordCount); + } + return map.entrySet().stream() + .sorted((o1, o2) -> { + int c = o2.getValue() - o1.getValue(); + if (c != 0) { + return c; + } + return o2.getKey().compareTo(o1.getKey());}) + .map(Entry::getKey) + .findFirst() + .orElse(""); + } +} diff --git a/Medium/Sentence Similarity II.java b/Medium/Sentence Similarity II.java index 7ec66eaa..cda4a674 100644 --- a/Medium/Sentence Similarity II.java +++ b/Medium/Sentence Similarity II.java @@ -1,60 +1,43 @@ class Solution { - public boolean areSentencesSimilarTwo(String[] words1, String[] words2, List> pairs) { - Map> map = new HashMap<>(); - - for (List pair : pairs) { - String word1 = pair.get(0); - String word2 = pair.get(1); - - map.computeIfAbsent(word1, k -> new HashSet()).add(word2); - map.computeIfAbsent(word2, k -> new HashSet()).add(word1); - } - - int idx1 = 0; - int idx2 = 0; - - while (idx1 < words1.length && idx2 < words2.length) { - if (words1[idx1].equals(words2[idx2])) { - idx1++; - idx2++; - continue; - } - - if (!dfs(map, words1[idx1], words2[idx2])) { - return false; - } - - idx1++; - idx2++; - } - - return idx1 == words1.length && idx2 == words2.length; + public boolean areSentencesSimilarTwo(String[] words1, String[] words2, List> pairs) { + if (words1.length != words2.length) { + return false; } - - private boolean dfs(Map> map, String s, String t) { - Stack stack = new Stack<>(); - Set visited = new HashSet<>(); - - stack.push(s); - visited.add(s); - - while (!stack.isEmpty()) { - String word = stack.pop(); - if (word.equals(t)) { - return true; - } - if (map.containsKey(word)) { - Iterator iterator = map.get(word).iterator(); - while (iterator.hasNext()) { - String temp = iterator.next(); - if (!visited.contains(temp)) { - stack.push(temp); - visited.add(temp); - } - } - } - } - + Map> map = new HashMap<>(); + for (List pair : pairs) { + String word1 = pair.get(0); + String word2 = pair.get(1); + map.computeIfAbsent(word1, k -> new HashSet<>()).add(word2); + map.computeIfAbsent(word2, k -> new HashSet<>()).add(word1); + } + + for (int i = 0; i < words1.length; i++) { + String start = words1[i]; + String end = words2[i]; + if (!dfs(map, start, end)) { return false; + } + } + return true; + } + + private boolean dfs(Map> map, String start, String end) { + Queue queue = new LinkedList<>(); + Set set = new HashSet<>(); + queue.add(start); + set.add(start); + while (!queue.isEmpty()) { + String removed = queue.remove(); + if (removed.equals(end)) { + return true; + } + for (String similar : map.getOrDefault(removed, new HashSet<>())) { + if (!set.contains(similar)) { + queue.add(similar); + set.add(similar); + } + } } + return false; + } } diff --git a/Medium/Sentence Similarity III.java b/Medium/Sentence Similarity III.java new file mode 100644 index 00000000..506dc110 --- /dev/null +++ b/Medium/Sentence Similarity III.java @@ -0,0 +1,26 @@ +class Solution { + public boolean areSentencesSimilar(String sentence1, String sentence2) { + int idxOneStart = 0; + int idxTwoStart = 0; + String[] wordsOne = sentence1.split("\\s+"); + String[] wordsTwo = sentence2.split("\\s+"); + while (idxOneStart < wordsOne.length && idxOneStart < wordsTwo.length && wordsOne[idxOneStart].equals(wordsTwo[idxTwoStart])) { + idxOneStart++; + idxTwoStart++; + } + boolean startFound = idxOneStart > 0; + if (idxOneStart == wordsOne.length && idxTwoStart == wordsTwo.length) { + return true; + } + int idxOneEnd = wordsOne.length - 1; + int idxTwoEnd = wordsTwo.length - 1; + while (idxOneEnd >= idxOneStart && idxTwoEnd >= idxTwoStart && wordsOne[idxOneEnd].equals(wordsTwo[idxTwoEnd])) { + idxOneEnd--; + idxTwoEnd--; + } + if (idxOneEnd != idxOneStart - 1 && idxTwoEnd != idxTwoStart - 1) { + return false; + } + return true; + } +} diff --git a/Medium/Separate Black and White Balls.java b/Medium/Separate Black and White Balls.java new file mode 100644 index 00000000..5fc4900f --- /dev/null +++ b/Medium/Separate Black and White Balls.java @@ -0,0 +1,13 @@ +class Solution { + public long minimumSteps(String s) { + int whitePos = 0; + long swaps = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '0') { + swaps += i - whitePos; + whitePos++; + } + } + return swaps; + } +} diff --git a/Medium/Sequential Digits.java b/Medium/Sequential Digits.java new file mode 100644 index 00000000..94cc1b23 --- /dev/null +++ b/Medium/Sequential Digits.java @@ -0,0 +1,18 @@ +class Solution { + public List sequentialDigits(int low, int high) { + String bucket = "123456789"; + int n = 10; + List result = new ArrayList<>(); + int minLength = String.valueOf(low).length(); + int maxLength = String.valueOf(high).length(); + for (int currLength = minLength; currLength <= maxLength; currLength++) { + for (int idx = 0; idx < n - currLength; idx++) { + int num = Integer.parseInt(bucket.substring(idx, idx + currLength)); + if (num >= low && num <= high) { + result.add(num); + } + } + } + return result; + } +} diff --git a/Medium/Serialize and Deserialize BST.java b/Medium/Serialize and Deserialize BST.java index 7f740386..a6da4bff 100644 --- a/Medium/Serialize and Deserialize BST.java +++ b/Medium/Serialize and Deserialize BST.java @@ -10,51 +10,49 @@ public class Codec { // Encodes a tree to a single string. - public StringBuilder sb; public String serialize(TreeNode root) { if (root == null) { return "#"; } - - sb = new StringBuilder(); - serializeHelper(root); - return sb.toString(); + StringBuilder sb = new StringBuilder(); + dfsSerialize(root, sb); + return sb.toString().trim(); } - - private void serializeHelper(TreeNode root) { + + private void dfsSerialize(TreeNode root, StringBuilder sb) { if (root == null) { - sb.append('#').append(','); + sb.append("#").append(" "); return; } - - sb.append(root.val).append(','); - serializeHelper(root.left); - serializeHelper(root.right); + sb.append(root.val).append(" "); + dfsSerialize(root.left, sb); + dfsSerialize(root.right, sb); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { - Queue q = new LinkedList<>(Arrays.asList(data.split(","))); - return deserializeHelper(q); + Queue queue = new LinkedList<>(Arrays.asList(data.split("\\s+"))); + return dfsDeserialize(queue); } - - private TreeNode deserializeHelper(Queue queue) { + + private TreeNode dfsDeserialize(Queue queue) { if (queue.isEmpty()) { return null; } - String s = queue.remove(); - if (s.equals("#")) { + String removed = queue.remove(); + if (removed.equals("#")) { return null; } - - TreeNode root = new TreeNode(Integer.parseInt(s)); - root.left = deserializeHelper(queue); - root.right = deserializeHelper(queue); - + TreeNode root = new TreeNode(Integer.parseInt(removed)); + root.left = dfsDeserialize(queue); + root.right = dfsDeserialize(queue); return root; } } // Your Codec object will be instantiated and called as such: -// Codec codec = new Codec(); -// codec.deserialize(codec.serialize(root)); +// Codec ser = new Codec(); +// Codec deser = new Codec(); +// String tree = ser.serialize(root); +// TreeNode ans = deser.deserialize(tree); +// return ans; diff --git a/Medium/Set Matrix Zeroes.java b/Medium/Set Matrix Zeroes.java index 6c043646..d2a2e67a 100644 --- a/Medium/Set Matrix Zeroes.java +++ b/Medium/Set Matrix Zeroes.java @@ -1,64 +1,52 @@ class Solution { - public void setZeroes(int[][] arr) { - if (arr.length == 0 || arr[0].length == 0) { - return; - } - - - int numOfRows = arr.length; - int numOfCols = arr[0].length; - boolean firstRowZero = false; - boolean firstColZero = false; - - for (int i = 0; i < numOfCols; i++) { - if (arr[0][i] == 0) { - firstRowZero = true; - break; - } - } - - for (int i = 0; i < numOfRows; i++) { - if (arr[i][0] == 0) { - firstColZero = true; - break; - } - } - - for (int i = 1; i < numOfRows; i++) { - for (int j = 0; j < numOfCols; j++) { - if (arr[i][j] == 0) { - arr[0][j] = 0; - arr[i][0] = 0; - } - } - } - - for (int i = 1; i < numOfRows; i++) { - if (arr[i][0] == 0) { - for (int j = 1; j < numOfCols; j++) { - arr[i][j] = 0; - } - } - } - - for (int i = 0; i < numOfCols; i++) { - if (arr[0][i] == 0) { - for (int j = 1; j < numOfRows; j++) { - arr[j][i] = 0; - } - } + public void setZeroes(int[][] matrix) { + int rows = matrix.length; + int cols = matrix[0].length; + boolean firstRowZero = false; + boolean firstColZero = false; + for (int i = 0; i < rows; i++) { + if (matrix[i][0] == 0) { + firstColZero = true; + break; + } + } + for (int i = 0; i < cols; i++) { + if (matrix[0][i] == 0) { + firstRowZero = true; + break; + } + } + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (matrix[i][j] == 0) { + matrix[0][j] = 0; + matrix[i][0] = 0; } - - if (firstRowZero) { - for (int i = 0; i < numOfCols; i++) { - arr[0][i] = 0; - } + } + } + for (int i = 1; i < rows; i++) { + if (matrix[i][0] == 0) { + for (int j = 0; j < cols; j++) { + matrix[i][j] = 0; } - - if (firstColZero) { - for (int i = 0; i < numOfRows; i++) { - arr[i][0] = 0; - } + } + } + for (int i = 1; i < cols; i++) { + if (matrix[0][i] == 0) { + for (int j = 0; j < rows; j++) { + matrix[j][i] = 0; } + } + } + if (firstRowZero) { + for (int i = 0; i < cols; i++) { + matrix[0][i] = 0; + } + } + if (firstColZero) { + for (int i = 0; i < rows; i++) { + matrix[i][0] = 0; + } } + } } diff --git a/Medium/Shifting Letters.java b/Medium/Shifting Letters.java index ccdaa3b4..7d1e7c18 100644 --- a/Medium/Shifting Letters.java +++ b/Medium/Shifting Letters.java @@ -1,40 +1,16 @@ class Solution { - public String shiftingLetters(String S, int[] shifts) { - long[] numOfShifts = getNumOfShifts(shifts); - String shiftedString = getShiftedString(S, numOfShifts); - - return shiftedString; - } - - private long[] getNumOfShifts(int[] shifts) { - long totalShifts = 0; - long[] cumulativeSum = new long[shifts.length]; - for (int i=0; i 0 ? cumulativeSum[i-1] : 0)) % 26; - } - - return numOfShifts; - } - - private String getShiftedString(String s, long[] numOfShifts) { - StringBuilder sb = new StringBuilder(); - - for (int i=0; i 122) { - shiftedValue = 96 + (shiftedValue - 122); - } - - sb.append((char) shiftedValue); - } - - return sb.toString(); + public String shiftingLetters(String s, int[] shifts) { + long totalShifts = 0; + StringBuilder sb = new StringBuilder(); + for (int i = shifts.length - 1; i >= 0; i--) { + totalShifts += shifts[i]; + sb.append(getShiftedChar(s.charAt(i), totalShifts)); } + return sb.reverse().toString(); + } + + private char getShiftedChar(char c, long shifts) { + long newAscii = ((int) c) + (shifts % 26); + return (char) (newAscii > 122 ? (97 + (newAscii - 122) - 1) : newAscii); + } } diff --git a/Medium/Short Encoding of Words.java b/Medium/Short Encoding of Words.java new file mode 100644 index 00000000..6eccb589 --- /dev/null +++ b/Medium/Short Encoding of Words.java @@ -0,0 +1,34 @@ +class Solution { + public int minimumLengthEncoding(String[] words) { + TrieNode root = new TrieNode(); + Map nodes = new HashMap<>(); + for (int i = 0; i < words.length; i++) { + TrieNode curr = root; + for (int j = words[i].length() - 1; j >= 0; j--) { + if (curr.children[words[i].charAt(j) - 'a'] == null) { + curr.children[words[i].charAt(j) - 'a'] = new TrieNode(); + curr.count++; + } + curr = curr.children[words[i].charAt(j) - 'a']; + } + nodes.put(curr, i); + } + int result = 0; + for (TrieNode node : nodes.keySet()) { + if (node.count == 0) { + result += words[nodes.get(node)].length() + 1; + } + } + return result; + } + + private class TrieNode { + TrieNode[] children; + int count; + + public TrieNode() { + this.children = new TrieNode[26]; + this.count = 0; + } + } +} diff --git a/Medium/Shortest Bridge.java b/Medium/Shortest Bridge.java new file mode 100644 index 00000000..f5194373 --- /dev/null +++ b/Medium/Shortest Bridge.java @@ -0,0 +1,65 @@ +class Solution { + + private static final int[][] DIRS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + + public int shortestBridge(int[][] grid) { + int n = grid.length; + int x = -1; + int y = -1; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1) { + x = i; + y = j; + break; + } + } + } + List queueOne = new ArrayList<>(); + List queueTwo = new ArrayList<>(); + queueOne.add(new int[]{x, y}); + queueTwo.add(new int[]{x, y}); + grid[x][y] = 2; + while (!queueOne.isEmpty()) { + List bfs = new ArrayList<>(); + for (int[] cell : queueOne) { + int currX = cell[0]; + int currY = cell[1]; + for (int[] dir : DIRS) { + int newX = currX + dir[0]; + int newY = currY + dir[1]; + if (newX >= 0 && newX < n && newY >= 0 && newY < n && grid[newX][newY] == 1) { + bfs.add(new int[]{newX, newY}); + queueTwo.add(new int[]{newX, newY}); + grid[newX][newY] = 2; + } + } + } + queueOne = bfs; + } + int distance = 0; + while (!queueTwo.isEmpty()) { + List bfs = new ArrayList<>(); + for (int[] cell : queueTwo) { + int currX = cell[0]; + int currY = cell[1]; + for (int[] dir : DIRS) { + int newX = currX + dir[0]; + int newY = currY + dir[1]; + if (newX >= 0 && newX < n && newY >= 0 && newY < n) { + if (grid[newX][newY] == 1) { + return distance; + } else if (grid[newX][newY] == 0) { + bfs.add(new int[]{newX, newY}); + grid[newX][newY] = -1; + } + } + } + } + queueTwo = bfs; + distance++; + } + return distance; + } +} + diff --git a/Medium/Shortest Distance After Road Addition Queries I.java b/Medium/Shortest Distance After Road Addition Queries I.java new file mode 100644 index 00000000..19a2ea74 --- /dev/null +++ b/Medium/Shortest Distance After Road Addition Queries I.java @@ -0,0 +1,39 @@ +class Solution { + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + Map> graph = new HashMap<>(); + for (int i = 0; i < n - 1; i++) { + graph.computeIfAbsent(i, k -> new HashSet<>()).add(i + 1); + } + int[] result = new int[queries.length]; + for (int i = 0; i < queries.length; i++) { + int[] query = queries[i]; + graph.computeIfAbsent(query[0], k -> new HashSet<>()).add(query[1]); + result[i] = findDistance(graph, n - 1); + } + return result; + } + + private int findDistance(Map> graph, int target) { + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); + queue.add(0); + int distance = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + Integer node = queue.poll(); + if (node == target) { + return distance; + } + for (Integer neighbor : graph.get(node)) { + if (!visited.contains(neighbor)) { + queue.add(neighbor); + visited.add(node); + } + } + } + distance++; + } + return -1; + } +} diff --git a/Medium/Shortest Path in Binary Matrix.java b/Medium/Shortest Path in Binary Matrix.java new file mode 100644 index 00000000..0be69c86 --- /dev/null +++ b/Medium/Shortest Path in Binary Matrix.java @@ -0,0 +1,40 @@ +class Solution { + + private static final int[][] DIRS = {{0,1},{0,-1},{1,0},{-1,0},{1,-1},{-1,1},{-1,-1},{1,1}}; + + public int shortestPathBinaryMatrix(int[][] grid) { + int numRows = grid.length; + int numCols = grid[0].length; + if (grid[0][0] == 1 || grid[numRows - 1][numCols - 1] == 1) { + return -1; + } + int shortestDistance = 0; + Queue queue = new LinkedList<>(); + queue.add(new int[]{0, 0}); + boolean[][] visited = new boolean[numRows][numCols]; + visited[0][0] = true; + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + if (removed[0] == (numRows - 1) && removed[1] == (numCols - 1)) { + return shortestDistance + 1; + } + for (int i = 0; i < DIRS.length; i++) { + int newX = removed[0] + DIRS[i][0]; + int newY = removed[1] + DIRS[i][1]; + if (isValidCoordinate(newX, newY, numRows, numCols, visited, grid)) { + queue.add(new int[]{newX, newY}); + visited[newX][newY] = true; + } + } + } + shortestDistance++; + } + return -1; + } + + private static boolean isValidCoordinate(int x, int y, int rows, int cols, boolean[][] visited, int[][] grid) { + return x >= 0 && x < rows && y >= 0 && y < cols && !visited[x][y] && grid[x][y] == 0; + } +} diff --git a/Medium/Shortest Path with Alternating Colors.java b/Medium/Shortest Path with Alternating Colors.java new file mode 100644 index 00000000..63f670d0 --- /dev/null +++ b/Medium/Shortest Path with Alternating Colors.java @@ -0,0 +1,57 @@ +class Solution { + + private static final Integer RED = 1; + private static final Integer BLUE = 2; + + public int[] shortestAlternatingPaths(int n, int[][] red_edges, int[][] blue_edges) { + Map> map = new HashMap<>(); + for (int[] edge : red_edges) { + map.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(new Connection(edge[1], RED)); + } + for (int[] edge : blue_edges) { + map.computeIfAbsent(edge[0], k -> new ArrayList<>()).add(new Connection(edge[1], BLUE)); + } + int[] distances = new int[n]; + for (int i = 1; i < n; i++) { + distances[i] = getDistance(map, i, n); + } + return distances; + } + + private int getDistance(Map> map, int target, int n) { + int steps = 0; + Queue queue = new LinkedList<>(); + boolean[][] visited = new boolean[2][n]; + queue.add(new int[]{0, -1}); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + int[] removed = queue.remove(); + if (removed[0] == target) { + return steps; + } + int color = removed[1]; + for (Connection connection : map.getOrDefault(removed[0], new ArrayList<>())) { + if (color == -1 && !visited[connection.color - 1][connection.val]) { + visited[connection.color - 1][connection.val] = true; + queue.add(connection.getArray()); + } else if (color == 1 && connection.color != 1 && !visited[connection.color - 1][connection.val]) { + visited[connection.color - 1][connection.val] = true; + queue.add(connection.getArray()); + } else if (color == 2 && connection.color != 2 && !visited[connection.color - 1][connection.val]) { + visited[connection.color - 1][connection.val] = true; + queue.add(connection.getArray()); + } + } + } + steps++; + } + return -1; + } + + private record Connection(int val, int color) { + public int[] getArray() { + return new int[]{this.val, this.color}; + } + } +} diff --git a/Medium/Shortest Subarray to be Removed to Make Array Sorted.java b/Medium/Shortest Subarray to be Removed to Make Array Sorted.java new file mode 100644 index 00000000..4ddb25e2 --- /dev/null +++ b/Medium/Shortest Subarray to be Removed to Make Array Sorted.java @@ -0,0 +1,18 @@ +class Solution { + public int findLengthOfShortestSubarray(int[] arr) { + int right = arr.length - 1; + while (right > 0 && arr[right] >= arr[right - 1]) { + right--; + } + int result = right; + int left = 0; + while (left < right && (left == 0 || arr[left - 1] <= arr[left])) { + while (right < arr.length && arr[left] > arr[right]) { + right++; + } + result = Math.min(result, right - left - 1); + left++; + } + return result; + } +} diff --git a/Medium/Shortest Unsorted Continuous Subarray.java b/Medium/Shortest Unsorted Continuous Subarray.java new file mode 100644 index 00000000..22fd54da --- /dev/null +++ b/Medium/Shortest Unsorted Continuous Subarray.java @@ -0,0 +1,21 @@ +class Solution { + public int findUnsortedSubarray(int[] nums) { + Stack stack = new Stack<>(); + int start = nums.length; + for (int i = 0; i < nums.length; i++) { + while (!stack.isEmpty() && nums[stack.peek()] > nums[i]) { + start = Math.min(start, stack.pop()); + } + stack.push(i); + } + stack.clear(); + int end = 0; + for (int i = nums.length - 1; i >= 0; i--) { + while (!stack.isEmpty() && nums[stack.peek()] < nums[i]) { + end = Math.max(end, stack.pop()); + } + stack.push(i); + } + return end - start > 0 ? end - start + 1 : 0; + } +} diff --git a/Medium/Shortest Way to Form String.java b/Medium/Shortest Way to Form String.java index e2eee944..e87eaf33 100644 --- a/Medium/Shortest Way to Form String.java +++ b/Medium/Shortest Way to Form String.java @@ -1,24 +1,23 @@ class Solution { public int shortestWay(String source, String target) { - int idx = 0; + Set letters = source.chars().mapToObj(c -> (char) c).collect(Collectors.toSet()); int count = 0; - int n = target.length(); - while (idx < n) { - int slow = idx; - - for (char c : source.toCharArray()) { - if (idx < n && c == target.charAt(idx)) { - idx++; - } - } - - if (slow == idx) { + int sourceIdx = 0; + int targetIdx = 0; + while (targetIdx < target.length()) { + char targetLetter = target.charAt(targetIdx); + if (!letters.contains(targetLetter)) { return -1; } - - count++; + if (targetLetter == source.charAt(sourceIdx)) { + targetIdx++; + } + sourceIdx++; + if (sourceIdx == source.length()) { + sourceIdx = 0; + count++; + } } - - return count; + return count + (sourceIdx == 0 ? 0 : 1); } } diff --git a/Medium/Shortest Word Distance II.java b/Medium/Shortest Word Distance II.java new file mode 100644 index 00000000..3a33f75d --- /dev/null +++ b/Medium/Shortest Word Distance II.java @@ -0,0 +1,36 @@ +class WordDistance { + + private Map> locations; + + public WordDistance(String[] wordsDict) { + this.locations = new HashMap<>(); + for (int i = 0; i < wordsDict.length; i++) { + this.locations.computeIfAbsent(wordsDict[i], k -> new ArrayList<>()).add(i); + } + } + + public int shortest(String word1, String word2) { + List indicesOne = this.locations.get(word1); + List indicesTwo = this.locations.get(word2); + int idxOne = 0; + int idxTwo = 0; + int minimumIndexDifference = Integer.MAX_VALUE; + while (idxOne < indicesOne.size() && idxTwo < indicesTwo.size()) { + minimumIndexDifference = Math.min( + minimumIndexDifference, + Math.abs(indicesOne.get(idxOne) - indicesTwo.get(idxTwo))); + if (indicesOne.get(idxOne) < indicesTwo.get(idxTwo)) { + idxOne++; + } else { + idxTwo++; + } + } + return minimumIndexDifference; + } +} + +/** + * Your WordDistance object will be instantiated and called as such: + * WordDistance obj = new WordDistance(wordsDict); + * int param_1 = obj.shortest(word1,word2); + */ diff --git a/Medium/Shortest Word Distance III.java b/Medium/Shortest Word Distance III.java new file mode 100644 index 00000000..fba93082 --- /dev/null +++ b/Medium/Shortest Word Distance III.java @@ -0,0 +1,24 @@ +class Solution { + public int shortestWordDistance(String[] wordsDict, String word1, String word2) { + int idxOne = -1; + int idxTwo = -1; + int minDistance = Integer.MAX_VALUE; + boolean sameWord = word1.equals(word2); + for (int i = 0; i < wordsDict.length; i++) { + if (wordsDict[i].equals(word1)) { + idxOne = sameWord ? (idxOne == -1 ? i : idxOne) : i; + } + if (wordsDict[i].equals(word2)) { + idxTwo = sameWord ? (idxOne != i ? i : idxTwo) : i; + } + if (idxOne != -1 && idxTwo != -1) { + minDistance = Math.min(minDistance, Math.abs(idxOne - idxTwo)); + if (sameWord) { + idxOne = idxTwo; + idxTwo = -1; + } + } + } + return minDistance; + } +} diff --git a/Medium/Simple Bank System.java b/Medium/Simple Bank System.java new file mode 100644 index 00000000..a674aa0f --- /dev/null +++ b/Medium/Simple Bank System.java @@ -0,0 +1,44 @@ +class Bank { + + private long[] balance; + public Bank(long[] balance) { + this.balance = balance; + } + + public boolean transfer(int account1, int account2, long money) { + if (isInvalidAccount(account1) || isInvalidAccount(account2) || balance[account1 - 1] < money) { + return false; + } + balance[account1 - 1] -= money; + balance[account2 - 1] += money; + return true; + } + + public boolean deposit(int account, long money) { + if (isInvalidAccount(account)) { + return false; + } + balance[account - 1] += money; + return true; + } + + public boolean withdraw(int account, long money) { + if (isInvalidAccount(account) || balance[account - 1] < money) { + return false; + } + balance[account - 1] -= money; + return true; + } + + private boolean isInvalidAccount(int accountId) { + return !(accountId >= 1 && accountId <= this.balance.length); + } +} + +/** + * Your Bank object will be instantiated and called as such: + * Bank obj = new Bank(balance); + * boolean param_1 = obj.transfer(account1,account2,money); + * boolean param_2 = obj.deposit(account,money); + * boolean param_3 = obj.withdraw(account,money); + */ diff --git a/Medium/Simplify Path.java b/Medium/Simplify Path.java index a968b625..b04ccd5e 100644 --- a/Medium/Simplify Path.java +++ b/Medium/Simplify Path.java @@ -1,46 +1,23 @@ class Solution { public String simplifyPath(String path) { Stack stack = new Stack<>(); - StringBuilder sb = new StringBuilder(); - int idx = 0; - int n = path.length(); - - while (idx < n) { - if (path.charAt(idx) != '/') { - sb.append(path.charAt(idx)); - while (idx + 1 < n && path.charAt(idx + 1) != '/') { - sb.append(path.charAt(idx + 1)); - idx++; - } - - if (sb.toString().equals("..")) { - if (!stack.isEmpty()) { - stack.pop(); - } - } - else if (!sb.toString().equals(".")) { - stack.push(sb.toString()); + String[] splits = path.split("\\/"); + for (String split : splits) { + if (split.equals(".") || split.equals("/") || split.isBlank()) { + continue; + } + if (split.equals("..")) { + if (!stack.isEmpty()) { + stack.pop(); } - - sb.setLength(0); + } else { + stack.push(split); } - - idx++; } - - List list = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); while (!stack.isEmpty()) { - list.add(stack.pop()); - } - - sb.append("/"); - for (int i = list.size() - 1; i >= 0; i--) { - sb.append(list.get(i)); - if (i != 0) { - sb.append("/"); - } + sb.insert(0, stack.pop()).insert(0, "/"); } - - return sb.toString(); + return sb.length() == 0 ? "/" : sb.toString(); } } diff --git a/Medium/Single Element in a Sorted Array.java b/Medium/Single Element in a Sorted Array.java index 82edcfee..924794d3 100644 --- a/Medium/Single Element in a Sorted Array.java +++ b/Medium/Single Element in a Sorted Array.java @@ -1,13 +1,25 @@ class Solution { public int singleNonDuplicate(int[] nums) { - boolean evenInd = true; - for (int i=0;i map = new HashMap<>(); - - for (int i=0;i entry : map.entrySet()) { - if (entry.getValue() != 3) { - return entry.getKey(); - } - } - - return -1; + public int singleNumber(int[] nums) { + int seenOnce = 0; + int seenTwice = 0; + for (int num : nums) { + seenOnce = ~seenTwice & (seenOnce ^ num); + seenTwice = ~seenOnce & (seenTwice ^ num); } + return seenOnce; + } } diff --git a/Medium/Single Number III.java b/Medium/Single Number III.java index f098e747..0409a84a 100644 --- a/Medium/Single Number III.java +++ b/Medium/Single Number III.java @@ -1,32 +1,17 @@ class Solution { - public int[] singleNumber(int[] nums) { - Map map = new HashMap(); - - for (int i=0;i entry : map.entrySet()) { - if (entry.getValue() == 1) { - if (j == 0) { - ans[j] = entry.getKey(); - j++; - } - else { - ans[j] = entry.getKey(); - break; - } - } - } - - return ans; + public int[] singleNumber(int[] nums) { + int xorValue = Integer.highestOneBit(Arrays.stream(nums) + .boxed() + .reduce((a, b) -> a ^ b) + .orElse(0)); + int[] result = new int[2]; + for (int num : nums) { + if ((xorValue & num) == 0) { + result[0] ^= num; + } else { + result[1] ^= num; + } } + return result; + } } diff --git a/Medium/Smallest Common Region.java b/Medium/Smallest Common Region.java new file mode 100644 index 00000000..4d8ce894 --- /dev/null +++ b/Medium/Smallest Common Region.java @@ -0,0 +1,32 @@ +class Solution { + public String findSmallestRegion(List> regions, String region1, String region2) { + Map regionToParentMap = new HashMap<>(); + for (List region : regions) { + String parent = region.getFirst(); + for (int i = 1; i < region.size(); i++) { + regionToParentMap.put(region.get(i), parent); + } + } + List pathOne = trace(region1, regionToParentMap); + List pathTwo = trace(region2, regionToParentMap); + int idxOne = 0; + int idxTwo = 0; + while (idxOne < pathOne.size() && idxTwo < pathTwo.size() && pathOne.get(idxOne).equals(pathTwo.get(idxTwo))) { + idxOne++; + idxTwo++; + } + return pathOne.get(idxOne - 1); + } + + private List trace(String region, Map regionToParentMap) { + List path = new ArrayList<>(); + path.add(region); + while (regionToParentMap.containsKey(region)) { + String parent = regionToParentMap.get(region); + path.add(parent); + region = parent; + } + Collections.reverse(path); + return path; + } +} diff --git a/Medium/Smallest Integer Divisible by K.java b/Medium/Smallest Integer Divisible by K.java new file mode 100644 index 00000000..52575545 --- /dev/null +++ b/Medium/Smallest Integer Divisible by K.java @@ -0,0 +1,15 @@ +class Solution { + public int smallestRepunitDivByK(int K) { + if (K % 2 == 0 || K % 5 == 0) { + return -1; + } + int remainder = 0; + for (int n = 1; n <= K; n++) { + remainder = (remainder * 10 + 1) % K; + if (remainder == 0) { + return n; + } + } + return -1; + } +} diff --git a/Medium/Smallest Number in Infinite Set.java b/Medium/Smallest Number in Infinite Set.java new file mode 100644 index 00000000..2555f5ce --- /dev/null +++ b/Medium/Smallest Number in Infinite Set.java @@ -0,0 +1,34 @@ +class SmallestInfiniteSet { + + private final PriorityQueue pq; + private int current; + + public SmallestInfiniteSet() { + this.pq = new PriorityQueue<>(); + this.current = 1; + } + + public int popSmallest() { + int result = current; + if (!pq.isEmpty() && pq.peek() < current) { + result = pq.poll(); + } else { + current++; + } + while (!pq.isEmpty() && pq.peek() == result) { + pq.poll(); + } + return result; + } + + public void addBack(int num) { + pq.add(num); + } +} + +/** + * Your SmallestInfiniteSet object will be instantiated and called as such: + * SmallestInfiniteSet obj = new SmallestInfiniteSet(); + * int param_1 = obj.popSmallest(); + * obj.addBack(num); + */ diff --git a/Medium/Smallest String Starting From Leaf.java b/Medium/Smallest String Starting From Leaf.java index d890af9e..6948a960 100644 --- a/Medium/Smallest String Starting From Leaf.java +++ b/Medium/Smallest String Starting From Leaf.java @@ -4,36 +4,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - public String smallestFromLeaf(TreeNode root) { - return helper(root); + public String smallestFromLeaf(TreeNode root) { + return dfs(root, ""); + } + + private String dfs(TreeNode root, String curr) { + if (root == null) { + return curr; } - - private String helper(TreeNode root) { - if (root == null) { - return null; - } - - char ch = (char) (97 + root.val); - String leftVal = helper(root.left); - String rightVal = helper(root.right); - - if (leftVal == null && rightVal == null) { - return "" + ch; - } - - if (root.left == null || root.right == null) { - return rightVal == null ? leftVal + ch : rightVal + ch; - } - - if (rightVal.compareTo(leftVal) > 0) { - return leftVal + ch; - } - else { - return rightVal + ch; - } + curr = "" + (char)(97 + root.val) + curr; + if (root.left == null && root.right == null) { + return curr; + } else if (root.left == null || root.right == null) { + return root.left == null ? dfs(root.right, curr) : dfs(root.left, curr); + } else { + String left = dfs(root.left, curr); + String right = dfs(root.right, curr); + return left.compareTo(right) <= 0 ? left : right; } + } } diff --git a/Medium/Smallest String With A Given Numeric Value.java b/Medium/Smallest String With A Given Numeric Value.java new file mode 100644 index 00000000..6957c53c --- /dev/null +++ b/Medium/Smallest String With A Given Numeric Value.java @@ -0,0 +1,12 @@ +class Solution { + public String getSmallestString(int n, int k) { + StringBuilder sb = new StringBuilder(); + while (k > 0) { + int maxPossible = Math.min(k - n + 1, 26); + sb.append((char) ('a' + maxPossible - 1)); + k -= maxPossible; + n--; + } + return sb.reverse().toString(); + } +} diff --git a/Medium/Smallest String With Swaps.java b/Medium/Smallest String With Swaps.java new file mode 100644 index 00000000..e9cea772 --- /dev/null +++ b/Medium/Smallest String With Swaps.java @@ -0,0 +1,60 @@ +class Solution { + public String smallestStringWithSwaps(String s, List> pairs) { + int n = s.length(); + DisjointSet disjointSet = new DisjointSet(n); + for (List pair : pairs) { + disjointSet.union(pair.get(0), pair.get(1)); + } + Map> map = new HashMap<>(); + for (int i = 0; i < n; i++) { + int root = disjointSet.find(i); + map.computeIfAbsent(root, k -> new PriorityQueue<>()).offer(s.charAt(i)); + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + sb.append(map.get(disjointSet.find(i)).poll()); + } + return sb.toString(); + } + + private static final class DisjointSet { + + private final int[] root; + private final int[] rank; + public int unionCount; + + public DisjointSet(int size) { + this.root = new int[size]; + this.rank = new int[size]; + for (int i = 0; i < size; i++) { + this.root[i] = i; + this.rank[i] = 1; + } + this.unionCount = size; + } + + public void union(int nodeOne, int nodeTwo) { + int rootOne = find(nodeOne); + int rootTwo = find(nodeTwo); + if (rootOne != rootTwo) { + if (this.rank[rootOne] > this.rank[rootTwo]) { + this.root[rootTwo] = rootOne; + } else if (this.rank[rootOne] < this.rank[rootTwo]) { + this.root[rootOne] = rootTwo; + } else { + this.root[rootTwo] = rootOne; + this.rank[rootOne]++; + } + this.unionCount--; + } + } + + + public int find(int node) { + if (node == root[node]) { + return node; + } + return root[node] = find(root[node]); + } + } +} diff --git a/Medium/Smallest Subtree with all the Deepest Nodes.java b/Medium/Smallest Subtree with all the Deepest Nodes.java new file mode 100644 index 00000000..5ad5f59d --- /dev/null +++ b/Medium/Smallest Subtree with all the Deepest Nodes.java @@ -0,0 +1,45 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode subtreeWithAllDeepest(TreeNode root) { + return dfs(root).node; + } + + private NodeResult dfs(TreeNode root) { + if (root == null) { + return new NodeResult(null, 0); + } + NodeResult leftResult = dfs(root.left); + NodeResult rightResult = dfs(root.right); + if (leftResult.distance > rightResult.distance) { + return new NodeResult(leftResult.node, leftResult.distance + 1); + } + if (leftResult.distance < rightResult.distance) { + return new NodeResult(rightResult.node, rightResult.distance + 1); + } + return new NodeResult(root, rightResult.distance + 1); + } + + private static class NodeResult { + TreeNode node; + int distance; + + public NodeResult(TreeNode node, int distance) { + this.node = node; + this.distance = distance; + } + } +} diff --git a/Medium/Smallest Value of the Rearranged Number.java b/Medium/Smallest Value of the Rearranged Number.java new file mode 100644 index 00000000..13dfdc46 --- /dev/null +++ b/Medium/Smallest Value of the Rearranged Number.java @@ -0,0 +1,35 @@ +class Solution { + public long smallestNumber(long num) { + return num < 0 ? + getArrangement(Math.abs(num), (o1, o2) -> (int) (o2 - o1), true) * -1 : + getArrangement(num, (o1, o2) -> (int) (o1 - o2), false); + } + + private long getArrangement(long num, Comparator comparator, boolean zeroAtEnd) { + PriorityQueue pq = new PriorityQueue<>(comparator); + long zeroMultiple = 1; + while (num > 0) { + long remainder = num % 10; + if (remainder == 0) { + zeroMultiple *= 10; + } else { + pq.add(remainder); + } + num /= 10; + } + long result = 0; + if (!pq.isEmpty()) { + result = result * 10 + pq.poll(); + } + if (!zeroAtEnd) { + result *= zeroMultiple; + } + while (!pq.isEmpty()) { + result = result * 10 + pq.poll(); + } + if (zeroAtEnd) { + result *= zeroMultiple; + } + return result; + } +} diff --git a/Medium/Snakes and Ladders.java b/Medium/Snakes and Ladders.java new file mode 100644 index 00000000..4c44f976 --- /dev/null +++ b/Medium/Snakes and Ladders.java @@ -0,0 +1,34 @@ +class Solution { + public int snakesAndLadders(int[][] board) { + int n = board.length; + Map map = new HashMap<>(); + map.put(1, 0); + Queue queue = new LinkedList<>(); + queue.add(1); + while (!queue.isEmpty()) { + int s = queue.remove(); + if (s == n * n) { + return map.get(s); + } + for (int i = s + 1; i <= Math.min(s + 6, n * n); i++) { + int rc = helper(i, n); + int r = rc / n; + int c = rc % n; + int point = board[r][c] == -1 ? i : board[r][c]; + if (!map.containsKey(point)) { + map.put(point, map.get(s) + 1); + queue.add(point); + } + } + } + return -1; + } + + public int helper(int s, int N) { + int quot = (s - 1) / N; + int rem = (s - 1) % N; + int row = N - 1 - quot; + int col = row % 2 != N % 2 ? rem : N - 1 - rem; + return row * N + col; + } +} diff --git a/Medium/Snapshot Array.java b/Medium/Snapshot Array.java new file mode 100644 index 00000000..282b6476 --- /dev/null +++ b/Medium/Snapshot Array.java @@ -0,0 +1,34 @@ +class SnapshotArray { + + private final TreeMap[] db; + private int currentSnapId; + + public SnapshotArray(int length) { + db = new TreeMap[length]; + for (int i = 0; i < length; i++) { + db[i] = new TreeMap(); + db[i].put(0, 0); + } + this.currentSnapId = 0; + } + + public void set(int index, int val) { + db[index].put(currentSnapId, val); + } + + public int snap() { + return currentSnapId++; + } + + public int get(int index, int snap_id) { + return db[index].floorEntry(snap_id).getValue(); + } +} + +/** + * Your SnapshotArray object will be instantiated and called as such: + * SnapshotArray obj = new SnapshotArray(length); + * obj.set(index,val); + * int param_2 = obj.snap(); + * int param_3 = obj.get(index,snap_id); + */ diff --git a/Medium/Solve the Equation.java b/Medium/Solve the Equation.java index e5edc253..bc506e04 100644 --- a/Medium/Solve the Equation.java +++ b/Medium/Solve the Equation.java @@ -1,93 +1,46 @@ class Solution { - public String solveEquation(String equation) { - int leftXCount = 0; - int rightXCount = 0; - int leftNumCount = 0; - int rightNumCount = 0; - boolean switchDone = false; - int sign = 1; - StringBuilder sb = new StringBuilder(); - - for (char c : equation.toCharArray()) { - if (c == '=') { - if (sb.length() > 0) { - leftNumCount += sign * Integer.parseInt(sb.toString()); - sb.setLength(0); - sign = 1; - } - - switchDone = true; - continue; - } - - if (c == 'x') { - if (switchDone) { - rightXCount += sign * (sb.length() > 0 ? Integer.parseInt(sb.toString()) : 1); - } - else { - leftXCount += sign * (sb.length() > 0 ? Integer.parseInt(sb.toString()) : 1); - } - - sign = 1; - sb.setLength(0); - } - else if (Character.isDigit(c)) { - sb.append(c); - } - else if (c == '+' || c == '-') { - if (sb.length() > 0) { - if (switchDone) { - rightNumCount += sign * (Integer.parseInt(sb.toString())); - } - else { - leftNumCount += sign * (Integer.parseInt(sb.toString())); - } - - sb.setLength(0); - } - - sign = c == '+' ? 1 : -1; - } - } - - if (sb.length() > 0) { - rightNumCount += sign * Integer.parseInt(sb.toString()); - } - - if (leftXCount == rightXCount && leftNumCount != rightNumCount) { - return "No solution"; - } - else if (leftXCount == rightXCount && leftNumCount == rightNumCount) { - return "Infinite solutions"; - } - else { - int totalXCount = leftXCount - rightXCount; - int totalValueCount = rightNumCount - leftNumCount; - - int gcd = getGcd(totalXCount, totalValueCount); - if (gcd != 0) { - totalXCount /= gcd; - totalValueCount /= gcd; - } - - if (totalXCount < 0) { - totalXCount *= -1; - totalValueCount *= -1; - } - - return new StringBuilder() - .append(totalXCount > 1 ? totalXCount : "") - .append("x=") - .append(totalValueCount) - .toString(); - } + public String solveEquation(String equation) { + int[] equationFirst = parseEquation(equation.split("=")[0]); + int[] equationSecond = parseEquation(equation.split("=")[1]); + int constantPart = equationSecond[1] - equationFirst[1]; + int variablePart = equationFirst[0] - equationSecond[0]; + if (variablePart == 0) { + return constantPart == 0 ? "Infinite solutions" : "No solution"; } - - private int getGcd(int totalXCount, int totalValueCount) { - if (totalXCount == 0) { - return totalValueCount; + int sign = (variablePart < 0 && constantPart < 0) || (variablePart > 0 && constantPart > 0) ? 1 : -1; + if (Math.abs(constantPart) % Math.abs(variablePart) == 0) { + constantPart = Math.abs(constantPart) / Math.abs(variablePart); + variablePart = 1; + } + return (variablePart > 1 ? variablePart : "") + "x=" + sign * constantPart; + } + + private int[] parseEquation(String s) { + int variablePart = 0; + int constantPart = 0; + int sign = 1; + int n = s.length(); + for (int idx = 0; idx < n;) { + if (s.charAt(idx) == 'x') { + variablePart += sign; + idx++; + sign = 1; + } else if (Character.isDigit(s.charAt(idx))) { + int num = 0; + while (idx < n && Character.isDigit(s.charAt(idx))) { + num = num * 10 + Character.getNumericValue(s.charAt(idx++)); + } + if (idx != n && s.charAt(idx) == 'x') { + variablePart += sign * num; + idx++; + } else { + constantPart += sign * num; } - - return getGcd(totalValueCount % totalXCount, totalXCount); + sign = 1; + } else { + sign = s.charAt(idx++) == '+' ? 1 : -1; + } } + return new int[]{variablePart, constantPart}; + } } diff --git a/Medium/Solving Questions With Brainpower.java b/Medium/Solving Questions With Brainpower.java new file mode 100644 index 00000000..76e640d1 --- /dev/null +++ b/Medium/Solving Questions With Brainpower.java @@ -0,0 +1,19 @@ +class Solution { + public long mostPoints(int[][] questions) { + Long[] dp = new Long[questions.length]; + return helper(questions, 0, dp); + } + + private long helper(int[][] questions, int idx, Long[] dp) { + if (idx >= questions.length) { + return 0; + } + if (dp[idx] != null) { + return dp[idx]; + } + return dp[idx] = Math.max( + questions[idx][0] + helper(questions, idx + questions[idx][1] + 1, dp), + helper(questions, idx + 1, dp) + ); + } +} diff --git a/Medium/Sort An Array.java b/Medium/Sort An Array.java index 7d4a1a41..a906afc4 100644 --- a/Medium/Sort An Array.java +++ b/Medium/Sort An Array.java @@ -1,18 +1,39 @@ class Solution { public int[] sortArray(int[] nums) { - int[] counter = new int[2 * 50000 + 1]; - for (int num : nums) { - counter[50000 + num]++; + mergeSort(nums, 0, nums.length - 1); + return nums; + } + + private void mergeSort(int[] nums, int start, int end) { + if (end - start <= 0) { + return; } - + int mid = start + (end - start) / 2; + mergeSort(nums, start, mid); + mergeSort(nums, mid + 1, end); + merge(nums, start, mid, end); + } + + private void merge(int[] nums, int start, int mid, int end) { + int left = start; + int right = mid + 1; + int[] temp = new int[end - start + 1]; int idx = 0; - for (int i = 0; i < counter.length; i++) { - int val = i > 50000 ? i - 50000 : -(50000 - i); - while (counter[i]-- > 0) { - nums[idx++] = val; + while (left <= mid && right <= end) { + if (nums[left] < nums[right]) { + temp[idx++] = nums[left++]; + } else { + temp[idx++] = nums[right++]; } } - - return nums; + while (left <= mid) { + temp[idx++] = nums[left++]; + } + while (right <= end) { + temp[idx++] = nums[right++]; + } + for (int i = start; i <= end; i++) { + nums[i] = temp[i - start]; + } } } diff --git a/Medium/Sort Characters By Frequency.java b/Medium/Sort Characters By Frequency.java index e504b12b..7c0978bc 100644 --- a/Medium/Sort Characters By Frequency.java +++ b/Medium/Sort Characters By Frequency.java @@ -1,47 +1,32 @@ class Solution { + private static final String ALL_LETTERS = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public String frequencySort(String s) { Map map = new HashMap<>(); - - for (int i=0;i sortedMap = sortByValue(map); - - - StringBuilder sb = new StringBuilder(""); - - for (Map.Entry entry : sortedMap.entrySet()) { - String t = String.join("", Collections.nCopies(entry.getValue(), String.valueOf(entry.getKey()))); - sb.append(t); + List[] frequencyToChar = new List[maxFrequency + 1]; + for (char c : map.keySet()) { + if (frequencyToChar[map.get(c)] == null) { + frequencyToChar[map.get(c)] = new ArrayList<>(); + } + frequencyToChar[map.get(c)].add(c); } - - return sb.toString(); - } - - private Map sortByValue(Map unsortMap) { - - List> list = - new LinkedList>(unsortMap.entrySet()); - - Collections.sort(list, new Comparator>() { - public int compare(Map.Entry o1, - Map.Entry o2) { - return (o2.getValue()).compareTo(o1.getValue()); + StringBuilder sb = new StringBuilder(); + for (int i = maxFrequency; i > 0; i--) { + List characters = frequencyToChar[i] == null ? + new ArrayList<>() : frequencyToChar[i]; + for (char c : characters) { + for (int j = 0; j < i; j++) { + sb.append(c); + } } - }); - - Map sortedMap = new LinkedHashMap(); - for (Map.Entry entry : list) { - sortedMap.put(entry.getKey(), entry.getValue()); } - - return sortedMap; + return sb.toString(); } } diff --git a/Medium/Sort Colors.java b/Medium/Sort Colors.java index fee68c3b..6bfe64e8 100644 --- a/Medium/Sort Colors.java +++ b/Medium/Sort Colors.java @@ -1,23 +1,19 @@ class Solution { - public void sortColors(int[] nums) { - int idx1 = 0; - int idx2 = nums.length - 1; - int idx = 0; - - while (idx <= idx2) { - if (nums[idx] == 0) { - nums[idx] = nums[idx1]; - nums[idx1] = 0; - idx1++; - } - if (nums[idx] == 2) { - nums[idx] = nums[idx2]; - nums[idx2] = 2; - idx2--; - idx--; - } - - idx++; - } + public void sortColors(int[] nums) { + int zeroIdx = 0; + int twoIdx = nums.length - 1; + for (int i = 0; i <= twoIdx; ) { + if (nums[i] == 0 && i != zeroIdx) { + int temp = nums[zeroIdx]; + nums[zeroIdx++] = nums[i]; + nums[i] = temp; + } else if (nums[i] == 2 && i != twoIdx) { + int temp = nums[twoIdx]; + nums[twoIdx--] = nums[i]; + nums[i] = temp; + } else { + i++; + } } + } } diff --git a/Medium/Sort Integers by The Power Value.java b/Medium/Sort Integers by The Power Value.java new file mode 100644 index 00000000..aa9a5fa6 --- /dev/null +++ b/Medium/Sort Integers by The Power Value.java @@ -0,0 +1,25 @@ +class Solution { + public int getKth(int lo, int hi, int k) { + Map cache = new HashMap<>(); + cache.put(1, 0); + PriorityQueue pq = new PriorityQueue<>( + Comparator.comparingInt((Integer o) -> cache.get(o)).thenComparingInt(o -> o)); + for (int i = lo; i <= hi; i++) { + calculateSteps(cache, i); + pq.add(i); + } + while (!pq.isEmpty() && k-- > 1) { + pq.poll(); + } + return pq.peek(); + } + + private int calculateSteps(Map cache, int num) { + if (cache.containsKey(num)) { + return cache.get(num); + } + int numOfSteps = 1 + calculateSteps(cache, (num % 2 == 0 ? num / 2 : num * 3 + 1)); + cache.put(num, numOfSteps); + return cache.get(num); + } +} diff --git a/Medium/Sort Linked List Already Sorted Using Absolute Values.java b/Medium/Sort Linked List Already Sorted Using Absolute Values.java new file mode 100644 index 00000000..fd43f251 --- /dev/null +++ b/Medium/Sort Linked List Already Sorted Using Absolute Values.java @@ -0,0 +1,25 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode sortLinkedList(ListNode head) { + ListNode curr = head; + while (curr != null && curr.next != null){ + if (curr.next.val < 0) { + // Make a new head with negative value and assign its next pointer to current head + head = new ListNode(curr.next.val,head); + curr.next = curr.next.next; + } else { + curr = curr.next; + } + } + return head; + } +} diff --git a/Medium/Sort List.java b/Medium/Sort List.java index 8a5a9166..013db8f6 100644 --- a/Medium/Sort List.java +++ b/Medium/Sort List.java @@ -3,26 +3,51 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode sortList(ListNode head) { - ArrayList arr = new ArrayList<>(); - ListNode curr = head; - while (curr != null) { - arr.add(curr.val); - curr = curr.next; - } - - Collections.sort(arr); - - curr = head; - for (int i=0;i priorityQueue = new PriorityQueue<>((o1, o2) -> { + if (o1[0] != o2[0]) { + return o1[0] - o2[0]; + } + return o1[1] - o2[1]; + }); + for (int i = 0; i < nums.length; i++) { + priorityQueue.add(new int[]{getUpdatedNumAfterMapping(nums[i], mapping), i, nums[i]}); + } + for (int i = 0; i < nums.length; i++) { + nums[i] = priorityQueue.poll()[2]; + } + return nums; + } + + private int getUpdatedNumAfterMapping(Integer original, int[] mapping) { + if (original <= 9) { + return mapping[original]; + } + int updatedNum = 0; + int factor = 1; + while (original > 0){ + updatedNum += mapping[original % 10] * factor; + factor *= 10; + original /= 10; + } + return updatedNum; + } +} diff --git a/Medium/Sort the Matrix Diagonally.java b/Medium/Sort the Matrix Diagonally.java new file mode 100644 index 00000000..003410db --- /dev/null +++ b/Medium/Sort the Matrix Diagonally.java @@ -0,0 +1,45 @@ +class Solution { + public int[][] diagonalSort(int[][] mat) { + int numRows = mat.length; + int numCols = mat[0].length; + for (int i = 0; i < numRows; i++) { + sortDiagonal(i, 0, mat); + } + for (int i = 0; i < numCols; i++) { + sortDiagonal(0, i, mat); + } + return mat; + } + + private void sortDiagonal(int row, int col, int[][] mat) { + int numRows = mat.length; + int numCols = mat[0].length; + List diagonal = new ArrayList<>(); + int diagonalLength = Math.min(numRows - row, numCols - col); + for (int i = 0; i < diagonalLength; i++) { + diagonal.add(mat[row + i][col + i]); + } + diagonal = countingSort(diagonal); + for (int i = 0; i < diagonalLength; i++) { + mat[row + i][col + i] = diagonal.get(i); + } + } + + private List countingSort(List list) { + int min = 1; + int max = 100; + int range = max - min + 1; + int[] frequency = new int[range]; + for (int num : list) { + frequency[num - min]++; + } + List sortedList = new ArrayList<>(); + for (int i = 0; i < range; i++) { + int count = frequency[i]; + while (count-- > 0) { + sortedList.add(i + min); + } + } + return sortedList; + } +} diff --git a/Medium/Sort the Students by Their Kth Score.java b/Medium/Sort the Students by Their Kth Score.java new file mode 100644 index 00000000..7c4f83e9 --- /dev/null +++ b/Medium/Sort the Students by Their Kth Score.java @@ -0,0 +1,6 @@ +class Solution { + public int[][] sortTheStudents(int[][] score, int k) { + Arrays.sort(score, (o1, o2) -> o2[k] - o1[k]); + return score; + } +} diff --git a/Medium/Sparse Matrix Multiplication.java b/Medium/Sparse Matrix Multiplication.java new file mode 100644 index 00000000..d612b920 --- /dev/null +++ b/Medium/Sparse Matrix Multiplication.java @@ -0,0 +1,15 @@ +class Solution { + public int[][] multiply(int[][] mat1, int[][] mat2) { + int[][] result = new int[mat1.length][mat2[0].length]; + for (int i = 0; i < mat1.length; i++) { + for (int j = 0; j < mat1[0].length; j++) { + if (mat1[i][j] != 0) { + for (int k = 0; k < mat2[0].length; k++) { + result[i][k] += mat1[i][j] * mat2[j][k]; + } + } + } + } + return result; + } +} diff --git a/Medium/Spiral Matrix II.java b/Medium/Spiral Matrix II.java index 70e30421..636fbb69 100644 --- a/Medium/Spiral Matrix II.java +++ b/Medium/Spiral Matrix II.java @@ -1,63 +1,33 @@ class Solution { public int[][] generateMatrix(int n) { - if (n == 0) { - return new int[0][0]; - } - - int[][] matrix = new int[n][n]; - int i = 0; - int j = 0; - int top = 0; - int bottom = n; - int left = 0; - int right = n; - int dir = 0; - int count = 1; - int limit = n*n; - - while (count <= limit) { - if (dir == 0) { - while (j < right) { - matrix[i][j++] = count; - count++; - } - dir++; - right--; - i++; - j--; + int[][] result = new int[n][n]; + int rowStart = 0; + int rowEnd = n - 1; + int colStart = 0; + int colEnd = n - 1; + int value = 1; + while (rowStart <= rowEnd && colStart <= colEnd) { + for (int i = colStart; i <= colEnd; i++) { + result[rowStart][i] = value++; } - else if (dir == 1) { - while (i < bottom) { - matrix[i++][j] = count; - count++; - } - dir++; - bottom--; - i--; - j--; + rowStart++; + for (int i = rowStart; i <= rowEnd; i++) { + result[i][colEnd] = value++; } - else if (dir == 2) { - while (j >= left) { - matrix[i][j--] = count; - count++; + colEnd--; + if (rowStart <= rowEnd) { + for (int i = colEnd; i >= colStart; i--) { + result[rowEnd][i] = value++; } - dir++; - i--; - j++; - left++; + rowEnd--; } - else if (dir == 3) { - while (i > top) { - matrix[i--][j] = count; - count++; + if (colStart <= colEnd) { + for (int i = rowEnd; i >= rowStart; i--) { + result[i][colStart] = value++; } - dir = 0; - top++; - i++; - j++; + colStart++; } } - - return matrix; + return result; } } diff --git a/Medium/Spiral Matrix IV.java b/Medium/Spiral Matrix IV.java new file mode 100644 index 00000000..5136b493 --- /dev/null +++ b/Medium/Spiral Matrix IV.java @@ -0,0 +1,45 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public int[][] spiralMatrix(int m, int n, ListNode head) { + int[][] result = new int[m][n]; + for (int i = 0; i < m; i++) { + Arrays.fill(result[i], -1); + } + int topRow = 0; + int bottomRow = m - 1; + int leftColumn = 0; + int rightColumn = n - 1; + while (head != null) { + for (int col = leftColumn; col <= rightColumn && head != null; col++) { + result[topRow][col] = head.val; + head = head.next; + } + topRow++; + for (int row = topRow; row <= bottomRow && head != null; row++) { + result[row][rightColumn] = head.val; + head = head.next; + } + rightColumn--; + for (int col = rightColumn; col >= leftColumn && head != null; col--) { + result[bottomRow][col] = head.val; + head = head.next; + } + bottomRow--; + for (int row = bottomRow; row >= topRow && head != null; row--) { + result[row][leftColumn] = head.val; + head = head.next; + } + leftColumn++; + } + return result; + } +} diff --git a/Medium/Spiral Matrix.java b/Medium/Spiral Matrix.java index 4054cc83..252374fb 100644 --- a/Medium/Spiral Matrix.java +++ b/Medium/Spiral Matrix.java @@ -1,64 +1,32 @@ class Solution { public List spiralOrder(int[][] matrix) { - List list = new ArrayList<>(); - - if (matrix.length == 0 || matrix[0].length == 0) { - return list; - } - - int i = 0; - int j = 0; - int top = 0; - int bottom = matrix.length; - int left = 0; - int right = matrix[0].length; - int dir = 0; - int count = 0; - int limit = matrix.length * matrix[0].length; - - while (count < limit) { - if (dir == 0) { - while (j < right) { - list.add(matrix[i][j++]); - count++; - } - dir++; - right--; - i++; - j--; + List result = new ArrayList<>(); + int rowStart = 0; + int rowEnd = matrix.length - 1; + int colStart = 0; + int colEnd = matrix[0].length - 1; + while (rowStart <= rowEnd && colStart <= colEnd) { + for (int i = colStart; i <= colEnd; i++) { + result.add(matrix[rowStart][i]); } - else if (dir == 1) { - while (i < bottom) { - list.add(matrix[i++][j]); - count++; - } - dir++; - bottom--; - i--; - j--; + rowStart++; + for (int i = rowStart; i <= rowEnd; i++) { + result.add(matrix[i][colEnd]); } - else if (dir == 2) { - while (j >= left) { - list.add(matrix[i][j--]); - count++; + colEnd--; + if (rowStart <= rowEnd) { + for (int i = colEnd; i >= colStart; i--) { + result.add(matrix[rowEnd][i]); } - dir++; - i--; - j++; - left++; + rowEnd--; } - else if (dir == 3) { - while (i > top) { - list.add(matrix[i--][j]); - count++; + if (colStart <= colEnd) { + for (int i = rowEnd; i >= rowStart; i--) { + result.add(matrix[i][colStart]); } - dir = 0; - top++; - i++; - j++; + colStart++; } } - - return list; + return result; } } diff --git a/Medium/Split Array into Consecutive Subsequences.java b/Medium/Split Array into Consecutive Subsequences.java new file mode 100644 index 00000000..17425bd5 --- /dev/null +++ b/Medium/Split Array into Consecutive Subsequences.java @@ -0,0 +1,33 @@ +class Solution { + public boolean isPossible(int[] nums) { + PriorityQueue pq = new PriorityQueue<>((int[] o1, int[] o2) -> { + if (o1[1] == o2[1]) { + return (o1[1] - o1[0]) - (o2[1] - o2[0]); + } + return o1[1] - o2[1]; + }); + for (int num : nums) { + while (!pq.isEmpty() && pq.peek()[1] + 1 < num) { + if (!isValidSubsequence(pq.poll())) { + return false; + } + } + if (pq.isEmpty() || pq.peek()[1] == num) { + pq.add(new int[]{num, num}); + } else { + int[] subsequence = pq.poll(); + pq.add(new int[]{subsequence[0], num}); + } + } + while (!pq.isEmpty()) { + if (!isValidSubsequence(pq.poll())) { + return false; + } + } + return true; + } + + private boolean isValidSubsequence(int[] subsequence) { + return subsequence[1] - subsequence[0] + 1 >= 3; + } +} diff --git a/Medium/Split Linked List in Parts.java b/Medium/Split Linked List in Parts.java new file mode 100644 index 00000000..2fdd787c --- /dev/null +++ b/Medium/Split Linked List in Parts.java @@ -0,0 +1,33 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode[] splitListToParts(ListNode head, int k) { + int length = 0; + ListNode curr = head; + while (curr != null) { + length++; + curr = curr.next; + } + ListNode[] splits = new ListNode[k]; + int elementsPerPart = length / k; + int partsWithExtra = length % k; + ListNode prev = null; + for (int i = 0; i < k && head != null; i++, partsWithExtra--) { + splits[i] = head; + for (int j = 0; j < elementsPerPart + (partsWithExtra > 0 ? 1 : 0); j++) { + prev = head; + head = head.next; + } + prev.next = null; + } + return splits; + } +} diff --git a/Medium/Split Linked List into Parts.java b/Medium/Split Linked List into Parts.java deleted file mode 100644 index 3fdff43c..00000000 --- a/Medium/Split Linked List into Parts.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ - -class Solution { - public ListNode[] splitListToParts(ListNode root, int k) { - int m = findLength(root); - ListNode temp = root; - - ListNode[] res = new ListNode[k]; - int size=m/k; - int l= m%k; - - for(int i=0;i1){ - temp=temp.next;j--; - } - if(size!=0 && l>0 && temp!=null){ temp=temp.next; l--;} - ListNode temp1=temp; - if(temp!=null) temp=temp.next; - if(temp1!=null) temp1.next=null; - res[i]=ans; - } - return res; - } - - private int findLength(ListNode root) { - if (root == null) return 0; - int l = 0; - while(root != null) { - l++; - root = root.next; - } - - return l; - } -} diff --git a/Medium/Split a String Into the Max Number of Unique Substrings.java b/Medium/Split a String Into the Max Number of Unique Substrings.java new file mode 100644 index 00000000..3e418df7 --- /dev/null +++ b/Medium/Split a String Into the Max Number of Unique Substrings.java @@ -0,0 +1,21 @@ +class Solution { + public int maxUniqueSplit(String s) { + Set seen = new HashSet<>(); + return backtrack(s, 0, seen); + } + + private int backtrack(String s, int idx, Set seen) { + if (idx == s.length()) { + return 0; + } + int count = 0; + for (int end = idx + 1; end <= s.length(); end++) { + String substring = s.substring(idx, end); + if (seen.add(substring)) { + count = Math.max(count, 1 + backtrack(s, end, seen)); + seen.remove(substring); + } + } + return count; + } +} diff --git a/Medium/Step-By-Step Directions From a Binary Tree Node to Another.java b/Medium/Step-By-Step Directions From a Binary Tree Node to Another.java new file mode 100644 index 00000000..59695899 --- /dev/null +++ b/Medium/Step-By-Step Directions From a Binary Tree Node to Another.java @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public String getDirections(TreeNode root, int startValue, int destValue) { + StringBuilder sourcePath = new StringBuilder(); + StringBuilder destinationPath = new StringBuilder(); + findPath(root, startValue, sourcePath); + findPath(root, destValue, destinationPath); + int idx = 0; + // Remove common prefix + while (idx < Math.min(sourcePath.length(), destinationPath.length()) && + sourcePath.charAt(sourcePath.length() - idx - 1) == destinationPath.charAt(destinationPath.length() - idx - 1)) { + idx++; + } + // Replace remaining sourcePath with 'U' and append remaining destinationPath + return "U".repeat(sourcePath.length() - idx) + destinationPath.reverse().toString().substring(idx); + } + + private boolean findPath(TreeNode root, int value, StringBuilder sb) { + if (root.val == value) { + return true; + } + if (root.left != null && findPath(root.left, value, sb)) { + sb.append("L"); + } + else if (root.right != null && findPath(root.right, value, sb)) { + sb.append("R"); + } + return sb.length() > 0; + } +} diff --git a/Medium/Stock Price Fluctuation.java b/Medium/Stock Price Fluctuation.java new file mode 100644 index 00000000..3b374efe --- /dev/null +++ b/Medium/Stock Price Fluctuation.java @@ -0,0 +1,49 @@ +class StockPrice { + Map map; + int mostRecentTimeStamp; + PriorityQueue minHeap; + PriorityQueue maxHeap; + public StockPrice() { + map = new HashMap<>(); + mostRecentTimeStamp = Integer.MIN_VALUE; + minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0])); + maxHeap = new PriorityQueue<>((a, b) -> b[0] - a[0]); + } + + public void update(int timestamp, int price) { + map.put(timestamp, price); + mostRecentTimeStamp = Math.max(mostRecentTimeStamp, timestamp); + minHeap.add(new int[]{price, timestamp}); + maxHeap.add(new int[]{price, timestamp}); + } + + public int current() { + return map.get(mostRecentTimeStamp); + } + + public int maximum() { + return getUpdatedValueFromHeap(maxHeap); + } + + public int minimum() { + return getUpdatedValueFromHeap(minHeap); + } + + private int getUpdatedValueFromHeap(PriorityQueue heap) { + int[] entry = heap.poll(); + while (entry[0] != map.get(entry[1])) { + entry = heap.poll(); + } + heap.add(entry); + return entry[0]; + } +} + +/** + * Your StockPrice object will be instantiated and called as such: + * StockPrice obj = new StockPrice(); + * obj.update(timestamp,price); + * int param_2 = obj.current(); + * int param_3 = obj.maximum(); + * int param_4 = obj.minimum(); + */ diff --git a/Medium/Stone Game II.java b/Medium/Stone Game II.java new file mode 100644 index 00000000..c56cbd43 --- /dev/null +++ b/Medium/Stone Game II.java @@ -0,0 +1,26 @@ +class Solution { + public int stoneGameII(int[] piles) { + Integer[][][] dp = new Integer[2][piles.length + 1][piles.length + 1]; + return helper(piles, dp, 0, 0, 1); + } + + private int helper(int[] piles, Integer[][][] dp, int p, int i, int m) { + if (i == piles.length) { + return 0; + } + if (dp[p][i][m] != null) { + return dp[p][i][m]; + } + int result = p == 1 ? 1000_000 : -1; + int s = 0; + for (int j = 1; j <= Math.min(2 * m, piles.length - i); j++) { + s += piles[i + j - 1]; + if (p == 0) { + result = Math.max(result, s + helper(piles, dp, 1, i + j, Math.max(m, j))); + } else { + result = Math.min(result, helper(piles, dp, 0, i + j, Math.max(m, j))); + } + } + return dp[p][i][m] = result; + } +} diff --git a/Medium/Strictly Palindromic Number.java b/Medium/Strictly Palindromic Number.java new file mode 100644 index 00000000..b2e27e3a --- /dev/null +++ b/Medium/Strictly Palindromic Number.java @@ -0,0 +1,32 @@ +class Solution { + public boolean isStrictlyPalindromic(int n) { + for (int i = 2; i <= n - 2; i++) { + if (!isPalindrome(convertToBase(n, i))) { + return false; + } + } + return true; + } + + private String convertToBase(int n, int base) { + StringBuilder sb = new StringBuilder(); + while (n > 0) { + sb.append(n % base); + n /= base; + } + return sb.reverse().toString(); + } + + private boolean isPalindrome(String s) { + int start = 0; + int end = s.length() - 1; + while (start < end) { + if (s.charAt(start) != s.charAt(end)) { + return false; + } + start++; + end--; + } + return true; + } +} diff --git a/Medium/String Compression III.java b/Medium/String Compression III.java new file mode 100644 index 00000000..03a6737c --- /dev/null +++ b/Medium/String Compression III.java @@ -0,0 +1,16 @@ +class Solution { + public String compressedString(String word) { + StringBuilder sb = new StringBuilder(); + int idx = 0; + while (idx < word.length()) { + char c = word.charAt(idx); + int count = 0; + while (idx < word.length() && word.charAt(idx) == c && count < 9) { + idx++; + count++; + } + sb.append(count).append(c); + } + return sb.toString(); + } +} diff --git a/Medium/String Compression.java b/Medium/String Compression.java new file mode 100644 index 00000000..060e655e --- /dev/null +++ b/Medium/String Compression.java @@ -0,0 +1,21 @@ +class Solution { + public int compress(char[] chars) { + int startIdx = 0; + for (int i = 0; i < chars.length;) { + char c = chars[i]; + int count = 0; + while (i < chars.length && chars[i] == c) { + count++; + i++; + } + chars[startIdx++] = c; + if (count > 1) { + String temp = String.valueOf(count); + for (char digit : temp.toCharArray()) { + chars[startIdx++] = digit; + } + } + } + return startIdx; + } +} diff --git a/Medium/String to Integer (atoi).java b/Medium/String to Integer (atoi).java new file mode 100644 index 00000000..e91cbec0 --- /dev/null +++ b/Medium/String to Integer (atoi).java @@ -0,0 +1,30 @@ +class Solution { + public int myAtoi(String s) { + int idx = 0; + int n = s.length(); + while (idx < n && s.charAt(idx) == ' ') { + idx++; + } + int sign = 1; + if (idx < n && (s.charAt(idx) == '-' || s.charAt(idx) == '+')) { + sign = s.charAt(idx) == '-' ? -1 : 1; + idx++; + } + if (idx == n || !Character.isDigit(s.charAt(idx))) { + return 0; + } + while (idx < n && s.charAt(idx) == '0') { + idx++; + } + int number = 0; + while (idx < n && Character.isDigit(s.charAt(idx))) { + int digit = Character.getNumericValue(s.charAt(idx)); + if ((number > Integer.MAX_VALUE / 10) || (number == Integer.MAX_VALUE / 10 && digit > Integer.MAX_VALUE % 10)) { + return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + number = number * 10 + digit; + idx++; + } + return number * sign; + } +} diff --git a/Medium/String to Integer(atoi).java b/Medium/String to Integer(atoi).java deleted file mode 100644 index 9d2aaf81..00000000 --- a/Medium/String to Integer(atoi).java +++ /dev/null @@ -1,34 +0,0 @@ -class Solution { - public int myAtoi(String str) { - if (str.length() == 0) { - return 0; - } - - int idx = 0; - int n = str.length(); - int sign = 1; - while (idx < n && str.charAt(idx) == ' ') { - idx++; - } - - if (idx < n && (str.charAt(idx) == '-' || str.charAt(idx) == '+')) { - sign = str.charAt(idx) == '-' ? -1 : 1; - idx++; - } - - long num = 0; - while (idx < n && Character.isDigit(str.charAt(idx))) { - num = num * 10 + Character.getNumericValue(str.charAt(idx++)); - - if ((sign == 1 && num > Integer.MAX_VALUE) || (-num < Integer.MIN_VALUE)) { - return getOverflowValue(sign); - } - } - - return sign * (int) num; - } - - private int getOverflowValue(int sign) { - return sign == -1 ? Integer.MIN_VALUE : Integer.MAX_VALUE; - } -} diff --git a/Medium/Subarray Product Less Than K.java b/Medium/Subarray Product Less Than K.java index abe4415d..3f53dc87 100644 --- a/Medium/Subarray Product Less Than K.java +++ b/Medium/Subarray Product Less Than K.java @@ -1,14 +1,19 @@ class Solution { public int numSubarrayProductLessThanK(int[] nums, int k) { - if (k<2) return 0; + if (k <= 1) { + return 0; + } + int prod = 1; + int start = 0; + int end = 0; + int n = nums.length; int result = 0; - int product = 1; - for (int i = 0, right = 0; right < nums.length; right++) { - product *= nums[right]; - while (i < nums.length && product >= k) { - product /= nums[i++]; + while (end < n) { + prod *= nums[end++]; + while (start < end && prod >= k) { + prod /= nums[start++]; } - result += right - i + 1; + result += end - start; } return result; } diff --git a/Medium/Subarray Sum Equals K.java b/Medium/Subarray Sum Equals K.java index 1a5b038a..03faa8e7 100644 --- a/Medium/Subarray Sum Equals K.java +++ b/Medium/Subarray Sum Equals K.java @@ -1,16 +1,14 @@ class Solution { - public int subarraySum(int[] nums, int k) { - Map map = new HashMap<>(); - map.put(0, 1); - int count = 0; - int currentSum = 0; - - for (int num : nums) { - currentSum += num; - count += map.getOrDefault(currentSum - k, 0); - map.put(currentSum, map.getOrDefault(currentSum, 0) + 1); - } - - return count; + public int subarraySum(int[] nums, int k) { + int sum = 0; + int count = 0; + Map map = new HashMap<>(); + map.put(0, 1); + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + count += map.getOrDefault(sum - k, 0); + map.put(sum, map.getOrDefault(sum, 0) + 1); } + return count; + } } diff --git a/Medium/Subarray Sums Divisible by K.java b/Medium/Subarray Sums Divisible by K.java index de3edc30..46033b44 100644 --- a/Medium/Subarray Sums Divisible by K.java +++ b/Medium/Subarray Sums Divisible by K.java @@ -1,20 +1,17 @@ class Solution { - public int subarraysDivByK(int[] A, int K) { - int count = 0; - int sum = 0; - Map map = new HashMap<>(); - map.put(0, 1); - - for (int i = 0; i < A.length; i++) { - sum = (sum + A[i]) % K; - if (sum < 0) { - sum += K; - } - - count += map.getOrDefault(sum, 0); - map.put(sum, map.getOrDefault(sum, 0) + 1); - } - - return count; + public int subarraysDivByK(int[] A, int K) { + int sum = 0; + int count = 0; + Map map = new HashMap<>(); + map.put(0, 1); + for (int i = 0; i < A.length; i++) { + sum = (sum + A[i]) % K; + if (sum < 0) { + sum += K; + } + count += map.getOrDefault(sum, 0); + map.put(sum, map.getOrDefault(sum, 0) + 1); } + return count; + } } diff --git a/Medium/Subdomain Visit Count.java b/Medium/Subdomain Visit Count.java new file mode 100644 index 00000000..f7900ef6 --- /dev/null +++ b/Medium/Subdomain Visit Count.java @@ -0,0 +1,22 @@ +class Solution { + public List subdomainVisits(String[] cpdomains) { + Map map = new HashMap<>(); + for (String cpdomain : cpdomains) { + int spaceIdx = cpdomain.indexOf(' '); + int count = Integer.parseInt(cpdomain.substring(0, spaceIdx)); + String[] subdomains = cpdomain.substring(spaceIdx + 1).split("\\."); + StringBuilder sb = new StringBuilder(); + for (int i = subdomains.length - 1; i >= 0; i--) { + sb.insert(0, subdomains[i]); + String currDomain = sb.toString(); + map.put(currDomain, map.getOrDefault(currDomain, 0L) + count); + sb.insert(0, "."); + } + } + List result = new ArrayList<>(); + for (String key : map.keySet()) { + result.add(map.get(key) + " " + key); + } + return result; + } +} diff --git a/Medium/Subrectangle Queries.java b/Medium/Subrectangle Queries.java new file mode 100644 index 00000000..2fb42221 --- /dev/null +++ b/Medium/Subrectangle Queries.java @@ -0,0 +1,32 @@ +class SubrectangleQueries { + List modifications; + int[][] rectangle; + public SubrectangleQueries(int[][] rectangle) { + this.rectangle = rectangle; + modifications = new ArrayList<>(); + } + + public void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) { + modifications.add(new int[]{row1, col1, row2, col2, newValue}); + } + + public int getValue(int row, int col) { + for (int i = modifications.size() - 1; i >= 0; i--) { + if (inRange(row, col, modifications.get(i))) { + return modifications.get(i)[4]; + } + } + return rectangle[row][col]; + } + + private boolean inRange(int row, int col, int[] modification) { + return row >= modification[0] && row <= modification[2] && col >= modification[1] && col <= modification[3]; + } +} + +/** + * Your SubrectangleQueries object will be instantiated and called as such: + * SubrectangleQueries obj = new SubrectangleQueries(rectangle); + * obj.updateSubrectangle(row1,col1,row2,col2,newValue); + * int param_2 = obj.getValue(row,col); + */ diff --git a/Medium/Subsets II.java b/Medium/Subsets II.java new file mode 100644 index 00000000..72d290b7 --- /dev/null +++ b/Medium/Subsets II.java @@ -0,0 +1,25 @@ +class Solution { + public List> subsetsWithDup(int[] nums) { + List> ans = new ArrayList<>(); + List curr = new ArrayList<>(); + int n = nums.length; + Arrays.sort(nums); + helper(nums, 0, n, ans, curr); + return new ArrayList<>(ans); + } + + private void helper(int[] nums, int idx, int n, List> ans, List curr) { + ans.add(new ArrayList<>(curr)); + if (idx >= n) { + return; + } + for (int i = idx; i < n; i++) { + if (i > idx && nums[i] == nums[i - 1]) { + continue; + } + curr.add(nums[i]); + helper(nums, i + 1, n, ans, curr); + curr.remove(curr.size() - 1); + } + } +} diff --git a/Medium/Subsets.java b/Medium/Subsets.java index 9444e97f..3e0aba4d 100644 --- a/Medium/Subsets.java +++ b/Medium/Subsets.java @@ -1,21 +1,20 @@ class Solution { - public static List> subsets(int[] nums) { + public List> subsets(int[] nums) { + List> result = new ArrayList<>(); + helper(nums, 0, new ArrayList<>(), result); + return new ArrayList<>(result); + } - Arrays.sort(nums); - List> perms = new ArrayList<>(); - List temp = new ArrayList<>(); - subsetsHelper(nums, perms, temp, 0); - - return perms; + private void helper(int[] nums, int currIdx, List currSubset, + List> result) { + result.add(new ArrayList<>(currSubset)); + if (currIdx >= nums.length) { + return; } - - private static void subsetsHelper(int[] nums, List> perms, List temp, int start) { - perms.add(new ArrayList<>(temp)); - - for (int i=start; i= success) { + minIdx = Math.min(minIdx, mid); + right = mid - 1; + } else { + left = mid + 1; + } + } + return minIdx == Integer.MAX_VALUE ? 0 : (potions.length - minIdx); + } +} diff --git a/Medium/Sum Multiples.java b/Medium/Sum Multiples.java new file mode 100644 index 00000000..59bfa012 --- /dev/null +++ b/Medium/Sum Multiples.java @@ -0,0 +1,7 @@ +class Solution { + public int sumOfMultiples(int n) { + return IntStream.rangeClosed(1, n) + .filter(value -> value % 3 == 0 || value % 5 == 0 || value % 7 == 0) + .sum(); + } +} diff --git a/Medium/Sum Root to Leaf Numbers.java b/Medium/Sum Root to Leaf Numbers.java index 3940ea06..0cad0868 100644 --- a/Medium/Sum Root to Leaf Numbers.java +++ b/Medium/Sum Root to Leaf Numbers.java @@ -4,22 +4,39 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ -class Solution { - public int sumNumbers(TreeNode root) { - return sum(root, 0); - } - - private int sum(TreeNode root, int sum) { +class Solution { + public int sumNumbers(TreeNode root) { if (root == null) { return 0; } - if (root.left == null && root.right == null) { - return sum*10 + root.val; + Queue queue = new LinkedList<>(); + queue.add(new NodeSumPair(root, 0)); + int totalSum = 0; + while (!queue.isEmpty()) { + NodeSumPair removed = queue.remove(); + TreeNode node = removed.node; + int currSum = removed.sum * 10 + node.val; + if (node.left == null && node.right == null) { + totalSum += currSum; + } + if (node.left != null) { + queue.add(new NodeSumPair(node.left, currSum)); + } + if (node.right != null) { + queue.add(new NodeSumPair(node.right, currSum)); + } } - - return sum(root.left, sum*10 + root.val) + sum(root.right, sum*10 + root.val); + return totalSum; } + + private static record NodeSumPair(TreeNode node, int sum) {} } diff --git a/Medium/Sum in a Matrix.java b/Medium/Sum in a Matrix.java new file mode 100644 index 00000000..0261f81b --- /dev/null +++ b/Medium/Sum in a Matrix.java @@ -0,0 +1,16 @@ +class Solution { + public int matrixSum(int[][] nums) { + for (int[] num : nums) { + Arrays.sort(num); + } + int score = 0; + for (int i = 0; i < nums[0].length; i++) { + int maxNum = 0; + for (int[] num : nums) { + maxNum = Math.max(maxNum, num[i]); + } + score += maxNum; + } + return score; + } +} diff --git a/Medium/Sum of Absolute Differences in a Sorted Array.java b/Medium/Sum of Absolute Differences in a Sorted Array.java new file mode 100644 index 00000000..de0e5920 --- /dev/null +++ b/Medium/Sum of Absolute Differences in a Sorted Array.java @@ -0,0 +1,22 @@ +class Solution { + public int[] getSumAbsoluteDifferences(int[] nums) { + int n = nums.length; + int[] answer = new int[n]; + int[] leftToRightSum = new int[n]; + int[] rightToLeftSum = new int[n]; + int currSum = 0; + for (int i = 0; i < n; i++) { + currSum += nums[i]; + leftToRightSum[i] = currSum; + } + currSum = 0; + for (int i = n - 1; i >= 0; i--) { + currSum += nums[i]; + rightToLeftSum[i] = currSum; + } + for (int i = 0; i < n; i++) { + answer[i] = (i == 0 ? 0 : i * nums[i] - leftToRightSum[i - 1]) + (i == n - 1 ? 0 : (rightToLeftSum[i + 1] - (n - 1 - i) * nums[i])); + } + return answer; + } +} diff --git a/Medium/Sum of Beauty of All Substrings.java b/Medium/Sum of Beauty of All Substrings.java new file mode 100644 index 00000000..17d57d14 --- /dev/null +++ b/Medium/Sum of Beauty of All Substrings.java @@ -0,0 +1,26 @@ +class Solution { + public int beautySum(String s) { + int sum = 0; + for (int i = 0; i < s.length(); i++) { + int[] charFrequency = new int[26]; + for (int j = i; j < s.length(); j++) { + charFrequency[s.charAt(j) - 'a']++; + sum += getBeauty(charFrequency); + } + } + return sum; + } + + private int getBeauty(int[] charFrequency) { + int min = Integer.MAX_VALUE ; + int max = Integer.MIN_VALUE; + for (int i = 0; i < 26; i++) { + if (charFrequency[i] == 0) { + continue; + } + min = Math.min(min, charFrequency[i]); + max = Math.max(max, charFrequency[i]); + } + return max - min; + } +} diff --git a/Medium/Sum of Even Numbers After Queries.java b/Medium/Sum of Even Numbers After Queries.java new file mode 100644 index 00000000..f8a3b043 --- /dev/null +++ b/Medium/Sum of Even Numbers After Queries.java @@ -0,0 +1,21 @@ +class Solution { + public int[] sumEvenAfterQueries(int[] nums, int[][] queries) { + int evenSum = 0; + for (int num : nums) { + evenSum += num % 2 == 0 ? num : 0; + } + int[] result = new int[nums.length]; + for (int i = 0; i < queries.length; i++) { + int idx = queries[i][1]; + if (nums[idx] % 2 == 0) { + evenSum -= nums[idx]; + } + nums[idx] += queries[i][0]; + if (nums[idx] % 2 == 0) { + evenSum += nums[idx]; + } + result[i] = evenSum; + } + return result; + } +} diff --git a/Medium/Sum of Nodes with Even-Valued Grandparent.java b/Medium/Sum of Nodes with Even-Valued Grandparent.java new file mode 100644 index 00000000..7e113144 --- /dev/null +++ b/Medium/Sum of Nodes with Even-Valued Grandparent.java @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public int sumEvenGrandparent(TreeNode root) { + int sum = 0; + Queue queue = new LinkedList<>(); + queue.add(new TreeNode[]{root, null, null}); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + TreeNode[] removed = queue.remove(); + TreeNode node = removed[0]; + TreeNode parent = removed[1]; + TreeNode grandParent = removed[2]; + if (grandParent != null && grandParent.val % 2 == 0) { + sum += node.val; + } + if (node.left != null) { + queue.add(new TreeNode[]{node.left, node, parent}); + } + if (node.right != null) { + queue.add(new TreeNode[]{node.right, node, parent}); + } + } + } + return sum; + } +} diff --git a/Medium/Sum of Numbers With Units Digit K.java b/Medium/Sum of Numbers With Units Digit K.java new file mode 100644 index 00000000..024b9dbf --- /dev/null +++ b/Medium/Sum of Numbers With Units Digit K.java @@ -0,0 +1,13 @@ +class Solution { + public int minimumNumbers(int num, int k) { + if (num == 0) { + return 0; + } + for (int i = 1; i * k <= num && i <= 10; i++) { + if (k * i % 10 == num % 10) { + return i; + } + } + return -1; + } +} diff --git a/Medium/Sum of Square Numbers.java b/Medium/Sum of Square Numbers.java new file mode 100644 index 00000000..13f138c2 --- /dev/null +++ b/Medium/Sum of Square Numbers.java @@ -0,0 +1,18 @@ +class Solution { + public boolean judgeSquareSum(int c) { + long left = 0; + long right = (long) Math.sqrt(c); + while (left <= right) { + long sum = left * left + right * right; + if (sum == c) { + return true; + } + if (sum > c) { + right--; + } else { + left++; + } + } + return false; + } +} diff --git a/Medium/Sum of Subarray Minimums.java b/Medium/Sum of Subarray Minimums.java new file mode 100644 index 00000000..942f0c91 --- /dev/null +++ b/Medium/Sum of Subarray Minimums.java @@ -0,0 +1,20 @@ +class Solution { + + private final static int MOD = 1000_000_007; + + public int sumSubarrayMins(int[] arr) { + Stack stack = new Stack<>(); + long sum = 0; + for (int i = 0; i <= arr.length; i++) { + while (!stack.isEmpty() && (i == arr.length || arr[stack.peek()] >= arr[i])) { + int minValue = stack.pop(); + int countOnLeft = stack.empty() ? -1 : stack.peek(); + int countOnRight = i; + long totalCount = (minValue - countOnLeft) * (countOnRight - minValue) % MOD; + sum = (sum + (totalCount * arr[minValue])) % MOD; + } + stack.push(i); + } + return (int) (sum); + } +} diff --git a/Medium/Summary Ranges.java b/Medium/Summary Ranges.java deleted file mode 100644 index 8964bcef..00000000 --- a/Medium/Summary Ranges.java +++ /dev/null @@ -1,45 +0,0 @@ -class Solution { - public List summaryRanges(int[] nums) { - List ranges = new ArrayList<>(); - - if (nums.length == 0) { - return ranges; - } - - int count = 1; - int i = 0; - StringBuilder sb = new StringBuilder(); - sb.append(nums[0]); - int n = nums.length-1; - - while (i < n) { - if (nums[i+1] - nums[i] == 1) { - count++; - } - else { - if (count > 1) { - sb.append("->").append(nums[i]); - ranges.add(sb.toString()); - count = 1; - } - else { - ranges.add(sb.toString()); - } - sb = new StringBuilder(); - sb.append(nums[i+1]); - } - - i++; - } - - if (count > 1) { - sb.append("->").append(nums[i]); - ranges.add(sb.toString()); - } - else { - ranges.add(sb.toString()); - } - - return ranges; - } -} diff --git a/Medium/Surrounded Regions.java b/Medium/Surrounded Regions.java new file mode 100644 index 00000000..1c161f6c --- /dev/null +++ b/Medium/Surrounded Regions.java @@ -0,0 +1,50 @@ +class Solution { + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + int rows = board.length; + int cols = board[0].length; + List> borders = new ArrayList<>(); + for (int r = 0; r < rows; r++) { + borders.add(Arrays.asList(r, 0)); + borders.add(Arrays.asList(r, cols - 1)); + } + for (int c = 0; c < cols; c++) { + borders.add(Arrays.asList(0, c)); + borders.add(Arrays.asList(rows - 1, c)); + } + for (List border : borders) { + dfs(board, border.get(0), border.get(1), rows, cols); + } + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + if (board[r][c] == 'O') { + board[r][c] = 'X'; + } + if (board[r][c] == 'E') { + board[r][c] = 'O'; + } + } + } + } + + private void dfs(char[][] board, int row, int col, int rows, int cols) { + if (board[row][col] != 'O') { + return; + } + board[row][col] = 'E'; + if (col < cols - 1) { + dfs(board, row, col + 1, rows, cols); + } + if (row < rows - 1) { + dfs(board, row + 1, col, rows, cols); + } + if (col > 0) { + dfs(board, row, col - 1, rows, cols); + } + if (row > 0) { + dfs(board, row - 1, col, rows, cols); + } + } +} diff --git a/Medium/Swap For Longest Repeated Character Substring.java b/Medium/Swap For Longest Repeated Character Substring.java new file mode 100644 index 00000000..fd71081e --- /dev/null +++ b/Medium/Swap For Longest Repeated Character Substring.java @@ -0,0 +1,40 @@ +class Solution { + public int maxRepOpt1(String text) { + int[] frequency = new int[26]; + for (char c : text.toCharArray()) { + frequency[c - 'a']++; + } + int maxRepeatingLength = 0; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + int j = i; + int count = 0; + int diff = 0; + while (j < text.length() && (c == text.charAt(j) || diff == 0) && count < frequency[c - 'a']) { + if (c != text.charAt(j)) { + diff++; + i = j - 1; + } + count++; + j++; + } + maxRepeatingLength = Math.max(maxRepeatingLength, count); + } + for (int i = text.length() - 1; i >= 0; i--) { + char c = text.charAt(i); + int count = 0; + int diff = 0; + int j = i; + while (j >= 0 && (c == text.charAt(j) || diff == 0) && count < frequency[c - 'a']) { + if (c != text.charAt(j)) { + diff++; + i = j + 1; + } + count++; + j--; + } + maxRepeatingLength = Math.max(maxRepeatingLength, count); + } + return maxRepeatingLength; + } +} diff --git a/Medium/Swap Nodes in Pair.java b/Medium/Swap Nodes in Pair.java deleted file mode 100644 index 2135fb05..00000000 --- a/Medium/Swap Nodes in Pair.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Definition for singly-linked list. - * public class ListNode { - * int val; - * ListNode next; - * ListNode(int x) { val = x; } - * } - */ -class Solution { - public ListNode swapPairs(ListNode head) { - if(head == null || head.next == null) return head; - - ListNode temp = head.next; - ListNode prev = null; - - while(head != null && head.next != null) { - - if(prev != null) { - prev.next = head.next; - } - - ListNode temp1 = head.next; - ListNode temp2 = head; - head.next = head.next.next; - head = temp1; - head.next = temp2; - prev = head.next; - head = head.next.next; - } - - return temp; - } -} diff --git a/Medium/Swap Nodes in Pairs.java b/Medium/Swap Nodes in Pairs.java new file mode 100644 index 00000000..505f7af0 --- /dev/null +++ b/Medium/Swap Nodes in Pairs.java @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode swapPairs(ListNode head) { + ListNode curr = head; + ListNode prev = null; + while (curr != null && curr.next != null) { + ListNode nextNode = curr.next; + ListNode nextToNext = curr.next.next; + if (prev == null) { + head = nextNode; + } + if (prev != null) { + prev.next = nextNode; + } + nextNode.next = curr; + curr.next = nextToNext; + prev = curr; + curr = nextToNext; + } + return head; + } +} diff --git a/Medium/Swapping Nodes in a Linked List.java b/Medium/Swapping Nodes in a Linked List.java new file mode 100644 index 00000000..8fdf72f4 --- /dev/null +++ b/Medium/Swapping Nodes in a Linked List.java @@ -0,0 +1,53 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode swapNodes(ListNode head, int k) { + int listLength = 0; + ListNode curr = head; + while (curr != null) { + listLength++; + curr = curr.next; + } + ListNode startPrev = null; + ListNode start = head; + ListNode endPrev = null; + ListNode end = head; + int count = k - 1; + while (count > 0) { + startPrev = start; + start = start.next; + count--; + } + count = listLength - k; + while (count > 0) { + endPrev = end; + end = end.next; + count--; + } + if (startPrev != null) { + startPrev.next = end; + } + if (endPrev != null) { + endPrev.next = start; + } + ListNode temp = start.next; + start.next = end.next; + end.next = temp; + // Updating head pointers if required + if (k == 1) { + head = end; + } + if (k == listLength) { + head = start; + } + return head; + } +} diff --git a/Medium/Synonymous Sentences.java b/Medium/Synonymous Sentences.java new file mode 100644 index 00000000..6de8d907 --- /dev/null +++ b/Medium/Synonymous Sentences.java @@ -0,0 +1,27 @@ +class Solution { + public List generateSentences(List> synonyms, String text) { + Map> synonymMapping = new HashMap<>(); + for (List synonym : synonyms) { + synonymMapping.computeIfAbsent(synonym.get(0), k -> new ArrayList<>()).add(synonym.get(1)); + synonymMapping.computeIfAbsent(synonym.get(1), k -> new ArrayList<>()).add(synonym.get(0)); + } + Set result = new TreeSet<>(); + Queue queue = new LinkedList<>(); + queue.add(text); + while (!queue.isEmpty()) { + String removed = queue.remove(); + result.add(removed); + String[] words = removed.split("\\s+"); + for (int i = 0; i < words.length; i++) { + for (String synonym : synonymMapping.getOrDefault(words[i], new ArrayList<>())) { + words[i] = synonym; + String updatedSentence = String.join(" ", words); + if (!result.contains(updatedSentence)) { + queue.add(updatedSentence); + } + } + } + } + return new ArrayList<>(result); + } +} diff --git a/Medium/Take K of Each Character From Left and Right.java b/Medium/Take K of Each Character From Left and Right.java new file mode 100644 index 00000000..4b878ce0 --- /dev/null +++ b/Medium/Take K of Each Character From Left and Right.java @@ -0,0 +1,27 @@ +class Solution { + public int takeCharacters(String s, int k) { + int[] counter = new int[3]; + int n = s.length(); + for (char c : s.toCharArray()) { + counter[c - 'a']++; + } + for (int i = 0; i < 3; i++) { + if (counter[i] < k) { + return -1; + } + } + int[] window = new int[3]; + int left = 0; + int maxWindow = 0; + for (int right = 0; right < n; right++) { + window[s.charAt(right) - 'a']++; + while (left <= right && + (counter[0] - window[0] < k || counter[1] - window[1] < k || counter[2] - window[2] < k)) { + window[s.charAt(left) - 'a']--; + left++; + } + maxWindow = Math.max(maxWindow, right - left + 1); + } + return n - maxWindow; + } +} diff --git a/Medium/Target Sum.java b/Medium/Target Sum.java new file mode 100644 index 00000000..d5c5e585 --- /dev/null +++ b/Medium/Target Sum.java @@ -0,0 +1,34 @@ +class Solution { + int count; + public int findTargetSumWays(int[] nums, int S) { + int[][] dp = new int[nums.length][2001]; + for (int[] row : dp) { + Arrays.fill(row, Integer.MIN_VALUE); + } + return calculateWays(nums, 0, 0, S, dp); + } + + private void calculateWaysDfs(int[] nums, int idx, int S) { + if (idx == nums.length) { + if (S == 0) { + count++; + } + return; + } + dfs(nums, idx + 1, S - nums[idx]); + dfs(nums, idx + 1, S + nums[idx]); + } + + private int calculateWaysDp(int[] nums, int idx, int sum, int S, int[][] dp) { + if (idx == nums.length) { + return sum == S ? 1 : 0; + } + if (dp[idx][sum + 1000] != Integer.MIN_VALUE) { + return dp[idx][sum + 1000]; + } + int add = calculateWaysDp(nums, idx + 1, sum + nums[idx], S, dp); + int sub = calculateWaysDp(nums, idx + 1, sum - nums[idx], S, dp); + dp[idx][sum + 1000] = add + sub; + return dp[idx][sum + 1000]; + } +} diff --git a/Medium/Task Scheduler.java b/Medium/Task Scheduler.java index e8843bf8..0023aa9d 100644 --- a/Medium/Task Scheduler.java +++ b/Medium/Task Scheduler.java @@ -1,45 +1,30 @@ class Solution { public int leastInterval(char[] tasks, int n) { Map map = new HashMap<>(); - for (char task : tasks) { - map.put(task, map.getOrDefault(task, 0) + 1); + for (char c : tasks) { + map.put(c, map.getOrDefault(c, 0) + 1); } - - PriorityQueue pq = new PriorityQueue<>((o1, o2) -> { - int c = map.get(o2).compareTo(map.get(o1)); - if (c != 0) { - return c; - } - - return o1 - o2; - }); - pq.addAll(map.keySet()); - - int count = 0; + PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); + pq.addAll(map.values()); + int cycles = 0; while (!pq.isEmpty()) { - int jump = n + 1; - List temp = new ArrayList<>(); - while (jump > 0 && !pq.isEmpty()) { - Character polled = pq.poll(); - map.put(polled, map.get(polled) - 1); - temp.add(polled); - jump--; - count++; - } - - for (Character executedTask : temp) { - if (map.get(executedTask) > 0) { - pq.add(executedTask); + List temp = new ArrayList<>(); + // Wait for one cooldown period and process one occurrence of all remaining tasks + for (int i = 0; i < n + 1; i++) { + if (!pq.isEmpty()) { + temp.add(pq.remove()); } } - - if (pq.isEmpty()) { - break; + // If task has more occurrences left then add it back to heap + for (int task : temp) { + if (task > 1) { + pq.add(task - 1); + } } - - count += jump; + // If heap is empty that means we finished all tasks and don't need to wait for + // the whole cooldown to finish else add one complete cooldown period + cycles += pq.isEmpty() ? temp.size() : n + 1; } - - return count; + return cycles; } } diff --git a/Medium/Teemo Attacking.java b/Medium/Teemo Attacking.java deleted file mode 100644 index 14f6e450..00000000 --- a/Medium/Teemo Attacking.java +++ /dev/null @@ -1,14 +0,0 @@ -class Solution { - public int findPoisonedDuration(int[] timeSeries, int duration) { - - if (timeSeries.length == 0 || duration == 0) return 0; - - int begin = timeSeries[0], total = 0; - for (int t : timeSeries) { - total = total + (t < begin + duration ? t - begin : duration); - begin = t; - } - - return total + duration; - } -} diff --git a/Medium/Ternary Expression Parser.java b/Medium/Ternary Expression Parser.java index 67b0118d..6798336d 100644 --- a/Medium/Ternary Expression Parser.java +++ b/Medium/Ternary Expression Parser.java @@ -1,30 +1,19 @@ class Solution { public String parseTernary(String expression) { - if (expression.length() <= 1) { - return expression; - } - - int idx = expression.indexOf('?'); - int count = 0; - - while (idx < expression.length()) { - if (expression.charAt(idx) == '?') { - count++; - } - else if (expression.charAt(idx) == ':') { - count--; - } - else if (count == 0) { - break; + Stack stack = new Stack<>(); + int idx = expression.length() - 1; + while (idx >= 0) { + char c = expression.charAt(idx); + if (c >= '0' && c <= '9' || c == 'T' || c == 'F') { + stack.push(c); + } else if (c == '?') { + char trueValue = stack.pop(); + char falseValue = stack.pop(); + stack.push(expression.charAt(idx - 1) == 'T' ? trueValue : falseValue); + idx--; } - - idx++; + idx--; } - - String booleanCheck = expression.substring(0, expression.indexOf('?')); - String left = expression.substring(expression.indexOf('?') + 1, idx-1); - String right = expression.substring(idx); - - return booleanCheck.equals("T") ? parseTernary(left) : parseTernary(right); + return String.valueOf(stack.pop()); } } diff --git a/Medium/The Earliest Moment When Everyone Become Friends.java b/Medium/The Earliest Moment When Everyone Become Friends.java index 739711d6..8de3e818 100644 --- a/Medium/The Earliest Moment When Everyone Become Friends.java +++ b/Medium/The Earliest Moment When Everyone Become Friends.java @@ -1,47 +1,41 @@ class Solution { - public int earliestAcq(int[][] logs, int N) { - Arrays.sort(logs, Comparator.comparingInt(o -> o[0])); - Map> map = new HashMap<>(); - + public int earliestAcq(int[][] logs, int n) { + Arrays.sort(logs, Comparator.comparingInt(a -> a[0])); + UnionFind uf = new UnionFind(n); for (int[] log : logs) { - boolean[] allDone = {false}; - map.computeIfAbsent(log[1], k -> new HashSet<>()).add(log[2]); - dfs(map, log[1], log[2], allDone, N); - - map.computeIfAbsent(log[2], k -> new HashSet<>()).add(log[1]); - dfs(map, log[2], log[1], allDone, N); - - - if (allDone[0]) { + uf.union(log[1], log[2]); + if (uf.count == 1) { return log[0]; } } - return -1; } - private void dfs(Map> map, int f1, int f2, boolean[] allDone, int N) { - Set visited = new HashSet<>(); - Queue queue = new LinkedList<>(); - queue.add(f1); - visited.add(f1); + static class UnionFind { + private final int[] parent; + private int count; - while (!queue.isEmpty()) { - int removed = queue.poll(); - Iterator iterator = map.getOrDefault(removed, new HashSet<>()).iterator(); - while (iterator.hasNext()) { - int friend = iterator.next(); - if (!visited.contains(friend)) { - queue.add(friend); - map.computeIfAbsent(friend, k -> new HashSet<>()).add(f2); - map.computeIfAbsent(f2, k -> new HashSet<>()).add(friend); + public UnionFind(int n) { + parent = new int[n]; + count = n; + for (int i = 0; i < n; i++) { + parent[i] = i; + } + } - if (map.get(f2).size() == N || map.get(friend).size() == N) { - allDone[0] = true; - } + public int find(int node) { + if (parent[node] != node) { + parent[node] = find(parent[node]); + } + return parent[node]; + } - visited.add(friend); - } + public void union(int x, int y) { + int rootX = find(x); + int rootY = find(y); + if (rootX != rootY) { + parent[rootX] = rootY; + count--; } } } diff --git a/Medium/The Number of Beautiful Subsets.java b/Medium/The Number of Beautiful Subsets.java new file mode 100644 index 00000000..7057a18d --- /dev/null +++ b/Medium/The Number of Beautiful Subsets.java @@ -0,0 +1,20 @@ +class Solution { + public int beautifulSubsets(int[] nums, int k) { + Map freqMap = new HashMap<>(); + Arrays.sort(nums); + return countBeautifulSubsets(nums, k, freqMap, 0) - 1; + } + + private int countBeautifulSubsets(int[] nums, int k, Map freqMap, int idx) { + if (idx == nums.length) { + return 1; + } + int count = countBeautifulSubsets(nums, k, freqMap, idx + 1); + if (freqMap.getOrDefault(nums[idx] - k, 0) == 0) { + freqMap.put(nums[idx], freqMap.getOrDefault(nums[idx], 0) + 1); + count += countBeautifulSubsets(nums, k, freqMap, idx + 1); + freqMap.put(nums[idx], freqMap.getOrDefault(nums[idx], 0) - 1); + } + return count; + } +} diff --git a/Medium/The Number of Full Rounds You Have Played.java b/Medium/The Number of Full Rounds You Have Played.java new file mode 100644 index 00000000..a265d7f7 --- /dev/null +++ b/Medium/The Number of Full Rounds You Have Played.java @@ -0,0 +1,24 @@ +class Solution { + public int numberOfRounds(String startTime, String finishTime) { + int startMinutes = toMinutes(startTime); + int finishMinutes = toMinutes(finishTime); + int roundedStart = toNextQuarter(startMinutes); + int roundedFinish = toPreviousQuarter(finishMinutes); + if (startMinutes < finishMinutes) { + return Math.max(0, (roundedFinish - roundedStart) / 15); + } + return (24 * 60 - roundedStart + roundedFinish) / 15; + } + + public static int toMinutes(String s) { + return Integer.parseInt(s.substring(0, 2)) * 60 + Integer.parseInt(s.substring(3, 5)); + } + + public static int toNextQuarter(int time) { + return ((time + 14) / 15) * 15; + } + + public static int toPreviousQuarter(int time) { + return (time / 15) * 15; + } +} diff --git a/Medium/The Number of Weak Characters in the Game.java b/Medium/The Number of Weak Characters in the Game.java new file mode 100644 index 00000000..18607097 --- /dev/null +++ b/Medium/The Number of Weak Characters in the Game.java @@ -0,0 +1,26 @@ +class Solution { + public int numberOfWeakCharacters(int[][] properties) { + int maxAttackValue = 0; + for (int[] property : properties) { + maxAttackValue = Math.max(maxAttackValue, property[0]); + } + int maxDefense[] = new int[maxAttackValue + 2]; + for (int[] property : properties) { + int attack = property[0]; + int defense = property[1]; + maxDefense[attack] = Math.max(maxDefense[attack], defense); + } + for (int i = maxAttackValue - 1; i >= 0; i--) { + maxDefense[i] = Math.max(maxDefense[i], maxDefense[i + 1]); + } + int count = 0; + for (int[] property : properties) { + int attack = property[0]; + int defense = property[1]; + if (defense < maxDefense[attack + 1]) { + count++; + } + } + return count; + } +} diff --git a/Medium/The Number of the Smallest Unoccupied Chair.java b/Medium/The Number of the Smallest Unoccupied Chair.java new file mode 100644 index 00000000..6bd41ad2 --- /dev/null +++ b/Medium/The Number of the Smallest Unoccupied Chair.java @@ -0,0 +1,35 @@ +class Solution { + public int smallestChair(int[][] times, int targetFriend) { + PriorityQueue pq = new PriorityQueue<>((o1, o2) -> { + int c = o1[0] - o2[0]; + if (c == 0) { + return o1[1] - o2[1]; + } + return c; + }); + for (int i = 0; i < times.length; i++) { + pq.add(new int[]{times[i][0], times[i][1], i}); + } + PriorityQueue occupiedChairs = new PriorityQueue<>(Comparator.comparingInt(o -> o[0])); + PriorityQueue emptyChairs = new PriorityQueue<>(); + int currChair = 0; + while (!pq.isEmpty()) { + int[] time = pq.poll(); + while (!occupiedChairs.isEmpty() && occupiedChairs.peek()[0] <= time[0]) { + int[] chair = occupiedChairs.poll(); + emptyChairs.add(chair[1]); + } + if (time[2] == targetFriend) { + return emptyChairs.isEmpty() ? currChair : emptyChairs.poll(); + } + if (emptyChairs.isEmpty()) { + occupiedChairs.add(new int[]{time[1], currChair}); + currChair++; + } else { + int chair = emptyChairs.poll(); + occupiedChairs.add(new int[]{time[1], chair}); + } + } + return -1; + } +} diff --git a/Medium/The k Strongest Values in an Array.java b/Medium/The k Strongest Values in an Array.java new file mode 100644 index 00000000..1bce4fc2 --- /dev/null +++ b/Medium/The k Strongest Values in an Array.java @@ -0,0 +1,14 @@ +class Solution { + public int[] getStrongest(int[] arr, int k) { + Arrays.sort(arr); + int i = 0; + int j = arr.length - 1; + int idx = 0; + int median = arr[(arr.length - 1) / 2]; + int[] res = new int[k]; + while (idx < k) { + res[idx++] = (median - arr[i] > arr[j] - median) ? arr[i++] : arr[j--]; + } + return res; + } +} diff --git a/Medium/The k-th Lexicographical String of All Happy Strings of Length n.java b/Medium/The k-th Lexicographical String of All Happy Strings of Length n.java new file mode 100644 index 00000000..413b67d5 --- /dev/null +++ b/Medium/The k-th Lexicographical String of All Happy Strings of Length n.java @@ -0,0 +1,28 @@ +class Solution { + private static final char[] CHARS = {'a', 'b', 'c'}; + + public String getHappyString(int n, int k) { + Set set = new HashSet<>(); + backtrack(set, new StringBuilder(), n); + if (set.size() < k) { + return ""; + } + List list = new ArrayList<>(set); + Collections.sort(list); + return list.get(k - 1); + } + + private void backtrack(Set set, StringBuilder sb, int n) { + if (sb.length() == n) { + set.add(sb.toString()); + return; + } + for (char c : CHARS) { + if (sb.isEmpty() || sb.charAt(sb.length() - 1) != c) { + sb.append(c); + backtrack(set, sb, n); + sb.deleteCharAt(sb.length() - 1); + } + } + } +} diff --git a/Medium/The kth Factor of n.java b/Medium/The kth Factor of n.java new file mode 100644 index 00000000..046b3293 --- /dev/null +++ b/Medium/The kth Factor of n.java @@ -0,0 +1,10 @@ +class Solution { + public int kthFactor(int n, int k) { + for (int i = 1; i <= n / 2; i++) { + if (n % i == 0 && --k == 0) { + return i; + } + } + return k == 1 ? n : -1; + } +} diff --git a/Medium/Throne Inheritence.java b/Medium/Throne Inheritence.java new file mode 100644 index 00000000..49b2ed0c --- /dev/null +++ b/Medium/Throne Inheritence.java @@ -0,0 +1,42 @@ +class ThroneInheritance { + Map> family; + Set deadPeople; + String king; + public ThroneInheritance(String kingName) { + this.king = kingName; + family = new HashMap<>(); + family.put(kingName, new ArrayList<>()); + deadPeople = new HashSet<>(); + } + + public void birth(String parentName, String childName) { + family.computeIfAbsent(parentName, k -> new ArrayList<>()).add(childName); + } + + public void death(String name) { + deadPeople.add(name); + } + + public List getInheritanceOrder() { + List inheritenceOrder = new ArrayList<>(); + findInheritenceRecursively(king, inheritenceOrder); + return inheritenceOrder; + } + + private void findInheritenceRecursively(String currPerson, List inheritenceOrder) { + if (!deadPeople.contains(currPerson)) { + inheritenceOrder.add(currPerson); + } + for (String children : family.getOrDefault(currPerson, new ArrayList<>())) { + findInheritenceRecursively(children, inheritenceOrder); + } + } +} + +/** + * Your ThroneInheritance object will be instantiated and called as such: + * ThroneInheritance obj = new ThroneInheritance(kingName); + * obj.birth(parentName,childName); + * obj.death(name); + * List param_3 = obj.getInheritanceOrder(); + */ diff --git a/Medium/Time Based Key-Value Store.java b/Medium/Time Based Key-Value Store.java new file mode 100644 index 00000000..7433689e --- /dev/null +++ b/Medium/Time Based Key-Value Store.java @@ -0,0 +1,49 @@ +class TimeMap { + + private Map> map; + + public TimeMap() { + this.map = new HashMap<>(); + } + + public void set(String key, String value, int timestamp) { + this.map.computeIfAbsent(key, k -> new ArrayList<>()).add(new TimeStampValuePair(timestamp, value)); + } + + public String get(String key, int timestamp) { + if (!this.map.containsKey(key)) { + return ""; + } + List pairs = this.map.get(key); + int left = 0; + int right = pairs.size() - 1; + int maxIdx = -1; + while (left <= right) { + int mid = (left + right) / 2; + if (pairs.get(mid).timestamp <= timestamp) { + maxIdx = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + return maxIdx == -1 ? "" : pairs.get(maxIdx).value; + } + + private class TimeStampValuePair { + int timestamp; + String value; + + public TimeStampValuePair(int timestamp, String value) { + this.timestamp = timestamp; + this.value = value; + } + } +} + +/** + * Your TimeMap object will be instantiated and called as such: + * TimeMap obj = new TimeMap(); + * obj.set(key,value,timestamp); + * String param_2 = obj.get(key,timestamp); + */ diff --git a/Medium/Time Needed to Inform All Employees.java b/Medium/Time Needed to Inform All Employees.java new file mode 100644 index 00000000..f8cc21ac --- /dev/null +++ b/Medium/Time Needed to Inform All Employees.java @@ -0,0 +1,24 @@ +class Solution { + public int numOfMinutes(int n, int headID, int[] manager, int[] informTime) { + Map> organization = new HashMap<>(); + for (int i = 0; i < manager.length; i++) { + if (manager[i] == -1) { + continue; + } + organization.computeIfAbsent(manager[i], k -> new ArrayList<>()).add(i); + } + int maxTime = 0; + Queue queue = new LinkedList<>(); + queue.add(new int[]{headID, 0}); + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int currManager = removed[0]; + int timeElapsed = removed[1]; + maxTime = Math.max(maxTime, timeElapsed); + for (Integer employee : organization.getOrDefault(currManager, new ArrayList<>())) { + queue.add(new int[]{employee, timeElapsed + informTime[currManager]}); + } + } + return maxTime; + } +} diff --git a/Medium/Time Needed to Rearrange a Binary String.java b/Medium/Time Needed to Rearrange a Binary String.java new file mode 100644 index 00000000..f9c4dcf5 --- /dev/null +++ b/Medium/Time Needed to Rearrange a Binary String.java @@ -0,0 +1,13 @@ +class Solution { + public int secondsToRemoveOccurrences(String s) { + int time = 0; + int zeros = 0; + for (int i = 0; i < s.length(); i++) { + zeros += s.charAt(i) == '0' ? 1 : 0; + if (s.charAt(i) == '1' && zeros > 0) { + time = Math.max(time + 1, zeros); + } + } + return time; + } +} diff --git a/Medium/Top K Frequent Elements.java b/Medium/Top K Frequent Elements.java index 918a9006..ffb13529 100644 --- a/Medium/Top K Frequent Elements.java +++ b/Medium/Top K Frequent Elements.java @@ -1,49 +1,25 @@ class Solution { - - public List topKFrequent(int[] nums, int k) { - Map map = new HashMap<>(); - - for (int i=0;i sortedMap = sortByValue(map); - - List ans = new ArrayList<>(); - int c = 0; - - for (Map.Entry entry : sortedMap.entrySet()) { - if (c == k) break; - ans.add(entry.getKey()); - - c++; - } - - return ans; + public int[] topKFrequent(int[] nums, int k) { + Map map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + Map> frequencyToValueMap = new HashMap<>(); + for (Integer key : map.keySet()) { + frequencyToValueMap.computeIfAbsent(map.get(key), j -> new ArrayList<>()).add(key); } - - private Map sortByValue(Map unsortMap) { - - List> list = - new LinkedList>(unsortMap.entrySet()); - - Collections.sort(list, new Comparator>() { - public int compare(Map.Entry o1, - Map.Entry o2) { - return (o2.getValue()).compareTo(o1.getValue()); - } - }); - - Map sortedMap = new LinkedHashMap(); - for (Map.Entry entry : list) { - sortedMap.put(entry.getKey(), entry.getValue()); + List result = new ArrayList<>(); + for (int i = nums.length; i >= 0 && result.size() < k; i--) { + List values = frequencyToValueMap.getOrDefault(i, new ArrayList<>()); + if (result.size() + values.size() <= k) { + result.addAll(values); + } else { + int idx = 0; + while (result.size() < k) { + result.add(values.get(idx++)); } - - return sortedMap; + } } + return result.stream().mapToInt(i -> i).toArray(); + } } diff --git a/Medium/Top K Frequent Words.java b/Medium/Top K Frequent Words.java index 5b26e158..7f1c4f9f 100644 --- a/Medium/Top K Frequent Words.java +++ b/Medium/Top K Frequent Words.java @@ -1,30 +1,29 @@ class Solution { - public List topKFrequent(String[] words, int k) { - Map map = new HashMap<>(); - for (String word : words) { - map.put(word, map.getOrDefault(word, 0) + 1); - } - - PriorityQueue pq = new PriorityQueue<>(new Comparator(){ - public int compare(String s1, String s2) { - int c = map.get(s2).compareTo(map.get(s1)); - if (c != 0) { - return c; - } - - return s1.compareTo(s2); - } - }); - - for (String key : map.keySet()) { - pq.add(key); - } - - List list = new ArrayList<>(); - while (k-- > 0 && !pq.isEmpty()) { - list.add(pq.poll()); - } - - return list; + public List topKFrequent(String[] words, int k) { + Map wordFrequency = new HashMap<>(); + Map> frequencyToWord = new HashMap<>(); + int maxFrequency = 0; + for (String word : words) { + if (!wordFrequency.containsKey(word)) { + wordFrequency.put(word, 1); + frequencyToWord.computeIfAbsent(1, j -> new HashSet<>()).add(word); + } else { + int oldFrequency = wordFrequency.get(word); + int newFrequency = oldFrequency + 1; + wordFrequency.put(word, newFrequency); + frequencyToWord.get(oldFrequency).remove(word); + frequencyToWord.computeIfAbsent(newFrequency, j -> new HashSet<>()).add(word); + } + maxFrequency = Math.max(maxFrequency, wordFrequency.get(word)); } + List result = new ArrayList<>(); + for (int i = maxFrequency; i > 0 && result.size() < k; i--) { + List currFreqWords = new ArrayList<>(frequencyToWord.get(i)); + Collections.sort(currFreqWords); + for (int j = 0; j < currFreqWords.size() && result.size() < k; j++) { + result.add(currFreqWords.get(j)); + } + } + return result; + } } diff --git a/Medium/Total Characters in String After Transformations I.java b/Medium/Total Characters in String After Transformations I.java new file mode 100644 index 00000000..3751ab7e --- /dev/null +++ b/Medium/Total Characters in String After Transformations I.java @@ -0,0 +1,25 @@ +class Solution { + + private static final int MOD = 1000_0000_07; + + public int lengthAfterTransformations(String s, int t) { + int[] frequency = new int[26]; + for (char c : s.toCharArray()) { + frequency[c - 'a']++; + } + for (int round = 0; round < t; round++) { + int[] next = new int[26]; + next[0] = frequency[25]; // Transformation from 'z' + next[1] = (frequency[25] + frequency[0]) % MOD; // Transformation from either 'z' or 'a' + for (int i = 2; i < 26; i++) { + next[i] = frequency[i - 1]; // Transformation for next character + } + frequency = next; + } + int result = 0; + for (int i = 0; i < 26; i++) { + result = (result + frequency[i]) % MOD; + } + return result; + } +} diff --git a/Medium/Total Cost to Hire K Workers.java b/Medium/Total Cost to Hire K Workers.java new file mode 100644 index 00000000..c5708a4b --- /dev/null +++ b/Medium/Total Cost to Hire K Workers.java @@ -0,0 +1,29 @@ +class Solution { + public long totalCost(int[] costs, int k, int candidates) { + PriorityQueue headWorkers = new PriorityQueue<>(); + PriorityQueue tailWorkers = new PriorityQueue<>(); + for (int i = 0; i < candidates; i++) { + headWorkers.add(costs[i]); + } + for (int i = Math.max(candidates, costs.length - candidates); i < costs.length; i++) { + tailWorkers.add(costs[i]); + } + int headIdx = candidates; + int tailIdx = costs.length - candidates - 1; + long result = 0; + for (int i = 0; i < k; i++) { + if (tailWorkers.isEmpty() || (!headWorkers.isEmpty() && headWorkers.peek() <= tailWorkers.peek())) { + result += headWorkers.poll(); + if (headIdx <= tailIdx) { + headWorkers.add(costs[headIdx++]); + } + } else { + result += tailWorkers.poll(); + if (headIdx <= tailIdx) { + tailWorkers.add(costs[tailIdx--]); + } + } + } + return result; + } +} diff --git a/Medium/Total Hamming Distance.java b/Medium/Total Hamming Distance.java new file mode 100644 index 00000000..afb641ab --- /dev/null +++ b/Medium/Total Hamming Distance.java @@ -0,0 +1,15 @@ +class Solution { + public int totalHammingDistance(int[] nums) { + int count = 0; + for (int i = 0; i < 32; i++) { + int bitCount = 0; + for (int j = 0; j < nums.length; j++) { + bitCount += (nums[j] >> i) & 1; + } + + count += bitCount * (nums.length - bitCount); + } + + return count; + } +} diff --git a/Medium/Tree Diameter.java b/Medium/Tree Diameter.java new file mode 100644 index 00000000..87d5eab9 --- /dev/null +++ b/Medium/Tree Diameter.java @@ -0,0 +1,39 @@ +class Solution { + public int treeDiameter(int[][] edges) { + int n = edges.length; + List> graph = new ArrayList<>(); + boolean[] visited = new boolean[n + 1]; + for (int i = 0; i < n + 1; i++) { + graph.add(new HashSet<>()); + } + for (int[] edge : edges) { + int nodeOne = edge[0]; + int nodeTwo = edge[1]; + graph.get(nodeOne).add(nodeTwo); + graph.get(nodeTwo).add(nodeOne); + } + int[] diameter = {0}; + dfs(0, visited, graph, diameter); + return diameter[0]; + } + + private int dfs(int node, boolean[] visited, List> graph, int[] diameter) { + int highestDistance = 0; + int secondHighestDistance = 0; + visited[node] = true; + for (Integer conn : graph.get(node)) { + int distance = 0; + if (!visited[conn]) { + distance = 1 + dfs(conn, visited, graph, diameter); + } + if (distance > highestDistance) { + secondHighestDistance = highestDistance; + highestDistance = distance; + } else if (distance > secondHighestDistance) { + secondHighestDistance = distance; + } + } + diameter[0] = Math.max(diameter[0], highestDistance + secondHighestDistance); + return highestDistance; + } +} diff --git a/Medium/Triangle.java b/Medium/Triangle.java new file mode 100644 index 00000000..0d4a8b54 --- /dev/null +++ b/Medium/Triangle.java @@ -0,0 +1,19 @@ +class Solution { + public int minimumTotal(List> triangle) { + Map dp = new HashMap<>(); + return minimumTotalHelper(triangle, dp, 0, 0); + } + + private int minimumTotalHelper(List> triangle, Map dp, int row, int col) { + String key = row + "|" + col; + if (dp.containsKey(key)) { + return dp.get(key); + } + int path = triangle.get(row).get(col); + if (row < triangle.size() - 1) { + path += Math.min(minimumTotalHelper(triangle, dp, row + 1, col), minimumTotalHelper(triangle, dp, row + 1, col + 1)); + } + dp.put(key, path); + return dp.get(key); + } +} diff --git a/Medium/Trim a Binary Search Tree.java b/Medium/Trim a Binary Search Tree.java new file mode 100644 index 00000000..d7b8d9ff --- /dev/null +++ b/Medium/Trim a Binary Search Tree.java @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public TreeNode trimBST(TreeNode root, int low, int high) { + if (root == null) { + return null; + } + if (root.val < low) { + return trimBST(root.right, low, high); + } else if (root.val > high) { + return trimBST(root.left, low, high); + } + root.left = trimBST(root.left, low, high); + root.right = trimBST(root.right, low, high); + return root; + } +} diff --git a/Medium/Tuple With Same Product.java b/Medium/Tuple With Same Product.java new file mode 100644 index 00000000..fa9165e6 --- /dev/null +++ b/Medium/Tuple With Same Product.java @@ -0,0 +1,14 @@ +class Solution { + public int tupleSameProduct(int[] nums) { + int count = 0; + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + for (int j = i + 1; j < nums.length; j++) { + int prod = nums[i] * nums[j]; + count += map.getOrDefault(prod, 0); + map.put(prod, map.getOrDefault(prod, 0) + 1); + } + } + return count * 8; + } +} diff --git a/Medium/Tweet Counts Per Frequency.java b/Medium/Tweet Counts Per Frequency.java new file mode 100644 index 00000000..9d58d990 --- /dev/null +++ b/Medium/Tweet Counts Per Frequency.java @@ -0,0 +1,36 @@ +class TweetCounts { + + private final Map> map; + private static final Map INTERVAL_MAP = Map.of( + "minute", 60, + "hour", 3600, + "day", 86400); + + public TweetCounts() { + this.map = new HashMap<>(); + } + + public void recordTweet(String tweetName, int time) { + map.computeIfAbsent(tweetName, k -> new TreeMap<>()); + map.get(tweetName).merge(time, 1, Integer::sum); + } + + public List getTweetCountsPerFrequency(String freq, String tweetName, int startTime, int endTime) { + int interval = INTERVAL_MAP.get(freq); + int size = ((endTime - startTime) / interval + 1); + int[] buckets = new int[size]; + TreeMap frequencyMap = map.get(tweetName); + for (Integer key : frequencyMap.subMap(startTime, endTime + 1).keySet()) { + int idx = (key - startTime) / interval; + buckets[idx] += frequencyMap.get(key); + } + return Arrays.stream(buckets).boxed().collect(Collectors.toList()); + } +} + +/** + * Your TweetCounts object will be instantiated and called as such: + * TweetCounts obj = new TweetCounts(); + * obj.recordTweet(tweetName,time); + * List param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime); + */ diff --git a/Medium/Two City Scheduling.java b/Medium/Two City Scheduling.java new file mode 100644 index 00000000..6f75aeda --- /dev/null +++ b/Medium/Two City Scheduling.java @@ -0,0 +1,11 @@ +class Solution { + public int twoCitySchedCost(int[][] costs) { + Arrays.sort(costs, (o1, o2) -> o1[0] - o1[1] - (o2[0] - o2[1])); + int total = 0; + int n = costs.length / 2; + for (int i = 0; i < n; ++i) { + total += costs[i][0] + costs[i + n][1]; + } + return total; + } +} diff --git a/Medium/Two Sum BSTs.java b/Medium/Two Sum BSTs.java new file mode 100644 index 00000000..d6dd2cf3 --- /dev/null +++ b/Medium/Two Sum BSTs.java @@ -0,0 +1,42 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean twoSumBSTs(TreeNode root1, TreeNode root2, int target) { + ArrayDeque stack = new ArrayDeque<>(); + Set set = new HashSet<>(); + while (!stack.isEmpty() || root1 != null) { + while (root1 != null) { + stack.push(root1); + root1 = root1.left; + } + root1 = stack.pop(); + set.add(target - root1.val); + root1 = root1.right; + } + while (!stack.isEmpty() || root2 != null) { + while (root2 != null) { + stack.push(root2); + root2 = root2.left; + } + root2 = stack.pop(); + if (set.contains(root2.val)) { + return true; + } + root2 = root2.right; + } + return false; + } +} diff --git a/Medium/Two Sum II - Input Array Is Sorted.java b/Medium/Two Sum II - Input Array Is Sorted.java new file mode 100644 index 00000000..f896157c --- /dev/null +++ b/Medium/Two Sum II - Input Array Is Sorted.java @@ -0,0 +1,17 @@ +class Solution { + public int[] twoSum(int[] numbers, int target) { + int leftIdx = 0; + int rightIdx = numbers.length - 1; + while (leftIdx < rightIdx) { + int currSum = numbers[leftIdx] + numbers[rightIdx]; + if (currSum == target) { + return new int[]{leftIdx + 1, rightIdx + 1}; + } else if (currSum > target) { + rightIdx--; + } else { + leftIdx++; + } + } + return new int[]{0}; + } +} diff --git a/Medium/UTF-8 Validation.java b/Medium/UTF-8 Validation.java new file mode 100644 index 00000000..bf7140f0 --- /dev/null +++ b/Medium/UTF-8 Validation.java @@ -0,0 +1,31 @@ +class Solution { + public boolean validUtf8(int[] data) { + int numberOfBytes = 0; + for (int i = 0; i < data.length; i++) { + String binaryRep = Integer.toBinaryString(data[i]); + binaryRep = binaryRep.length() >= 8 ? + binaryRep.substring(binaryRep.length() - 8) : + "00000000".substring(binaryRep.length() % 8) + binaryRep; + if (numberOfBytes == 0) { + for (int j = 0; j < binaryRep.length(); j++) { + if (binaryRep.charAt(j) == '0') { + break; + } + numberOfBytes++; + } + if (numberOfBytes == 0) { + continue; + } + if (numberOfBytes > 4 || numberOfBytes == 1) { + return false; + } + } else { + if (!(binaryRep.charAt(0) == '1' && binaryRep.charAt(1) == '0')) { + return false; + } + } + numberOfBytes--; + } + return numberOfBytes == 0; + } +} diff --git a/Medium/Ugly Number II.java b/Medium/Ugly Number II.java index f7705d14..d9fe4082 100644 --- a/Medium/Ugly Number II.java +++ b/Medium/Ugly Number II.java @@ -1,35 +1,30 @@ class Solution { - public static int nthUglyNumber(int n) { - int[] arr = new int[n]; - arr[0] = 1; - int i2 = 0; - int i3 = 0; - int i5 = 0; - - int mul2 = 2; - int mul3 = 3; - int mul5 = 5; - - int ugly = 1; - - for (int i=1; i map; - public ValidWordAbbr(String[] dictionary) { - map = new HashMap<>(); - - for (String word : dictionary) { - String abbr = getAbbr(word); - if (map.containsKey(abbr)) { - if (!map.get(abbr).equals(word)) { - map.put(abbr, ""); - } - } - else { - map.put(abbr, word); - } - } - } - - public boolean isUnique(String word) { - String abbr = getAbbr(word); - return !map.containsKey(abbr) || map.get(abbr).equals(word); + private final Map abbreviationToWordMap; + + public ValidWordAbbr(String[] dictionary) { + this.abbreviationToWordMap = new HashMap<>(); + for (String word : dictionary) { + String abbreviation = buildAbbreviation(word); + if (this.abbreviationToWordMap.containsKey(abbreviation) && + !this.abbreviationToWordMap.get(abbreviation).equals(word)) { + this.abbreviationToWordMap.put(abbreviation, ""); + } else { + this.abbreviationToWordMap.put(abbreviation, word); + } } + } - private String getAbbr(String word) { - if (word.length() <= 2) { - return word; - } + public boolean isUnique(String word) { + String abbreviation = buildAbbreviation(word); + return !this.abbreviationToWordMap.containsKey(abbreviation) || this.abbreviationToWordMap.get( + abbreviation).equals(word); + } - int num = word.length() - 2; - StringBuilder sb = new StringBuilder(); - sb.append(word.charAt(0)).append(String.valueOf(num)).append(word.charAt(word.length()-1)); - - return sb.toString(); + private String buildAbbreviation(String s) { + if (s.length() <= 2) { + return s; } + return s.charAt(0) + String.valueOf(s.length() - 2) + s.charAt(s.length() - 1); + } } - - /** * Your ValidWordAbbr object will be instantiated and called as such: * ValidWordAbbr obj = new ValidWordAbbr(dictionary); diff --git a/Medium/Using a Robot to Print the Lexicographically Smallest String.java b/Medium/Using a Robot to Print the Lexicographically Smallest String.java new file mode 100644 index 00000000..8d9c2064 --- /dev/null +++ b/Medium/Using a Robot to Print the Lexicographically Smallest String.java @@ -0,0 +1,31 @@ +class Solution { + public String robotWithString(String s) { + int[] counter = new int[26]; + for (char c : s.toCharArray()) { + counter[c - 'a']++; + } + Stack stack = new Stack<>(); + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + stack.push(c); + counter[c - 'a']--; + while (!stack.isEmpty() && isSmallest(stack.peek(), counter)) { + sb.append(stack.pop()); + } + } + while (!stack.isEmpty()) { + sb.append(stack.pop()); + } + return sb.toString(); + } + + private boolean isSmallest(char c, int[] counter) { + int limit = c - 'a'; + for (int i = 0; i < limit; i++) { + if (counter[i] > 0) { + return false; + } + } + return true; + } +} diff --git a/Medium/Valid Parenthesis String.java b/Medium/Valid Parenthesis String.java new file mode 100644 index 00000000..f4ffdb1c --- /dev/null +++ b/Medium/Valid Parenthesis String.java @@ -0,0 +1,15 @@ +class Solution { + public boolean checkValidString(String s) { + int low = 0; + int high = 0; + for (char c : s.toCharArray()) { + low += c == '(' ? 1 : -1; + high += c != ')' ? 1 : -1; + if (high < 0) { + break; + } + low = Math.max(low, 0); + } + return low == 0; + } +} diff --git a/Medium/Valid Square.java b/Medium/Valid Square.java new file mode 100644 index 00000000..31a72df4 --- /dev/null +++ b/Medium/Valid Square.java @@ -0,0 +1,17 @@ +class Solution { + public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) { + int[][] points = {p1, p2, p3, p4}; + Arrays.sort(points, (i1, i2) -> i2[0] == i1[0] ? i1[1] - i2[1] : i1[0] - i2[0]); + return ( + getDistance(points[0], points[1]) != 0 && + getDistance(points[0], points[1]) == getDistance(points[1], points[3]) && + getDistance(points[1], points[3]) == getDistance(points[3], points[2]) && + getDistance(points[3], points[2]) == getDistance(points[2], points[0]) && + getDistance(points[0],points[3])==getDistance(points[1],points[2]) + ); + } + + private double getDistance(int[] p1, int[] p2) { + return (p2[1] - p1[1]) * (p2[1] - p1[1]) + (p2[0] - p1[0]) * (p2[0] - p1[0]); + } +} diff --git a/Medium/Valid Sudoku.java b/Medium/Valid Sudoku.java new file mode 100644 index 00000000..88538727 --- /dev/null +++ b/Medium/Valid Sudoku.java @@ -0,0 +1,30 @@ +class Solution { + public boolean isValidSudoku(char[][] board) { + int N = 9; + int[][] rows = new int[N][N]; + int[][] cols = new int[N][N]; + int[][] boxes = new int[N][N]; + for (int r = 0; r < N; r++) { + for (int c = 0; c < N; c++) { + if (board[r][c] == '.') { + continue; + } + int pos = board[r][c] - '1'; + if (rows[r][pos] == 1) { + return false; + } + rows[r][pos] = 1; + if (cols[c][pos] == 1) { + return false; + } + cols[c][pos] = 1; + int idx = (r / 3) * 3 + c / 3; + if (boxes[idx][pos] == 1) { + return false; + } + boxes[idx][pos] = 1; + } + } + return true; + } +} diff --git a/Medium/Validate Binary Search Tree.java b/Medium/Validate Binary Search Tree.java new file mode 100644 index 00000000..7989ffbf --- /dev/null +++ b/Medium/Validate Binary Search Tree.java @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + public boolean isValidBST(TreeNode root) { + return isValidBSTHelper(root, (((long) Integer.MAX_VALUE) + 1), ((long) Integer.MIN_VALUE) - 1); + } + + private boolean isValidBSTHelper(TreeNode node, long max, long min) { + if (node == null) { + return true; + } + if (node.val >= max || node.val <= min) { + return false; + } + return isValidBSTHelper(node.left, node.val, min) && isValidBSTHelper(node.right, max, node.val); + } +} diff --git a/Medium/Validate IP Address.java b/Medium/Validate IP Address.java index 7435cbc7..b63c5a59 100644 --- a/Medium/Validate IP Address.java +++ b/Medium/Validate IP Address.java @@ -1,74 +1,97 @@ class Solution { - Set hexCharSet = new HashSet<>(Arrays.asList('a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F')); - - public String validIPAddress(String IP) { - if (IP.indexOf('.') != -1) { - return isValidIPv4(IP) ? "IPv4" : "Neither"; - } - else if (IP.indexOf(':') != -1) { - return isValidIPv6(IP) ? "IPv6" : "Neither"; - } - - return "Neither"; + public String validIPAddress(String IP) { + if (IP.indexOf(':') != -1) { + return validateIPv6(IP); + } + else if (IP.indexOf('.') != -1) { + return validateIPv4(IP); } - - private boolean isValidIPv4(String ip) { - if (ip.startsWith(".") || ip.endsWith(".")) { - return false; + else { + return "Neither"; + } + } + + private String validateIPv6(String ip) { + int count = 0; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ip.length(); i++) { + if (ip.charAt(i) == ':') { + if (!isValidIPv6(sb.toString())) { + return "Neither"; } - String[] components = ip.split("\\."); - if (components.length != 4) { - return false; + sb = new StringBuilder(); + count++; + } + else { + sb.append(ip.charAt(i)); + } + if (i == ip.length() - 1) { + if (!isValidIPv6(sb.toString())) { + return "Neither"; } - - for (String component : components) { - try { - int value = Integer.parseInt(component); - if (value < 0 || value > 255) { - return false; - } - - if (value > 0 && component.startsWith("0")) { - return false; - } - - if (value == 0 && component.length() > 1) { - return false; - } - } catch(Exception e) { - return false; - } + } + } + return count == 7 ? "IPv6" : "Neither"; + } + + private boolean isValidIPv6(String s) { + String lower = "abcdef"; + String upper = "ABCDEF"; + if (s.length() == 0 || s.length() > 4) { + return false; + } + for (char c : s.toCharArray()) { + if (!Character.isDigit(c)) { + if (lower.indexOf(c) == -1 && upper.indexOf(c) == -1) { + return false; } - - return true; + } } - - private boolean isValidIPv6(String ip) { - if (ip.startsWith(":") || ip.endsWith(":")) { - return false; + return true; + } + + private String validateIPv4(String ip) { + StringBuilder sb = new StringBuilder(); + int count = 0; + for (int i = 0; i < ip.length(); i++) { + if (ip.charAt(i) == '.') { + if (!isValidIPv4(sb.toString())) { + return "Neither"; } - - String[] components = ip.split(":"); - if (components.length != 8) { - return false; + sb = new StringBuilder(); + count++; + } + else { + if (!Character.isDigit(ip.charAt(i))) { + return "Neither"; } - - for (String component : components) { - if (component.length() > 4 || component.length() == 0) { - return false; - } - for (char c : component.toCharArray()) { - if (Character.isLetter(c) && hexCharSet.contains(c)) { - continue; - } - else if (Character.isDigit(c)) { - continue; - } - else { - return false; - } - } + sb.append(ip.charAt(i)); + } + if (i == ip.length() - 1) { + if (!isValidIPv4(sb.toString())) { + return "Neither"; } - return true; + } + } + return count == 3 ? "IPv4" : "Neither"; + } + + private boolean isValidIPv4(String s) { + if (s.length() == 0) { + return false; + } + try { + int val = Integer.parseInt(s); + if (val < 0 || val > 255) { + return false; + } + if ((s.startsWith("0") && val != 0) || (val == 0 && s.length() > 1)) { + return false; + } + } + catch (NumberFormatException e) { + return false; } + return true; + } } diff --git a/Medium/Validate Stack Sequences.java b/Medium/Validate Stack Sequences.java new file mode 100644 index 00000000..64ae1452 --- /dev/null +++ b/Medium/Validate Stack Sequences.java @@ -0,0 +1,20 @@ +class Solution { + public boolean validateStackSequences(int[] pushed, int[] popped) { + Stack stack = new Stack<>(); + int pushedIdx = 0; + int poppedIdx = 0; + while (pushedIdx < pushed.length && poppedIdx < popped.length) { + if (!stack.isEmpty() && stack.peek() == popped[poppedIdx]) { + stack.pop(); + poppedIdx++; + } else { + stack.push(pushed[pushedIdx++]); + } + } + while (poppedIdx < popped.length && !stack.isEmpty() && stack.peek() == popped[poppedIdx]) { + stack.pop(); + poppedIdx++; + } + return pushedIdx == pushed.length && poppedIdx == popped.length; + } +} diff --git a/Medium/Verify Preorder Serialization of a Binary Tree.java b/Medium/Verify Preorder Serialization of a Binary Tree.java index 3e1b5151..db43f945 100644 --- a/Medium/Verify Preorder Serialization of a Binary Tree.java +++ b/Medium/Verify Preorder Serialization of a Binary Tree.java @@ -1,24 +1,15 @@ class Solution { - public boolean isValidSerialization(String preorder) { - Stack stack = new Stack<>(); - String[] array = preorder.split(","); - - for (String node : array) { - if (node.equals("#")) { - while (!stack.isEmpty() && stack.peek().equals("#")) { - stack.pop(); - if (stack.isEmpty()) { - return false; - } - stack.pop(); - } - stack.push(node); - } - else { - stack.push(node); - } - } - - return stack.size() == 1 && stack.peek().equals("#"); + public boolean isValidSerialization(String preorder) { + String[] nodes = preorder.split(","); + int diff = 1; + for (String node : nodes) { + if (--diff < 0) { + return false; + } + if (!node.equals("#")) { + diff += 2; + } } + return diff == 0; + } } diff --git a/Medium/Vertical Order Traversal Of Binary Tree.java b/Medium/Vertical Order Traversal Of Binary Tree.java deleted file mode 100644 index a4bb8784..00000000 --- a/Medium/Vertical Order Traversal Of Binary Tree.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode(int x) { val = x; } - * } - */ -class Solution { - class NewNode { - TreeNode t; - int x; - int y; - int level; - - NewNode(TreeNode t, int x, int y, int level) { - this.t = t; - this.x = x; - this.y = y; - this.level = level; - } - } - - int maxLeft; - int maxRight; - Map> map; - - public List> verticalTraversal(TreeNode root) { - maxLeft = 0; - maxRight = 0; - map = new HashMap<>(); - - helper(root, 0); - - List> list = new ArrayList<>(); - - while (maxLeft <= maxRight) { - if (map.containsKey(maxLeft)) { - List temp = map.get(maxLeft); - - Collections.sort(temp, new Comparator() { - @Override - public int compare(NewNode o1, NewNode o2) { - int c = Integer.valueOf(o1.x).compareTo(Integer.valueOf(o2.x)); - if (c == 0) { - c = Integer.valueOf(o2.y).compareTo(Integer.valueOf(o1.y)); - } - - if (c == 0) { - c = Integer.valueOf(o1.t.val).compareTo(Integer.valueOf(o2.t.val)); - } - - return c; - } - }); - - List valList = new ArrayList<>(); - for (NewNode node : temp) { - valList.add(node.t.val); - } - - list.add(valList); - } - - maxLeft++; - } - - return list; - } - - private void helper(TreeNode root, int level) { - if (root == null) { - return; - } - - NewNode node = new NewNode(root, 0, 0, level); - Queue queue = new LinkedList<>(); - - queue.add(node); - - while (!queue.isEmpty()) { - int size = queue.size(); - - while (size-- > 0) { - NewNode temp = queue.remove(); - map.computeIfAbsent(temp.level, k -> new ArrayList<>()).add(temp); - - maxLeft = Math.min(maxLeft, temp.level - 1); - maxRight = Math.max(maxRight, temp.level + 1); - - if (temp.t.left != null) { - queue.add(new NewNode(temp.t.left, temp.x - 1, temp.y - 1, temp.level - 1)); - } - - if (temp.t.right != null) { - queue.add(new NewNode(temp.t.right, temp.x + 1, temp.y - 1, temp.level + 1)); - } - } - } - } -} diff --git a/Medium/Vowel Spellchecker.java b/Medium/Vowel Spellchecker.java index 0d9801ee..105ad71f 100644 --- a/Medium/Vowel Spellchecker.java +++ b/Medium/Vowel Spellchecker.java @@ -1,55 +1,38 @@ class Solution { - public String[] spellchecker(String[] wordlist, String[] queries) { - Map caseMap = new HashMap<>(); - Set set = new HashSet<>(); - - // Case Part - for (String word : wordlist) { - if (!caseMap.containsKey(word.toLowerCase())) { - caseMap.put(word.toLowerCase(), word); - } - - set.add(word); - } - - // Vowel Part - Map vowelMap = new HashMap<>(); - for (String word : wordlist) { - String genericVal = makeGenericVowel(word); - if (!vowelMap.containsKey(genericVal)) { - vowelMap.put(genericVal, word); - } - } - - String[] ans = new String[queries.length]; - - for (int i=0; i capsMap = new HashMap<>(); + Map vowMap = new HashMap<>(); + Set perfect = new HashSet<>(); + for (String word : wordlist) { + perfect.add(word); + capsMap.putIfAbsent(word.toLowerCase(), word); + vowMap.putIfAbsent(getVowelKey(word.toLowerCase()), word); } - - private String makeGenericVowel(String s) { - String vowel = "aeiou"; - char[] ch = s.toLowerCase().toCharArray(); - for (int i=0; i obstacleSet = new HashSet<>(); + for (int[] obstacle : obstacles) { + obstacleSet.add(hashCoordinates(obstacle[0], obstacle[1])); + } + int maxDistance = 0; + int currentDirection = 0; + int x = 0; + int y = 0; + for (int command : commands) { + if (command == -1) { + currentDirection = (currentDirection + 1) % 4; + continue; + } + if (command == -2) { + currentDirection = (currentDirection + 3) % 4; + continue; + } + int[] direction = DIRECTIONS[currentDirection]; + for (int i = 0; i < command; i++) { + int nextX = x + direction[0]; + int nextY = y + direction[1]; + if (obstacleSet.contains(hashCoordinates(nextX, nextY))) { + break; + } + x = nextX; + y = nextY; + } + maxDistance = Math.max(maxDistance, x * x + y * y); + } + return maxDistance; + } + + private static int hashCoordinates(int x, int y) { + return x + HASH_MULTIPLIER * y; + } +} diff --git a/Medium/Walls and Gates.java b/Medium/Walls and Gates.java new file mode 100644 index 00000000..02b45cc4 --- /dev/null +++ b/Medium/Walls and Gates.java @@ -0,0 +1,32 @@ +class Solution { + int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + public void wallsAndGates(int[][] rooms) { + if (rooms.length == 0 || rooms[0].length == 0) { + return; + } + final int INF = Integer.MAX_VALUE; + Queue queue = new LinkedList<>(); + int rows = rooms.length; + int cols = rooms[0].length; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (rooms[i][j] == 0) { + queue.add(new int[]{i, j}); + } + } + } + while (!queue.isEmpty()) { + int[] removed = queue.remove(); + int x = removed[0]; + int y = removed[1]; + for (int[] dir : dirs) { + int newX = x + dir[0]; + int newY = y + dir[1]; + if (newX >= 0 && newY >= 0 && newX < rows && newY < cols && rooms[newX][newY] == INF) { + rooms[newX][newY] = rooms[x][y] + 1; + queue.add(new int[]{newX, newY}); + } + } + } + } +} diff --git a/Medium/Water Bottles II.java b/Medium/Water Bottles II.java new file mode 100644 index 00000000..d9205f31 --- /dev/null +++ b/Medium/Water Bottles II.java @@ -0,0 +1,12 @@ +class Solution { + public int maxBottlesDrunk(int numBottles, int numExchange) { + int total = numBottles; + while (numBottles >= numExchange) { + numBottles -= numExchange; + numExchange++; + total++; + numBottles++; + } + return total; + } +} diff --git a/Medium/Watering Plants.java b/Medium/Watering Plants.java new file mode 100644 index 00000000..afa36ee2 --- /dev/null +++ b/Medium/Watering Plants.java @@ -0,0 +1,16 @@ +class Solution { + public int wateringPlants(int[] plants, int capacity) { + int idx = 0; + int currCapacity = capacity; + int totalSteps = 0; + while (idx < plants.length) { + if (currCapacity < plants[idx]) { + currCapacity = capacity; + totalSteps += 2 * idx; + } + currCapacity -= plants[idx++]; + totalSteps++; + } + return totalSteps; + } +} diff --git a/Medium/Web Crawler.java b/Medium/Web Crawler.java new file mode 100644 index 00000000..57737330 --- /dev/null +++ b/Medium/Web Crawler.java @@ -0,0 +1,33 @@ +/** + * // This is the HtmlParser's API interface. + * // You should not implement it, or speculate about its implementation + * interface HtmlParser { + * public List getUrls(String url) {} + * } + */ + +class Solution { + public List crawl(String startUrl, HtmlParser htmlParser) { + int startIdx = startUrl.indexOf("//") + 2; + int endIdx = startUrl.indexOf("/", startIdx) == -1 ? startUrl.length() : startUrl.indexOf("/", startIdx); + String domain = startUrl.substring(0, endIdx); + Set visitedUrls = new HashSet<>(); + Queue queue = new LinkedList<>(); + queue.add(startUrl); + while (!queue.isEmpty()) { + int size = queue.size(); + while (size-- > 0) { + String removed = queue.remove(); + visitedUrls.add(removed); + List urls = htmlParser.getUrls(removed); + for (String url : urls) { + if (url.startsWith(domain) && !visitedUrls.contains(url)) { + visitedUrls.add(url); + queue.add(url); + } + } + } + } + return new ArrayList<>(visitedUrls); + } +} diff --git a/Medium/Widest Vertical Area Between Two Points Containing No Points.java b/Medium/Widest Vertical Area Between Two Points Containing No Points.java new file mode 100644 index 00000000..d2e07d21 --- /dev/null +++ b/Medium/Widest Vertical Area Between Two Points Containing No Points.java @@ -0,0 +1,11 @@ +class Solution { + public int maxWidthOfVerticalArea(int[][] points) { + Arrays.sort(points, (a, b) -> a[0] - b[0]); + int maxWidth = 0; + for (int i = 1; i < points.length; i++) { + int width = points[i][0] - points[i - 1][0]; + maxWidth = Math.max(maxWidth, width); + } + return maxWidth; + } +} diff --git a/Medium/Wiggle Sort.java b/Medium/Wiggle Sort.java index 56acbb46..68cac74b 100644 --- a/Medium/Wiggle Sort.java +++ b/Medium/Wiggle Sort.java @@ -1,32 +1,11 @@ class Solution { public void wiggleSort(int[] nums) { - if (nums.length <= 1) { - return; + for (int i = 1; i < nums.length; i++) { + if ((i % 2 == 1 && nums[i] < nums[i - 1]) || (i % 2 != 1 && nums[i] > nums[i - 1])) { + int temp = nums[i]; + nums[i] = nums[i - 1]; + nums[i - 1] = temp; + } } - - if (nums.length == 2) { - if (nums[0] > nums[1]) { - swap(nums, 0, 1); - } - } - - int i=0; - while (i < nums.length) { - if (i+1 < nums.length && nums[i] > nums[i+1]) { - swap(nums, i, i+1); - } - - if (i+1 < nums.length && i+2 < nums.length && nums[i+1] <= nums[i+2]) { - swap(nums, i+1, i+2); - } - - i += 2; - } - } - - public void swap(int[] nums, int i, int j) { - int temp = nums[i]; - nums[i] = nums[j]; - nums[j] = temp; } } diff --git a/Medium/Wiggle Subsequence.java b/Medium/Wiggle Subsequence.java new file mode 100644 index 00000000..4e066527 --- /dev/null +++ b/Medium/Wiggle Subsequence.java @@ -0,0 +1,19 @@ +class Solution { + public int wiggleMaxLength(int[] nums) { + if (nums.length < 2) { + return nums.length; + } + int[] increasing = new int[nums.length]; + int[] decreasing = new int[nums.length]; + for (int i = 0; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + increasing[i] = Math.max(increasing[i], decreasing[j] + 1); + } else if (nums[i] < nums[j]) { + decreasing[i] = Math.max(decreasing[i], increasing[j] + 1); + } + } + } + return 1 + Math.max(decreasing[nums.length - 1], increasing[nums.length - 1]); + } +} diff --git a/Medium/Word Break.java b/Medium/Word Break.java index e79bd39f..e678079f 100644 --- a/Medium/Word Break.java +++ b/Medium/Word Break.java @@ -1,19 +1,23 @@ class Solution { - public boolean wordBreak(String s, List wordDict) { - Set wordDictSet=new HashSet(wordDict); - - boolean[] dp = new boolean[s.length() + 1]; - dp[0] = true; - - for (int i = 1; i <= s.length(); i++) { - for (int j = 0; j < i; j++) { - if (dp[j] && wordDictSet.contains(s.substring(j, i))) { - dp[i] = true; - break; - } + public boolean wordBreak(String s, List wordDict) { + Set set = new HashSet<>(wordDict); + Queue queue = new LinkedList<>(); + int[] visited = new int[s.length()]; + queue.add(0); + while (!queue.isEmpty()) { + int start = queue.remove(); + if (visited[start] == 0) { + for (int end = start + 1; end <= s.length(); end++) { + if (set.contains(s.substring(start, end))) { + queue.add(end); + if (end == s.length()) { + return true; } + } } - - return dp[s.length()]; + visited[start] = 1; + } } + return false; + } } diff --git a/Medium/Word Ladder.java b/Medium/Word Ladder.java index 3017beb1..97528684 100644 --- a/Medium/Word Ladder.java +++ b/Medium/Word Ladder.java @@ -1,52 +1,45 @@ class Solution { - public int ladderLength(String beginWord, String endWord, List wordList) { - int l = beginWord.length(); - Map> combMap = new HashMap<>(); - - for (String word : wordList) { - for (int i = 0; i < l; i++) { - String wildCardWord = word.substring(0, i) + "*" + word.substring(i + 1, l); - combMap.computeIfAbsent(wildCardWord, k -> new ArrayList<>()).add(word); - } - } - - Queue queue = new LinkedList<>(); - queue.add(new WordLevel(beginWord, 1)); - - Set visited = new HashSet<>(); - visited.add(beginWord); - - while (!queue.isEmpty()) { - WordLevel removed = queue.remove(); - String word = removed.word; - int level = removed.level; - - for (int i = 0; i < l; i++) { - String newWord = word.substring(0, i) + "*" + word.substring(i+1); - - for (String wildCardWord : combMap.getOrDefault(newWord, new ArrayList<>())) { - if (wildCardWord.equals(endWord)) { - return level + 1; - } - - if (!visited.contains(wildCardWord)) { - visited.add(wildCardWord); - queue.add(new WordLevel(wildCardWord, level + 1)); - } - } - } + public int ladderLength(String beginWord, String endWord, List wordList) { + int l = beginWord.length(); + Map> map = new HashMap<>(); + for (String word : wordList) { + for (int i = 0; i < l; i++) { + String wildCard = word.substring(0, i) + "*" + word.substring(i + 1, l); + map.computeIfAbsent(wildCard, k -> new ArrayList<>()).add(word); + } + } + Queue queue = new LinkedList<>(); + queue.add(new Node(beginWord, 1)); + Set visited = new HashSet<>(); + visited.add(beginWord); + while (!queue.isEmpty()) { + Node removed = queue.remove(); + String word = removed.word; + int currLevel = removed.level; + for (int i = 0; i < l; i++) { + String newWord = word.substring(0, i) + "*" + word.substring(i + 1); + for (String wildCard : map.getOrDefault(newWord, new ArrayList<>())) { + if (wildCard.equals(endWord)) { + return currLevel + 1; + } + if (!visited.contains(wildCard)) { + visited.add(wildCard); + queue.add(new Node(wildCard, currLevel + 1)); + } } - - return 0; + } } + return 0; + } } -class WordLevel { - String word; - int level; - - public WordLevel(String word, int level) { - this.word = word; - this.level = level; - } + +class Node { + String word; + int level; + + public Node(String word, int level) { + this.word = word; + this.level = level; + } } diff --git a/Medium/Word Search.java b/Medium/Word Search.java index 8f6b43c3..5a63db20 100644 --- a/Medium/Word Search.java +++ b/Medium/Word Search.java @@ -1,51 +1,33 @@ class Solution { + + private static final int[][] DIRS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + public boolean exist(char[][] board, String word) { - if (board == null || word == null || word.length() == 0) { - return false; - } - - int[][] dirs = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; - int row = board.length; - int col = board[0].length; - - boolean[][] visited = new boolean[row][col]; - for (int i=0; i= row || y >= col || visited[x][y]) { - continue; - } - - if (dfs(board, x, y, word, start + 1, row, col, visited, dirs)) { - return true; - } + if (row < 0 || col < 0 || row >= m || col >= n || board[row][col] != word.charAt(idx)) { + return false; } - - visited[i][j] = false; - - return false; + board[row][col] ^= 256; + boolean result = false; + for (int[] dir : DIRS) { + result = result || isFound(board, word, idx + 1, row + dir[0], col + dir[1], m, n); + } + board[row][col] ^= 256; + return result; } - } diff --git a/Medium/Word Subsets.java b/Medium/Word Subsets.java new file mode 100644 index 00000000..9c93be7d --- /dev/null +++ b/Medium/Word Subsets.java @@ -0,0 +1,32 @@ +class Solution { + public List wordSubsets(String[] words1, String[] words2) { + int[] word2MaxCount = new int[26]; + for (String word : words2) { + int[] count = getFrequencyArray(word); + for (int i = 0; i < 26; i++) { + word2MaxCount[i] = Math.max(word2MaxCount[i], count[i]); + } + } + List result = new ArrayList<>(); + for (String word : words1) { + int[] count = getFrequencyArray(word); + for (int i = 0; i < 26; i++) { + if (count[i] < word2MaxCount[i]) { + break; + } + if (i == 25) { + result.add(word); + } + } + } + return result; + } + + private static int[] getFrequencyArray(String s) { + int[] count = new int[26]; + for (char c : s.toCharArray()) { + count[c - 'a']++; + } + return count; + } +} diff --git a/Medium/XOR Queries of a Subarray.java b/Medium/XOR Queries of a Subarray.java new file mode 100644 index 00000000..0bdfc9ca --- /dev/null +++ b/Medium/XOR Queries of a Subarray.java @@ -0,0 +1,24 @@ +class Solution { + public int[] xorQueries(int[] arr, int[][] queries) { + int n = arr.length; + int[] prefixXors = new int[n]; + int xor = 0; + for (int i = 0; i < n; i++) { + xor = xor ^ arr[i]; + prefixXors[i] = xor; + } + n = queries.length; + int[] result = new int[n]; + for (int i = 0; i < n; i++) { + int[] query = queries[i]; + int left = query[0]; + int right = query[1]; + int xorResult = prefixXors[right]; + if (left != 0) { + xorResult = xorResult ^ prefixXors[left - 1]; + } + result[i] = xorResult; + } + return result; + } +} diff --git a/Medium/Zero Array Transformation I.java b/Medium/Zero Array Transformation I.java new file mode 100644 index 00000000..2b9ab602 --- /dev/null +++ b/Medium/Zero Array Transformation I.java @@ -0,0 +1,24 @@ +class Solution { + public boolean isZeroArray(int[] nums, int[][] queries) { + int n = nums.length; + int[] diff = new int[n + 1]; + for (int[] query : queries) { + int left = query[0]; + int right = query[1]; + diff[left] += 1; + diff[right + 1] -= 1; + } + int[] operation = new int[n + 1]; + int currOperation = 0; + for (int i = 0; i < n + 1; i++) { + currOperation += diff[i]; + operation[i] = currOperation; + } + for (int i = 0; i < n; i++) { + if (operation[i] < nums[i]) { + return false; + } + } + return true; + } +} diff --git a/Medium/ZigZag Conversion.java b/Medium/ZigZag Conversion.java index d3c2cc5c..31793633 100644 --- a/Medium/ZigZag Conversion.java +++ b/Medium/ZigZag Conversion.java @@ -1,26 +1,29 @@ class Solution { public String convert(String s, int numRows) { - List list = new ArrayList<>(); + if (numRows == 1) { + return s; + } + StringBuilder[] rows = new StringBuilder[numRows]; for (int i = 0; i < numRows; i++) { - list.add(new StringBuilder()); + rows[i] = new StringBuilder(); } - + int row = 0; + int n = s.length(); int idx = 0; - while (idx < s.length()) { - for (int i = 0; i < numRows && idx < s.length(); i++) { - list.get(i).append(s.charAt(idx++)); + while (idx < n) { + while (idx < n && row < numRows) { + rows[row++].append(s.charAt(idx++)); } - - for (int i = numRows - 2; i > 0 && idx < s.length(); i--) { - list.get(i).append(s.charAt(idx++)); + row -= 2; + while (idx < n && row >= 0) { + rows[row--].append(s.charAt(idx++)); } + row += 2; } - - StringBuilder ans = new StringBuilder(); - for (StringBuilder sb : list) { - ans.append(sb.toString()); + StringBuilder result = new StringBuilder(); + for (StringBuilder sb : rows) { + result.append(sb.toString()); } - - return ans.toString(); + return result.toString(); } } diff --git a/Medium/Zigzag Iterator.java b/Medium/Zigzag Iterator.java index 442497c1..1b4f8554 100644 --- a/Medium/Zigzag Iterator.java +++ b/Medium/Zigzag Iterator.java @@ -1,52 +1,35 @@ public class ZigzagIterator { - - List l1; - List l2; - int start1; - int start2; - int end1; - int end2; - boolean flag; - - public ZigzagIterator(List v1, List v2) { - l1 = v1; - l2 = v2; - start1 = 0; - start2 = 0; - end1 = l1.size(); - end2 = l2.size(); - flag = true; - } - public int next() { - if (start1 < end1 && start2 < end2) { - int ans = -1; - if (flag) { - ans = l1.get(start1); - start1++; - flag = !flag; - } - else { - ans = l2.get(start2); - start2++; - flag = !flag; - } - - return ans; - } - else if (start1 < end1) { - return l1.get(start1++); - } - else { - return l2.get(start2++); - } - } + private final List listOne; + private final List listTwo; + int idxOne; + int idxTwo; + boolean pickFromListOne; + public ZigzagIterator(List v1, List v2) { + this.listOne = v1; + this.listTwo = v2; + this.idxOne = 0; + this.idxTwo = 0; + this.pickFromListOne = true; + } - public boolean hasNext() { - return !(start1 == end1 && start2 == end2); + public int next() { + if ((pickFromListOne && idxOne < listOne.size()) || (!pickFromListOne + && idxTwo == listTwo.size())) { + pickFromListOne = !pickFromListOne; + return listOne.get(idxOne++); } + pickFromListOne = !pickFromListOne; + return listTwo.get(idxTwo++); + } + + public boolean hasNext() { + return idxOne < listOne.size() || idxTwo < listTwo.size(); + } } + + /** * Your ZigzagIterator object will be instantiated and called as such: * ZigzagIterator i = new ZigzagIterator(v1, v2); diff --git a/README.md b/README.md index 41f80fd8..617cd951 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ -# LeetCode-Java-Solutions -Repository to store solutions to various problems in Leetcode practice and weekly contests +# Leetcode-Java-Solutions -[My Leetcode Profile](https://leetcode.com/varunu28/) +## Solutions to Leetcode problems in Java -![image](https://cdn-images-1.medium.com/max/1360/1*5qdPLs4x9TuabvQJwu7iuA.png) +## [Current Leetcode profile: Solved 1700+ Problems](https://leetcode.com/varunsjsu/) +## [Previous Leetcode profile: Solved 759 Problems](https://leetcode.com/varunu28/) + +Problem Category | Count +--- | --- +[Easy](https://github.com/varunu28/LeetCode-Java-Solutions/blob/master/Easy/README.md) | 607 +[Medium](https://github.com/varunu28/LeetCode-Java-Solutions/blob/master/Medium/README.md) | 793 +[Hard](https://github.com/varunu28/LeetCode-Java-Solutions/blob/master/Hard/README.md) | 125 +[Concurrency](https://github.com/varunu28/LeetCode-Java-Solutions/blob/master/Concurrency/README.md) | 9 diff --git a/commit-script.sh b/commit-script.sh new file mode 100755 index 00000000..90a4f404 --- /dev/null +++ b/commit-script.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +git add . + +if git status | grep -q 'modified'; then + status=$(git status | grep 'modified') + modified_file=${status##*/} + git commit -m "Updated ${modified_file}" +elif git status | grep -q 'new file:'; then + status=$(git status | grep 'new file:') + added_file=${status##*/} + git commit -m "Added ${added_file}" +fi + +git push diff --git a/script.py b/script.py new file mode 100755 index 00000000..4fe80e71 --- /dev/null +++ b/script.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import os +from os import listdir, getcwd +from os.path import isfile, join + + +current_dir = getcwd() + +# Clean up +# current_files = os.listdir(current_dir) +# for item in current_files: +# if item.endswith(".md"): +# os.remove(os.path.join(current_dir, item)) + +tree_path = "https://github.com/varunu28/LeetCode-Java-Solutions/tree/master/" +levels = ["Easy", "Medium", "Hard"] +for level in levels: + if os.path.exists(current_dir + "/" + level + "/README.md"): + os.remove(current_dir + "/" + level + "/README.md") + onlyfiles = [f for f in listdir(current_dir + "/" + level)] + f= open(current_dir + "/" + level + "/README.md","w+") + f.write("# " + level + " LeetCode-Java-Solutions \n") + f.write("S.no | Coding Problem \n") + f.write("--- | --- \n") + count = 1 + for file_name in onlyfiles: + only_name = file_name[:file_name.find('.')] + updated_file_name = file_name.replace(' ', '%20') + f.write(str(count) + "|" + '[{}]({})\n'.format(only_name, (tree_path + level + "/" + updated_file_name))) + count = count + 1 + print(level + ": " + str(count)) + f.close()