Coding Questions Flashcards

1
Q

Product of Array Except Self

Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].

Example:

Input: [1,2,3,4]
Output: [24,12,8,6]
Constraint: It’s guaranteed that the product of the elements of any prefix or suffix of the array (including the whole array) fits in a 32 bit integer.

Note: Please solve it without division and in O(n).

Follow up:
Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.)

A

Trick is to create two arrays with left product and right product, where left product of an element at ith position in the array will contain product of elements from 0 to i-1. Similarly right will contain n to i+1.

Then multiple left and right array and result will contain answer

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

TrieNode

A
class TrieNode {
    TrieNode[] children;
    String word;
    TrieNode() {
        children = new TrieNode[26];
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Merge Intervals

Given a collection of intervals, merge all overlapping intervals.

Example 1:

Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Example 2:

Input: [[1,4],[4,5]]
Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.
NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature.

A

Sort by start and check if overlaps with next and change end time

Missed cases could be - if the current intervals end time is greater than next intervals end time

public int[][] merge(int[][] intervals) {
if(intervals == null || intervals.length == 0) return intervals;

    Queue queue = new PriorityQueue<>( (a,b) -> {
       return a[0] - b[0];
    });

    for(int [] interval : intervals) {
        queue.add(interval);
    }

    List list =  new ArrayList<>();
    int[] curr = queue.remove();
    while(!queue.isEmpty()) {
        int[] next = queue.remove();
            if(curr[1] >= next[0]) {
                curr[1] = Math.max(curr[1],next[1]);
            } else {
                list.add(curr);
                curr = next;
            }
        }
    list.add(curr);

    int[][] result = new int[list.size()][2];
    for(int i=0; i
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Trick for solving linked list

A

Create a dummy node and use it to point to head

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Task Scheduler

A

Finding the idle timeout will determine the total time required. For example if there is one task to be executed thrice and the cool down period is 5 then total time required for the CPU to finish would be 13 (1+5+1+5+1).

Therefore idle time = 10

If there were another task to be executed twice then idle time would be 10-2 = 8, which is 13 (1+1+4+1+1+4+1)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Meeting rooms II, find how minimum meeting rooms required, give the meeting intervals

A

First approach -
Sort by start time and put the end time in the heap, for every interval check if the start is greater then the last end time. If there is then we can reuse the room or else we need a new room and put the new endtime in the heap.

Second Approach - 
       Arrays.sort(starts);
        Arrays.sort(ends);
        int rooms = 0;
        int endsItr = 0;
        for(int i=0; i
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Car pooling with capacity

A
public boolean carPooling(int[][] trips, int capacity) {
        Map m = new TreeMap<>();
        for (int[] t : trips) {
            m.put(t[1], m.getOrDefault(t[1], 0) + t[0]);
            m.put(t[2], m.getOrDefault(t[2], 0) - t[0]);
        }
        for (int v : m.values()) {
            capacity -= v;
            System.out.println(capacity);
            if (capacity < 0) {
                return false;
            }
        }
        return true;
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Find Kth largest number in an array

A

quickSelect(arr, l, r, kSmallest) {
if(l == r) return arr[l];

int pivot_index = getRandomPivot(l,r);

pi = partition(arr, l, r, pivot_index);
if(pi == ksmallest) return arr[pi];
else if(ksmallest < pi) return quick_select(arr, l, pi-1, kSmallest);
else return quick_select(arr, pi+1, r, kSmallest);
}
int partition(arr, l, r, pi) {
int pivot = arr[pi];
swap(pi, r);
int index = l;
for(int i=l; i<=r; i++) {
if(arr[i] < pivot) {
swap(i, index);
index++;
}
}

swap(index, r)
return index;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Interval Search Tree

A

Build a BST with start time as the node key and at every node remember the max end interval.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Minimum Remove to Make Valid Parentheses

A

Needs two iteration one from back and one from start that way in first iteration remove invalid open parentheses if starting from back and in second iteration remove invalid open parentheses from start. Remember to use stack and then stringbuilder to respond

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Remove Invalid Parentheses

Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

Note: The input string may contain letters other than the parentheses ( and ).

Example 1:

Input: “()())()”
Output: [”()()()”, “(())()”]
Example 2:

Input: “(a)())()”
Output: [“(a)()()”, “(a())()”]
Example 3:

Input: “)(“
Output: [””]

A

1) There is no straight forward DP solution, this needs to be solved in exponential complexity
2) Find the open and close paratheses to remove
3) Keep count of open and close during recursion and verify while inserting into result whether open count is equal to close count
4) While excluding make sure to exclude only if open remaining and close remaining are valid
5) Remember to use set as while recursion you might end up adding same expression multiple times

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Graph problems Dijkstra’s - Network Delay Time

