剑指 Offer(第 2 版)30余道中等题知识点总结

花了几天时间把剑指 Offer的中等题刷完了。
稍微总结一下:

大概就这么些考点

二叉树

剑指 Offer 07. 重建二叉树:前序遍历和中序遍历的复习。map的应用,还有递归。
剑指 Offer 26. 树的子结构:二叉树递归,一直比两棵树,到NULL为止。
剑指 Offer 32 - III. 从上到下打印二叉树 III:BFS
剑指 Offer 33. 二叉搜索树的后序遍历序列:DFS判断

bool verify(vector<int>& postorder,int i,int j){
        if(i>=j)return true;
        int p=i;
        while(postorder[p]<postorder[j])p++;
        int m=p;
        while(postorder[p]>postorder[j])p++;
        return p==j&&verify(postorder,i,m-1)&&verify(postorder,m,j-1);
    }

剑指 Offer 34. 二叉树中和为某一值的路径:DFS遍历所有路径然后满足要求的收入res数组
剑指 Offer 36. 二叉搜索树与双向链表:中序遍历加单开数组存储

DFS

剑指 Offer 12. 矩阵中的路径:DFS(剪枝和函数内包矩阵)
剑指 Offer 13. 机器人的运动范围:DFS(全局矩阵剪枝)
剑指 Offer 38. 字符串的排列:DFS,回溯(主要回溯完)visited数组的运用(节省时间复杂度)

DP

剑指 Offer 14 剪绳子:小数可以考虑DP,大数只能用规律:1段为3最佳,其次为2,最后一段1时,化前面一段为2*2;
剑指 Offer 46. 把数字翻译成字符串:DP

        int f(int num){
        if(num<10)return 1;
        if((num/10)%10==1||(num/10)%10==2&&num%10<=5){
            return f(num/100)+f(num/10);
        }
        else return f(num/10);
    }

剑指 Offer 47. 礼物的最大价值:经典DP
剑指 Offer 48. 最长不含重复字符的子字符串:暴力,滑动窗口,DP
剑指 Offer 49. 丑数:暴力过不了,淦。只能DP,不过是三个有序数组的合并罢了

class Solution {
public:
    int nthUglyNumber(int n) {
        int a=0,b=0,c=0;
        vector<int>dp(n+1);
        dp[0]=1;
        for(int i=1;i<n+1;i++){
            int x1=dp[a]*2,x2=dp[b]*3,x3=dp[c]*5;
            dp[i]=min(min(x1,x2),x3);
            if(dp[i]==dp[a]*2)a++;
            if(dp[i]==dp[b]*3)b++;
            if(dp[i]==dp[c]*5)c++;
        }
        return dp[n-1];
    }
};

剑指 Offer 60. n个骰子的点数:正向DP和反向DP
从小到大的DP:

vector<double>dp(6,1.0/6.0);
        for(int i=2;i<=n;i++){
            vector<double>tmp(5*i+1,0);
            for(int j=0;j<dp.size();j++){
                for(int k=0;k<6;k++){
                    tmp[j+k]+=dp[j]/6.0;
                }
            }
            dp=tmp;
        }

剑指 Offer 63. 股票的最大利润:双变量秒杀,DP范畴

剑指 Offer 66. 构建乘积数组:
在这里插入图片描述

位运算

剑指 Offer 16. 数值的整数次方:快速幂:转化为二进制来取

while(b){
            if(b&1==1){
                result*=x;
            }
            x*=x;
            b>>=1;
        }

剑指 Offer 56 - I. 数组中数字出现的次数:寻找异或结果第一个1的那一位来分组,分组异或。

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int ret=0;
        for(int n:nums)ret^=n;
        int dic=1;
        while((dic&ret)==0){
            dic<<=1;
        }
        int a=0,b=0;
        for(int n:nums){
            if(dic&n)a^=n;
            else b^=n;
        }
        return vector<int>{a,b};
    }
};

剑指 Offer 56 - II. 数组中数字出现的次数 II:二进制统计所有位余3,剩下的必然是那个数字。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ans=0;
        int bit=0;
        for(int j=31;j>=0;j--){
            for(int i=0;i<nums.size();i++){
                bit+=nums[i]>>j&1;
            }
            ans=ans*2+bit%3;
            bit=0;
        }
        return ans;
    }
};

栈,链表,队列

剑指 Offer 31. 栈的压入、弹出序列:设置一个栈来搞

stack<int> V;
        for (pushOrd = 0, popOrd = 0; pushOrd < pushV.size(); ++pushOrd)  // 按顺序遍历
        {
            V.push(pushV[pushOrd]);  // 入栈
            while (!V.empty() &&popV[popOrd] == V.top())  // 如果栈顶元素等于出栈元素
            {
                V.pop();   // 出栈
                popOrd += 1;  // 向后移
            }
        }

剑指 Offer 35. 复杂链表的复制:哈希表/节点拆分

unordered_map<Node*,Node*>map;
        while(cur!=NULL){
            map[cur]=new Node(cur->val);
            cur=cur->next;
        }
        cur=head;
        while(cur!=NULL){
            map[cur]->next=map[cur->next];//cur->next;自己写的时候写错了
            map[cur]->random=map[cur->random];//cur->random;
            cur=cur->next;
        }
        return map[head];

剑指 Offer 59 - II. 队列的最大值:用了个双向队列
可以从后面出去。pop_back!deque!

void push_back(int value) {
        while(!d.empty()&&d.back()<value)d.pop_back();
        d.push_back(value);
        res.push(value);
    }

字符串、自动机相关

剑指 Offer 20. 表示数值的字符串:自动机以及普通判断方法,这个题有点麻,看了半天似懂非懂,前几天看的现在有点不知所措

剑指 Offer 45. 把数组排成最小的数:字符串是以字典序比大小的

                string a=to_string(nums[i]);
                string b=to_string(nums[j]);
                string x=a+b,y=b+a;
                if(x>y)swap(nums[i],nums[j]);

剑指 Offer 67. 把字符串转换成整数:添加flag来识别正负
判断是否溢出:

for(;i<str.size()&&str[i]>='0'&&str[i]<='9';i++){
            if(res>INT_MAX/10||res==INT_MAX/10&&(str[i]-'0')>7){
                return flag==1?INT_MAX:INT_MIN;
            }
            res=10*res+(str[i]-'0');
        }

其他思维题

剑指 Offer 04. 二维数组中的查找:选择一个合适的位置,比如左下和右上,保证两个方向遍历的单调性。

剑指 Offer 44. 数字序列中某一位的数字:数字,数位。
char转数字是char-‘0’。

        int digit=1;
        int start=1;
        long count=9;//细节long
        while(n>count){
            n-=count;
            start*=10;
            digit+=1;
            count=9L*start*digit;//细节9L
        }

剑指 Offer 64. 求1+2+…+n:短路运算,感觉意义不大

int sumNums(int n) {
        n && (n += sumNums(n-1));
        return n;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值