Tuesday, November 3, 2020

1492. The kth Factor of n -------M

Given two positive integers n and k.

A factor of an integer n is defined as an integer i where n % i == 0.

Consider a list of all factors of n sorted in ascending order, return the kth factor in this list or return -1 if n has less than k factors.

 

Example 1:

Input: n = 12, k = 3
Output: 3
Explanation: Factors list is [1, 2, 3, 4, 6, 12], the 3rd factor is 3.

Example 2:

Input: n = 7, k = 2
Output: 7
Explanation: Factors list is [1, 7], the 2nd factor is 7.

Example 3:

Input: n = 4, k = 4
Output: -1
Explanation: Factors list is [1, 2, 4], there is only 3 factors. We should return -1.

Example 4:

Input: n = 1, k = 1
Output: 1
Explanation: Factors list is [1], the 1st factor is 1.

Example 5:

Input: n = 1000, k = 3
Output: 4
Explanation: Factors list is [1, 2, 4, 5, 8, 10, 20, 25, 40, 50, 100, 125, 200, 250, 500, 1000].

 

Constraints:

  • 1 <= k <= n <= 1000

 A:

不知道考什么。 一个个试就pass了

class Solution {
public:
    int kthFactor(int n, int k) {
        int c = 0;
        for(int i =1;i<=n;i++){
            if(n % i ==0){
                ++c;
                if(c==k){
                    return i;
                }
            }
        }
        return -1;
    }
};




1415. The k-th Lexicographical String of All Happy Strings of Length n -----M

 A happy string is a string that:

  • consists only of letters of the set ['a', 'b', 'c'].
  • s[i] != s[i + 1] for all values of i from 1 to s.length - 1 (string is 1-indexed).

For example, strings "abc", "ac", "b" and "abcbabcbcb" are all happy strings and strings "aa", "baa" and "ababbc" are not happy strings.

Given two integers n and k, consider a list of all happy strings of length n sorted in lexicographical order.

Return the kth string of this list or return an empty string if there are less than k happy strings of length n.

 

Example 1:

Input: n = 1, k = 3
Output: "c"
Explanation: The list ["a", "b", "c"] contains all happy strings of length 1. The third string is "c".

Example 2:

Input: n = 1, k = 4
Output: ""
Explanation: There are only 3 happy strings of length 1.

Example 3:

Input: n = 3, k = 9
Output: "cab"
Explanation: There are 12 different happy string of length 3 ["aba", "abc", "aca", "acb", "bab", "bac", "bca", "bcb", "cab", "cac", "cba", "cbc"]. You will find the 9th string = "cab"

Example 4:

Input: n = 2, k = 7
Output: ""

Example 5:

Input: n = 10, k = 100
Output: "abacbabacb"

 

Constraints:

  • 1 <= n <= 10
  • 1 <= k <= 100

A:

