剑指OFFER51-60题

51构建乘积数组
给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]* A[1]* …* A[i-1]* A[i+1]*…*A[n-1]。不能使用除法。

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        vector<int> b;
        for(int i=0;i<A.size();i++){
            b.push_back(1);
            for(int j=0;j<A.size();j++){
                if(j!=i){
                    b[i]*=A[j];
                }
            }
        }
        return b;
    }
};

52正则表达式匹配
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配

class Solution {
public:
    bool match(char* str, char* pattern){
        if(str==nullptr || pattern==nullptr)return false;
        return matchCore(str,pattern);
    }
    bool matchCore(char *str,char *pattern)
        if(*str=='\0' && *pattern=='\0')return true;
        if(*str!='\0' && *pattern=='\0')return false;
        if(*(pattern+1)=='*'){
            if(*str==*pattern || (*pattern=='.' && *str!='\0'))
                return matchCore(str+1,pattern+2)||matchCore(str+1,pattern)||matchCore(str,pattern+2);
            else
                return matchCore(str,pattern+2);
        }
        if(*str==*pattern || (*pattern=='.' && *str!='\0'))
            return matchCore(str+1,pattern+1);
        return false;
    }
};
/*
思路
如果模式串此时是'.',那么只需要模式串与匹配串都往后移动一个位置即可
如果现在这位的字符能匹配且且模式串的下一位是'*',我们则需要分情况讨论
1.匹配串往后移动1位,模式串跳过'*'
2.匹配串往后移动1位,模式串不动
3.匹配串不动,模式串跳过'*'
*/



53表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

class Solution {
public:
    bool isNumeric(char* string){
        int dotIdx=0;//first find dot
        for(int i=0;string[i]!='\0';i++){
            if(string[i]=='.'){
                if(dotIdx!=0)return false;
                dotIdx=i;
            }
        }
        int flag=0;//e flag
        for(int i=0;string[i]!='\0';i++){
            //cout<<string[i]<<endl;
            if(i==0 && string[i]=='+')continue;
            if(i==0 && string[i]=='-')continue;
            if(string[i]=='E' || string[i]=='e'){
                flag++;
                if( flag==2 || i<dotIdx )return false;
                if( string[i+1]=='+' || string[i+1]=='-')i++;
                if( string[i+1]<'0' || string[i+1]>'9' )return false;
                else continue;
            }
            if(string[i]>='0' && string[i]<='9')continue;
            if(string[i]=='.')continue;
            return false;
        }
        return true;
    }
};

54字符流中第一个不重复的字符
题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。

class Solution
{
public:
  //Insert one char from stringstream
    vector<char> let;
    vector<int> num;
    void Insert(char ch)
    {
        for(int i=0;i<let.size();i++){
            if(let[i]==ch){
                num[i]++;
                return ;
            }
        }
        let.push_back(ch);
        num.push_back(1);
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce(){
        for(int i=0;i<num.size();i++){
            if(num[i]==1){
                return let[i];
            }
        }
        return '#';
    }
};

55链表中环的入口结点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    set<ListNode*> s;
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        ListNode* p=pHead;
        while(p!=NULL){
            if(s.find(p)!=s.end()){
                return p;
            }
            s.insert(p);
            p=p->next;
        }
        return NULL;
    }
};

56删除链表中重复的结点
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead){
        if (pHead == NULL)return NULL;          // 先判断空
        if (pHead->next == NULL)return pHead;   // 判断是否只有一个节点
        ListNode* pre = new ListNode(int());    // 我们采用带头链表,自己添加一个头
        pre->next = pHead;                      // 把头节点链接在链表上
        
        ListNode* pre_head = pre;        // 用来保存头节点,用于返回删除后的链表
        ListNode* cur = pHead;           //中指针
        ListNode* nex = pHead->next;     // 后面指针
        
        while (nex != NULL){ // 结束条件
            while (nex != NULL && cur->val == nex->val)nex = nex->next;
            // 当NEX跳到空,或者与中指针值不同时就是进入下面的判断
            if (cur->next != nex){ // 中针与后针不相邻则必定有重复
                while (cur != nex){ // 把CUR一直后移,直到CUR是后针为止
                    pre->next = cur->next;//前针的后继指向中针的后继
                    cur = pre->next;//中针记为前针后继(结合上一句,不就是它自己的后继吗!)
                }
                if (nex != NULL) // 这里一定要要注意,要防止走到NULL发生段错误
                nex = nex->next;//中针已经指向了后后,所以后针也要后移了
            }
            else{ //cur->next == nex 没有重复的情况,CUR点是要插入的
                pre = cur;       //前针后移
                nex = nex->next; //后针后移
                cur = cur->next; //中针后移
            }
        }
        ListNode* head = pre_head->next; //自定义的头结点不是真正的起点
        return head;//输出真正的头指针
    }
};

