640. Solve the Equation

Solve a given equation and return the value of x in the form of string “x=#value”. The equation contains only ‘+’, ‘-‘ operation, the variable x and its coefficient.

If there is no solution for the equation, return “No solution”.

If there are infinite solutions for the equation, return “Infinite solutions”.

If there is exactly one solution for the equation, we ensure that the value of x is an integer.

Example 1:

Input: "x+5-3+x=6+x-2"
Output: "x=2"

Example 2:

Input: "x=x"
Output: "Infinite solutions"

Example 3:

Input: "2x=x"
Output: "x=0"

Example 4:

Input: "2x+3x-6x=x+2"
Output: "x=-1"

Example 5:

Input: "x=x+2"
Output: "No solution"


class Solution {
    public String solveEquation(String equation) {
        String[] explodes = equation.split("=");
        
        int coeffX = 0;
        int number = 0;
        int cur  = 0;
        int digit = 0;
        
        boolean left = false;
        
        for (String s : explodes){
            left = !left;
            boolean positive = true;
            
            for (int i = 0; i < s.length(); i ++){
                char c = s.charAt(i);
                
                if (c == '+' || c == '-'){
                    // Push previous integer to number
                    number -= cur*(positive? 1 : -1)*(left? 1 : -1);
                    cur = 0; digit = 0;
                    positive = c == '+';
                    
                } else if(c =='x') {
                    // Push previous coeff of x to coeffX
                    if (digit == 0){
                        // If no coeff, coeff = 1
                        cur = 1;
                    }
                    coeffX += cur*(positive? 1 : -1)*(left? 1 : -1);
                    cur = 0; digit = 0;
                } else {
                    // It's a number.
                    cur = 10 * cur +  Integer.valueOf(s.charAt(i)-'0');
                    digit ++;
                }
            }
            
            // If last in group is a number, redundant
            if (digit > 0){
                number += cur*( ! positive? 1 : -1)*(left? 1 : -1);
                cur = 0; digit = 0;
            }
        }
        
        if (coeffX == 0 && number == 0){
            return "Infinite solutions";
        } else if (coeffX == 0){
            return "No solution";
        }
        return "x="+String.valueOf(number/coeffX);
    }
}

 

1277. Count Square Submatrices with All Ones

Given a m * n matrix of ones and zeros, return how many square submatrices have all ones.

 

Example 1:

Input:

 matrix =
[
  [0,1,1,1],
  [1,1,1,1],
  [0,1,1,1]
]

Output:

 15

Explanation:

 
There are 10 squares of side 1.
There are 4 squares of side 2.
There is one square of side 3.
Total number of squares = 10 + 4 + 1 = 15

Example 2:

Input:

 matrix = 
[
  [1,0,1],
  [1,1,0],
  [1,1,0]
]

Output:

 7

Explanation:

 
There are 6 squares of side 1.  
There is 1 square of side 2. 
Total number of squares = 6 + 1 = 7

 

Constraints:

  • 1 <= arr.length <= 300
  • 1 <= arr[0].length <= 300
  • 0 <= arr[i][j] <= 1

 

Example:

[0,1,1,1],
[1,1,1,1],
[0,1,1,1]

  1. count single ones
  2. count 2×2
  3. count 3×3
  4. ……

Goal: reduce n x n to (n-1)x(n-1) … to 2×2

Now scan 2×2 block, for each position(i,j) scan (i+1,j) (i,j+1) (i+1, j+1)
[0,1,1,1],
[1,1,1,1],
[0,1,1,1]

if the 2×2 scanning block contains 0, update (i,j) to 0
[0,1,1,1],
[0,1,1,1],
[0,1,1,1]

then we can reduce it by removing (ignoring) the last row and column.

[0,1,1],
[0,1,1]

Then walk through with the 2×2 scanning block again.

the counter could be updated when the whole 2×2 block is 1, OR count number of ones in the next round.

Version A, update counter during 2×2 scan