There are N network nodes, labelled 1 to N.

Given times, a list of travel times as directed edges times[i] = (u, v, w), where u is the source node, v is the target node, and w is the time it takes for a signal to travel from source to target.

Now, we send a signal from a certain node K. How long will it take for all nodes to receive the signal? If it is impossible, return -1.

Input: times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2
Output: 2

A

public int networkDelayTime(int[][] times, int N, int K) {

    Map> map = new HashMap<>();

    for(int[] time : times) {
        List list = map.getOrDefault(time[0], new ArrayList<>());
        list.add(new int[] { time[1], time[2] });
        map.put(time[0], list);
    }
        Map dist = new HashMap<>();
        Queue queue = new PriorityQueue<>((a,b) -> {
            // sort by weights
            return a[1] - b[1];
        });
    queue.add(new int[] {K, 0});

    while(!queue.isEmpty()) {
        int[] node = queue.remove();
        int u = node[0];
        int w = node[1];

        if(!dist.containsKey(u)) {
            dist.put(u, w);

            if(map.containsKey(u)) {
                for(int[] edge : map.get(u)) {
                    int v = edge[0];
                    int w2 = edge[1];

                    if(!dist.containsKey(v)) {
                        queue.add(new int[] {v, w+w2});
                    }
                }
            }
        }
    }

    if(dist.size() != N) {
        return -1;
    }

    int max = 0;

    for(int w : dist.values()) {
        max = Math.max(max, w);
    }

    return max;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.
Example 2:

Input: “bbbbb”
Output: 1
Explanation: The answer is “b”, with the length of 1.
Example 3:

Input: “pwwkew”
Output: 3
Explanation: The answer is “wke”, with the length of 3.
Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

A

“abba”
This is the most important test case, make sure to only consider an index which is found later, in the above case when index of ‘a’ is calculated it becomes to be higher, but ‘b’ appears in between and that needs to be considered.

Remember to add +1 as we are calculating difference between two relative indexes.

    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        Map map = new HashMap<>(); // current index of character
        // try to extend the range [i, j]
        for (int j = 0, i = 0; j < n; j++) {
            if (map.containsKey(s.charAt(j))) {
                i = Math.max(map.get(s.charAt(j)), i);
            }
            ans = Math.max(ans, j - i + 1);
            map.put(s.charAt(j), j + 1);
        }
        return ans;
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Longest Palindromic Substring
Medium

6371

508

Add to List

Share
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example 2:

Input: “cbbd”
Output: “bb”

A

You can do better than O(n2), but that is Manchester algorithm, which is difficult to understand and not expected.

Remember to return indices properly, in the below while condition the start and end are one additional left and right to the index, end is fine as when substring is called, it excludes the end character.

public String longestPalindrome(String s) {
        if(s == null || s.length() == 0) {
            // throw exception
            return "";
        }
    int max = 0;
    int start = 0;
    int end = 0;
        for(int i=0; i len2 &amp;&amp; len1 > max) {
                start = i1[0];
                end = i1[1];
                max = len1;
            } else if(len2 > max) {
                start = i2[0];
                end = i2[1];
                max = len2;
            }
        }
    return s.substring(start, end);
}

private int[] expand(String s, int l, int r) {
    int start = l;
    int end = r;

    while(start >= 0 &amp;&amp; end < s.length() &amp;&amp; s.charAt(start) == s.charAt(end)) {
        start--;
        end++;
    }

    return new int[] {start+1, end};
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

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

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm’s runtime complexity must be in the order of O(log n).

Example 1:

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

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

A

The main thing to identify here is the boundary conditions of where to move left or right based on the mid value

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] &amp;&amp; target >= nums[start]) 
                end = mid - 1;
             else
                start = mid + 1;
        } 
            if (nums[mid] <= nums[end]){
                if (target > nums[mid] &amp;&amp; target <= nums[end])
                    start = mid + 1;
                 else
                    end = mid - 1;
            }
        }
        return -1;
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Course Schedule II, solution is different than question below

There are a total of numCourses courses you have to take, labeled from 0 to numCourses-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example 1:

Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:

Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should
also have finished course 1. So it is impossible.

A

Key point to note, add to queue only if there are no in degree left and decrement in degree as and when encountered