57二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        if(pNode==NULL)return NULL;
        if(pNode->right!=NULL){
            TreeLinkNode* p = pNode->right;
            while(p->left!=NULL){
                    p=p->left;
                }
                return p;
        }
        if(pNode->right==NULL && pNode->next!=NULL && pNode==pNode->next->left)return pNode->next;

        if(pNode->right==NULL && pNode->next!=NULL && pNode==pNode->next->right){
            TreeLinkNode* p = pNode->next;
            while( p->next!=NULL && p==p->next->right )p=p->next;
            return p->next;
        }
        
        return NULL;
        
    }
};

58对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的
class Solution {
public:
bool dfs(TreeNode* p1,TreeNode* p2){
if(p1NULL && p2NULL)return true;//双空
if(p1NULL && p2!=NULL)return false;//右空
if(p2
NULL && p1!=NULL)return false;//左空
if(p1->val != p2->val)return false;//值不等
return ( dfs(p1->left,p2->right) && dfs(p1->right,p2->left) );//判左儿与右儿
}
bool isSymmetrical(TreeNode* pRoot)
{
if(pRoot==NULL)return true;
return dfs(pRoot->left,pRoot->right);
}

};
59按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
        vector<vector<int> > ans;
    queue<TreeNode*> q1,q2;
    void f1(){
        while(!q2.empty())q2.pop();
        vector<int>tmp;
        while(!q1.empty()){
            TreeNode* t=q1.front();
            tmp.push_back(t->val);
            q1.pop();
            if(t->left!=NULL)q2.push(t->left);
            if(t->right!=NULL)q2.push(t->right);
        }
        if(tmp.size()!=0)ans.push_back(tmp);
    }
    void f2(){
        while(!q1.empty())q1.pop();
        vector<int>tmp;
        while(!q2.empty()){
            TreeNode* t=q2.front();
            tmp.push_back(t->val);
            q2.pop();
            if(t->left!=NULL)q1.push(t->left);
            if(t->right!=NULL)q1.push(t->right);
        }
        if(tmp.size()!=0){
            for(int x=0;x<tmp.size()/2;x++){
                swap(tmp[x],tmp[tmp.size()-x-1]);
            }
            ans.push_back(tmp);
        }
    }
    vector<vector<int> > Print(TreeNode* pRoot) {
        if(pRoot==NULL)return ans;
        q1.push(pRoot);
        while(!q1.empty()||!q2.empty()){
            f1();
            f2();
        }
        return ans;
    }
    
};

60把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector<vector<int> > ans;
    queue<TreeNode*> q1,q2;
    void f1(){
        while(!q2.empty())q2.pop();
        vector<int>tmp;
        while(!q1.empty()){
            TreeNode* t=q1.front();
            tmp.push_back(t->val);
            q1.pop();
            if(t->left!=NULL)q2.push(t->left);
            if(t->right!=NULL)q2.push(t->right);
        }
        if(tmp.size()!=0)ans.push_back(tmp);
    }
    void f2(){
        while(!q1.empty())q1.pop();
        vector<int>tmp;
        while(!q2.empty()){
            TreeNode* t=q2.front();
            tmp.push_back(t->val);
            q2.pop();
            if(t->left!=NULL)q1.push(t->left);
            if(t->right!=NULL)q1.push(t->right);
        }
        if(tmp.size()!=0)ans.push_back(tmp);
    }
    vector<vector<int> > Print(TreeNode* pRoot) {
        if(pRoot==NULL)return ans;
        q1.push(pRoot);
        while(!q1.empty()||!q2.empty()){
            f1();
            f2();
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/cj1064789374/article/details/85010854