Wednesday, February 20, 2019

392. Is Subsequence

392Is Subsequence
Given a string s and a string t, check if s is subsequence of t.
You may assume that there is only lower case English letters in both s and tt is potentially a very long (length ~= 500,000) string, and sis a short string (<=100).
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not).
Example 1:
s = "abc"t = "ahbgdc"
Return true.
Example 2:
s = "axc"t = "ahbgdc"
Return false.
Follow up:
If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
------------------
没啥好说的
class Solution {
    public boolean isSubsequence(String s, String t) {
        int i = 0, j = 0;
        
        while (i < s.length() && j < t.length()) {
            char c1 = s.charAt(i);
            char c2 = t.charAt(j);
            
            if (c1 != c2) j++;
            else {
                i++;
                j++;
            }
        }
        
        return i == s.length();
    }
}

Monday, February 18, 2019

583. Delete Operation for Two Strings

583Delete Operation for Two Strings
Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same, where in each step you can delete one character in either string.
Example 1:
Input: "sea", "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".
Note:
  1. The length of given words won't exceed 500.
  2. Characters in given words can only be lower-case letters.
--------------------
Solution #1
2个单词的长度和 -longest common subsequence * 2

class Solution {
    public int minDistance(String word1, String word2) {
        return word1.length() + word2.length() - 2 * lcs(word1,word2);
    }
    
    private int lcs(String s1, String s2) {
        int m = s1.length(), n = s2.length();
        int[][] dp = new int[m + 1][n + 1];
        
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) dp[i][j] = 1 + dp[i - 1][j - 1];
                else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        
        return dp[m][n];
    }
}

Solution #2 DP, ToDo
类似edit distance, 方程:
dp[x][y] = dp[x - 1][y - 1] if s1[x] == s2[y]
dp[x][y] = 1 + min(dp[x - 1][y], dp[x][y - 1) if s1[x] != s2[y]

Sunday, February 17, 2019

523. 560, Continuous Subarray Sum, Subarray Sum Equals K

523Continuous Subarray Sum
Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer.
Example 1:
Input: [23, 2, 4, 6, 7],  k=6
Output: True
Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.
Example 2:
Input: [23, 2, 6, 4, 7],  k=6
Output: True
Explanation: Because [23, 2, 6, 4, 7] is an continuous subarray of size 5 and sums up to 42.
Note:
  1. The length of the array won't exceed 10,000.
  2. You may assume the sum of all the numbers is in the range of a signed 32-bit integer.
-----------------
(sum - preSum) % k = 0
=>
sum % k = preSum % k

所以set里面要存的是sum % k,
class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        if (nums == null || nums.length < 2) return false; 
        if (checkZeros(nums)) return true;
        if (k == 0) return false;
        
        int sum = nums[0];
        Set<Integer> set = new HashSet<>();
        set.add(0);
        set.add(sum);
        
        for (int i = 1; i < nums.length; i++) {
            sum += nums[i];
            sum %= k;
            if (set.contains(sum)) {
                return true;
            }
            set.add(sum);
        }
        
        return false;
    }
    
    private boolean checkZeros(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == 0 && nums[i - 1] == 0) return true;
        }
        
        return false;
    }
}


560Subarray Sum Equals K
Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.
Example 1:
Input:nums = [1,1,1], k = 2
Output: 2
Note:
  1. The length of the array is in range [1, 20,000].
  2. The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].
---------------
class Solution {
    public int subarraySum(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        map.put(0,1);
        int sum = 0;
        int rt = 0;
        
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if (map.containsKey(sum - k)) rt += map.get(sum - k);
            map.put(sum, map.getOrDefault(sum, 0) + 1);
        }
        
        return rt;
    }
}

Saturday, February 16, 2019

Pure Storage


画圆经典题。followup: 如果像素点较少怎么办。
利口六六一
-------------------

https://www.1point3acres.com/bbs/thread-475566-1-1.html


小印面试官全程冷冰冰,没有交流,感觉开始就要fail我的样子

if (n%2 == 0) n = n/2

else n = 3*n + 1

3 --> 10 --> 5 ---> 16 ---> 8 ---> 4 ---> 2 ----> 1

总共需要7步

写一个函数计算步数,系统可能要call 几百万,所以需要计算这个步数更快



关于第二题 既然bottleneck在速度 我目前只能想到


(1) 不要recursively 要iteratively 因为arithmetic ops太cheap了 much lower than recursion overhead.


(2) For even number, simply use shifting ops 因为移位是底层arch实现里几乎最简单的操作了 比加法还快 while (x&1) { x = x>>1; ans++; } arch pipeline移动一步就可以做一个iteration了 没什么继续加速的必要了


