Skip to content

Commit 3ff83ef

Browse files
committed
Add jzo 60-66
1 parent 5e0fabd commit 3ff83ef

7 files changed

+393
-0
lines changed
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
https://www.nowcoder.com/practice/445c44d982d04483b04a54f298796288
3+
4+
题目描述
5+
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
6+
*/
7+
8+
#include <queue>
9+
#include <tuple>
10+
#include <vector>
11+
using namespace std;
12+
13+
// struct TreeNode {
14+
// int val;
15+
// struct TreeNode *left;
16+
// struct TreeNode *right;
17+
// TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
18+
// };
19+
20+
class Solution {
21+
public:
22+
vector<vector<int>> Print(TreeNode *pRoot) {
23+
vector<vector<int>> res;
24+
if (!pRoot) {
25+
return res;
26+
}
27+
TreeNode *p;
28+
vector<int> row;
29+
queue<tuple<TreeNode *, int>> q;
30+
q.push(make_tuple(pRoot, 0));
31+
int curLevel = 0, level;
32+
while (!q.empty()) {
33+
tie(p, level) = q.front();
34+
q.pop();
35+
if (level > curLevel) {
36+
curLevel = level;
37+
res.push_back(row);
38+
row.clear();
39+
}
40+
row.push_back(p->val);
41+
if (p->left) {
42+
q.push(make_tuple(p->left, level + 1));
43+
}
44+
if (p->right) {
45+
q.push(make_tuple(p->right, level + 1));
46+
}
47+
}
48+
res.push_back(row);
49+
return res;
50+
}
51+
};