public int[] findOrder(int numCourses, int[][] prerequisites) {
Map> map = new HashMap<>();
int[] indegree = new int[numCourses];

        for (int i=0; i list = map.getOrDefault(u, new ArrayList());
            list.add(v);
            map.put(u, list);
        }
        Queue queue = new LinkedList();
        for (int i=0; i stack = new Stack<>();
        while (!queue.isEmpty()) {
            int u = queue.poll();
            stack.push(u);
            if(map.containsKey(u)) {
                for(int v : map.get(u)) {
                    if (--indegree[v] == 0) {
                        queue.add(v);
                    }
                }
            }
        }
    if(stack.size() != numCourses) {
        return new int[]{};
    }
        int[] result = new int[stack.size()];
        int i=0;
        while(!stack.isEmpty()) {
            result[i++] = stack.pop();
        }
    return result;
}
17
Q

General approach to backtracking solutions

A

https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)

18
Q

Rotate Image

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Note:

You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.

Example 1:

Given input matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],
rotate the input matrix in-place such that it becomes:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]
Example 2:
Given input matrix =
[
  [ 5, 1, 9,11],
  [ 2, 4, 8,10],
  [13, 3, 6, 7],
  [15,14,12,16]
], 
rotate the input matrix in-place such that it becomes:
[
  [15,13, 2, 5],
  [14, 3, 4, 1],
  [12, 6, 8, 9],
  [16, 7,10,11]
]
A

The obvious idea would be to transpose the matrix first and then reverse each row. This simple approach already demonstrates the best possible time complexity O(N^2)

class Solution {
  public void rotate(int[][] matrix) {
    int n = matrix.length;
    // transpose matrix
    for (int i = 0; i < n; i++) {
      for (int j = i; j < n; j++) {
        int tmp = matrix[j][i];
        matrix[j][i] = matrix[i][j];
        matrix[i][j] = tmp;
      }
    }
    // reverse each row
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n / 2; j++) {
        int tmp = matrix[i][j];
        matrix[i][j] = matrix[i][n - j - 1];
        matrix[i][n - j - 1] = tmp;
      }
    }
  }
}
19
Q

Group Anagrams

Given an array of strings, group anagrams together.

Example:

Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]
Note:

All inputs will be in lowercase.
The order of your output does not matter.

A

Use the count approach where we can create a array of size 26 and we don’t need to sort and form hash by appending some special character after every count

In Java, the hashable representation of our count will be a string delimited with ‘#’ characters. For example, abbccc will be #1#2#3#0#0#0…#0 where there are 26 entries total. In python, the representation will be a tuple of the counts. For example, abbccc will be (1, 2, 3, 0, 0, …, 0), where again there are 26 entries total.

public List> groupAnagrams(String[] strs) {
        if (strs.length == 0) return new ArrayList();
        Map ans = new HashMap();
        int[] count = new int[26];
        for (String s : strs) {
            Arrays.fill(count, 0);
            for (char c : s.toCharArray()) count[c - 'a']++;
        StringBuilder sb = new StringBuilder("");
        for (int i = 0; i < 26; i++) {
            sb.append('#');
            sb.append(count[i]);
        }
        String key = sb.toString();
        if (!ans.containsKey(key)) ans.put(key, new ArrayList());
        ans.get(key).add(s);
    }
    return new ArrayList(ans.values());
}
20
Q

Maximum Product Subarray

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

A

Requires to use there variables
current_max, current_min and max

temp = current_max;

current_max = Math.max(Math.max(current_max*nums[i], current_min * nums[i]), nums[i]);

current_max = Math.min(Math.min(temp*nums[i], current_min * nums[i]), nums[i]);

max = Math.max(max, current_max);

21
Q

Spiral Matrix

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

Example 1:

Input:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]
Example 2:
Input:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
A
public List < Integer > spiralOrder(int[][] matrix) {
        List ans = new ArrayList();
        if (matrix.length == 0)
            return ans;
        int r1 = 0, r2 = matrix.length - 1;
        int c1 = 0, c2 = matrix[0].length - 1;
        while (r1 <= r2 &amp;&amp; c1 <= c2) {
            for (int c = c1; c <= c2; c++) ans.add(matrix[r1][c]);
            for (int r = r1 + 1; r <= r2; r++) ans.add(matrix[r][c2]);
            if (r1 < r2 &amp;&amp; c1 < c2) {
                for (int c = c2 - 1; c > c1; c--) ans.add(matrix[r2][c]);
                for (int r = r2; r > r1; r--) ans.add(matrix[r][c1]);
            }
            r1++;
            r2--;
            c1++;
            c2--;
        }
        return ans;
    }
22
Q

Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

Example:

Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
Jump 1 step from index 0 to 1, then 3 steps to the last index.

A