(3) For odd number, simply use x + (x<<1) + 1, 两个加法和一个移位,也是底层arch里最简单的操作之一 结合(2)(3) 应该是快得要飞起来了 pipeline走几步就做完一组了


(4) 要考虑一下是不是一定有解 这个数学上证明一下就好 很简单的反证法 如果我碰到这题 肯定会主动证明这个结论


(5) 要是可以数学上估计出step的upper bound就更完美了 我没想出来



--------------------

https://www.1point3acres.com/bbs/thread-298316-1-1.html


valid square 给平面上四个点,判断是否能组成一个正方形。每个点是由(x,y)坐标表示。follow up是给n个点,问可以组成多少个valid square,要求先O(n^4),再改进到O(n^3),最后改进到 O(n^2)
event fire https://instant.1point3acres.com/thread/177053 https://www.evernote.com/shard/s260/sh/a01e5b26-d3eb-44c0-8ef4-01086605f675/da31dd196df57906d67ab4ea189304f1
bitmap http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=226030&extra=page%3D127%26filter%3Dsortid%26sortid%3D311%26sortid%3D311


http://www.1point3acres.com/bbs/thread-271461-1-1.html


画圆 可能需要用数学方法证明解法的正确性 http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=192327&extra=page%3D43%26filter%3Dsortid%26sortid%3D311%26sortid%3D311 https://www.cs.uic.edu/~jbell/CourseNotes/ComputerGraphics/Circles.html
implement O(1) set https://instant.1point3acres.com/thread/177053
image smooth 这篇帖子说要求in place http://www.1point3acres.com/bbs/thread-138406-1-1.html-baidu 1point3acres


另外一篇帖子里又说 in place 行不通 http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=202635&extra=page%3D5%26filter%3Dsortid%26sortid%3D311%26sortid%3D311


align rectangle/textbox http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=202635&extra=page%3D5%26filter%3Dsortid%26sortid%3D311%26sortid%3D311
c++ virtual table 相关知识 https://www.evernote.com/shard/s260/sh/dfc7453b-e50f-46c0-b223-196bead364a9/c41f1cea8f38c1802d1941338b03d375
call api http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=192290&extra=page%3D109%26filter%3Dsortid%26sortid%3D311%26sortid%3D311 http://www.1point3acres.com/bbs/thread-206999-1-1.html
sort color (3-way partition) 要求swap次数最少 http://www.1point3acres.com/bbs/thread-206999-1-1.html
which number can be represented as two decimal http://softwarecareerup.blogspot.com/2015/03/pure-storage-interview.html
implement lock http://softwarecareerup.blogspot.com/2015/03/pure-storage-interview.html
happy number LC 202 http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=192327&extra=page%3D43%26filter%3Dsortid%26sortid%3D311%26sortid%3D311
memcpy, memmove http://www.1point3acres.com/bbs/thread-206999-1-1.html
fibonacci number both iterative and recursive http://www.1point3acres.com/bbs/thread-141925-1-1.html
coin change LC 322 http://www.1point3acres.com/bbs/thread-141925-1-1.html
min stack http://www.1point3acres.com/bbs/thread-141925-1-1.html
LRU cache, Skyline, Permutation, combination sum, roman to int
What data structure would you use to construct a skip list? Implement search() and insert(). http://www.cnblogs.com/binyue/p/4545555.html http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html http://www.sanfoundry.com/java-program-implement-skip-list/
thread-safe stack 多线程下的stack的push和pop,好像只有校招会碰到。

Thursday, February 14, 2019

332. Reconstruct Itinerary

332Reconstruct Itinerary
Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK.
Note:
  1. If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary ["JFK", "LGA"] has a smaller lexical order than ["JFK", "LGB"].
  2. All airports are represented by three capital letters (IATA code).
  3. You may assume all tickets form at least one valid itinerary.
Example 1:
Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Output: ["JFK", "MUC", "LHR", "SFO", "SJC"]
Example 2:
Input: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Output: ["JFK","ATL","JFK","SFO","ATL","SFO"]
Explanation: Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"].
             But it is larger in lexical order.
-------------------------
Solution #1
很直接的graph traversal,要对edge做visited,而不是node

class Solution {
    
    public List<String> findItinerary(String[][] tickets) {
        Map<String, Node> graph = buildGraph(tickets);
        
        List<String> rt = new ArrayList<>();
        rt.add("JFK");
        dfs(graph.get("JFK"), rt, tickets.length);
        
        return rt;
    }
    
