23.1.14力扣刷题

文章讲述了多个编程问题的解决方案,包括使用自动机判断字符串是否表示数值,计算序列中不同最大公约数的数目,二叉树的镜像与对称性判断,以及矩阵的顺时针打印。此外,还讨论了栈的压入、弹出序列验证,层次遍历二叉树,以及在排序数组中查找和缺失数字的问题。这些问题涉及到递归、动态规划和数据结构的运用。
摘要由CSDN通过智能技术生成

早上起来满脑子都是那个自动机怎么写

剑指 Offer 20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(‘+’ 或 ‘-’)
下述格式之一:
至少一位数字,后面跟着一个点 ‘.’
至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(‘+’ 或 ‘-’)
至少一位数字
部分数值列举如下:
[“+100”, “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]
部分非数值列举如下:
[“12e”, “1a3.14”, “1.2.3”, “±5”, “12e+5.4”]

过了
自动机
其实就是判断状态的不断转移
就像是每个状态下if-else
这题好妙
我用了数组来表述所以可读性不高,或许像题解一样写会好些
大头在小数点表示部分,我用了四个状态T~T,题解用了三个

class Solution {
public:
    bool isNumber(string s) {
        int a[15][10]={0},zt;//每行代表一个状态,数值是0代表无法转移状态
        //列代表条件 1空格 2符号 3. 4数字 5e/E
        a[1][1]=1;a[1][2]=2;a[1][3]=5;a[1][4]=3;
        a[2][3]=5;a[2][4]=3;
        a[3][3]=4;a[3][4]=3;a[3][5]=7;a[3][1]=10;
        a[4][4]=6;a[4][5]=7;a[4][1]=10;
        a[5][4]=6;
        a[6][1]=10;a[6][4]=6;a[6][5]=7;
        a[7][2]=8;a[7][4]=9;
        a[8][4]=9;
        a[9][4]=9;a[9][1]=10;
        a[10][1]=10;
        zt=1;//状态从1开始
        for(char i:s)
        {
            //cout<<zt<<endl;
            int t;
            if(i==' ') t=1;
            else if(i=='+'||i=='-') t=2;
            else if(i=='.') t=3;
            else if(i>='0'&&i<='9') t=4;
            else if(i=='e'||i=='E') t=5;
            else
                return false;
            zt=a[zt][t];
            //cout<<t<<"---"<<zt<<endl;
            if(!zt)
                return false;
        }
        return zt==3||zt==4||zt==6||zt==9||zt==10;
    }
};

1819. 序列中不同最大公约数的数目
给你一个由正整数组成的数组 nums 。
数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。
例如,序列 [4,6,16] 的最大公约数是 2 。
数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。
计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目 。

看了题解
改了好久才过T~T那个动态数组不能用map替代
可能是vector是直接读取内存的原因吧

class Solution {
public:
    int countDifferentSubsequenceGCDs(vector<int>& nums) {
        int mx=*max_element(nums.begin(),nums.end());
        vector<bool> mp(mx+5, false);
        for(int i:nums)
            mp[i]=true;
        int ans=0;
        for(int i=1;i<=mx;i++)
        {
            int t=0;
            for(int j=i;j<=mx;j+=i)//关键点
            {
                if(mp[j])//关键点
                {
                    if(t==0)
                          t=j;
                    else
                        t=__gcd(t,j);
                    if(t==i)
                    {
                           ans++;
                          break;
                     }
                }
            }
        }
        return ans;
    }
};

剑指 Offer 27. 二叉树的镜像
请完成一个函数,输入一个二叉树,该函数输出它的镜像。

想到了之前做的树的题目
用递归真的是神

class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(root==NULL)
            return NULL;
        else
        {
            TreeNode *t=root->left;
            root->left=mirrorTree(root->right);
            root->right=mirrorTree(t);
            return root;
        }
    }
};

剑指 Offer 28. 对称的二叉树
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

爱上递归,用上递归
其实这些都是那个判断子结构类似的

class Solution {
public:
    bool issame(TreeNode *a,TreeNode *b)
    {
        if(!a&&!b)
            return true;
        else if(!a||!b)
            return false;
        else
        {
            if(a->val==b->val)
                return issame(a->left,b->right)&&issame(a->right,b->left);
            else
                return false;
        }
    }
    bool isSymmetric(TreeNode* root) {
        if(!root)
            return true;
        return issame(root->left,root->right);
    }
};

剑指 Offer 29. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

纯模拟。。。
看了一下题解以为有简单方法。。没有==那只能老老实实敲代码了
顺时针
也就是走法是固定的
也就是
向右
向下
向左
向上
向右…四个方向不断循环
向右即打印现在下表到右

