题目1
实现一个 Trie (前缀树),包含 insert
, search
, 和 startsWith
这三个操作。
示例:
Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // 返回 true trie.search("app"); // 返回 false trie.startsWith("app"); // 返回 true trie.insert("app"); trie.search("app"); // 返回 true
说明:
- 你可以假设所有的输入都是由小写字母
a-z
构成的。 - 保证所有输入均为非空字符串。
思路及代码
建树的过程,只不过这里一个节点可以有26个孩子,因为英文26个字母。然后叶子节点存一下string,来证明有这个值。
前缀的话只要搜索树,节点存在即可。
class Trie {
public:
struct TrieNode{
//孩子节点,分别记录26个字母
struct TrieNode* children[26];
//当前的节点(叶子节点)对应的单词
string item;
};
TrieNode* root;
/** Initialize your data structure here. */
Trie() {
root = new TrieNode();
}
/** Inserts a word into the trie. */
void insert(string word) {
TrieNode* p = root;
int len = word.size();
for(int i = 0;i < len;i++){
if(p->children[word[i] - 'a'] == NULL){
p->children[word[i] - 'a'] = new TrieNode();
}
p = p->children[word[i] - 'a'];
}
p->item = word;
}
/** Returns if the word is in the trie. */
bool search(string word) {
TrieNode* p = root;
int len = word.size();
for(int i = 0;i < len;i++){
if(p->children[word[i] - 'a'] == NULL){
return false;
}
p = p->children[word[i] - 'a'];
}
return p->item == word;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
TrieNode* p = root;
int len = prefix.size();
for(int i = 0;i < len;i++){
if(p->children[prefix[i] - 'a'] == NULL){
return false;
}
p = p->children[prefix[i] - 'a'];
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
题目2
一个N x N的网格(grid)
代表了一块樱桃地,每个格子由以下三种数字的一种来表示:
- 0 表示这个格子是空的,所以你可以穿过它。
- 1 表示这个格子里装着一个樱桃,你可以摘到樱桃然后穿过它。
- -1 表示这个格子里有荆棘,挡着你的路。
你的任务是在遵守下列规则的情况下,尽可能的摘到最多樱桃:
- 从位置 (0, 0) 出发,最后到达 (N-1, N-1) ,只能向下或向右走,并且只能穿越有效的格子(即只可以穿过值为0或者1的格子);
- 当到达 (N-1, N-1) 后,你要继续走,直到返回到 (0, 0) ,只能向上或向左走,并且只能穿越有效的格子;
- 当你经过一个格子且这个格子包含一个樱桃时,你将摘到樱桃并且这个格子会变成空的(值变为0);
- 如果在 (0, 0) 和 (N-1, N-1) 之间不存在一条可经过的路径,则没有任何一个樱桃能被摘到。
示例 1:
输入: grid = [[0, 1, -1], [1, 0, -1], [1, 1, 1]] 输出: 5 解释: 玩家从(0,0)点出发,经过了向下走,向下走,向右走,向右走,到达了点(2, 2)。 在这趟单程中,总共摘到了4颗樱桃,矩阵变成了[[0,1,-1],[0,0,-1],[0,0,0]]。 接着,这名玩家向左走,向上走,向上走,向左走,返回了起始点,又摘到了1颗樱桃。 在旅程中,总共摘到了5颗樱桃,这是可以摘到的最大值了。
说明:
grid
是一个N
*N
的二维数组,N的取值范围是1 <= N <= 50
。- 每一个
grid[i][j]
都是集合{-1, 0, 1}
其中的一个数。 - 可以保证起点
grid[0][0]
和终点grid[N-1][N-1]
的值都不会是 -1。
思路及代码
用DP的,难题,不是很懂,这篇题解看完后,列下方程能够理解了,但是代码还是写不出来ORZ
class Solution {
public:
int cherryPickup(vector<vector<int>>& grid) {
int N = grid.size(), dp[N+1][N+1];
memset(dp, 0x80, sizeof(dp)); //-2139062144, 作用相当于 INT_MIN
dp[N-1][N-1] = grid[N-1][N-1]; // 初始边界条件
for(int sum = 2*N - 3; sum >= 0; --sum)
for(int i1 = max(0, sum - N + 1); i1 <= min(N-1,sum); ++i1)
for(int i2 = i1; i2 <= min(N-1,sum); ++i2)
{
int j1 = sum - i1, j2 = sum - i2;
if(grid[i1][j1] == -1 || grid[i2][j2] == -1)
dp[i1][i2] = INT_MIN;
else
dp[i1][i2] = grid[i1][j1] + (i1 != i2 || j1 != j2)*grid[i2][j2] + max(
max(dp[i1][i2+1], dp[i1+1][i2]),
max(dp[i1+1][i2+1], dp[i1][i2])
);
}
return max(0, dp[0][0]);
}
};
题目3
最大树定义:一个树,其中每个节点的值都大于其子树中的任何其他值。
给出最大树的根节点 root
。
就像之前的问题那样,给定的树是从表 A
(root = Construct(A)
)递归地使用下述 Construct(A)
例程构造的:
- 如果
A
为空,返回null
- 否则,令
A[i]
作为 A 的最大元素。创建一个值为A[i]
的根节点root
root
的左子树将被构建为Construct([A[0], A[1], ..., A[i-1]])
root
的右子树将被构建为Construct([A[i+1], A[i+2], ..., A[A.length - 1]])
- 返回
root
请注意,我们没有直接给定 A,只有一个根节点 root = Construct(A)
.
假设 B
是 A
的副本,并附加值 val
。保证 B
中的值是不同的。
返回 Construct(B)
。
示例 1:
输入:root = [4,1,3,null,null,2], val = 5 输出:[5,4,null,1,3,null,null,2] 解释:A = [1,4,2,3], B = [1,4,2,3,5]
示例 2:
输入:root = [5,2,4,null,1], val = 3 输出:[5,2,4,null,1,null,3] 解释:A = [2,1,5,4], B = [2,1,5,4,3]
示例 3:
输入:root = [5,2,3,null,1], val = 4 输出:[5,2,4,null,1,3] 解释:A = [2,1,5,3], B = [2,1,5,3,4]
提示:
1 <= B.length <= 100
思路及代码
比根节点要大,直接在当前这里新建节点了,否则向右递归
/**
* 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:
TreeNode* insertIntoMaxTree(TreeNode* root, int val) {
if(root == NULL){
return new TreeNode(val);
}else{
if(root->val < val){
TreeNode* _root = new TreeNode(val);
_root->left = root;
return _root;
}else{
TreeNode* _right = insertIntoMaxTree(root->right, val);
root->right = _right;
return root;
}
}
}
};