    private boolean dfs(Node node, List<String> rt, int count) {
        if (count == 0) {
            return true;
        }
                
        for (int i = 0; i < node.next.size(); i++) {
            Node n = node.next.get(i);
            rt.add(n.airport);
            
            if (!node.visited[i]) {
                node.visited[i] = true;
                if (dfs(n, rt, count - 1)) return true;
                node.visited[i] = false;
            } 
            
            rt.remove(rt.size() - 1);
        }
        
        return false;
    }
    
    private Map<String, Node> buildGraph(String[][] tickets) {
        Map<String, Node> graph = new HashMap<>();
        
        for (String[] t : tickets) {
            if (!graph.containsKey(t[0])) {
                graph.put(t[0], new Node(t[0]));
            }
            if (!graph.containsKey(t[1])) {
                graph.put(t[1], new Node(t[1]));
            }
            
            graph.get(t[0]).next.add(graph.get(t[1]));
        }
        
        for (Node n : graph.values()) {
            Collections.sort(n.next, (a,b) -> a.airport.compareTo(b.airport));
            n.visited = new boolean[n.next.size()];
        }
        
        return graph;
    }
    
    class Node{
        public String airport;
        public List<Node> next;
        public boolean[] visited;
        public Node(String airport) {
            this.airport = airport;
            next = new ArrayList<>();
        }
    }
}

Solution #2 Eulerian Path Algorithm,题目已经说了路径一定存在
Eulerian Path的特点是一笔画,所有graph里面最多只有1个node有incoming degree - outgoing == 1, 只有一个node outgoing degree - incoming == 1. 所有要么是若干个环状,要么是一个单条路径 + 若干个环状路径。算法就是遇到死路就back tracking继续。(看下面youtube的视频)

ref: https://www.youtube.com/watch?v=8MpoO2zA2l4
Code ref: https://leetcode.com/problems/reconstruct-itinerary/discuss/78768/Short-Ruby-Python-Java-C++

class Solution {
    public List<String> findItinerary(String[][] tickets) {
        Map<String, PriorityQueue<String>> map = new HashMap<>();        
        
        for (String[] t : tickets) {
            if (!map.containsKey(t[0])) {
                map.put(t[0],new PriorityQueue<String>((a,b) -> a.compareTo(b)));
            }
            
            map.get(t[0]).add(t[1]);
        }
        
        List<String> rt = new ArrayList<>();
        dfs(map,rt,"JFK");
        
        Collections.reverse(rt);
        return rt;
    }
    
    private void dfs(Map<String, PriorityQueue<String>> map, List<String> rt, String ap) {
        
        while (map.containsKey(ap) && !map.get(ap).isEmpty()) {
            dfs(map,rt, map.get(ap).poll());
        }
        
        rt.add(ap);
    }
}

Tuesday, February 12, 2019

655. Print Binary Tree

655Print Binary Tree
Print a binary tree in an m*n 2D string array following these rules:
  1. The row number m should be equal to the height of the given binary tree.
  2. The column number n should always be an odd number.
  3. The root node's value (in string format) should be put in the exactly middle of the first row it can be put. The column and the row where the root node belongs will separate the rest space into two parts (left-bottom part and right-bottom part). You should print the left subtree in the left-bottom part and print the right subtree in the right-bottom part. The left-bottom part and the right-bottom part should have the same size. Even if one subtree is none while the other is not, you don't need to print anything for the none subtree but still need to leave the space as large as that for the other subtree. However, if two subtrees are none, then you don't need to leave space for both of them.
  4. Each unused space should contain an empty string "".
  5. Print the subtrees following the same rules.
Example 1:
Input:
     1
    /
   2
Output:
[["", "1", ""],
 ["2", "", ""]]
Example 2:
Input:
     1
    / \
   2   3
    \
     4
Output:
[["", "", "", "1", "", "", ""],
 ["", "2", "", "", "", "3", ""],
 ["", "", "4", "", "", "", ""]]
Example 3:
Input:
      1
     / \
    2   5
   / 
  3 
 / 
4 
Output:

[["",  "",  "", "",  "", "", "", "1", "",  "",  "",  "",  "", "", ""]
 ["",  "",  "", "2", "", "", "", "",  "",  "",  "",  "5", "", "", ""]
 ["",  "3", "", "",  "", "", "", "",  "",  "",  "",  "",  "", "", ""]
 ["4", "",  "", "",  "", "", "", "",  "",  "",  "",  "",  "", "", ""]]