nowcoder/jzo.61.SerializeTree.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
https://www.nowcoder.com/practice/cf7e25aa97c04cc1a68c8f040e71fb84
3+
4+
题目描述
5+
请实现两个函数,分别用来序列化和反序列化二叉树
6+
7+
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保
8+
存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过某种符号表示
9+
空节点(#),以 ! 表示一个结点值的结束(value!)。
10+
11+
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
12+
*/
13+
14+
#include <cstdio>
15+
#include <cstring>
16+
#include <stack>
17+
#include <string>
18+
19+
using namespace std;
20+
21+
// struct TreeNode {
22+
// int val;
23+
// struct TreeNode *left;
24+
// struct TreeNode *right;
25+
// TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
26+
// };
27+
28+
class Solution {
29+
public:
30+
char *Serialize(TreeNode *root) {
31+
string res = "";
32+
stack<TreeNode *> st;
33+
st.push(root);
34+
// use stack to perform preorder traverse
35+
while (!st.empty()) {
36+
TreeNode *node = st.top();
37+
st.pop();
38+
if (!node) {
39+
res += '#';
40+
continue;
41+
}
42+
res += to_string(node->val) + '!';
43+
st.push(node->right);
44+
st.push(node->left);
45+
}
46+
char *cres = new char[res.length() + 1];
47+
strcpy(cres, res.c_str());
48+
return cres;
49+
}
50+
51+
TreeNode *MyDeserialize(char *str, int &pos) {
52+
if (str == nullptr || strlen(str + pos) == 0) {
53+
return nullptr;
54+
};
55+
if (str[pos] == '#') {
56+
pos += 1;
57+
return nullptr;
58+
}
59+
int val = atoi(str + pos);
60+
TreeNode *node = new TreeNode(val);
61+
pos = strchr(str + pos, '!') - str + 1;
62+
node->left = MyDeserialize(str, pos);
63+
node->right = MyDeserialize(str, pos);
64+
return node;
65+
}
66+
67+
TreeNode *Deserialize(char *str) {
68+
int pos = 0;
69+
return MyDeserialize(str, pos);
70+
}
71+
};
72+
73+
// int main() {
74+
// char stree[100] = "1!2!#3!###";
75+
// Solution solu;
76+
// TreeNode *root = solu.Deserialize(stree);
77+
// puts(solu.Serialize(root));
78+
// return 0;
79+
// }

nowcoder/jzo.62.KSmallestNode.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
https://www.nowcoder.com/practice/ef068f602dde4d28aab2b210e859150a
3+
4+
题目描述
5+
给定一棵二叉搜索树,请找出其中的第k小的结点。例如,(5,3,7,2,4,6,8)中,
6+
按结点数值大小顺序第三小结点的值为4。
7+
*/
8+
9+
#include <stack>
10+
11+
using namespace std;
12+
13+
// struct TreeNode {
14+
// int val;
15+
// struct TreeNode *left;
16+
// struct TreeNode *right;
17+
// TreeNode(int x) : val(x), left(NULL), right(NULL) {}
18+
// };
19+
20+
class Solution {
21+
public:
22+
TreeNode *KthNode(TreeNode *pRoot, int k) {
23+
stack<TreeNode *> st;
24+
TreeNode *p = pRoot;
25+
// use stack to perform in-order traverse
26+
while (p || !st.empty()) {
27+
// only node without a left child can be poped
28+
while (p) {
29+
st.push(p);
30+
p = p->left;
31+
}
32+
p = st.top();
33+
st.pop();
34+
35+
--k;
36+
if (k == 0) {
37+
return p;
38+
}
39+
p = p->right;
40+
}
41+
42+
return nullptr;
43+
}
44+
};

nowcoder/jzo.63.MedianOfStream.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
https://www.nowcoder.com/practice/9be0172896bd43948f8a32fb954e1be1
3+
4+
题目描述
5+
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流
6+
中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()
7+
方法获取当前读取数据的中位数。
8+
*/
9+
10+
#include <queue>
11+
using namespace std;
12+
13+
class Solution {
14+
public:
15+
priority_queue<int> left; // maximum at top
16+
priority_queue<int, vector<int>, greater<int>> right; // minimum at top
17+
18+
void Insert(int num) {
19+
if (left.empty() || num <= left.top()) {
20+
left.push(num);
21+
} else {
22+
right.push(num);
23+
}
24+
if (left.size() > right.size() + 1) {
25+
right.push(left.top());
26+
left.pop();
27+
} else if (left.size() < right.size()) {
28+
left.push(right.top());
29+
right.pop();
30+
}
31+
}
32+
33+
double GetMedian() {
34+
if (left.size() > right.size()) {
35+
return left.top();
36+
}
37+
return (left.top() + right.top()) / 2.0;
38+
}
39+
};

nowcoder/jzo.64.MaxInWindows.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788
3+
4+
题目描述
5+
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,
6+
那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5};
7+
针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2, 3,4],2,6,2,5,1},
8+
{2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1},
9+
{2,3,4,2,[6,2,5], 1}, {2,3,4,2,6,[2,5,1]}。
10+
11+
单调队列: https://oi-wiki.org/ds/monotonous-queue
12+
*/
13+
14+
#include <deque>
15+
#include <iostream>
16+
#include <vector>
17+
using namespace std;
18+
19+
class Solution {
20+
public:
21+
vector<int> maxInWindows(const vector<int> &num, unsigned int size) {
22+
vector<int> res;
23+
if (size == 0) {
24+
return res;
25+
}
26+
27+
deque<int> mono_queue; // decreasing monotonous queue
28+
for (unsigned i = 0; i < num.size(); ++i) {
29+
// keep nums decreasing in queue
30+
while (!mono_queue.empty() && num[i] >= num[mono_queue.back()]) {
31+
mono_queue.pop_back();
32+
}
33+
mono_queue.push_back(i);
34+
if (i + 1 >= size) {
35+
// front num of queue is out of window
36+
if (i - mono_queue.front() >= size) {
37+
mono_queue.pop_front();
38+
}
39+
res.push_back(num[mono_queue.front()]);
40+
}
41+
}
42+
return res;
43+
}
44+
};
45+
46+
// int main() {
47+
// unsigned int size = 3u;
48+
// auto res = Solution().maxInWindows({2, 3, 4, 2, 6, 2, 5, 1}, size);
49+
// for (int x : res) {
50+
// cout << x << ' ';
51+
// }
52+
// cout << endl;
53+
// return 0;
54+
// }

