Thursday, March 27, 2025

513. Find Bottom Left Tree Value (Medium)

Given the root of a binary tree, return the leftmost value in the last row of the tree.

 

Example 1:

Input: root = [2,1,3]
Output: 1

Example 2:

Input: root = [1,2,3,4,null,5,6,null,null,7]
Output: 7

 

Constraints:

  • The number of nodes in the tree is in the range [1, 104].
  • -231 <= Node.val <= 231 - 1

A:

递归, 找出高度,然后对比看看左子树的是不是这个高度。 

如果是,则只需要看左子树。否则看右子树

/**
* 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:
int findBottomLeftValue(TreeNode* root) {
return helper(root, getHeight(root));
}
private:
int helper(TreeNode* root, int height){
if(height == 1)
return root->val;
int leftHeight = getHeight(root->left);
if(leftHeight == height -1){
return helper(root->left, height-1);
}else{
return helper(root->right, height-1);
}
}
int getHeight(TreeNode* root){
if(!root)
return 0;
return 1 + max(getHeight(root->left), getHeight(root->right));
}
};

但是上面的解法time 效率不好

************下面是 迭代解法。 beat 100%***************

class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
vector<TreeNode*> V{root};
int idx = 0;
while(idx < V.size()){
if(V[idx]->right){
V.push_back(V[idx]->right);
}
if(V[idx]->left){
V.push_back(V[idx]->left);
}
idx++;
}
return V.back()->val;
}
};


 

Tuesday, March 25, 2025

901. Online Stock Span !!!!!!!!!!

 Design an algorithm that collects daily price quotes for some stock and returns the span of that stock's price for the current day.

The span of the stock's price in one day is the maximum number of consecutive days (starting from that day and going backward) for which the stock price was less than or equal to the price of that day.

  • For example, if the prices of the stock in the last four days is [7,2,1,2] and the price of the stock today is 2, then the span of today is 4 because starting from today, the price of the stock was less than or equal 2 for 4 consecutive days.
  • Also, if the prices of the stock in the last four days is [7,34,1,2] and the price of the stock today is 8, then the span of today is 3 because starting from today, the price of the stock was less than or equal 8 for 3 consecutive days.

Implement the StockSpanner class:

  • StockSpanner() Initializes the object of the class.
  • int next(int price) Returns the span of the stock's price given that today's price is price.

 

Example 1:

Input
["StockSpanner", "next", "next", "next", "next", "next", "next", "next"]
[[], [100], [80], [60], [70], [60], [75], [85]]
Output
[null, 1, 1, 1, 2, 1, 4, 6]

Explanation
StockSpanner stockSpanner = new StockSpanner();
stockSpanner.next(100); // return 1
stockSpanner.next(80);  // return 1
stockSpanner.next(60);  // return 1
stockSpanner.next(70);  // return 2
stockSpanner.next(60);  // return 1
stockSpanner.next(75);  // return 4, because the last 4 prices (including today's price of 75) were less than or equal to today's price.
stockSpanner.next(85);  // return 6

 

Constraints:

  • 1 <= price <= 105
  • At most 104 calls will be made to next.

A:
不能光靠脑子想。
还是要用手画一下。就想出来了。 
思路是这样的:
按照给出的例子:  画了一下,发现stack🀄️ , 必须保存最大的。  不然来了一个新的值, 不能只和最小的比较

但是,如果来了一个大的,那么它前面的小的,就都没有必要保留了。aka,都可以换成他的位置

然后就一下子想出来了。  

还是要画个草图,各种情况都想一下, 就能决定结构。 最终发现还是比较简单的。  
然而,前后花了我最深2,3个小时,如果再加上由此而浪费的时间,就更是太多了

class StockSpanner {
public:
StockSpanner() {
}
int next(int price) {
int preDay = ++nDays;
// first add to stack. then return
while( ! S.empty() && S.top().first <= price){
preDay = S.top().second;
S.pop();
}
S.push({price, preDay});
return nDays - preDay + 1;
}
private:
stack<pair<int,int>> S; // stack, smaller value on higher position. (smallest on top)
int nDays = 0;
};

/**
* Your StockSpanner object will be instantiated and called as such:
* StockSpanner* obj = new StockSpanner();
* int param_1 = obj->next(price);
*/









Sunday, March 23, 2025

636. Exclusive Time of Functions ---Medium !!!!!! 自己对定义理解不清楚

 On a single-threaded CPU, we execute a program containing n functions. Each function has a unique ID between 0 and n-1.

Function calls are stored in a call stack: when a function call starts, its ID is pushed onto the stack, and when a function call ends, its ID is popped off the stack. The function whose ID is at the top of the stack is the current function being executed. Each time a function starts or ends, we write a log with the ID, whether it started or ended, and the timestamp.

You are given a list logs, where logs[i] represents the ith log message formatted as a string "{function_id}:{"start" | "end"}:{timestamp}". For example, "0:start:3" means a function call with function ID 0 started at the beginning of timestamp 3, and "1:end:2" means a function call with function ID 1 ended at the end of timestamp 2. Note that a function can be called multiple times, possibly recursively.