就是实现题。  一个个数呗  (唯一可能tricky的地方就是 需要k--, 来变成 0 based

class Solution {
public:
    string getHappyString(int n, int k) {
        vector<int> c(n+1,1);
        for(int j = n-1; j>=0; j--){
            c[j] = (j==0?3:2) * c[j+1];
        }
        string res = "";
        k--;// zero index
        if(c[0] <= k){ // since we have k-- above
            return res;
        }
        for(int i =0;i<n;i++){
            // find how many next iter count
            int count = k/c[i+1]; // count can be 0, 1,2
            if(i == 0){
                res+= ('a'+count);
            }else{
                res += getNext(res.back(), count);
            }
            k -= count * c[i+1];
        }
        return res;
    }
private:
    char getNext(char pre, int count){ // count can only be 0 or 1
        if(pre == 'a'){
            return count==0? 'b' : 'c';
        }else if(pre == 'b'){
            return count==0? 'a' : 'c';
        }else{// if(pre == 'c'){
            return count==0? 'a' : 'b';
        }
    }
};




1471. The k Strongest Values in an Array ------M

 Given an array of integers arr and an integer k.

A value arr[i] is said to be stronger than a value arr[j] if |arr[i] - m| > |arr[j] - m| where m is the median of the array.
If |arr[i] - m| == |arr[j] - m|, then arr[i] is said to be stronger than arr[j] if arr[i] > arr[j].

Return a list of the strongest k values in the array. return the answer in any arbitrary order.

Median is the middle value in an ordered integer list. More formally, if the length of the list is n, the median is the element in position ((n - 1) / 2) in the sorted list (0-indexed).

  • For arr = [6, -3, 7, 2, 11]n = 5 and the median is obtained by sorting the array arr = [-3, 2, 6, 7, 11] and the median is arr[m] where m = ((5 - 1) / 2) = 2. The median is 6.
  • For arr = [-7, 22, 17, 3]n = 4 and the median is obtained by sorting the array arr = [-7, 3, 17, 22] and the median is arr[m] where m = ((4 - 1) / 2) = 1. The median is 3.

 

Example 1:

Input: arr = [1,2,3,4,5], k = 2
Output: [5,1]
Explanation: Median is 3, the elements of the array sorted by the strongest are [5,1,4,2,3]. The strongest 2 elements are [5, 1]. [1, 5] is also accepted answer.
Please note that although |5 - 3| == |1 - 3| but 5 is stronger than 1 because 5 > 1.

Example 2:

Input: arr = [1,1,3,5,5], k = 2
Output: [5,5]
Explanation: Median is 3, the elements of the array sorted by the strongest are [5,5,1,1,3]. The strongest 2 elements are [5, 5].

Example 3:

Input: arr = [6,7,11,7,6,8], k = 5
Output: [11,8,6,6,7]
Explanation: Median is 7, the elements of the array sorted by the strongest are [11,8,6,6,7,7].
Any permutation of [11,8,6,6,7] is accepted.

Example 4:

Input: arr = [6,-3,7,2,11], k = 3
Output: [-3,11,2]

Example 5:

Input: arr = [-7,22,17,3], k = 2
Output: [22,17]

 

Constraints:

  • 1 <= arr.length <= 10^5
  • -10^5 <= arr[i] <= 10^5
  • 1 <= k <= arr.length


A:

就是排序,然后前后取

class Solution {
public:
    vector<int> getStrongest(vector<int>& arr, int k) {
        sort(arr.begin(), arr.end());//default is the assending order
        int n = arr.size();
        int median = arr[(n-1)/2];
        
        vector<int> res;
        int begin = 0, end = n-1;
        while(res.size()<k){
            if(abs(arr[begin] -median) > abs(arr[end] - median)  ){
                res.push_back(arr[begin++]);
            }else{ // if(abs(arr[begin] -median) < abs(arr[end] - median)  ){
                res.push_back(arr[end--]);
            }
        }
        return res;
    }
};


Wednesday, October 28, 2020

L 1135. Connecting Cities With Minimum Cost ----M ~~~~~练习MST的Kruskal实现

There are N cities numbered from 1 to N.

You are given connections, where each connections[i] = [city1, city2, cost] represents the cost to connect city1 and city2 together.  (A connection is bidirectional: connecting city1 and city2 is the same as connecting city2 and city1.)

Return the minimum cost so that for every pair of cities, there exists a path of connections (possibly of length 1) that connects those two cities together.  The cost is the sum of the connection costs used. If the task is impossible, return -1.

 

Example 1:

Input: N = 3, connections = [[1,2,5],[1,3,6],[2,3,1]]
Output: 6
Explanation: 
Choosing any 2 edges will connect all cities so we choose the minimum 2.

Example 2:

Input: N = 4, connections = [[1,2,3],[3,4,4]]
Output: -1
Explanation: 
There is no way to connect all cities even if all edges are used.

 

Note:

  1. 1 <= N <= 10000
  2. 1 <= connections.length <= 10000
  3. 1 <= connections[i][0], connections[i][1] <= N
  4. 0 <= connections[i][2] <= 10^5
  5. connections[i][0] != connections[i][1]

 A:

就是经典的minimum spanning tree,   用Prim   or   Kruskal 

但是没有用Union_by rank .而只是随机union了

class Solution {
public:
    int minimumCost(int N, vector<vector<int>>& connections) {
        sort(connections.begin(), connections.end(),
            [](const vector<int>& a, const vector<int>& b)
            {
                return a[2] < b[2];
            });
        // make set
        for (int i = 1; i <= N; i++) {
            parent[i] = i;
        }
        int res = 0;
        int edgeCount = 0;
        for (auto edge : connections) {
            int city1 = edge[0];
            int city2 = edge[1];
            if (find_set(city1) != find_set(city2)) {
                union_set(city1, city2); // merge their parent
                edgeCount++;
                res += edge[2]; // cost
            }
            if (edgeCount == N - 1) {
                return res;
            }
        }
        return -1;
    }
private:
    unordered_map<int, int> parent;
    int find_set(int city) {
        if (parent[city] != city) {
            parent[city] = find_set(parent[city]);
        }
        return parent[city];
    }
    void union_set(int city1, int city2) {
        parent[find_set(city1)] = parent[find_set(city2)];
    }
};


这个题,以前没有做过,需要多多熟悉


Tuesday, October 27, 2020

L 272. Closest Binary Search Tree Value II -----------H ~~~~~!!!!!!!!!

Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.

Note:

  • Given target value is a floating point.
  • You may assume k is always valid, that is: k ≤ total nodes.
  • You are guaranteed to have only one unique set of k values in the BST that are closest to the target.

Example:

Input: root = [4,2,5,1,3], target = 3.714286, and k = 2

    4
   / \
  2   5
 / \
1   3

Output: [4,3]

Follow up:

Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)? 