public int jump(int[] nums) {
int n = nums.length;
if (n < 2) return 0;

    // max position one could reach 
    // starting from index <= i 
    int maxPos = nums[0];
    // max number of steps one could do
    // inside this jump
    int maxSteps = nums[0];
    int jumps = 1;
    for (int i = 1; i < n; ++i) {
      // if to reach this point 
      // one needs one more jump
      if (maxSteps < i) {
        \++jumps;
        maxSteps = maxPos;
      }
      maxPos = Math.max(maxPos, nums[i] + i);
    }
    return jumps;
  }
23
Q

Insert Interval

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).

You may assume that the intervals were initially sorted according to their start times.

Example 1:

Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
Output: [[1,5],[6,9]]
Example 2:

Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
Output: [[1,2],[3,10],[12,16]]
Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].

A

This is tricky because we need to cover various test cases -

1) If new interval is before the 1st interval or after last interval
2) If it overlaps with more than one intervals, this boils down to merge interval problem
3) Interval list is empty, this needs to be the only interval which needs to be added

public int[][] insert(int[][] intervals, int[] newInterval) {
if(intervals == null || intervals.length == 0) {
return new int[][]{newInterval};
}

    List list = new ArrayList<>();
    boolean inserted = false;
    int ns = newInterval[0];
    int ne = newInterval[1];

    for(int[] interval : intervals) {
        int s = interval[0];
        int e = interval[1];
            if(!inserted) {
                // new interval is after this interval
                if(ns > e) {
                    list.add(interval);
                    continue;
                }
                // new interval is before this interval
                if(ne < s) {
                    list.add(newInterval);
                    list.add(interval);
                    inserted = true;
                    continue;
                }
                // new interval overlaps with this
                interval[0] = Math.min(s, ns);
                interval[1] = Math.max(e, ne);
                list.add(interval);
                inserted = true;
            } else {
                int[] prev = list.get(list.size()-1);
                if(prev[1] >= s) {
                    prev[1] = Math.max(prev[1], e);
                } else {
                    list.add(interval);
                }
            }
        }
    if(!inserted) {
        list.add(newInterval);
    }

    int[][] result = new int[list.size()][2];
    for(int i=0; i
24
Q

Set Matrix Zeroes

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.

Example 1:

Input: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
Output: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]
Example 2:
Input: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
Output: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]
Follow up:

A straight forward solution using O(mn) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?

A

There is no better solution iterating loop twice, overall complexity is O(mn)
Efficient solution is to make first row and first column for storing zeros (place holder) and in the second iteration set the row, column to zero

public void setZeroes(int[][] matrix) {
Boolean isCol = false;
int R = matrix.length;
int C = matrix[0].length;

for (int i = 0; i < R; i++) {
      // Since first cell for both first row and first column is the same i.e. matrix[0][0]
      // We can use an additional variable for either the first row/column.
      // For this solution we are using an additional variable for the first column
      // and using matrix[0][0] for the first row.
      if (matrix[i][0] == 0) {
        isCol = true;
      }
      for (int j = 1; j < C; j++) {
        // If an element is zero, we set the first element of the corresponding row and column to 0
        if (matrix[i][j] == 0) {
          matrix[0][j] = 0;
          matrix[i][0] = 0;
        }
      }
    }
    // Iterate over the array once again and using the first row and first column, update the elements.
    for (int i = 1; i < R; i++) {
      for (int j = 1; j < C; j++) {
        if (matrix[i][0] == 0 || matrix[0][j] == 0) {
          matrix[i][j] = 0;
        }
      }
    }
    // See if the first row needs to be set to zero as well
    if (matrix[0][0] == 0) {
      for (int j = 0; j < C; j++) {
        matrix[0][j] = 0;
      }
    }
    // See if the first column needs to be set to zero as well
    if (isCol) {
      for (int i = 0; i < R; i++) {
        matrix[i][0] = 0;
      }
    }
  }
25
Q

Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

Example:

Input: S = “ADOBECODEBANC”, T = “ABC”
Output: “BANC”
Note:

If there is no such window in S that covers all characters in T, return the empty string “”.
If there is such window, you are guaranteed that there will always be only one unique minimum window in S.

A

The trick is to use left and right pointer. Increment right pointer to a point where all characters of T are covered. Once right pointer is reached, we start incrementing left counter and continue as long as it either reaches right pointer or the substring between l and r doesn’t contain all characters in T.

