数学题:先写几项观察规律,然后采用归纳演绎法证明。
class Solution {
public:
bool divisorGame(int n) {
return n % 2 == 0;
}
};
递归的传入当前祖先中的最大和最小值,然后比较即可
/**
* 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 maxAncestorDiff(TreeNode* root)
{
nRet = 0;
if (root)
findMostVal(root->val, root->val, root);
return nRet;
}
private:
int nRet;
void findMostVal(int nUp, int nDown, TreeNode* pNode)
{
if (pNode == NULL) return;
int nMax = max(abs(nUp - pNode->val), abs(nDown - pNode->val));
nRet = max(nRet, nMax);
nUp = max(nUp, pNode->val);
nDown = min(nDown, pNode->val);
findMostVal(nUp, nDown, pNode->left);
findMostVal(nUp, nDown, pNode->right);
}
};
很容易想到用动态规划求解:dp[i][d]表示以i结尾公差为d的子数组长度,循环的时候为了不用遍历d,所以采用j = 0到 i - 1,然后依次取出公差,对对应的公差项进行++操作即可
class Solution {
public:
int longestArithSeqLength(vector<int>& nums)
{
int nRet = 0;
int nSize = nums.size();
vector<vector<int>> dp(nSize, vector<int>(1001, 0));
for (int i = 1; i < nSize; ++i)
{
for (int j = 0; j < i; ++j)
{
int diff = nums[i] - nums[j] + 500;
dp[i][diff] = dp[j][diff] + 1;
nRet = max(nRet, dp[i][diff]);
}
}
return nRet + 1;
}
};
先序遍历的特点是先根,然后左,最后右。对应于本题,首先需要读取当前的深度及值,然后根据深度判断和上一个节点的关系:左节点,或者前面某一位置的右节点(一定不可能是上一节点的右节点,因为题目规定了必须保证只有一个子节点的时候是左节点,所以最多只能同级)。因此用一个栈来保存前面的节点们,然后依次出栈直至刚好栈深度为当前深度。之后再将该节点入栈即可。
/**
* 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* recoverFromPreorder(string traversal)
{
stack<TreeNode*> path;
int pos = 0;
while (pos < traversal.size())
{
int level = 0;
while (traversal[pos] == '-')
{
++level;
++pos;
}
int value = 0;
while (pos < traversal.size() && isdigit(traversal[pos]))
{
value = value * 10 + (traversal[pos] - '0');
++pos;
}
TreeNode* node = new TreeNode(value);
if (level == path.size())
{
if (!path.empty())
{
path.top()->left = node;
}
}
else
{
while (level != path.size())
{
path.pop();
}
path.top()->right = node;
}
path.push(node);
}
while (path.size() > 1)
{
path.pop();
}
return path.top();
}
};
贪心算法:假设所有人都去B,然后从中挑一些去A,则费用的变化是priceA - priceB,肯定是优先挑选差值小的,所以就按差值排序,然后取前一半去A后一半去B即可
class Solution {
public:
int twoCitySchedCost(vector<vector<int>>& costs) {
// Sort by a gain which company has
// by sending a person to city A and not to city B
sort(begin(costs), end(costs),
[](const vector<int> &o1, const vector<int> &o2) {
return (o1[0] - o1[1] < o2[0] - o2[1]);
});
int total = 0;
int n = costs.size() / 2;
// To optimize the company expenses,
// send the first n persons to the city A
// and the others to the city B
for (int i = 0; i < n; ++i) total += costs[i][0] + costs[i + n][1];
return total;
}
};
遍历+输出
class Solution {
public:
int dist(int r1, int c1, int r2, int c2) {
return abs(r1 - r2) + abs(c1 - c2);
}
vector<vector<int>> allCellsDistOrder(int rows, int cols, int rCenter, int cCenter) {
int maxDist = max(rCenter, rows - 1 - rCenter) + max(cCenter, cols - 1 - cCenter);
vector<vector<vector<int>>> bucket(maxDist + 1);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int d = dist(i, j, rCenter, cCenter);
vector<int> tmp = {i, j};
bucket[d].push_back(move(tmp));
}
}
vector<vector<int>> ret;
for (int i = 0; i <= maxDist; i++) {
for (auto &it : bucket[i]) {
ret.push_back(it);
}
}
return ret;
}
};
先取前缀和,然后遍历即可。
class Solution {
public:
int maxSumTwoNoOverlap(vector<int>& nums, int L, int M) {
int n = nums.size();
vector<int> p(n+1);
for(int i=1; i<=n; i++) p[i] = p[i-1] + nums[i-1];
int res = 0;
// 枚举 L
for(int i=0; i+L<=n; i++){
int sumL = p[i+L] - p[i];
for(int j=0; j+M<i; j++){ // L前面 M 部分
int sumM = p[j+M] - p[j];
res = max(res, sumL + sumM);
}
for(int j = i+L; j+M<=n; j++){ // L后面的 M 部分
int sumM = p[j+M]-p[j];
res = max(res, sumL+sumM);
}
}
return res;
}
};