nowcoder/jzo.65.MatrixPath.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
https://www.nowcoder.com/practice/c61c6999eecb4b8f88a98f66b273a3cc
3+
4+
题目描述
5+
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步
6+
可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
7+
例如 [a b c e; s f c s; a d e e]
8+
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字
9+
符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
10+
*/
11+
12+
#include <deque>
13+
#include <iostream>
14+
#include <vector>
15+
using namespace std;
16+
17+
int dx[] = {0, 0, -1, 1};
18+
int dy[] = {-1, 1, 0, 0};
19+
20+
class Solution {
21+
public:
22+
bool dfs(int i, int j, int &rows, int &cols, char *matrix, char *s) {
23+
if (!s[0]) {
24+
return true;
25+
}
26+
bool flag = false;
27+
char tmp = matrix[i * cols + j];
28+
matrix[i * cols + j] = 0;
29+
for (int d = 0; d < 4; ++d) {
30+
int r = i + dx[d];
31+
int c = j + dy[d];
32+
if (r >= 0 && r < rows && c >= 0 && c < cols &&
33+
matrix[r * cols + c] == s[0]) {
34+
flag = flag || dfs(r, c, rows, cols, matrix, s + 1);
35+
}
36+
}
37+
matrix[i * cols + j] = tmp;
38+
return flag;
39+
}
40+
41+
bool hasPath(char *matrix, int rows, int cols, char *str) {
42+
if (matrix == nullptr || !rows || !cols) {
43+
return false;
44+
}
45+
for (int i = 0; i < rows; ++i) {
46+
for (int j = 0; j < cols; ++j) {
47+
if (matrix[i * cols + j] == str[0]) {
48+
if (dfs(i, j, rows, cols, matrix, str + 1)) {
49+
return true;
50+
}
51+
}
52+
}
53+
}
54+
return false;
55+
}
56+
};
57+
58+
// int main() {
59+
// char mat[] = "abcesfcsadee";
60+
// char s[] = "bcced";
61+
// cout << Solution().hasPath(mat, 3, 4, s);
62+
// return 0;
63+
// }

nowcoder/jzo.66.MovingCount.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
https://www.nowcoder.com/practice/6e5207314b5241fb83f2329e89fdecc8
3+
4+
题目描述
5+
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
6+
例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 =
7+
18。但是,它不能进入方格(35,38),因为3+5+3+8 =
8+
19。请问该机器人能够达到多少个格子?
9+
*/
10+
11+
#include <iostream>
12+
using namespace std;
13+
14+
int dx[] = {0, 0, -1, 1};
15+
int dy[] = {-1, 1, 0, 0};
16+
17+
class Solution {
18+
public:
19+
int digitsSum(int a, int b) {
20+
int res = 0;
21+
while (a || b) {
22+
res += a % 10;
23+
res += b % 10;
24+
a /= 10;
25+
b /= 10;
26+
}
27+
return res;
28+
}
29+
30+
void dfs(int r, int c, int &rows, int &cols, int &cnt, bool vis[]) {
31+
vis[r * cols + c] = true;
32+
cnt += 1;
33+
for (int d = 0; d < 4; ++d) {
34+
int nr = r + dx[d];
35+
int nc = c + dy[d];
36+
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols &&
37+
!vis[nr * cols + nc]) {
38+
dfs(nr, nc, rows, cols, cnt, vis);
39+
}
40+
}
41+
}
42+
43+
int movingCount(int threshold, int rows, int cols) {
44+
if (threshold < 0) {
45+
return 0;
46+
}
47+
48+
bool vis[rows * cols];
49+
for (int i = 0; i < rows; ++i) {
50+
for (int j = 0; j < cols; ++j) {
51+
vis[i * cols + j] = (digitsSum(i, j) > threshold);
52+
}
53+
}
54+
int cnt = 0;
55+
dfs(0, 0, rows, cols, cnt, vis);
56+
return cnt;
57+
}
58+
};
59+
60+
// int main() {
61+
// cout << Solution().movingCount(2, 3, 3);
62+
// return 0;
63+
// }

0 commit comments

Comments
 (0)