class Solution {
    public String minWindow(String s, String t) {
    if (s.length() == 0 || t.length() == 0) {
        return "";
    }

    Map dictT = new HashMap();

    for (int i = 0; i < t.length(); i++) {
        int count = dictT.getOrDefault(t.charAt(i), 0);
        dictT.put(t.charAt(i), count + 1);
    }

    int required = dictT.size();
        // Filter all the characters from s into a new list along with their index.
        // The filtering criteria is that the character should be present in t.
        List> filteredS = new ArrayList>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (dictT.containsKey(c)) {
                filteredS.add(new Pair(i, c));
            }
        }
        int l = 0, r = 0, formed = 0;
        Map windowCounts = new HashMap();  
        int[] ans = {-1, 0, 0};
        // Look for the characters only in the filtered list instead of entire s.
        // This helps to reduce our search.
        // Hence, we follow the sliding window approach on as small list.
        while (r < filteredS.size()) {
            char c = filteredS.get(r).getValue();
            int count = windowCounts.getOrDefault(c, 0);
            windowCounts.put(c, count + 1);
        if (dictT.containsKey(c) &amp;&amp; windowCounts.get(c).intValue() == dictT.get(c).intValue()) {
            formed++;
        }
            // Try and contract the window till the point where it ceases to be 'desirable'.
            while (l <= r &amp;&amp; formed == required) {
                c = filteredS.get(l).getValue();
                // Save the smallest window until now.
                int end = filteredS.get(r).getKey();
                int start = filteredS.get(l).getKey();
                if (ans[0] == -1 || end - start + 1 < ans[0]) {
                    ans[0] = end - start + 1;
                    ans[1] = start;
                    ans[2] = end;
                }
            windowCounts.put(c, windowCounts.get(c) - 1);
            if (dictT.containsKey(c) &amp;&amp; windowCounts.get(c).intValue() < dictT.get(c).intValue()) {
                formed--;
            }
            l++;
        }
        r++;   
    }
    return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1);
} }
26
Q

Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

Example 1:

Input:
s = “barfoothefoobarman”,
words = [“foo”,”bar”]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are “barfoo” and “foobar” respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:

Input:
s = “wordgoodgoodgoodbestword”,
words = [“word”,”good”,”best”,”word”]
Output: []

A

Important clue here is to see that words need to be continuous even if they are totally random order. Make a map of words to be searched and iterate through original string for every index. Create a copy of the map and iterate through word length and decrement every word from the map. If the map is empty at last that means we have a substring containing all the words and we add starting index to the result

public List findSubstring(String S, String[] L) {
        List res = new ArrayList();
        if (S == null || L == null || L.length == 0) return res;
        int len = L[0].length(); // length of each word
        Map map = new HashMap(); // map for L
        for (String w : L) map.put(w, map.containsKey(w) ? map.get(w) + 1 : 1);
        for (int i = 0; i <= S.length() - len * L.length; i++) {
            Map copy = new HashMap(map);
            for (int j = 0; j < L.length; j++) { // checkc if match
                String str = S.substring(i + j*len, i + j*len + len); // next word
                if (copy.containsKey(str)) { // is in remaining words
                    int count = copy.get(str);
                    if (count == 1) copy.remove(str);
                    else copy.put(str, count - 1);
                    if (copy.isEmpty()) { // matches
                        res.add(i);
                        break;
                    }
                } else break; // not in L
            }
        }
        return res;
    }
27
Q

Find All Anagrams in a String

Given a string s and a non-empty string p, find all the start indices of p’s anagrams in s.

Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.

The order of output does not matter.

Example 1:

Input:
s: “cbaebabacd” p: “abc”

Output:
[0, 6]

Explanation:
The substring with start index = 0 is “cba”, which is an anagram of “abc”.
The substring with start index = 6 is “bac”, which is an anagram of “abc”.
Example 2:

Input:
s: “abab” p: “ab”

Output:
[0, 1, 2]

Explanation:
The substring with start index = 0 is “ab”, which is an anagram of “ab”.
The substring with start index = 1 is “ba”, which is an anagram of “ab”.
The substring with start index = 2 is “ab”, which is an anagram of “ab”.

A

Most of the substring problems will require to use two pointers, where end pointer will track whether the string is found and start pointer will ensure it meets the given requirement. Incase of All Anagrams, the requirement is that the string needs to be continuous therefore checking (end-start+1 > t.length()) will ensure we only consider strings of that length.

If count of a character matches with the required, we increment ‘found’ variable. We only decrease if the count goes below required, because when the count is more, that means we have more characters and decrementing it would get the counter to negative value.

Example
s = “abbbba”
t = “ab”

At some point we will have b’s value as 4