class Solution {
    public int countSquares(int[][] matrix) {
        int c = 0;
        
        int m  = matrix.length;
        int n  = matrix[0].length;
        
        for (int i = 0; i < m; i ++){
            for (int j = 0; j < n; j ++){
                if (matrix[i][j] == 1){
                    c++;
                } 
            }
        }
        
        
        while (m > 1 && n > 1){
            for (int i = 0; i < m-1; i ++){
                for (int j = 0; j < n-1; j ++){
                    if (  matrix[i][j]     == 0 
                       || matrix[i+1][j]   == 0
                       || matrix[i][j+1]   == 0
                       || matrix[i+1][j+1] == 0)
                    {
                        matrix[i][j] = 0;
                    }  else {
                        c++;
                    }
                }
            }
            // lower m and n (ignoring last row and column)
            m --;
            n --;
        }
        return c;
        
    }
}

 

B, a more compact version, update counter next round, count number of ones.
slightly slower for more loops

 

class Solution {
    public int countSquares(int[][] matrix) {
        int c = 0;
        
        int m  = matrix.length;
        int n  = matrix[0].length;
        
        
        
        while (m > 0 && n > 0){
            
            for (int i = 0; i < m; i ++){
                for (int j = 0; j < n; j ++){
                    if (matrix[i][j] == 1){
                        c++;
                    } 
                }
            }
            
            
            for (int i = 0; i < m-1; i ++){
                for (int j = 0; j < n-1; j ++){
                    if (matrix[i][j] == 0 
                       || matrix[i+1][j] == 0
                       || matrix[i][j+1] == 0
                       || matrix[i+1][j+1] == 0){
                        matrix[i][j] = 0;
                    }
                }
            }
            // lower m and n (ignoring last row and column)
            m --;
            n --;
        }
        return c;
        
    }
}

A: 86-110 ms
B: 160-170 ms

1276. Number of Burgers with No Waste of Ingredients

Given two integers tomatoSlices and cheeseSlices. The ingredients of different burgers are as follows:

  • Jumbo Burger: 4 tomato slices and 1 cheese slice.
  • Small Burger: 2 Tomato slices and 1 cheese slice.

Return [total_jumbo, total_small] so that the number of remaining tomatoSlices equal to 0 and the number of remaining cheeseSlices equal to 0. If it is not possible to make the remaining tomatoSlices and cheeseSlices equal to 0 return [].

 

Example 1:

Input:

 tomatoSlices = 16, cheeseSlices = 7

Output:

 [1,6]

Explantion:

 To make one jumbo burger and 6 small burgers we need 4*1 + 2*6 = 16 tomato and 1 + 6 = 7 cheese. There will be no remaining ingredients.

Example 2:

Input:

 tomatoSlices = 17, cheeseSlices = 4

Output:

 []

Explantion:

 There will be no way to use all ingredients to make small and jumbo burgers.

Example 3:

Input:

 tomatoSlices = 4, cheeseSlices = 17

Output:

 []

Explantion:

 Making 1 jumbo burger there will be 16 cheese remaining and making 2 small burgers there will be 15 cheese remaining.

Example 4:

Input:

 tomatoSlices = 0, cheeseSlices = 0

Output:

 [0,0]

Example 5:

Input:

 tomatoSlices = 2, cheeseSlices = 1

Output:

 [0,1]

 

Constraints:

  • 0 <= tomatoSlices <= 10^7
  • 0 <= cheeseSlices <= 10^7

 

Should be an easy question..

class Solution {
    public List<Integer> numOfBurgers(int tomatoSlices, int cheeseSlices) {
        
        List<Integer> result = new ArrayList<>();
        
        if (tomatoSlices % 2 ==1 || cheeseSlices * 4 < tomatoSlices || cheeseSlices * 2 > tomatoSlices){
            return result;
        }
        
        int x = (tomatoSlices - cheeseSlices*2)/2;
        result.add(x);
        result.add(cheeseSlices-x);
        
        return result;
    }
}

 

1268. Search Suggestions System

Given an array of strings products and a string searchWord. We want to design a system that suggests at most three product names from products after each character of searchWord is typed. Suggested products should have common prefix with the searchWord. If there are more than three products with a common prefix return the three lexicographically minimums products.

Return list of lists of the suggested products after each character of searchWord is typed.

 

Example 1:

Input:

 products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"

