Sample code for google interview preparation
/**
* 1.1 Find Popular Element.
* Given an array of size n, find all elements in array that appear more than n/k times.
* input: k = 4, arr = [3,1,2,2,2,1,4,3,3]
* output: [2,3]
*
* Time: O(n) Space: O(n)
*
* @param arr
* @param k
* @return
*/
public int[] findPopularElements(int[] arr, int k) {
int target = arr.length / k;
List<Integer> li = new ArrayList<Integer>();
HashMap<Integer, Integer> popMap = new HashMap<>();
// Count the frequency of each element
for (int i = 0; i < arr.length; i++) {
if (popMap.containsKey(arr[i])) {
int cur = popMap.get(arr[i]);
popMap.put(arr[i], cur + 1);
} else {
popMap.put(arr[i], 1);
}
}
// Iterate over each element in the hash table
// and check their frequency, if it is more than
// n/k, add them to the result
for (Map.Entry ent : popMap.entrySet()) {
int frq = (int)ent.getValue();
if (frq > target) {
li.add((int)ent.getKey());
}
}
int[] result = new int[li.size()];
for (int j=0; j<li.size(); j++) {
result[j] = li.get(j);
}
return result;
}
/**
* 1.2 Follow up: Find popular in a sorted array
* Write a function in Java that takes a sorted array and returns any popular element
* A popular element: x in array of size n is such that the number of occurrence of x > n/4
* In other words, the element must be repeated in the array more than a quarter of the time
*
* Time: O(log n); Space: O(1)
*
* @param arr
* @return
*/
public int findPopular(int[] arr) throws Exception {
int len = arr.length;
int target = len/4;
if (countOccurances(arr, arr[len/4]) > target) return arr[len/4];
else if (countOccurances(arr, arr[len/2]) > target) return arr[len/2];
else if (countOccurances(arr, arr[(3*len)/4]) > target) return arr[(3*len)/4];
else throw new Exception();
}
/**
* Find the first and last occurrence of the target number
* @param array
* @param num
* @return the number of the occurrence
*/
private int countOccurances(int[] array, int num) {
int first = binarySearch(array, num, true);
int last = binarySearch(array, num, false);
return last - first + 1;
}
/**
* Binary search to look for the first or last occurrence of target number
* @param array
* @param target
* @param searchFirst
* @return
*/
private int binarySearch(int[] array, int target, boolean searchFirst) {
int left = 0;
int right = array.length;
int result = -1;
while (left <= right) {
int mid = (left + right)/2;
if (array[mid] == target) {
result = mid;
if (searchFirst) {
right = mid - 1;
} else {
left = mid + 1;
}
} else if (array[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
/**
* 2. LC 1610 Maximum Number of Visible Points
*
* 这道题需要考虑 end超过angle list里面点的数量的情况,因为可以被套圈
*
* @param points
* @param angle
* @param location
* @return
*/
public int visiblePoints(List<List<Integer>> points, int angle, List<Integer> location) {
List<Double> angles = new ArrayList<Double>();
int myposition = 0;
// 将每一个点转化为一个角度的数值,然后把它加入到angles这个list里面
for (List<Integer> point : points) {
double y = (double)(point.get(1) - location.get(1));
double x = (double)(point.get(0) - location.get(0));
// The current point is in my location
if (x==0 && y==0) {
myposition++;
continue;
}
double thisAngle = 180*Math.atan(y/x)/Math.PI;
if (x < 0) {
thisAngle = 180.0 + thisAngle; // 该point在第二和第三象限
} else if (y < 0) {
thisAngle = 360.0 + thisAngle; // 该point在第四象限
}
angles.add(thisAngle);
}
Collections.sort(angles);
int max = 0;
int start = 0;
int end = 0;
int size = angles.size();
// start的初始位置是正东(y=0),因此start回到正东方向的时候,end会大于size
while (start < size) {
while ((end<size?angles.get(end) : angles.get(end%size)+360) - angles.get(start) <= angle) {
end++;
}
if (end > start) {
max = Math.max(end - start, max);
}
start++;
}
return max+myposition;
}
/**
*3.1 Leetcode 295 Find Median from Data Stream
*/
public class MedianFinder {
private List<Integer> stream;
public MedianFinder() {
this.stream = new ArrayList<>();
}
public void addNum(int num) {
stream.add(num);
}
public double findMedian() {
if (stream.isEmpty()) {
return 0.0;
}
if (stream.size() == 1) {
return stream.get(0);
}
Collections.sort(stream);
if (stream.size()%2 == 0) {
return (stream.get(stream.size()/2 - 1) + stream.get(stream.size()/2))/2.0;
}
return stream.get(stream.size()/2);
}
}
// 3.2 Faster than 98% || Two heap approach
public class MedianFinder {
PriorityQueue<Integer> min;
PriorityQueue<Integer> max;
public MedianFinder() {
min = new PriorityQueue<>();
max = new PriorityQueue<>(Comparator.reverseOrder());
}
public void addNum(int num) {
if (min.isEmpty() && max.isEmpty()) {
max.add(num);
} else if (num > max.peek()) {
min.add(num);
if (min.size() - max.size() >= 2) {
max.add(min.poll());
}
} else {
max.add(num);
if (max.size() - min.size() >= 2) {
min.add(max.poll());
}
}
}
public double findMedian() {
if (max.size() == min.size()) {
return (max.peek() + min.peek())/2.0;
}
if (min.size() > max.size()) {
return (double)min.peek();
}
return (double)max.peek();
}
}
Follow Up: No idea how to resolve it
If all integer numbers from the stream are between 0 and 100, how would you optimize it?
If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?
// 4. Codec design for Tree
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
return dfs(root, "");
}
private String dfs(TreeNode root, String output) {
if (root == null) {
output += "null";
} else {
output += String.valueOf(root.val) + ",";
output = dfs(root.left, output);
output = dfs(root.right, output);
}
return output;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] data_array = data.split(",");
List<String> data_list = new LinkedList<String>(Arrays.asList(data_array));
return helper(data_list);
}
private TreeNode helper(List<String> dataList) {
if (dataList.get(0).equals("null")) {
dataList.remove(0);
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(dataList.get(0)));
dataList.remove(0);
root.left = helper(dataList);
root.right = helper(dataList);
return root;
}
}
/**
* 5.1 Leetcode 269 Alien Dictionary (BFS method)
* @param words
* @return
*/
public String alienOrderI(String[] words) {
// Step 0: Create data structures and find all unique letters.
Map<Character, List<Character>> adjList = new HashMap<>();
Map<Character, Integer> counts = new HashMap<>();
for (String word : words) {
for (char c : word.toCharArray()) {
counts.put(c, 0);
adjList.put(c, new ArrayList<>());
}
}
// Step 1: Find all edges.
for (int i = 0; i < words.length - 1; i++) {
String word1 = words[i];
String word2 = words[i + 1];
// Check that word2 is not a prefix of word1.
if (word1.length() > word2.length() && word1.startsWith(word2)) {
return "";
}
// Find the first non match and insert the corresponding relation.
for (int j = 0; j < Math.min(word1.length(), word2.length()); j++) {
if (word1.charAt(j) != word2.charAt(j)) {
adjList.get(word1.charAt(j)).add(word2.charAt(j));
counts.put(word2.charAt(j), counts.get(word2.charAt(j)) + 1);
break;
}
}
}
// Step 2: Breadth-first search.
StringBuilder sb = new StringBuilder();
Queue<Character> queue = new LinkedList<>();
for (Character c : counts.keySet()) {
if (counts.get(c).equals(0)) {
queue.add(c);
}
}
while (!queue.isEmpty()) {
Character c = queue.remove();
sb.append(c);
for (Character next : adjList.get(c)) {
counts.put(next, counts.get(next) - 1);
if (counts.get(next).equals(0)) {
queue.add(next);
}
}
}
if (sb.length() < counts.size()) {
return "";
}
return sb.toString();
}
/**
* 7.Leetcode 392 Is Subsequence
* @param s
* @param t
* @return
*/
public boolean isSubsequence(String s, String t) {
if (s.length() == 0) {
return true;
}
if (s.length() > t.length()) {
return false;
}
char[] sarr = s.toCharArray();
char[] tarr = t.toCharArray();
int slow = 0;
int fast = 0;
int flag = 0;
while (slow < sarr.length && fast < tarr.length) {
while (fast < tarr.length) {
if (sarr[slow] == tarr[fast]) {
slow++;
flag++;
if (flag == sarr.length) {
return true;
}
}
fast++;
}
}
return false;
}