剑指offer刷题记录(C++)

1.二维数组的查找

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution {
public:
    bool Find(int target, vector > array) {
        int m=array.size();
        if(m==0)return false;
        int n=array[0].size();
        int row=0,col=n-1;
        while(row=0){
            if(array[row][col]==target)return true;
            else if(array[row][col]>target)col--;
            else row++;
        }
        return false;
        
    }
};

2.替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

class Solution {
public:
    void replaceSpace(char *str,int length) {//length 为数组总容量
        int strsize=0;
        int space=0;
        for(int i=0;ilength)return;
        char *left=str+strsize,*right=left+2*space;
        *right='\0';
        while(left

3.从头到尾打印链表

输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector printListFromTailToHead(ListNode* head) {
        if(head==NULL)return {};
        vector res=printListFromTailToHead(head->next);
        res.push_back(head->val);
        return res;
    }
};

4.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector pre,vector vin) {
        if(pre.size()==0)return NULL;
        TreeNode* res=func(pre,vin,0,pre.size()-1,0,vin.size()-1);
        return res;
    }
    
    TreeNode* func(vector &pre,vector &in,int preleft, int preright,int inleft,int inright){
        if(preleft>preright || inleft>inright)return NULL;
        int val=pre[preleft],inroot;
        for(int i=inleft;i<=inright;i++){
            if (in[i]==val){
                inroot=i;
                break;
            }
        }
        TreeNode* root=new TreeNode(val);
        root->left=func(pre,in,preleft+1,inroot-inleft+preleft,inleft,inroot-1);
        root->right=func(pre,in,inroot-inleft+preleft+1,preright,inroot+1,inright);
        return root;
    }
};

5.用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        int res=stack2.top();
        stack2.pop();
        return res;
    }

private:
    stack stack1;
    stack stack2;
};

6.旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

class Solution {
public:
    int minNumberInRotateArray(vector rotateArray) {
        if(rotateArray.size()==0)return 0;
        int l=0,r=rotateArray.size()-1,mid;
        while(l=rotateArray[r]){
                if(rotateArray[mid]>=rotateArray[l]){
                    l=mid+1;
                }
                else{
                    r=mid;
                }
            }
            else{
                break;
            }
        }
        return rotateArray[l]; 
    }
};

7.斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。

n<=39

class Solution {
private:
    vector res;
public:
    Solution(){
        res.resize(40);
       res[0]=0;
        res[1]=1;
        for(int i=2;i<40;i++)res[i]=res[i-1]+res[i-2];
    }
    int Fibonacci(int n) {
        return res[n];

    }
};

8.跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

class Solution {
public:
    int jumpFloor(int number) {
        if(number<=2)return number;
        int prepre=1,pre=2,cur;
        for(int i=3;i<=number;i++){
            cur=pre+prepre;
            prepre=pre;
            pre=cur;
        }
        return cur;
    }
};

9.变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

class Solution {
public:
    int jumpFloorII(int number) {
        return pow(2,number-1);
    }
};

10.矩形覆盖

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

class Solution {
public:
    int rectCover(int number) {
        if(number<2)return number;
        vector dp(number+1);
        dp[0]=dp[1]=1;
        for(int i=2;i<=number;i++)
            dp[i]=dp[i-1]+dp[i-2];
            //最后一块板子横着放或者竖着放,分别对应i-1和i-2
        return dp[number];

    }
};

11.二进制中1的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

class Solution {
public:
     int  NumberOf1(int n) {
         int count=0;
         while(n){
             n=n&(n-1);
             count++;
         }
         return count;
     }
};

12.数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

class Solution {
public:
    double Power(double base, int exponent) {
        if(exponent==0)return 1.0;
        if(base==0)return 0.0;
        if(exponent==1) return base;
        if(exponent<0) return 1.0/Power(base,-exponent);
        double res=1.0,temp=base;
        for(int i=1;i

13.调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

class Solution {
public:
    void reOrderArray(vector &array) {
        for(int i=1;i0;j--){
                if(array[j]%2!=0&&array[j-1]%2==0)
                    swap(array[j],array[j-1]);
            }
        }
    }
};

14.链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==NULL||k<1)return NULL;
        ListNode* left=pListHead,*right=pListHead;
        for(int i=1;inext;
            if(right==NULL)return NULL;
        }
        while(right->next){
            right=right->next;
            left=left->next;
        }
        return left;
    }
};

