Problem
Given an NxN matrix of positive and negative integers, write code to find the sub- matrix with the largest possible sum.
Solution
This is DP problem. Here is the good solution.References
Data structures, Algorithms, Coding, Technical Interview Questions and much more. (Still work in progress)
Given an NxN matrix of positive and negative integers, write code to find the sub- matrix with the largest possible sum.
Imagine you have a square matrix, where each cell is filled with either black or white. Design an algorithm to find the maximum subsquare such that all four borders are filled with black pixels.
public static int[][] findMaxSubsquare(int[][] square) {
int[][] maxSubsquare = null;
int maxSize = 0;
for (int col = 0; square.length - col > maxSize; ++col) {
for (int row = 0; square.length - row > maxSize; ++row) {
for (int size = square.length - Math.max(row, col);
size > maxSize; --size) {
if (isValidSubsquare(square, row, col, size)) {
maxSize = size;
maxSubsquare = new int[size][size];
for (int i = row; i < size + row; ++i)
System.arraycopy(square[i], col, maxSubsquare[i
- row], 0, size);
}
}
}
}
return maxSubsquare;
}
private static boolean isValidSubsquare(int[][] square, int row, int col,
int size) {
// up and bottom border
for (int j = col; j < col + size; ++j) {
if (square[row][j] == 0)
return false;
if (square[row + size - 1][j] == 0)
return false;
}
// left and right border
for (int i = row; i < row + size; ++i) {
if (square[i][col] == 0)
return false;
if (square[i][col + size - 1] == 0)
return false;
}
return true;
}
Given two words of equal length that are in a dictionary, write a method to transform one word into another word by changing only one letter at a time. The new word you get in each step must be in the dictionary.
EXAMPLE
Input: DAMP, LIKE
Output: DAMP -> LAMP -> LIMP -> LIME -> LIKE
public static List<String> transform(String src, String des,
Set<String> dictionary) {
Queue<String> Q = new LinkedList<String>();
Set<String> visited = new HashSet<String>();
Map<String, String> routes = new HashMap<String, String>();
Q.add(src);
visited.add(src);
while (!Q.isEmpty()) {
String t = Q.poll();
if (t.equals(des)) {
LinkedList<String> list = new LinkedList<String>();
while (t != null) {
list.add(0, t);
t = routes.get(t);
}
return list;
}
for (String o : getAllTransformations(t, dictionary)) {
if (!visited.contains(o)) {
visited.add(o);
Q.add(o);
routes.put(o, t);
}
}
}
return null;
}
private static List<String> getAllTransformations(String src,
Set<String> dictionary) {
List<String> results = new LinkedList<String>();
for (int i = 0; i < src.length(); ++i) {
for (char c = 'A'; c <= 'Z'; ++c) {
String newStr = src.substring(0, i) + c + src.substring(i + 1);
if (!src.equals(newStr) && dictionary.contains(newStr))
results.add(newStr);
}
}
return results;
}
Given a string s and an array of smaller strings T, design a method to search s for each small string in T.
| [0] | “mississippi” |
| [1] | “ississippi” |
| [2] | “ssissippi” |
| [3] | “sissippi” |
| [4] | “issippi” |
| [5] | “ssippi” |
| [6] | “sippi” |
| [7] | “ippi” |
| [8] | “ppi” |
| [9] | “pi” |
| [10] | “i” |
public static class SuffixTree {
SuffixTreeNode root = new SuffixTreeNode();
public SuffixTree(String s) {
for (int i = 0; i < s.length(); ++i) {
root.insert(s.substring(i), i);
}
}
public List<Integer> getIndexes(String s) {
return root.getIndices(s);
}
}
public static class SuffixTreeNode {
private char c;
private List<Integer> indices = new ArrayList<Integer>();;
private Map<Character, SuffixTreeNode> children =
new HashMap<Character, SuffixTreeNode>();
public void insert(String s, int index) {
indices.add(index);
if (s != null && s.length() > 0) {
char character = s.charAt(0);
if (children.keySet().contains(character)) {
children.get(character).insert(
s.substring(1), index);
} else {
SuffixTreeNode child = new SuffixTreeNode();
children.put(character, child);
child.insert(s.substring(1), index);
}
}
}
public List<Integer> getIndices(String s) {
if (s == null || s.length() == 0)
return indices;
else {
char character = s.charAt(0);
if (children.containsKey(character))
return children.get(character).getIndices(
s.substring(1));
else
return null;
}
}
}
Write a program to find the longest word made of other words.Solution
EXAMPLE
Input: test, tester, testertest, testing, testingtester
Output: testingtester
public static class LengthComparator implements Comparator<String> {
public int compare(String o1, String o2) {
if (o1.length() < o2.length())
return 1;
else if (o1.length() > o2.length())
return -1;
else
return 0;
}
}
public static String longestWordMadeOfOtherWords(String[] words) {
Arrays.sort(words, new LengthComparator());
for (String word : words) {
String backup = new String(word);
for (String otherWord : words) {
if (!otherWord.equals(backup) && word.contains(otherWord)) {
word = word.replace(otherWord, "");
}
}
if (word.length() == 0)
return backup;
}
return null;
}
Describe an algorithm to find the largest 1 million numbers in 1 billion numbers. Assume that the computer memory can hold all one billion numbers.
public static int quickPartition(int[] array, int low, int high) {
if (high <= low)
return -1;
// randomly choose a pivot
int index = new Random().nextInt(high - low + 1) + low;
int pivot = array[index];
// swap the pivot to the front
int num = array[index];
array[index] = array[low];
array[low] = num;
// partition as in Quicksort
int L = low + 1;
int R = high;
while (R >= L) {
while (R >= L && array[L] < pivot)
L++;
while (R >= L && array[R] >= pivot)
R--;
if (R >= L) {
int temp = array[L];
array[L] = array[R];
array[R] = temp;
L++;
R--;
}
}
// swap the pivot back to appropriate position.
num = array[R];
array[R] = array[low];
array[low] = num;
return R;
}
public static List<Integer> largestM(int[] numbers, int M, int low, int high) {
// RIndex = index of pivot
int RIndex = quickPartition(numbers, low, high);
// mFound = # of the largest numbers
int mFound = high + 1 - RIndex;
List<Integer> results = new LinkedList<Integer>();
if (mFound == M) { // Done!
int i = RIndex;
for (; i <= high; ++i)
<span class="skimlinks-unlinked">results.add(numbers</span>[i]);
return results;
} else if (mFound > M) { // Keep looking
// check if those mFound elements are actually the same
boolean duplicates = true;
for (int i = RIndex; i <= high; ++i) {
if (numbers[i] != numbers[RIndex])
duplicates = false;
}
if (!duplicates)
return largestM(numbers, M, RIndex, high);
else {
// if they are the same, just return M duplicates of them
for (int k = 0; k < M; ++k)
<span class="skimlinks-unlinked">results.add(numbers</span>[RIndex]);
return results;
}
} else { // Has found some, keep looking for the rest
int i = RIndex;
for (; i < numbers.length; ++i)
<span class="skimlinks-unlinked">results.add(numbers</span>[i]);
results.addAll(largestM(numbers, M - mFound, low, RIndex - 1));
return results;
}
}
k, replace the current min m with max(k, m). Afterwards the heap holds the 100 largest inputs.
You have a large text file containing words. Given any two words, find the shortest distance (in terms of number of words) between them in the file. Can you make the searching operation in O(1) time? What about the space complexity for your solution?
OR
Find the minimum distance between 2 numbers in the array?
as was is the as the yahoo you me was the andExample 1
static int getMinDistance(String[] words, String word1, String word2) {
int pos = 0;
int min = Integer.MAX_VALUE / 2;
int word1_pos = -min;
int word2_pos = -min;
for (int i = 0; i < words.length; i++) {
String current_word = words[i];
if (current_word.equals(word1)) {
word1_pos = pos;
int distance = word1_pos - word2_pos;
if (min > distance)
min = distance;
} else if (current_word.equals(word2)) {
word2_pos = pos;
int distance = word2_pos - word1_pos;
if (min > distance) min = distance;
}
++pos;
}
return min;
}
private static Map<String, ArrayList<Integer>> locations = new HashMap<String, ArrayList<Integer>>();
private static void storeLocations(String[] text) {
for (int i = 0; i < text.length; ++i) {
String word = text[i];
if (locations.keySet().contains(word)) {
ArrayList<Integer> location = locations.get(word);
location.add(i);
Collections.sort(location);
locations.put(word, location);
} else {
ArrayList<Integer> location = new ArrayList<Integer>();
location.add(i);
locations.put(word, location);
}
}
}
private static int modified_binary_search(ArrayList<Integer> array,
int target) {
int low = 0;
int high = array.size();
while (low < high) {
int mid = low + (high - low) / 2;
if (target == array.get(mid))
return target;
if (target < array.get(mid))
high = mid;
else
low = mid + 1;
}
if (low >= 0 && low < array.size())
return array.get(low);
else
return array.get(array.size() - 1);
}
private static int shortest_distance(String a, String b) {
int min = Integer.MAX_VALUE;
for (int index_a : locations.get(a)) {
ArrayList<Integer> array = locations.get(b);
int nearest_index_b = modified_binary_search(array, index_a);
int distance = Math.abs(nearest_index_b - index_a);
if (distance < min)
min = distance;
}
return min;
}
Write a method to count the number of 2s between 0 and n.
// Take n = 319 as example
public static int numberOf2s(int n) {
if (n < 2)
return 0;
int result = 0;
int power10 = 1;
while (power10 * 10 < n) {
power10 *= 10;
}
// power10 = 100
int msb = n / power10; // 3
int reminder = n % power10; // 19
// Count # of 2s from MSB
if (msb > 2)
// This counts the first 2 from 200 to 299
result += power10;
if (msb == 2)
// If n = 219, this counts the first 2
// from 200 to 219 (20 of 2s).
result += reminder + 1;
// Count # of 2s from reminder
// This (recursively) counts for # of 2s from 1 to 100
// msb = 3, so we need to multiply by that.
result += msb * numberOf2s(power10);
// This (recursively) counts for # of 2s from 1 to reminder
result += numberOf2s(reminder);
return result;
}
Write a method to randomly generate a set of m integers from an array of size n Each element must have equal probability of being chosen.
let m be the number of elements to select for i = 1; i <= m; i++ pick a random number from 1 to n, call it j swap array[j] and array [n] (assuming 1 indexed arrays) n--
public static int[] chooseNFromM(int[] array, int m) {
if (m > array.length)
return null;
int[] results = new int[m];
for (int i = 0; i < m; ++i) {
int index, temp;
do {
index = new Random().nextInt(array.length);
} while (index < i);
temp = array[index];
array[index] = array[i];
array[i] = temp;
}
for (int i = 0; i < m; ++i) {
results[i] = array[i];
}
return results;
}
Write a function Add() that returns sum of two integers. The function should not use any of the arithmetic operators (+, ++, –, -, .. etc).Solution
int Add(int x, int y)
{
// Iterate till there is no carry
while (y != 0)
{
// carry now contains common set bits of x and y
int carry = x & y;
// Sum of bits of x and y where at least one of the bits is not set
x = x ^ y;
// Carry is shifted by one so that adding it to x gives the required sum
y = carry << 1;
}
return x;
}
int Add(int x, int y)
{
if (y == 0)
return x;
else
return Add( x ^ y, (x & y) << 1);
}
Numbers are randomly generated and passed to a method. Write a program to find and maintain the median value as new values are generated.OR
You are given a stream of numbers which can be positive or negative. You are required to provide an operation FIND MEDIAN..which when invoked should be able return the median of the numbers in stream(in say O(1) time)
Find the rolling median?
Step 1: Add next item to one of the heaps
if next item is smaller than maxHeap root add it to maxHeap,
else add it to minHeap
Step 2: Balance the heaps (after this step heaps will be either balanced or
one of them will contain 1 more item)
if number of elements in one of the heaps is greater than the other by
more than 1, remove the root element from the one containing more elements and
add to the other one
if some one calls getMedian...then
If the heaps contain equal elements;
median = (root of maxHeap + root of minHeap)/2
Else
median = root of the heap with more elements
public static class maxComparator implements Comparator<Double> {
public int compare(Double o1, Double o2) {
return -o1.compareTo(o2);
}
}
static PriorityQueue<Double> minHeap = new PriorityQueue<Double>(11,
new maxComparator());
static PriorityQueue<Double> maxHeap = new PriorityQueue<Double>();
public static void addToHeap(double number) {
if (minHeap.size() == maxHeap.size()) {
if (minHeap.isEmpty())
minHeap.add(number);
else if (number > minHeap.peek())
maxHeap.add(number);
else { // number < minHeap.peek()
maxHeap.add(minHeap.poll());
minHeap.add(number);
}
} else if (minHeap.size() > maxHeap.size()) {
if (number > minHeap.peek())
maxHeap.add(number);
else { // number <= minHeap.peek()
maxHeap.add(minHeap.poll());
minHeap.add(number);
}
} else { // minHeap.size() < maxHeap.size()
if (number < maxHeap.peek())
minHeap.add(number);
else { // number >= maxHeap.peek()
minHeap.add(maxHeap.poll());
maxHeap.add(number);
}
}
}
public static double getMedian() {
if (minHeap.size() == maxHeap.size())
return (minHeap.peek() + maxHeap.peek()) / 2;
else if (minHeap.size() > maxHeap.size())
return minHeap.peek();
else
return maxHeap.peek();
}