Output:

 [
["mobile","moneypot","monitor"],
["mobile","moneypot","monitor"],
["mouse","mousepad"],
["mouse","mousepad"],
["mouse","mousepad"]
]

Explanation:

 products sorted lexicographically = ["mobile","moneypot","monitor","mouse","mousepad"]
After typing m and mo all products match and we show user ["mobile","moneypot","monitor"]
After typing mou, mous and mouse the system suggests ["mouse","mousepad"]

Example 2:

Input:

 products = ["havana"], searchWord = "havana"

Output:

 [["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]]

Example 3:

Input:

 products = ["bags","baggage","banner","box","cloths"], searchWord = "bags"

Output:

 [["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]]

Example 4:

Input:

 products = ["havana"], searchWord = "tatiana"

Output:

 [[],[],[],[],[],[],[]]

 

Constraints:

  • 1 <= products.length <= 1000
  • 1 <= Σ products[i].length <= 2 * 10^4
  • All characters of products[i] are lower-case English letters.
  • 1 <= searchWord.length <= 1000
  • All characters of searchWord are lower-case English letters.
class Solution {
    public List<List<String>> suggestedProducts(String[] products, String searchWord) {
        
        List<List<String>> r = new ArrayList<>();
        Arrays.sort(products);

        for (int i = 0; i < searchWord.length(); i ++){
            List<String> rr = new ArrayList<>();
            String prefix = searchWord.substring(0,i+1);

            for (int j = 0; j < products.length && rr.size() < 3; j ++){
                if(products[j].startsWith(prefix)){
                    rr.add(products[j]);
                }
            }

            r.add (rr);
        }
        return r;
    }
}

 

Yes, we can introduce trie for more results. 3 is fairly small here

1267. Count Servers that Communicate

You are given a map of a server center, represented as a m * n integer matrix grid, where 1 means that on that cell there is a server and 0 means that it is no server. Two servers are said to communicate if they are on the same row or on the same column.

Return the number of servers that communicate with any other server.

 

Example 1:

Input:

 grid = [[1,0],[0,1]]

Output:

 0
Explanation: No servers can communicate with others.

Example 2:

Input:

 grid = [[1,0],[1,1]]

Output:

 3
Explanation: All three servers can communicate with at least one other server.

Example 3:

Input:

 grid = [[1,1,0,0],[0,0,1,0],[0,0,1,0],[0,0,0,1]]

Output:

 4
Explanation: The two servers in the first row can communicate with each other. The two servers in the third column can communicate with each other. The server at right bottom corner can't communicate with any other server.

 

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m <= 250
  • 1 <= n <= 250
  • grid[i][j] == 0 or 1
class Solution {
    public int countServers(int[][] grid) {
        int result = 0 ;
        int[] a = new int[grid.length];
        int[] b = new int[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){
                    a[i] ++;
                    b[j] ++;
                    result ++;
                }
            }
        }
        
        for (int i = 0; i < grid.length; i ++){
            for (int j = 0; j < grid[0].length; j ++){
                if (a[i] == 1 && b[j] == 1 && grid[i][j] == 1){
                    result --;
                }
            }
        }
        
        return result;
    }
    
}

 

1161. Maximum Level Sum of a Binary Tree

Given the root of a binary tree, the level of its root is 1, the level of its children is 2, and so on.

Return the smallest level X such that the sum of all the values of nodes at level X is maximal.

 

Example 1:

Input:

[1,7,0,7,-8,null,null]

Output:

2

Explanation:

Level 1 sum = 1.
Level 2 sum = 7 + 0 = 7.
Level 3 sum = 7 + -8 = -1.
So we return the level with the maximum sum which is level 2.

 

Note:

  1. The number of nodes in the given tree is between 1 and 10^4.
  2. -10^5 <= node.val <= 10^5

 

Another “Follow your heart” question.

I’m using level order traversal (BFS) here.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxLevelSum(TreeNode root) {
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        int max = 0;
        int lv = 1;
        
        int max_lv = 0;
        
        while (! q.isEmpty()){
            
            int size = q.size();
            int level_sum = 0;
            for (int i = 0; i < size; i ++){
                TreeNode cur = q.poll();
                if(cur.left != null)
                    q.add(cur.left);
                if (cur.right != null)
                    q.add(cur.right);
                level_sum += cur.val;
            }
            if (level_sum > max){
                max = level_sum;
                max_lv = lv;
            }
            lv ++;
            
        }
        return max_lv;
    }
    
    
}

 

904. Fruit Into Baskets

In a row of trees, the i-th tree produces fruit with type tree[i].

You start at any tree of your choice, then repeatedly perform the following steps:

  1. Add one piece of fruit from this tree to your baskets.  If you cannot, stop.
  2. Move to the next tree to the right of the current tree.  If there is no tree to the right, stop.

Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then step 2, then back to step 1, then step 2, and so on until you stop.

You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only carry one type of fruit each.

What is the total amount of fruit you can collect with this procedure?

 

Example 1:

Input:

[1,2,1]

Output:

3

Explanation:

We can collect [1,2,1].

Example 2:

Input:

[0,1,2,2]

Output:

3

Explanation:

We can collect [1,2,2].
If we started at the first tree, we would only collect [0, 1].

Example 3:

Input:

[1,2,3,2,2]

Output:

4

Explanation:

We can collect [2,3,2,2].
If we started at the first tree, we would only collect [1, 2].

Example 4:

Input:

[3,3,3,1,2,1,1,2,3,3,4]

Output:

5

Explanation:

We can collect [1,2,1,1,2].
If we started at the first tree or the eighth tree, we would only collect 4 fruits.

 

Note:

  1. 1 <= tree.length <= 40000
  2. 0 <= tree[i] < tree.length

First Draft.

Code is accepted, but the quality is a JOKE.

class Solution {
    public int totalFruit(int[] tree) {
        
        if (tree.length <= 2){
            return tree.length;
        }
        
        int max = 2;
        int cur_max = 2;
        
        int a = tree[0];
        int b = tree[1];
        
        int a_last_index = 0;
        Integer b_last_index = null;
        
        boolean a_is_eldest = true;
        
        // get the second <Unique> number
        for(int i = 1; i < tree.length; i ++){
            if (tree[i] != a){
                b = tree[i];
                b_last_index = i;
                break;
            } else {
                // And we have to update last index of a as well
                cur_max ++;
                a_last_index = i;
                a_is_eldest = false;
            }
        }
        // update max here
        max = Math.max(max, cur_max);
        
        // if only single unique number in the array...
        if (b_last_index == null){
            return tree.length;
        }
        
        
        // Scan from the right of the second unique number
        for(int i = b_last_index+1; i < tree.length; i ++){
            int cur = tree[i];
            
            if(cur == a){

                cur_max ++;
                a_last_index = i;
                a_is_eldest = false;

            } else if (cur == b){

                cur_max ++;
                b_last_index = i;
                a_is_eldest = true;

            } else {

                // Third unique number appeared!
                // Remove eldest, and reduce current max to the last occurance of the number to be removed.
                if(a_is_eldest){
                    cur_max = i - a_last_index;
                    a = cur;
                    a_last_index = i;
                    a_is_eldest = false;
                } else {
                    cur_max = i - b_last_index;
                    b = cur;
                    b_last_index = i;
                    a_is_eldest = true;
                }
            }
            max = Math.max(max, cur_max);
        }
        return max;
    }
}

 

Code after refactoring:

class Solution {
    public int totalFruit(int[] tree) {
        
        if (tree.length <= 2){
            return tree.length;
        }
        
        int max = 2;
        int cur_max = 1;
        
        int a = tree[0];
        int a_last_index = 0;
        
        Integer b = null;
        Integer b_last_index = null;
        
        boolean a_is_eldest = true;
    
        
        for(int i = 1; i < tree.length; i ++){
            int cur = tree[i];
            
            if(cur == a){
                cur_max ++;
                a_last_index = i;
                a_is_eldest = false;
                
            } else if (b == null || cur == b) {
                
                if(b == null){
                    b = cur;
                }
                cur_max ++;
                b_last_index = i;
                a_is_eldest = true;
                
            } else {

                if(a_is_eldest){
                    cur_max = i - a_last_index;
                    a = cur;
                    a_last_index = i;
                    a_is_eldest = false;
                } else {
                    cur_max = i - b_last_index;
                    b = cur;
                    b_last_index = i;
                    a_is_eldest = true;
                }

            }
            max = Math.max(max, cur_max);
        }
        return max;
    }
}

 

There could be more things for refactoring, putting that aside, can we use any data structure?

Maybe LinkedHashMap<Type, LastSeenIndex> in access order mode?  it’s an overkill for ‘collecting two types’,  but could be useful for 3 or more types.

 

Starting by copy & paste from LRUCache. I added a variable to save the value of the most recent removed entry. The value of it is updated before the eldest entry is removed.

 

The modified LRUCache

class LRUCache extends LinkedHashMap<Integer, Integer>{
    private int capacity;

    // Save the latest index of the recent removed item.
    int index_removed = 0;
    
    public LRUCache(int capacity) {
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }

    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    public void put(int key, int value) {
        super.put(key, value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {

        // If the eldest has to be removed, save it's value (most recent index)
        if(size() > capacity){
            index_removed = eldest.getValue();
        }

        return size() > capacity; 
    }
}

 

Then, update the main function… and combine them

 

class Solution {

    public static final int TYPES_ALLOWED = 2;
 
    public int totalFruit(int[] tree) {
        
        if (tree.length <= TYPES_ALLOWED){
            return tree.length;
        }
        
        int cur_max = 1;
        int max = 1;
        
        // For a follow-up of more than 2 types is allowed.. just change the number here
        LRUCache map = new LRUCache(TYPES_ALLOWED);
    
        map.put(tree[0], 0);
        
        for(int i = 1; i < tree.length; i ++){
            int cur = tree[i];
            if (map.get(cur) != -1 || map.size() < 2){
                cur_max ++;
                map.put(cur, i);
            } else {
                map.put(cur, i);
                cur_max = i - map.index_removed;
            }
            
            max = Math.max(max, cur_max);
            
        }
        return max;
    }
}

class LRUCache extends LinkedHashMap<Integer, Integer>{
    private int capacity;
    int index_removed = 0;
    
    public LRUCache(int capacity) {
        super(capacity, 0.75F, true);
        this.capacity = capacity;
    }

    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    public void put(int key, int value) {
        super.put(key, value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        if(size() > capacity){
            index_removed = eldest.getValue();
        }
        return size() > capacity; 
    }
}

Time complexity. O(n). basically going through all elements once (n),  times LRUCache O(1).

This is basically a sliding window solution, while the Map is used for maintaining the valid window status.

Well, we can also use other Collections, giving the accepted types is two. The search and insertion time have to be counted after the number of accepted types is increased. So a Hash* will have a better performance.

 

Can we use a LinkedHashSet? Yes, then giving the type to be removed, find the closest index before the current index.

 

973. K Closest Points to Origin

We have a list of points on the plane.  Find the K closest points to the origin (0, 0).

(Here, the distance between two points on a plane is the Euclidean distance.)

You may return the answer in any order.  The answer is guaranteed to be unique (except for the order that it is in.)

 

Example 1:

Input:

points = [[1,3],[-2,2]], K = 1

Output:

[[-2,2]]

Explanation:

The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]].

Example 2:

Input:

points = [[3,3],[5,-1],[-2,4]], K = 2

Output:

[[3,3],[-2,4]]
(The answer [[-2,4],[3,3]] would also be accepted.)

 

Note:

  1. 1 <= K <= points.length <= 10000
  2. -10000 < points[i][0] < 10000
  3. -10000 < points[i][1] < 10000
A acceptable but definitely no the best solution….
In PHP:
  1. a ** b means power (a,b)
  2.  <=>, the spaceship operator,  used by ‘comparator’
    1. if left < right return -1
    2. if left > right return 1
    3. if left == right return 0
class Solution {

    /**
     * @param Integer[][] $points
     * @param Integer $K
     * @return Integer[][]
     */
    function kClosest($points, $K) {
        usort($points, function ($a, $b){
            return ($a[0]**2 + $a[1]**2) <=> ($b[0]**2 + $b[1]**2);
        });
        
        $result = [];
        $i = 0;
        foreach($points as $p){
            if($i >= $K){
                break;   
            }
            $result[] = $p;
            $i ++;
    
        }
        return $result;
    }
}