过了

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int>res;
        int y=0,x=0,f=0;//f代表方向
        //0向右 1向下 2向左 3向上
        int n=matrix.size();
        if(n==0)
            return res;
        int m=matrix[0].size();
        int left=-1,right=m,up=-1,down=n;
        while(left+1<right&&up+1<down)
        {
            if(f==0)//向右,当前下一直输出到右边界y不变
            {
                while(x<right)
                {
                    res.push_back(matrix[y][x]);
                    x++;
                }
                f=1;//接下来向下
                x--;y++;
                up++;//上边界减小 
            }
            else if(f==1)//其他同理
            {
                while(y<down)
                {
                    res.push_back(matrix[y][x]);
                    y++;
                }
                f=2;//接下来向左
                y--;x--;
                right--;//右边界减小 
            }
            else if(f==2)//其他同理
            {
                while(x>left)
                {
                    res.push_back(matrix[y][x]);
                    x--;
                }
                f=3;//接下来向上
                x++;y--;
                down--;//下边界减小 
            }
            else
            {
                while(y>up)
                {
                    res.push_back(matrix[y][x]);
                    y--;
                }
                f=0;//接下来向右 
                y++;x++;
                left++;//左边界减小 
            }
        }
        return res;
    }
};

剑指 Offer 31. 栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。

好眼熟啊==好像很多年前做过
emm中等题?过了欸

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        int i=0,j=0;
        int n=pushed.size(),m=popped.size();
        if(!n&&!m)
            return true;
        if(!n||!m)
            return false;
        stack<int>st;
        while(i<n&&j<m)
        {
            if(st.empty()||st.top()!=popped[j])
            {
                st.push(pushed[i++]);
            }
            while(j<m&&!st.empty()&&st.top()==popped[j])
            {
                st.pop();
                j++;
            }
        }
        return i==n&&j==m;
    }
};

思路差不多,如果想要简写那就是像题解一样

剑指 Offer 32 - I. 从上到下打印二叉树
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

层次遍历欸
额啊哦好像忘了

啊不对好像用队列就ok

class Solution {
public:
    vector<int> levelOrder(TreeNode* root) {
        queue<TreeNode*>que;
        vector<int>v;
        if(root==NULL)
            return v;
        que.push(root);
        while(!que.empty())
        {
            TreeNode *t=que.front();
            que.pop();
            if(t!=nullptr)
            {
                v.push_back(t->val);
                que.push(t->left);
                que.push(t->right);
            }
        }
        return v;
    }
};

过了>_<?中等题么

剑指 Offer 32 - II. 从上到下打印二叉树 II
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

太奇怪了
可能是分类错了==一是中等题,二居然是简单题
这个计算层数emmm我记得当初数据结构上机考试我想到一个方法来着的

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>>v;
        queue<TreeNode*>que;
        int index=0,num=1,nxt=0;//num当前层数剩余个数,nxt下一层数计数
        if(!root)
            return v;
        que.push(root);
        v.push_back(vector<int>());
        while(!que.empty())
        {
            TreeNode *t=que.front();
            que.pop();
            v[index].push_back(t->val);
            if(t->left!=NULL)
            {
                que.push(t->left);
                nxt++;
            }
            if(t->right!=NULL)
            {
                que.push(t->right);
                nxt++;
            }
            if(--num==0)//当前一层空了
            {
                num=nxt;
                index++;
                nxt=0;
                if(!que.empty())
                    v.push_back(vector<int>());
            }
        }
        return v;
    }
};

对哦其实不需要计数
就是每次打印完这层
当前队列的个数就是等于这一层的层数
好妙

剑指 Offer 53 - I. 在排序数组中查找数字 I
统计一个数字在排序数组中出现的次数。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int res=0;
        for(int i:nums)
            if(i==target)
                res++;
        return res;
    }
};

这也可以2分emmm

剑指 Offer 53 - II. 0~n-1中缺失的数字
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

害这里用二分吧
二分的边界好难调
调了十几分钟ok了

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int l=0,r=nums.size()-1;
        if(nums[0]==1)
            return 0;
        if(nums[r]==r)
            return r+1;
        while(l<r)
        {
            int mid=(l+r)/2;
            if(nums[mid]!=mid)
                r=mid;
            else
            {
                l=mid+1;
            }
        }
        return l;
    }
};

剑指 Offer 32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

用双向队列就ok
从左到右取
从右到左取
不同取法的时候放法也不同

yeah~>_<打败百分之百的时间

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        int index=0,f=0;//f=0从左到右,f=1从右到左
        vector<vector<int>>v;
        if(root==NULL)
            return v;
        deque<TreeNode*>que;
        que.push_back(root);
        v.push_back(vector<int>());
        while(!que.empty())
        {
            deque<TreeNode*>que2;
            int len=que.size();
            for(int i=0;i<len;i++)
            {
                TreeNode *t;
                if(!f)
                {
                    t=que.front();
                    que.pop_front();
                    v[index].push_back(t->val);
                    if(t->left!=NULL)
                        que2.push_back(t->left);
                     if(t->right!=NULL)
                        que2.push_back(t->right);
                }
                else
                {
                    t=que.back();
                    que.pop_back();
                    v[index].push_back(t->val);
                    if(t->right!=NULL)
                        que2.push_front(t->right);
                    if(t->left!=NULL)
                        que2.push_front(t->left);
                }
            }
            f=~f;
            if(!que2.empty())
                v.push_back(vector<int>());
            que=que2;
            index++;
        }
        return v;
    }
};

剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。

这题应该跟树没啥关系吧?
找出对应的规则判断?
噢噢二叉搜索树
也就是左边的值要小于节点值,右边的值也需要小于节点值

一个猜想,从头开始遍历,当前节点的值至少小于
emm写一下其他东西打游戏把这题放明天今天先到这里吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值