public class Solution {
    public List findAnagrams(String s, String p) {
        List result = new ArrayList<>();
        if(s == null || s.length() == 0 || p == null || p.length() == 0 || p.length() > s.length()) {
            return result;
        }
    int m = p.length();
    int n = s.length();
    Map pMap = new HashMap<>();
    for(int i=0; i sMap = new HashMap<>();
        for(int end=0; end sMap.get(c1)) {
                        found--;
                    }
                }
            }
        }
    return result;
} }
28
Q

Minimum Height Trees

For an undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.

Format
The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels).

You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

Example 1 :

Input: n = 4, edges = [[1, 0], [1, 2], [1, 3]]

        0
        |
        1
       / \
      2   3 

Output: [1]
Example 2 :

Input: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]

     0  1  2
      \ | /
        3
        |
        4
        |
        5 

Output: [3, 4]
Note:

According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”
The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.

A

Trick is to use topological sorting by find leaf nodes (which can be done by checking the ones which have indegree count of one) and remove edges as encountered and continue doing it until we have either 1 or 2 nodes, those will be the middle nodes.

public List findMinHeightTrees(int n, int[][] edges) {
if(edges == null || edges.length == 0 || n < 2) {
return Collections.singletonList(0);
}

    Map> adj = new HashMap<>();
    for(int[] edge : edges) {
        int u = edge[0];
        int v = edge[1];

        Set uAdj = adj.getOrDefault(u, new HashSet<>());
        uAdj.add(v);
        adj.put(u, uAdj);

        Set vAdj = adj.getOrDefault(v, new HashSet<>());
        vAdj.add(u);
        adj.put(v, vAdj);
    }

    List leaves = new ArrayList<>();
    for(Map.Entry> entry : adj.entrySet()) {
        if(entry.getValue().size() == 1) {
            leaves.add(entry.getKey());
        }
    }

    while(adj.size() > 2) {
        List newLeaves = new ArrayList<>();
        for(int leaf : leaves) {
            Set nodes = adj.remove(leaf);
            for(int node : nodes) {
                Set set = adj.get(node);
                set.remove(leaf);

                if(set.size() == 1) {
                    newLeaves.add(node);
                }
            }
        }

        leaves = newLeaves;
    }

    return leaves;
}
29
Q

Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

Example 1:

Input:
s = “barfoothefoobarman”,
words = [“foo”,”bar”]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are “barfoo” and “foobar” respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:

Input:
s = “wordgoodgoodgoodbestword”,
words = [“word”,”good”,”best”,”word”]
Output: []

A

public List findSubstring(String s, String[] words) {
List result = new ArrayList<>();

    if(s == null || s.length() == 0 || words == null || words.length == 0) {
        return result;
    }

    Map wMap = new HashMap<>();
    for(String word : words) {
        wMap.put(word, wMap.getOrDefault(word, 0)+1);
    }
        int k = words.length;
        int m = words[0].length();
        int n = s.length();
        int required = wMap.size();
        int found = 0;
        Map sMap = new HashMap<>();
        for(int i=0; i wMap.get(t)) {
                        break;
                    }
                if(sMap.get(t).equals(wMap.get(t))) {
                    found++;
                }
                    j += m;
                } else {
                    break;
                }
            }
        if(found == required) {
            result.add(i);
        }

        sMap.clear();
        found = 0;
    }

    return result;
}
30
Q

Sliding Window Maximum

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

Follow up:
Could you solve it in linear time?

Example:

Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7]
Explanation:

Window position                Max
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

Constraints:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length

A

For Example: A = [2,1,3,4,6,3,8,9,10,12,56], w=4

partition the array in blocks of size w=4. The last block may have less then w.
2, 1, 3, 4 | 6, 3, 8, 9 | 10, 12, 56|

Traverse the list from start to end and calculate max_so_far. Reset max after each block boundary (of w elements).
left_max[] = 2, 2, 3, 4 | 6, 6, 8, 9 | 10, 12, 56

Similarly calculate max in future by traversing from end to start.
right_max[] = 4, 4, 4, 4 | 9, 9, 9, 9 | 56, 56, 56

now, sliding max at each position i in current window, sliding-max(i) = max{right_max(i), left_max(i+w-1)}
sliding_max = 4, 6, 6, 8, 9, 10, 12, 56

code:

public static int[] slidingWindowMax(final int[] in, final int w) {
final int[] max_left = new int[in.length];
final int[] max_right = new int[in.length];

max_left[0] = in[0];
max_right[in.length - 1] = in[in.length - 1];

for (int i = 1; i < in.length; i++) {
    max_left[i] = (i % w == 0) ? in[i] : Math.max(max_left[i - 1], in[i]);

    final int j = in.length - i - 1;
    max_right[j] = (j % w == 0) ? in[j] : Math.max(max_right[j + 1], in[j]);
}

final int[] sliding_max = new int[in.length - w + 1];
for (int i = 0, j = 0; i + w <= in.length; i++) {
    sliding_max[j++] = Math.max(max_right[i], max_left[i + w - 1]);
}

return sliding_max; }
31
Q

Subarrays with K Different Integers

Given an array A of positive integers, call a (contiguous, not necessarily distinct) subarray of A good if the number of different integers in that subarray is exactly K.

(For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.)

Return the number of good subarrays of A.

Example 1:

Input: A = [1,2,1,2,3], K = 2
Output: 7
Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].
Example 2:

Input: A = [1,2,1,3,4], K = 3
Output: 3
Explanation: Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4].

Note:

1 <= A.length <= 20000
1 <= A[i] <= A.length
1 <= K <= A.length

A

Approach: To directly count the subarrays with exactly K different integers is hard but to find the count of subarrays with at most K different integers is easy. So the idea is to find the count of subarrays with at most K different integers, let it be C(K), and the count of subarrays with at most (K – 1) different integers, let it be C(K – 1) and finally take their difference, C(K) – C(K – 1) which is the required answer.
Count of subarrays with at most K different elements can be easily calculated through the sliding window technique. The idea is to keep expanding the right boundary of the window till the count of distinct elements in the window is less than or equal to K and when the count of distinct elements inside the window becomes more than K, start shrinking the window from the left till the count becomes less than or equal to K. Also for every expansion, keep counting the subarrays as right – left + 1 where right and left are the boundaries of the current window.

// Function to return the count of subarrays 
    // with at most K distinct elements using 
    // the sliding window technique 
    private static int atMostK(int arr[], int n, int k) 
    { 
        // To store the result 
        int count = 0; 
        // Left boundary of window 
        int left = 0; 
        // Right boundary of window 
        int right = 0; 
        // Map to keep track of number of distinct 
        // elements in the current window 
        HashMap map = new HashMap<>(); 
        // Loop to calculate the count 
        while (right < n) { 
            // Calculating the frequency of each 
            // element in the current window 
            map.put(arr[right], map.getOrDefault(arr[right], 0) + 1); 
            // Shrinking the window from left if the 
            // count of distinct elements exceeds K 
            while (map.size() > k) { 
                map.put(arr[left], map.get(arr[left]) - 1); 
                if (map.get(arr[left]) == 0) 
                    map.remove(arr[left]); 
                left++; 
            } 
        // Adding the count of subarrays with at most 
        // K distinct elements in the current window 
        count += right - left + 1; 
        right++; 
    } 
    return count; 
} 
    // Function to return the count of subarrays 
    // with exactly K distinct elements 
    private static int exactlyK(int arr[], int n, int k) 
    { 
        // Count of subarrays with exactly k distinct 
        // elements is equal to the difference of the 
        // count of subarrays with at most K distinct 
        // elements and the count of subararys with 
        // at most (K - 1) distinct elements 
        return (atMostK(arr, n, k) - atMostK(arr, n, k - 1)); 
    }
32
Q

Decode Ways

A message containing letters from A-Z is being encoded to numbers using the following mapping:

'A' -> 1
'B' -> 2
...
'Z' -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.

Example 1:

Input: “12”
Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).
Example 2:

Input: “226”
Output: 3
Explanation: It could be decoded as “BZ” (2 26), “VF” (22 6), or “BBF” (2 2 6).

A

Recurrence relation is
f(n) = f(n+1) + f(n+2)

with following conditions

1) if n == length, return 1
2) if n == 0 then return 0
3) if substring(n, n+2) is greater than 9 but less than 27 then f(n+2) is considered

Below is the DP solution

public int numDecodings(String s) {
if(s == null || s.length() == 0) {
return 0;
}

    int pp = 1;
    int p = s.charAt(0) == '0'? 0 : 1;

    for(int i=1; i 9 &amp;&amp; num < 27) {
            cur += pp;
        }

        pp = p;
        p = cur;
    }

    return p;
}
33
Q

Decode Ways II

A message containing letters from A-Z is being encoded to numbers using the following mapping way:

'A' -> 1
'B' -> 2
...
'Z' -> 26
Beyond that, now the encoded string can also contain the character '*', which can be treated as one of the numbers from 1 to 9.

Given the encoded message containing digits and the character ‘*’, return the total number of ways to decode it.

Also, since the answer may be very large, you should return the output mod 109 + 7.