A:

首先想到都弄到一个数组里,然后全部排序。  然而不是optimal

思路是找到k个比他小的, 和k个比他大的。 然后前后两头儿检查 删除一个。
O( k + log N ) time,  O(k) space

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> closestKValues(TreeNode* root, double target, int k) {
        deque<int> res;
        // find up to k values, that smaller than(or equal to) target
        find_k_smallerEq(root, target, k, res);
        deque<int> resBigger;
        find_k_bigger(root, target, k, resBigger);
        for (auto v : resBigger) {
            res.push_back(v);
        }

        while (res.size() > k) {
            if (abs(res.front() - target) >= abs(res.back() - target)) {
                res.pop_front();
            }
            else {
                res.pop_back();
            }
        }
        return vector<int>(res.begin(), res.end());
    }
private:
    void find_k_smallerEq(TreeNode* root, double target, const int k, deque<int>& res) {
        if (not root || res.size() >= k)
            return;
        if (root->val > target) {
            find_k_smallerEq(root->left, target, k, res);
            return;
        }
        find_k_smallerEq(root->right, target, k, res);
        if (res.size() < k)
            res.push_front(root->val);
        find_k_smallerEq(root->left, target, k, res);
    }
    void find_k_bigger(TreeNode* root, double target, const int k, deque<int>& res) {
        if (not root || res.size() >= k) {
            return;
        }
        if (root->val <= target) {
            find_k_bigger(root->right, target, k, res);
            return;
        }
        find_k_bigger(root->left, target, k, res);
        if (res.size() < k)
            res.push_back(root->val);
        find_k_bigger(root->right, target, k, res);
    }
};


Faster than 95.75%的

Mistakes:

要注意root value不是先插入的


***********上面思路的简化版本***********




L 311. Sparse Matrix Multiplication ---------M

 Given two sparse matrices A and B, return the result of AB.

You may assume that A's column number is equal to B's row number.

Example:

Input:

A = [
  [ 1, 0, 0],
  [-1, 0, 3]
]

B = [
  [ 7, 0, 0 ],
  [ 0, 0, 0 ],
  [ 0, 0, 1 ]
]

Output:

     |  1 0 0 |   | 7 0 0 |   |  7 0 0 |
AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
                  | 0 0 1 |

 

Constraints:

  • 1 <= A.length, B.length <= 100
  • 1 <= A[i].length, B[i].length <= 100
  • -100 <= A[i][j], B[i][j] <= 100


A:

实现题

class Solution {
public:
    vector<vector<int>> multiply(vector<vector<int>>& A, vector<vector<int>>& B) {
        int m = A.size();
        if (m == 0) {
            return vector<vector<int>>();
        }
        int n = A[0].size();
        int k = B[0].size();
        vector<vector<int>> res(m, vector<int>(k, 0));
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < k; j++) {
                for (int t = 0; t < n; t++) {
                    res[i][j] += A[i][t] * B[t][j];
                }
            }
        }
        return res;
    }
};




L 379. Design Phone Directory ---------M

Design a Phone Directory which supports the following operations:

 

  1. get: Provide a number which is not assigned to anyone.
  2. check: Check if a number is available or not.
  3. release: Recycle or release a number.

 

Example:

// Init a phone directory containing a total of 3 numbers: 0, 1, and 2.
PhoneDirectory directory = new PhoneDirectory(3);

// It can return any available phone number. Here we assume it returns 0.
directory.get();

// Assume it returns 1.
directory.get();

// The number 2 is available, so return true.
directory.check(2);

// It returns 2, the only number that is left.
directory.get();

// The number 2 is no longer available, so return false.
directory.check(2);

// Release number 2 back to the pool.
directory.release(2);

// Number 2 is available again, return true.
directory.check(2);

 

Constraints:

  • 1 <= maxNumbers <= 10^4
  • 0 <= number < maxNumbers
  • The total number of call of the methods is between [0 - 20000]

 

A:

就是用一个 set 来保存所有的数据。

class PhoneDirectory {
public:
    /** Initialize your data structure here
        @param maxNumbers - The maximum numbers that can be stored in the phone directory. */
    PhoneDirectory(int maxNumbers) {
        for(int i =0;i<maxNumbers; i++){
            mySet.insert(i);
        }
    }
    