Note: The height of binary tree is in the range of [1, 10].
-------------------
先计算出高和宽,然后直接递归
ref: https://zxi.mytechroad.com/blog/tree/leetcode-655-print-binary-tree/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<String>> printTree(TreeNode root) {
        int h = getHeight(root);
        int w = (1 << h) - 1;
        
        List<List<String>> rt = new ArrayList<>();
        for (int i = 0; i < h; i++) {
            List<String> l = new ArrayList<>();
            
            for (int j = 0; j < w; j++) {
                l.add("");
            }
            
            rt.add(l);
        }
        
        rec(root, rt, 0, w - 1, 0);
        
        return rt;
    }
    
    private void rec(TreeNode root, List<List<String>> rt, int left, int right, int level) {
        if (root == null) return;
        int mid = (left + right) / 2;
        rt.get(level).set(mid, Integer.toString(root.val));
        
        rec(root.left, rt, left, mid - 1, level + 1);
        rec(root.right, rt, mid + 1, right, level + 1);
    }
    
    private int getHeight(TreeNode root) {
        if (root == null) return 0;
        return Math.max(getHeight(root.left), getHeight(root.right)) + 1;
    }
}

Solution #2, level order traversal
2个queue,一个记录node,另一个记录node所对应的范围(left, right)
ref: https://leetcode.com/problems/print-binary-tree/discuss/106269/Java-Iterative-Level-Order-Traversal-with-Queue

Monday, February 11, 2019

362. Design Hit Counter

362Design Hit Counter
Design a hit counter which counts the number of hits received in the past 5 minutes.
Each function accepts a timestamp parameter (in seconds granularity) and you may assume that calls are being made to the system in chronological order (ie, the timestamp is monotonically increasing). You may assume that the earliest timestamp starts at 1.
It is possible that several hits arrive roughly at the same time.
Example:
HitCounter counter = new HitCounter();

// hit at timestamp 1.
counter.hit(1);

// hit at timestamp 2.
counter.hit(2);

// hit at timestamp 3.
counter.hit(3);

// get hits at timestamp 4, should return 3.
counter.getHits(4);

// hit at timestamp 300.
counter.hit(300);

// get hits at timestamp 300, should return 4.
counter.getHits(300);

// get hits at timestamp 301, should return 3.
counter.getHits(301); 
Follow up:
What if the number of hits per second could be very large? Does your design scale?
------------------
Solution #1, 用2个array,一个记录module后timesstamp里存是否为当前的timestamp, 另一个存count
O(1) hit
O(s) getHits
class HitCounter {

    private int[] timestamps;
    private int[] counts;
    
    /** Initialize your data structure here. */
    public HitCounter() {
        timestamps = new int[300];
        counts = new int[300];
    }
    
    /** Record a hit.
        @param timestamp - The current timestamp (in seconds granularity). */
    public void hit(int timestamp) {
        int tmp = timestamp % 300;
        if (timestamps[tmp] != timestamp) {
            counts[tmp] = 1;
            timestamps[tmp] = timestamp;
        }else {
            counts[tmp]++;
        }
        
    }
    
    /** Return the number of hits in the past 5 minutes.
        @param timestamp - The current timestamp (in seconds granularity). */
    public int getHits(int timestamp) {
        
        int total = 0;
        for (int i = 0; i < 300; i++) {
            if (timestamp - timestamps[i] < 300) {
                total += counts[i];        
            }
        }
        
        return total;
    }
}

/**
 * Your HitCounter object will be instantiated and called as such:
 * HitCounter obj = new HitCounter();
 * obj.hit(timestamp);
 * int param_2 = obj.getHits(timestamp);
 */

Solution #2,
因为#2存了重复的,数据量大的时候还是#1高效一些
class HitCounter {

    private Queue<Integer> times;
    
    /** Initialize your data structure here. */
    public HitCounter() {
        times = new LinkedList<>();
    }
    
    /** Record a hit.
        @param timestamp - The current timestamp (in seconds granularity). */
    public void hit(int timestamp) {
        
        times.add(timestamp);
        prune(timestamp);
    }
    
    /** Return the number of hits in the past 5 minutes.
        @param timestamp - The current timestamp (in seconds granularity). */
    public int getHits(int timestamp) {
        
        prune(timestamp);
        return times.size();
    }
    
    private void prune(int timestamp) {
        while (!times.isEmpty() && timestamp - times.peek() >= 300) {
            times.poll();
        }
    }
}

/**
 * Your HitCounter object will be instantiated and called as such:
 * HitCounter obj = new HitCounter();
 * obj.hit(timestamp);
 * int param_2 = obj.getHits(timestamp);
 */