为什么难度从2easy1medium突然就变成了2medium1hard,自闭自闭
1.最大宽度坡(中等)
题目链接:https://leetcode-cn.com/problems/maximum-width-ramp/
差点就死在第一题手上了…
最开始的思路是暴力+剪枝,剪枝的思路就是对应每一个起始点得到的最长距离,作为下一次比较的初始距离。比如样例1里面先对起始点6求最大结果,为2(2 - 0),下一次对起始点0求解时,直接从 0 + 2 开始往后遍历。
然后就TLE了一个50000个数据的递减自闭样例,所以重新想算法。
尝试把数组按值排序,然后根据下标找最大差值:
A : [0, 1, 2, 5, 6, 8]
index : [1, 4, 3, 5, 0, 2]
这里找到的最大差值就是 5 - 1 = 4,但是不是全局最大值和最小值的差值,而是将下标数组 index 分为前后两部分,前半部分的最小值和后半部分的最大值的差值是我们需要的,所以前缀最小值数组,后缀最大值数组,找相邻下标的最大差值即可。同样以样例1为例,最值数组如下(注意是对index数组做):
minimum::[1, 1, 1, 1, 0, 0]
maximum:[5, 5, 5, 5, 2, 2]
代码如下:
class Solution {
public:
struct Node {
int val;
int index;
}a[50005];
static bool cmp(Node a, Node b) {
if(a.val == b.val) {
return a.index < b.index;
}
return a.val < b.val;
}
int maxWidthRamp(vector<int>& A) {
for(int i = 0; i < A.size(); i++) {
a[i].val = A[i];
a[i].index = i;
}
int len = A.size();
sort(a, a + len, cmp);
vector<int> minimum(len, 0);
vector<int> maximum(len, 0);
minimum[0] = a[0].index;
maximum[len - 1] = a[len - 1].index;
for(int i = 1; i < len; i++) {
minimum[i] = min(minimum[i - 1], a[i].index);
}
for(int i = len - 2; i >= 0; i--) {
maximum[i] = max(maximum[i + 1], a[i].index);
}
int res = 0;
for(int i = 0; i < len - 1; i++) {
res = max(res, maximum[i + 1] - minimum[i]);
}
return res;
}
};
2.具有所有最深结点的最小子树(中等)
题目链接:https://leetcode-cn.com/problems/smallest-subtree-with-all-the-deepest-nodes/
对树的掌握还是有点差,所以代码很乱,思路是dfs求层数并记录到数组floor中,每个节点根据其值(因为题目说了唯一)记录父节点及其左右(father[i][0]记录父节点值,father[i][1]记录是父节点的左子树还是右子树)。然后对所有的最大深度节点逐个求其父节点并放到数组cnt中,直到cnt中只有一个节点,就是要求的节点,再根据其father数组逆推路径,最后从根节点按照路径找到该TreeNode结点。
代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int father[505][2];
int floor[505];
int mxval = 0;
int mxfloor = 0;
void dfs(TreeNode* root, int level) {
floor[root->val] = level;
//printf("floor[%d] = %d\n", root->val, level);
mxval = max(mxval, root->val);
if(root->left != NULL) {
dfs(root->left, level + 1);
father[root->left->val][0] = root->val;
father[root->left->val][1] = 0;
}
if(root->right != NULL) {
dfs(root->right, level + 1);
father[root->right->val][0] = root->val;
father[root->right->val][1] = 1;
}
}
TreeNode* subtreeWithAllDeepest(TreeNode* root) {
if(root == NULL) {
return root;
}
father[root->val][0] = -1;
mxval = max(mxval, root->val);
if(root->left == NULL && root->right == NULL) {
return root;
}
if(root->left != NULL) {
dfs(root->left, 1);
father[root->left->val][0] = root->val;
father[root->left->val][1] = 0;
}
if(root->right != NULL) {
dfs(root->right, 1);
father[root->right->val][0] = root->val;
father[root->right->val][1] = 1;
}
for(int i = 0; i <= mxval; i++) {
//printf("floor[%d] = %d\n", i, floor[i]);
mxfloor = max(mxfloor, floor[i]);
}
cout << "max_floor = " << mxfloor << endl;
queue<int> q;
for(int i = 0; i <= mxval; i++) {
if(floor[i] == mxfloor) {
q.push(i);
}
}
int ans = 0;
if(q.size() == 1) {
ans = q.front();
} else {
int cnt[505] = {0};
int count = 0;
while(1) {
while(!q.empty()) {
if(!cnt[father[q.front()][0]]) {
cnt[father[q.front()][0]] = 1;
count++;
}
q.pop();
}
if(count == 1) {
break;
}
for(int i = 0; i <= mxval; i++) {
if(cnt[i] == 1) {
q.push(i);
}
}
fill(cnt, cnt + 505, 0);
count = 0;
}
for(int i = 0; i <= mxval; i++) {
if(cnt[i] == 1) {
cout << "find! value = " << i << endl;
ans = i;
break;
}
}
}
printf("ans = %d\n", ans);
stack<int> s;
while(father[ans][0] != -1) {
s.push(father[ans][1]);
ans = father[ans][0];
}
while(!s.empty()) {
if(s.top() == 0) {
root = root->left;
} else {
root = root->right;
}
s.pop();
}
return root;
}
};
看了题解之后emmmmm,照猫画虎来一遍吧:
第一遍dfs求最大深度
第二遍answer(另一个深搜函数)返回最终结点
answer的原理:
最底层遇到最大深度结点则返回该节点,否则返回NULL;
中间层分别调用左右子树的answer结果,若左右子树结果均不为NULL,说明都含最大深度,则返回当前节点,否则哪个子树结果不为NULL就返回该子树结果。若两子树结果均为NULL说明后代无最大深度节点,返回NULL;
代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
map<TreeNode*, int> depth;
int max_depth = -1;
TreeNode* subtreeWithAllDeepest(TreeNode* root) {
depth[NULL] = -1;
dfs(root, NULL);
return answer(root);
}
void dfs(TreeNode* root, TreeNode* parent) {
if(root != NULL) {
depth[root] = depth[parent] + 1;
max_depth = max(max_depth, depth[root]);
dfs(root->left, root);
dfs(root->right, root);
}
}
TreeNode* answer(TreeNode* root) {
if(root == NULL || depth[root] == max_depth) {
return root;
}
TreeNode* L = answer(root->left);
TreeNode* R = answer(root->right);
if(L != NULL && R != NULL) {
return root;
}
if(L != NULL) {
return L;
}
if(R != NULL) {
return R;
}
return NULL;
}
};
3.猜猜这个单词(困难)
题目链接:https://leetcode-cn.com/problems/guess-the-word/
开始开心的二分,然后发现毫无规律,最后也没出来。
题解看不懂,等哪天看懂了再补全,告辞!