    /** Provide a number which is not assigned to anyone.
        @return - Return an available number. Return -1 if none is available. */
    int get() {
        if(mySet.empty()){
            return -1;
        }
        int res = *(mySet.begin());
        mySet.erase(res);
        return res;        
    }
    
    /** Check if a number is available or not. */
    bool check(int number) {
        return mySet.find(number) != mySet.end();
    }
    
    /** Recycle or release a number. */
    void release(int number) {
        mySet.insert(number);
    }
private:
    unordered_set<int> mySet;
};

/**
 * Your PhoneDirectory object will be instantiated and called as such:
 * PhoneDirectory* obj = new PhoneDirectory(maxNumbers);
 * int param_1 = obj->get();
 * bool param_2 = obj->check(number);
 * obj->release(number);
 */







1585. Check If String Is Transformable With Substring Sort Operations ------ H ~~~

 Given two strings s and t, you want to transform string s into string t using the following operation any number of times:

  • Choose a non-empty substring in s and sort it in-place so the characters are in ascending order.

For example, applying the operation on the underlined substring in "14234" results in "12344".

Return true if it is possible to transform string s into string t. Otherwise, return false.

substring is a contiguous sequence of characters within a string.

 

Example 1:

Input: s = "84532", t = "34852"
Output: true
Explanation: You can transform s into t using the following sort operations:
"84532" (from index 2 to 3) -> "84352"
"84352" (from index 0 to 2) -> "34852"

Example 2:

Input: s = "34521", t = "23415"
Output: true
Explanation: You can transform s into t using the following sort operations:
"34521" -> "23451"
"23451" -> "23415"

Example 3:

Input: s = "12345", t = "12435"
Output: false

Example 4:

Input: s = "1", t = "2"
Output: false

 

Constraints:

  • s.length == t.length
  • 1 <= s.length <= 105
  • s and t only contain digits from '0' to '9'.

A:

稍微试了几个, 找到了原理, 就是 每次找t中的下一个char , 然后在s中 查找, 在找到该char之前的所有的char,不能比他小,否则就 sort不过来。  


sol 1:  每次找到一个,  用类似bubble sort的方式 float up 

class Solution {
public:
    bool isTransformable(string s, string t) {
        int n = s.length();
        //idea: switch to make the first char, by switch one by one, to keep order
        for(int start =0; start < n; start++){
            int targetIndex = start;
            while(targetIndex < n && s[targetIndex] != t[start]){
                targetIndex++;
            }
            if(targetIndex >= n){
                return false;
            }
            // bubble sort to float up the target char
            for(int i =targetIndex; i> start;i--){
                if(s[i-1] < t[start]){  // make sure all can be floated up
                    return false;
                }
                s[i] = s[i-1];
            }
        }
        return true;
    }
};

逻辑是正确的。   然而LTE了。  上面太多的move操作,而且重复了。


现在,去掉重复move, 改用一个数组来flag一个char 是否visited了

class Solution {
public:
    bool isTransformable(string s, string t) {
        int n = s.length();
        vector<bool> visited(n, false);
        //idea: switch to make the first char, by switch one by one, to keep order
        int startS = 0;
        for(int it =0; it < n; it++){
            char targetChar = t[it];
            int is=startS;
            while(is< n && (visited[is] ||  s[is] > targetChar ) ){
                is++;
            }
            if(is >= n || s[is] != targetChar){
                return false;
            }
            visited[is] = true;
            while(startS < n && visited[startS]){// amortized time complexity is O(1)
                startS++;
            }
        }
        return true;
    }
};

我XXXXXXX ,竟然还    LTE

看了下结果, 是0--9 可能一个位置,有太多重复的了。看这个例子

所以,优化只能是第一个while


那么,我们用一个数组来记录每个char的位置, 这样就不用挨个查了。(最多查9个,所以还是O(1)的复杂度)


class Solution {
public:
    bool isTransformable(string s, string t) {
        int n = s.length();
        vector<vector<int>> Pos(10, vector<int>());
        for (int i = n - 1; i >= 0; i--) {
            Pos[s[i] - '0'].push_back(i);
        }
        for (int i = 0; i < n; i++) {
            int val = t[i] - '0';
            // check that no values smaller than val, is ahead of it.            
            if (Pos[val].empty()) {
                return false;
            }
            int valPos = Pos[val].back();
            for (int v = 0; v < val; v++) {
                if (!Pos[v].empty() && Pos[v].back() < valPos) {
                    return false;
                }
            }
            Pos[val].pop_back();
        }
        return true;
    }
}