A function's exclusive time is the sum of execution times for all function calls in the program. For example, if a function is called twice, one call executing for 2 time units and another call executing for 1 time unit, the exclusive time is 2 + 1 = 3.

Return the exclusive time of each function in an array, where the value at the ith index represents the exclusive time for the function with ID i.

 

Example 1:

Input: n = 2, logs = ["0:start:0","1:start:2","1:end:5","0:end:6"]
Output: [3,4]
Explanation:
Function 0 starts at the beginning of time 0, then it executes 2 for units of time and reaches the end of time 1.
Function 1 starts at the beginning of time 2, executes for 4 units of time, and ends at the end of time 5.
Function 0 resumes execution at the beginning of time 6 and executes for 1 unit of time.
So function 0 spends 2 + 1 = 3 units of total time executing, and function 1 spends 4 units of total time executing.

Example 2:

Input: n = 1, logs = ["0:start:0","0:start:2","0:end:5","0:start:6","0:end:6","0:end:7"]
Output: [8]
Explanation:
Function 0 starts at the beginning of time 0, executes for 2 units of time, and recursively calls itself.
Function 0 (recursive call) starts at the beginning of time 2 and executes for 4 units of time.
Function 0 (initial call) resumes execution then immediately calls itself again.
Function 0 (2nd recursive call) starts at the beginning of time 6 and executes for 1 unit of time.
Function 0 (initial call) resumes execution at the beginning of time 7 and executes for 1 unit of time.
So function 0 spends 2 + 4 + 1 + 1 = 8 units of total time executing.

Example 3:

Input: n = 2, logs = ["0:start:0","0:start:2","0:end:5","1:start:6","1:end:6","0:end:7"]
Output: [7,1]
Explanation:
Function 0 starts at the beginning of time 0, executes for 2 units of time, and recursively calls itself.
Function 0 (recursive call) starts at the beginning of time 2 and executes for 4 units of time.
Function 0 (initial call) resumes execution then immediately calls function 1.
Function 1 starts at the beginning of time 6, executes 1 unit of time, and ends at the end of time 6.
Function 0 resumes execution at the beginning of time 6 and executes for 2 units of time.
So function 0 spends 2 + 4 + 1 = 7 units of total time executing, and function 1 spends 1 unit of total time executing.

 

Constraints:

  • 1 <= n <= 100
  • 1 <= logs.length <= 500
  • 0 <= function_id < n
  • 0 <= timestamp <= 109
  • No two start events will happen at the same timestamp.
  • No two end events will happen at the same timestamp.
  • Each function has an "end" log for each "start" log.
A:

下面是自己的理解:但是是错误的。  原因在代码下方
class Solution {
public:
vector<int> exclusiveTime(int n, vector<string>& logs) {
vector<int> V(n,0);
// [pre, cur]=[start ,start], we can calculate first,
// [start, end] // its a pair ,thus we calculate end
// [end, end] // we need calculate end
// [end, start] we calculate nothing. NOTE: there might be some gap in between,
Event pre = {1,false, 0}, cur = {0, false,0};// does not matter what the initial value
for(int i =0; i< logs.size(); i++){
pre = cur;
helper(logs[i], cur);
if(i != 0){
if(!cur.isStart){// it is end
V[cur.id] += cur.time - pre.time + (pre.isStart? 1: 0) ;
}else if(pre.isStart){ //now cur is start, [start ,start], calculate first
V[pre.id] = cur.time - pre.time;
}
}
}
return V;
}
private:
struct Event {
int id;
bool isStart;
int time;
};
void helper(const string &log, Event &evt){
int posColon1 = log.find(':', 0);
evt.id = stoi(log.substr(0,posColon1));
evt.isStart = log[posColon1+1] == 's';
int posColon2 = log.find(':', posColon1+1);
evt.time = stoi(log.substr(posColon2+1, log.size() - posColon2-1));
}
};

原因是, 如果stack里有,  那么会继续执行,  而中途又被打断。
所以,不能只看最近2个的情况。
class Solution {
public:
vector<int> exclusiveTime(int n, vector<string>& logs) {
// [pre, cur]=[start ,start], we can calculate first,
// [start, end] // its a pair ,thus we calculate end
// [end, end] // we need calculate end
// [end, start] we calculate nothing. NOTE: there might be some gap in
// between,
vector<int> V(n, 0);
stack<Event> S; // save only the ones that is running on stack
for (int i = 0; i < logs.size(); i++) {
Event cur = helper(logs[i]);
if (!cur.isStart) {
V[cur.id] += cur.time - S.top().time + 1;
S.pop();
if (!S.empty()) {
S.top().time = cur.time + 1; // task on top will resume
}
} else { // cur.isStart == true
if (!S.empty() && S.top().isStart) {
V[S.top().id] += cur.time - S.top().time;
}
S.push(cur);
}
}
return V;
}

private:
struct Event {
int id;
bool isStart;
int time;
};
Event helper(const string& log) {
int posColon1 = log.find(':', 0);
int id = stoi(log.substr(0, posColon1));
bool isStart = log[posColon1 + 1] == 's';
int posColon2 = log.find(':', posColon1 + 1);
int time = stoi(log.substr(posColon2 + 1, log.size() - posColon2 - 1));
Event evt = {id, isStart, time};
return evt;
}
};