1.递减元素使数组呈锯齿状 暴力
分析:暴力,依次按照两种方式进行遍历即可
class Solution {
public:
int movesToMakeZigzag(vector<int>& nums) {
//依次尝试两种方法
int ans = 0, ans1 = 0;
vector<int>nums1;
nums1.clear();
for(int i=0;i<nums.size();i++)
nums1.push_back(nums[i]);
for(int i = 1; i < nums.size();i+=2)
{
if(i==nums.size()-1) {
if(nums[i]>=nums[i-1]) {
ans+=(nums[i]-nums[i-1]+1);
}
if(nums1[i]<=nums1[i-1]) {
ans1+=(nums1[i-1]-nums1[i]+1);
}
}
else {
//第一种
int m1 = nums[i-1]>nums[i+1]?nums[i+1]:nums[i-1];
if(nums[i]<m1) ans+=0;
else ans+=(nums[i]-m1+1);
//第二种
int m2 = nums1[i-1]>nums1[i+1]?nums1[i-1]:nums1[i+1];
if(nums1[i]>m2) ans1+=0;
else {
while(nums1[i-1]>=nums1[i]) {
ans1++;
nums1[i-1]--;
}
while(nums1[i+1]>=nums1[i]) {
ans1++;
nums1[i+1]--;
}
}
}
}
return ans>ans1?ans1:ans;
}
};
2.二叉树着色游戏 思维 搜索
分析:对于其中一个节点已经染色,那么此时放置另一种颜色的节点,只有放置到已染色节点的父亲,左儿子节点和右儿子节点才能使得己方胜率最大,依次尝试
/**
* 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 num;
TreeNode* dfs(TreeNode* root,int x)
{
if(root==nullptr) return nullptr;
if(root->val==x) return root;
TreeNode* now = dfs(root->left,x);
if(now!=nullptr) return now;
now = dfs(root->right,x);
if(now!=nullptr) return now;
return nullptr;
}
void dfsL(TreeNode* root)
{
if(root==nullptr) return;
if(root!=nullptr) num++;
dfsL(root->left);
dfsL(root->right);
}
bool btreeGameWinningMove(TreeNode* root, int n, int x) {
//在x点的左子树,右子树和父亲节点分别尝试染蓝色,最后取蓝色最大即可
TreeNode* now = dfs(root,x);
//1.左子树
num = 0;
dfsL(now->left);
int left = num;
//2.右子树
num = 0;
dfsL(now->right);
int right = num;
//3.父亲节点
int parent = n-(left+right+1);
int k = max(max(left,right),parent);
if(k>n-k) return true;
else return false;
}
};
3.快照数组 思维 二分
分析:每次变化都会改变某个index位置的值,每一次执行快照函数都会产生一个当前整个数组的快照,输入一个快照的id号,要求得到这个id号所对应index位置的值。
我们可以这样,先建一个vector<pair<int,int>> a[maxn],用来存储每个index位置值的变化情况,当然还需要一个变量q来存储当前是第几次变化,接着建一个vector<int>b,用来存储每次快照的时候,当前是第几次变化,b中下标是快照id,值是当前的变化次数,那么当我们进行查询的时候,我们可以直接对a中index行进行查找,我们继续观察a中index行中的内容,发现每个pair中的first值必然是有序的,基于这样的情况使用二分,直接调用upper_bound(),需要注意的是这里进行的是pair类型的二分,经过尝试,pair数组在进行sort排序时,首先会根据first值进行排序,接着如果first值相同,那么会按照second值排序。针对这道题,index行的所有pair,只是first有序,在进行二分upper_bound的时候,会首先比较first值,如果first值相同,那么再比较second值,那么我们的second值选取就比较关键。
参考了大佬的写法:
const int maxn = 50005;
class SnapshotArray {
public:
int q,n;
vector<pair<int,int>> a[maxn];
vector<int>b;
SnapshotArray(int length) {
q = 0;
n = length;
b.clear();
//每个索引进行初始化
for(int i=0;i<length;i++)
{
a[i].clear();
a[i].push_back(make_pair(0,0));
}
}
void set(int index, int val) {
a[index].push_back(make_pair(++q,val));
}
int snap() {
b.push_back(q);
return b.size()-1;
}
int get(int index, int snap_id) {
int k = lower_bound(a[index].begin(),a[index].end(),make_pair(b[snap_id],0))-a[index].begin();
if(k>=a[index].size()) {
return a[index][k-1].second;
}
else{
if(a[index][k].first==b[snap_id]) {
return a[index][k].second;
}
else {
return a[index][k-1].second;
}
}
}
};
/**
* Your SnapshotArray object will be instantiated and called as such:
* SnapshotArray* obj = new SnapshotArray(length);
* obj->set(index,val);
* int param_2 = obj->snap();
* int param_3 = obj->get(index,snap_id);
*/