Example 1:
Input: “
Output: 9
Explanation: The encoded message can be decoded to the string: “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”.
Example 2:
Input: “1

Output: 9 + 9 = 18
Note:
The length of the input string will fit in range [1, 105].
The input string will only contain the character ‘*’ and digits ‘0’ - ‘9’.

A

The trick is to identify the number of possible combinations when we encounter *

public class Solution {
    int M = 1000000007;
    public int numDecodings(String s) {
        long[] dp = new long[s.length() + 1];
        dp[0] = 1;
        dp[1] = s.charAt(0) == '*' ? 9 : s.charAt(0) == '0' ? 0 : 1;
        for (int i = 1; i < s.length(); i++) {
            if (s.charAt(i) == '*') {
                dp[i + 1] = 9 * dp[i];
                if (s.charAt(i - 1) == '1')
                    dp[i + 1] = (dp[i + 1] + 9 * dp[i - 1]) % M;
                else if (s.charAt(i - 1) == '2')
                    dp[i + 1] = (dp[i + 1] + 6 * dp[i - 1]) % M;
                else if (s.charAt(i - 1) == '*')
                    dp[i + 1] = (dp[i + 1] + 15 * dp[i - 1]) % M;
            } else {
                dp[i + 1] = s.charAt(i) != '0' ? dp[i] : 0;
                if (s.charAt(i - 1) == '1')
                    dp[i + 1] = (dp[i + 1] + dp[i - 1]) % M;
                else if (s.charAt(i - 1) == '2' &amp;&amp; s.charAt(i) <= '6')
                    dp[i + 1] = (dp[i + 1] + dp[i - 1]) % M;
                else if (s.charAt(i - 1) == '*')
                    dp[i + 1] = (dp[i + 1] + (s.charAt(i) <= '6' ? 2 : 1) * dp[i - 1]) % M;
            }
        }
        return (int) dp[s.length()];
    }
}
34
Q

3 sum a+b+c=0

A

1) Check if duplicate elements need to be considered
2) Sort elements
3) make sure to skip duplicate by checking i >0 && nums[i] == nums[i-1]
4) After finding a match make sure to increment start and end pointer to skip duplicates with the while loop

35
Q

Task scheduler

A

time_wait = (max_count-1) * n => n is the cooldown time
after subtracting
if time_wait > 0 return time_wait+tasks.length
else tasks.length

36
Q
  1. Regular Expression Matching

Given an input string (s) and a pattern (p), implement regular expression matching with support for ‘.’ and ‘*’.

’.’ Matches any single character.
‘*’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

Note:

s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.
Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
A

Don’t forget to fill first row when string is empty and make sure to check for one occurrence of character before * with condition p[i-2] == s[i-1], this we can ignore *

public boolean isMatch(String s, String p) {
if (p == null || p.length() == 0) return (s == null || s.length() == 0);

    boolean dp[][] = new boolean[s.length()+1][p.length()+1];
    dp[0][0] = true;
    for (int j=2; j<=p.length(); j++) {
        dp[0][j] = p.charAt(j-1) == '*' &amp;&amp; dp[0][j-2]; 
    }
        for (int j=1; j<=p.length(); j++) {
            for (int i=1; i<=s.length(); i++) {
                if (p.charAt(j-1) == s.charAt(i-1) || p.charAt(j-1) == '.') 
					dp[i][j] = dp[i-1][j-1];
                else if(p.charAt(j-1) == '*')
                    dp[i][j] = dp[i][j-2] || ((s.charAt(i-1) == p.charAt(j-2) || p.charAt(j-2) == '.') &amp;&amp; dp[i-1][j]); 
            }
        }
        return dp[s.length()][p.length()];
    }
37
Q
  1. Best Time to Buy and Sell Stock IV

Say you have an array for which the i-th element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Example 1:

Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Example 2:

Input: [3,2,6,5,0,3], k = 2
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.

A

public int maxProfit(int k, int[] prices) {
if(prices == null || prices.length == 0 || k == 0) {
return 0;
}

        if(k>=prices.length/2){
            int maxProfit = 0;
            for(int i=1; iprices[i-1]) maxProfit += prices[i]-prices[i-1];
            }
            return maxProfit;
        }
    int[][] sells = new int[k][2];

    for(int[] sell : sells) {
        sell[0] = Integer.MAX_VALUE;
        sell[1] = 0;
    }

    for(int price : prices) {
        int[] first = sells[0];
        first[0] = Math.min(first[0], price);
        first[1] = Math.max(first[1], price-first[0]);

        for(int i=1; i