15.反转链表

输入一个链表,反转链表后,输出新链表的表头。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode *cur=pHead,*next,*pre=NULL;
        while(cur!=NULL){
            next=cur->next;
            cur->next=pre;
            pre=cur;
            cur=next;
        }
        return pre;

    }
};

16.合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==NULL&&pHead2==NULL)return NULL;
        if(pHead1==NULL||pHead2==NULL)return pHead1?pHead1:pHead2;
        if(pHead1->valval){
            pHead1->next=Merge(pHead1->next,pHead2);
            return pHead1;
        }
        else{
            pHead2->next=Merge(pHead1,pHead2->next);
            return pHead2;
        }
    }
};

17.树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot1==NULL&&pRoot2==NULL)return false;
        if(pRoot1==NULL||pRoot2==NULL)return false;//空树不是子结构
        if (isSub(pRoot1,pRoot2))return true;
        return HasSubtree(pRoot1->left,pRoot2)||HasSubtree(pRoot1->right,pRoot2);
    }
    bool isSub(TreeNode* root1,TreeNode* root2){
        if(root2==NULL)return true;
        if(root1==NULL)return false;
        if(root1->val!=root2->val)return false;
        return isSub(root1->left,root2->left)&&isSub(root1->right,root2->right);
    }
};

对比:判断二叉树的子树

