牛牛的字符反转

题意:给出一个数字n和k,我们可以进行的操作是将1-n的排列进行选择区间进行反转,问得到将1-n序列向右循环移动k个位置的序列所需要操作的最少的次数为多少。
思路:我们反过来思考,我们先将1-n向右进行循环位移k个单位,然后选择合适的区间进行反转,问回到1-n的排列所需要的操作次数为多少?我们先讨论特殊的,如果k为n的倍数的话,那显然不要进行操作即可。如果n=2的时候,最多也只需要操作1次,当n>2时,我们发现,如果k%n<=2的时候,我们只要进行最少2次操作即可,如:n=6,k=2,就是561234,先将下标区间为[2-n]进行反转得543216,然后将下标区间为[1-n-1]进行反转即可得到1-n,同理n=6,k=4也是如此,其余的就是先将两边进行反转得到局部右序,然后进行一次整体反转得到全部有序。
代码:

class Solution {
public:
    /**
     * 
     * @param n int整型 字符串长度n
     * @param k int整型 循环右移次数k
     * @return int整型
     */
    int solve(int n, int k) {
        // write code here
       int tmp=k%n;
       if(tmp==0)  return 0;
       else if(n==2)  return 1;
       else if(tmp==1||n-tmp==1)  return 2;
       else if(tmp==2||n-tmp==2)  return 2;
       return 3;
    }
};

牛牛的木板

题意:给你一个01序列,然后可以有k次机会将其中的0变为1,问最后最长的连续1长度为多少?
思路:一个双指针进行处理,区间修改也类似于用单调队列进行维护,我们维护一个区间,区间里面的0个个数最多就k个即可。
代码:

class Solution {
public:
    /**
     * 
     * @param n int整型 
     * @param m int整型 
     * @param a int整型vector 
     * @return int整型
     */
    int solve(int n, int m, vector<int>& a) {
        // write code here
        int dp[2],maxNum=0,res=0;
        dp[1]=dp[0]=0;
        for(int i=0,j=0;j<n;j++){
            dp[a[j]]++;
            maxNum=max(maxNum,dp[1]);
            while(j-i+1-maxNum>m){
                dp[a[i]]--;
                i++;
            }
            res=max(res,j-i+1);
        }
        return res;
    }
};

中序序列

题意:给出一颗二叉树的后序遍历和前序遍历,求最后的中序遍历的序列。
思路:一个很裸的题目,和我们已知前序和中序遍历,求后续遍历的思路一样,我们利用递归不断构建二叉树的左右子树既可以了。只是这里要注意的是我们如何确定二叉树的左右子树的范围。
代码:

class Solution {
public:
    /**
     * 返回所求中序序列
     * @param n int整型 二叉树节点数量
     * @param pre int整型vector 前序序列
     * @param suf int整型vector 后序序列
     * @return int整型vector
     */
     vector<int> ans;
    void build(int ll,int lr,vector<int> &pre,int rl,int rr,vector<int>& suf){
//这里的ll,lr表示的是先序遍历的序列范围,rl,rr表示的是后序遍历的序列范围
        if(ll>lr) return;
        if(ll==lr){
            ans.push_back(pre[ll]);
            return;
        }
        int pos;
        for(int i=rl;i<=rr;i++){
            if(suf[i]==pre[ll+1]){
                pos=i;  //找到当前父结点下的左子树的根节点
                break;
            }
        }
        int len=pos-rl;
        build(ll+1,ll+1+len,pre,rl,pos,suf); //构建左子树
        ans.push_back(pre[ll]);
        build(len+ll+2,lr,pre,pos+1,rr-1,suf);  //构建右子树
    }
    vector<int> solve(int n, vector<int>& pre, vector<int>& suf) {
        // write code here
        build(0,n-1,pre,0,n-1,suf);
        return ans;
    }
};