/**
 * 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:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        if(s==NULL && t==NULL)return true;
        if(s==NULL || t==NULL)return false;
        if(isSame(s,t))return true;
        return isSubtree(s->left,t)||isSubtree(s->right,t);
    }
private:
    bool isSame(TreeNode* s, TreeNode* t){
        if(s==NULL && t==NULL)return true;
        if(s==NULL || t==NULL)return false;
        if(s->val!=t->val)return false;
        return isSame(s->left,t->left)&&isSame(s->right,t->right);
    }
};

18.二叉树的镜像

操作给定的二叉树,将其变换为源二叉树的镜像。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        helper(pRoot);
    }
    
    TreeNode* helper(TreeNode *root){
        if(root==NULL){
            return NULL;
        }
        TreeNode* temp=root->left;
        root->left=helper(root->right);
        root->right=helper(temp);
        return root;
    }
};

19.顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

class Solution {
public:
    vector printMatrix(vector > matrix) {
        vector res;
        if(matrix.size()==0||matrix[0].size()==0)return res;
        int m=matrix.size();
        int n=matrix[0].size();
        for(int level=0;2*levellevel)for(int i=n-level-1;i>=level;i--)res.push_back(matrix[m-level-1][i]);
            if(n-level-1>level)for(int j=m-level-2;j>level;j--)res.push_back(matrix[j][level]);
        }
        return res;

    }
};

20.包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

class Solution {
public:
    void push(int value) {
        s.push(value);
        if(sm.empty()||sm.top()>=value)sm.push(value);
    }
    void pop() {
        if(sm.top()==s.top())sm.pop();
        s.pop();
    }
    int top() {
        return s.top();
    }
    int min() {
        return sm.top();
    }
    stack s,sm;
};

21.栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

class Solution {
public:
    bool IsPopOrder(vector pushV,vector popV) {
        stack st;
        int pushInd=0,popInd=0;
        while(pushInd

22.从上往下打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    vector PrintFromTopToBottom(TreeNode* root) {
        vector res;
        if(root==NULL)return res;//attention!
        queue q;
        q.push(root);
        while(!q.empty()){
            TreeNode *front=q.front();
            res.push_back(front->val);
            q.pop();
            if(front->left)q.push(front->left);
            if(front->right)q.push(front->right);
            
        }
        return res;

    }
};

23.二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

class Solution {
public:
    bool VerifySquenceOfBST(vector sequence) {
        if(sequence.size()==0)return false;
        return func(sequence,0,sequence.size()-1);
    }
    bool func(vector &post,int left,int right){
        if(left>=right)return true;
        int indexl=left-1,indexr=right;
        while(post[indexl+1]post[right])indexr--;
        bool res=(indexl+1==indexr);
        return res&&func(post,left,indexl)&&func(post,indexr,right-1);
    }
};

24.二叉树中和为某一值的路径

输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    vector > FindPath(TreeNode* root,int expectNumber) {
        vector> res;
        vector temp;
        if(root==NULL)return res;
        dfs(root,expectNumber,res,temp);
        sort(res.begin(),res.end(),cmp);
        return res;
    }
    bool static cmp(vectora,vector b){
        return a.size()>b.size();
    }
    void dfs(TreeNode* root,int num, vector> &res, vector &temp){
        //题目没有说所有节点为正整数
        if(root->left==NULL && root->right==NULL){
            if(num==root->val){
                temp.push_back(root->val);
                res.push_back(temp);
                temp.pop_back();
            }
            return;
        }
        temp.push_back(root->val);
        if(root->left)dfs(root->left,num-root->val,res,temp);
        if(root->right)dfs(root->right,num-root->val,res,temp);
        temp.pop_back();
    }
};

25.复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead==NULL)return NULL;
        RandomListNode* cur=pHead,*next;
        while(cur!=NULL){
            next=cur->next;
            cur->next=new RandomListNode(cur->label);
            cur->next->next=next;
            cur->next->random=cur->random;
            cur=next;
        }
        cur=pHead->next;
        while(cur->next!=NULL){ //attention next
            cur->random=cur->random?cur->random->next:NULL;//attention ?:
            cur=cur->next->next;
        }
        RandomListNode* res=pHead->next;
        cur=pHead;
        while(cur!=NULL){
            next=cur->next->next;
            cur->next->next=next?next->next:NULL;
            cur->next=next;
            cur=next;
        }
        return res;
    }
};

26.二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree==NULL)return NULL;
        TreeNode* pre=NULL;
        inorder(pRootOfTree,pre);
        TreeNode* res=pRootOfTree;
        while(res->left)res=res->left;//注意是while
        return res;
    }
    
    void inorder(TreeNode* cur, TreeNode* &pre)
    {
        if(cur==NULL) return;
        inorder(cur->left,pre);
        if(pre)pre->right=cur;
        cur->left=pre;
        pre=cur;
        inorder(cur->right,pre);
    }
};

27.字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

class Solution {
public:
    vector Permutation(string str) { //需要排除重复字符串,字典序排列
        vector res;
        set s;
        if(str=="")return res;
        dfs(str,0,res,s);
        sort(res.begin(),res.end());//字典序排列,只需sort一下emmm
        return res;
    }
    void dfs(string &str,int begin,vector &res,set &s){
        if(begin==str.size()){
            if(s.find(str)==s.end()){
                res.push_back(str);
            }
            s.insert(str);
        }
        else{
            for(int i=begin;i

剑指offer刷题记录(C++)_第1张图片

图源:牛客网用户HAHA7877

28.数组中出现次数超过一次的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

class Solution {
public:
    int MoreThanHalfNum_Solution(vector numbers) {
        int res=numbers[0],cur=1;
        for(int i=1;inumbers.size())return res;
        else return 0;
    }
};

29.最小的K个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

class Solution {
public:
    vector GetLeastNumbers_Solution(vector input, int k) {
        vector res;
        if(k<1||input.size()k-1){
                    ed=index-1;
                    index=partition(input,st,ed);
                }
                else {
                    st=index+1;
                    index=partition(input,st,ed);
                }
            }
            for(int i=0;i &input,int st,int ed){
        int pivot=input[st];
        int l=st,r=ed;
        while(l!=r){
            while(lpivot)r--;
            while(l

30.连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

class Solution {
public:
    int FindGreatestSumOfSubArray(vector array) {
        int res=array[0],temp=0;
        for(int i=0;ires)res=temp;
            if(temp<0)temp=0;
        }
        return res;
    }
};

31.整数中1出现的次数

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int res=0,cur=1,right,left,num;
        while(n/cur){
            left=n/cur/10;
            right=n%cur;
            num=n/cur%10;
            if(num==0)res+=left*cur;
            else if(num==1)res+=left*cur+right+1;
            else res+=(left+1)*cur;
            cur*=10;
        }
        return res;
    }
};

32.把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

class Solution {
public:
    string PrintMinNumber(vector numbers) {
        sort(numbers.begin(),numbers.end(),cmp);
        string res;
        for(auto it:numbers)res+=to_string(it);
        return res;
        
    }
    
    bool static cmp(int a,int b){
        return to_string(a)+to_string(b)

33.丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index<1)return 0;
        vector res(index); //空间换时间
        res[0]=1;
        int cur2=0,cur3=0,cur5=0;
        for(int i=1;i

 

34.第一个只出现一次的字符

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        unordered_map mp;
        for(auto c:str)++mp[c];
        for(int i=0;i

35.数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

class Solution {
public:
    int mod=1000000007;
    int InversePairs(vector data) {
        if(data.size()<=1)return 0;
        vector copy(data);
        int res=fun(data,copy,0,data.size()-1);
        return res;
    }
    int fun(vector &data,vector ©, int start, int end ){
        if(start==end)
        {
            copy[start]=data[start];
            return 0;
        }
        int length=(end-start)/2;
        int left=fun(copy,data,start,start+length);
        int right=fun(copy,data,start+length+1,end);
        
        int i=start+length;
        int j=end;
        int indexcopy=end;
        int count=0;
        while(i>=start && j>=start+length+1){
            if(data[i]>data[j]){
                copy[indexcopy--]=data[i--];
                count=(count+j-(start+length))%mod;
            }
            else copy[indexcopy--]=data[j--];
        }
        while(i>=start)copy[indexcopy--]=data[i--];
        while(j>=start+length+1)copy[indexcopy--]=data[j--];
        return (left+right+count)%mod;
    }
};

36.两个链表的第一个公共结点

输入两个链表,找出它们的第一个公共结点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1==NULL||pHead2==NULL)return NULL;
         ListNode* p1=pHead1,*p2=pHead2;
        while(p1!=p2){
            p1=p1==NULL?pHead2:p1->next;
            p2=p2==NULL?pHead1:p2->next;
        }
        return p1;
        
    }
};

37.数字在排序数组中出现的次数

统计一个数字在排序数组中出现的次数。

class Solution {
public:
    int GetNumberOfK(vector data ,int k) {
        if(data.size()==0||data[0]>k||data[data.size()-1]=k)right=mid;
            else left=mid+1;
        }
        if(data[left]!=k)return 0;
        int i=left;
        right=data.size()-1;
        while(left

38.二叉树的深度

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot==NULL)return 0;
        int l=TreeDepth(pRoot->left);
        int r=TreeDepth(pRoot->right);
        return max(l,r)+1;
    }
};

39.平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

class Solution {
public:
    bool res=true;
    bool IsBalanced_Solution(TreeNode* pRoot) {
        depth(pRoot);
        return res;
    }
    
    int depth(TreeNode* root){
        if(root==NULL)return 0;
        int l=depth(root->left);
        int r=depth(root->right);
        if(abs(l-r)>1)res=false;
        return max(l,r)+1;
    }
};

40.数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

class Solution {
public:
    void FindNumsAppearOnce(vector data,int* num1,int *num2) {
        int diff=0;
        for(auto it:data)diff^=it;
        diff&=-diff;
        *num1=*num2=0;
        for(auto it:data){
            if((it&diff)==0)*num1^=it;//与运算的括号不能忘
            else *num2^=it;
        }
    }
};

41.和为S的连续正数序列

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

class Solution {
public:
    vector > FindContinuousSequence(int sum) {
        vector> res;
        unordered_map mp;
        int cur=0;
        mp[0]=0;
        for(int i=1;i<=sum/2+1;i++){
            cur+=i;
            if(mp.find(cur-sum)!=mp.end()){
                int j=mp[cur-sum]+1;
                if(i>j){
                    vector temp;
                    for(;j<=i;j++)
                        temp.push_back(j);
                    res.push_back(temp);
                }
            }
            mp[cur]=i;
        }
        return res;
    }
};

42.和为S的两个数字

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

class Solution {
public:
    vector FindNumbersWithSum(vector array,int sum) {
        unordered_mapmp;
        int res=-1;
        for(int i=0;i0)res=array[i];
            mp[array[i]]++;
        }
        if(res==-1)return {};
        return {sum-res,res};
    }
};

43.左旋转字符串

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它

class Solution {
public:
    string LeftRotateString(string str, int n) {
        if(str.size()==0||n==0)return str;
        n=n%str.size();
        reverse(str.begin(),str.begin()+n);
        reverse(str.begin()+n,str.end());
        reverse(str.begin(),str.end());
        return str;
    }
};

44.翻转单词顺序列

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

class Solution {
public:
    string ReverseSentence(string str) {
        if(str=="")return str;
        reverse(str.begin(),str.end());
        int i=0;
        while(i

45.扑克牌顺子

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

class Solution {
public:
    bool IsContinuous( vector numbers ) {
        if(numbers.size()<3)return false;
        sort(numbers.begin(),numbers.end());
        int num0=0;
        int numgap=0;
        for(int i=0;i1)numgap+=numbers[i+1]-numbers[i]-1;
        }
        return num0>=numgap;
    }
};

46.求1+2+3+...+n

求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

class Solution {
public:
    int Sum_Solution(int n) {
        int res=0;
        n&&(res=n+Sum_Solution(n-1));
        return res;
    }
};

47.不用加减乘除做加法

 

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

class Solution {
public:
    int Add(int num1, int num2)
    {
        return num2?Add(num1^num2,(num1&num2)<<1):num1;
    }
};

48.把字符串转换成整数

将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。

class Solution {
public:
	int StrToInt(string str) {
		if (str == "")return 0;
		if (!valid(str))return 0;
		bool negative = str[0] == '-' ? true : false;
		int minq = INT_MIN / 10;
		int minr = INT_MIN % 10;
		int res = 0, cur = 0;
		for (int i = (negative || str[0] == '+') ? 1 : 0; i'9')return false;
		}
		else if (str.size() == 1 || str[1] == '0')return false;
		if (str.size()>1 && str[0] == '0')return false;
		for (int i = 1; i'9')return false;
		}
		return true;
	}
};

49.数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
        for(int i=0;i

50.构建乘积数组

给定一个数组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 multiply(const vector& A) {
        vector res(A.size());
        int temp=1;
        for(int i=0;i=0;i--){
            res[i]*=temp;
            temp*=A[i];
        }
        return res;
    }
};

51.正则表达式匹配

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

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if(str==NULL || pattern==NULL)return false;
        return func(str,pattern);
    }
    
    bool func(char* str,char* pattern){
        if(*str==0&&*pattern==0)return true;
        if(*str!=0&&*pattern==0)return false;
        if(*(pattern+1)=='*'){
            if(*pattern==*str||(*pattern=='.'&&*str!=0))
                return func(str+1,pattern+2)||func(str+1,pattern)||func(str,pattern+2);
            else return func(str,pattern+2);
        }
        if(*str==*pattern||(*pattern=='.'&&*str!=0))
            return func(str+1,pattern+1);
        return false;
    }
};

52.表示数值的字符串

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

class Solution {
public:
    bool isNumeric(char* string)
    {
        if(string==NULL)return false;
        bool num=scanInt(&string);
        if(*string=='.'){
            ++string;
            num=scanUint(&string)||num;
        }
        if(*string=='e'||*string=='E'){
            ++string;
            num=num&&scanInt(&string);
        }
        return num&&*string==0;
    }
    bool scanUint(char** str){
        char* before=*str;
        while(**str!=0 && **str >= '0' && **str <= '9')++(*str);
        return *str>before;
    }
    bool scanInt(char** str){
        if(**str=='+'||**str=='-')++(*str);
        return scanUint(str);
    }

};

53.字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

class Solution
{
public:
  //Insert one char from stringstream
    void Insert(char ch)
    {
         s+=ch;
        mp[ch]++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {
        while(cur1)cur++;
        if(cur==s.size())return '#';
        return s[cur];
    }
    string s;
    int cur=0;
    mapmp;

};

54.链表环的入口节点

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

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        ListNode* fast=pHead,*slow=pHead;
        do{
            if(fast==NULL||fast->next==NULL)return NULL;
            fast=fast->next->next;
            slow=slow->next;
        }while(fast!=slow);
        fast=pHead;
        while(fast!=slow){
            fast=fast->next;
            slow=slow->next;
        }
        return fast;
            
    }
};

55.删除链表中重复的节点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表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;
        ListNode *pre=NULL, *cur=pHead,*next;
        while(cur!=NULL){
            next=cur->next;
            if(next!=NULL && next->val==cur->val){
                while(next!=NULL && next->val==cur->val)next=next->next;
                if(pre==NULL)pHead=next;
                else pre->next=next;
                cur=next;
            }
            else{
                pre=cur;
                cur=next;
            }
        }
        return pHead;
    }
};

56.二叉树的下一个节点

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

/*
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->right==NULL){
            TreeLinkNode* cur = pNode;
            TreeLinkNode* next = pNode->next;
            while(next && next->right==cur){
                cur=next;
                next=next->next;
            }
            return next;
        }
        TreeLinkNode* cur=pNode->right;
        while(cur->left){
            cur=cur->left;
        }
        return cur;
    }
};

57.对称的二叉树

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)//审清题意!!
    {
        if(pRoot==NULL)return true;
        return isSymmetrical(pRoot->left,pRoot->right);
       
    }
    bool isSymmetrical(TreeNode* l,TreeNode* r)
    {
        if(l==NULL&&r==NULL)return true;
        if(l==NULL||r==NULL)return false;
        return (l->val==r->val)&&isSymmetrical(l->right,r->left)&&isSymmetrical(l->left,r->right);
    }

};

58.按之字形打印二叉树

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

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector > Print(TreeNode* pRoot) {
        vector> res;
        if(pRoot==NULL)return res;
        queue q;
        q.push(pRoot);
        int pre,cur=1,level=1;
        while(!q.empty()){
            vector temp;
            pre=cur;
            cur=0;
            for(int i=0;ival);
                if(front->left)q.push(front->left),cur++;
                if(front->right)q.push(front->right),cur++;
                
            }
            if(level++%2==0)reverse(temp.begin(),temp.end());
            res.push_back(temp);
        }
        return res;
    }
    
};

59.把二叉树打印成多行

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

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
        vector > Print(TreeNode* pRoot) {
            queue q;
            vector>res;
            if(pRoot==NULL)return res;
            q.push(pRoot);
            int count=1;
            while(!q.empty()){
                int num=count;
                count=0;
                vector v;
                for(int i=0;ival);
                    if(f->left){q.push(f->left);count++;}
                    if(f->right){q.push(f->right);count++;}
                }
                res.push_back(v);
            }
            return res;
        }
    
};

60.序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    char* Serialize(TreeNode *root) {
        string str;
        ser(root,str);
        char* res=new char[str.size()+1];
        for(int i=0;ival)+",";
        ser(root->left,str);
        ser(root->right,str);
    }
    TreeNode* Deserialize(char *str) {
        return deser(&str);
    }
    TreeNode* deser(char** str){
        if(**str=='#'){
            (*str)++;
            return NULL;
        }
        int num=0,negative=1;
        if(**str=='-'){
            negative=-1;
            (*str)++;
        }
        while(**str!=0 && **str!=','){
            num=num*10+(**str)-'0';
            (*str)++;
        }
        TreeNode* root=new TreeNode(num*negative);
        if(**str==0)return root;
        else (*str)++;
        root->left=deser(str);
        root->right=deser(str);
        return root;
    }
};

61.二叉搜索树的第k个节点

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        if(pRoot==NULL||k<=0)return NULL;
        return func(pRoot,k);
    }
    TreeNode* func(TreeNode* root, int& k)
    {
        TreeNode* res=NULL;
        if(root->left)res=func(root->left,k);
        if(res==NULL){
            if(k==1)return root;
               k--;
        }
        if(res==NULL && root->right)res=func(root->right,k);
        return res;
        
    }   
};

62.数据流的中位数

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

class Solution {
public:
    priority_queue,less> smallq;
    priority_queue,greater> bigq;
    
    void Insert(int num)
    {
        if(smallq.empty()||num

63.滑动窗口的最大值

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

class Solution {
public:
    vector maxInWindows(const vector& num, unsigned int size)
    {
        vector res;
        if(num.size() dq;
        for(int i=0;i=size-1)res.push_back(num[dq.front()]);
        }
        return res;
        
    }
};

64.矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

class Solution {
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        if(matrix==NULL||rows<1||cols<1||str==NULL)return false;
        vector visit(rows*cols,false);
        int index=0;
        for(int i=0;i &visit){
        if(str[index]==0)return true;
        bool res=false;
        if(i>=0 && i=0 && j

65.机器人的运动范围

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

class Solution {
public:
    int movingCount(int threshold, int rows, int cols)
    {
        int res=0;
        vector> visit(rows,vector(cols));
        dfs(threshold,rows,cols,0,0,visit,res);
        return res;
    }
    void dfs(int threshold, int rows, int cols, int i, int j,vector> &visit, int &res){
        if(i>=0 && i=0 &&j

66.剪绳子

给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

class Solution {
public:
    int cutRope(int number) {
        if(number==2)return 1;
        if(number==3)return 2;
        int res=1;
        while(number>4){
            res*=3;
            number-=3;
        }
        return res*number;
    }
};

 

你可能感兴趣的:(算法,C++)