1、编写赋值运算符
四点:返回值、参数类型、释放已有内存、自身赋值特殊情况。
进阶:异常安全性。1
2
3
4
5
6
7
8
9
10
11CMyString& CMyString::operator=(const CMyString& rhs)
{
	if(this!=&rhs)
	{
		CMyString temp(rhs);//调用copy构造函数
		char* ptemp=temp.m_pData;
		temp.m_pData=m_pData;
		m_pData=ptemp;
	}
	return *this;
}
2、简单实现一个Singleton类。
1  | class singleton  | 
3、找出数组中重复的数字。
1  | int question3_3(vector<int>& vec)  | 
4、二维数组中的查找
1  | bool Find(int target, vector<vector<int> > array) {  | 
5、替换空格
1  | void replaceSpace(char *str,int length) {  | 
6、从尾到头打印链表。
1  | void Recursion(ListNode* head, vector<int> &res)  | 
反转链表:
1  | ListNode* ReverseList(ListNode* head)  | 
树的四种遍历七种写法:
1  | void PreorderTra_Loop(TreeNode * root)//先序循环  | 
7、重建二叉树。
1  | TreeNode* recursion(vector<int>& pre,const int preStart,const int preEnd,vector<int>& vin,const int vinStart,const int vinEnd)  | 
8、二叉树的下一节点
1  | BinaryTreeNode* GetNext(BinaryTreeNode* pNode)  | 
9、用两个栈实现队列
1  | class Solution  | 
10、斐波那契数列。
最容易想到的是递归,但是递归效率低下,栈可能溢出,在面试中最好使用从下往上的循环而不用递归。
利用从下往上循环的DP解法如下:1
2
3
4
5
6
7int Fibonacci(int n) {
        vector<int> dp(n+1,0);
        dp[1]=1;
        for(int i=2;i<=n;i++)
            dp[i]=dp[i-1]+dp[i-2];
        return dp[n];
    }
快排:
1  | int Partition(vector<int>& data, int start, int end)  | 
11、旋转数组的最小数字
最好利用二分查找,时间效率快。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33int MinInOrder(vector<int> & rotateArray,int left,int right)
    {
        int small=rotateArray[left];
        for(int i=left+1;i<=right;i++)
            if(rotateArray[i]<small)
                small=rotateArray[i];
        return small;
    }
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size()<=0)
            return 0;
        int left=0,right=rotateArray.size()-1;
        int mid=left;
        while(rotateArray[left]>=rotateArray[right])
        {
            if(right-left==1)
            {
                mid=right;
                break;
            }
            mid=left+((right-left)>>1);
            //如果left、right、mid指向的三个数字相同,则只能进行顺序查找
            if(rotateArray[left]==rotateArray[right]&&rotateArray[right]==rotateArray[mid])
                return MinInOrder(rotateArray,left,right);
            
            if(rotateArray[left]<=rotateArray[mid])
                left=mid;
            else if(rotateArray[right]>=rotateArray[mid])
                right=mid;
        }
        return rotateArray[mid];
    }
12、矩阵中的路径(回溯法)
1  | bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int& pathLength, bool* visited);  | 
13、机器人的运动范围
1  | class Solution {  | 
14、剪绳子
动态规划和贪婪法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42//常规动态规划方法,要求至少剪一刀
int maxProductAfterCutting(int length)
{
	if (length < 2)
		return 0;
	if (length == 2)
		return 1;
	if (length == 3)
		return 2;
	vector<int> dp(length+1, 0);
	dp[0] = 0;
	dp[1] = 1;
	dp[2] = 2;
	for (int i = 3; i < length+1; i++)
	{
		int max = i ;
		for (int j = 1; j < i; j++)
		{
			int cur = dp[i - j] * dp[j];
			if (cur > max)
				max = cur;
		}
		dp[i] = max;
	}
	return dp[length];
}
//贪婪法:需要想到数学证明
int maxProductAfterCutting_2(int length)
{
	if (length < 2)
		return 0;
	if (length == 2)
		return 1;
	if (length == 3)
		return 2;
	int timeOf3 = length / 3;
	if (length % 3 == 1)
		timeOf3--;
	int timeOf2 = (length - 3 * timeOf3) / 2;
	return (int)(pow(3, timeOf3))*(pow(2, timeOf2));
}
15、判断二进制数中1 的个数
1  | int NumberOf1(int n) {  | 
16、数值的整数次方
注意:本例虽然过了,但是double 型数值的比较建议使用范围比较1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32class Solution {
public:
    double PowerWithAbsexponent(double base,int exponent)
    {
        if(exponent==0)
            return 1;
        if(exponent==1)
            return base;
        double result=PowerWithAbsexponent(base,exponent>>1);
        result*=result;
        if((exponent&0x1)==1)
            result*=base;
        return result;
        
    }
    double Power(double base, int exponent) {
        if(exponent==0)
            return 1;
        if(base==0.0&&exponent<0)
        {
            InvalidInput=true;
            return 0.0;
        }
        int absExponent=(exponent>0)?exponent:(0-exponent);
        double result=PowerWithAbsexponent(base,absExponent);
        if(exponent<0)
            result=1/result;
        return result;
    }
private:
    bool InvalidInput=false;
};
17、打印从1到最大的n位数
1  | void Print1ToMaxOfNDigits_2(int n)  | 
18
18-1、删除链表结点
1  | void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)  | 
18-2 删除链表中重复结点
1  | ListNode* deleteDuplication(ListNode* pHead)  | 
19、正则表达式匹配
1  | bool match(const char* str, const char* pattern)  | 
20、表示数值的字符串
1  | bool isNumeric(const char* str)  | 
21、调整数组顺序使奇数位于偶数前面
1  | void reOrderArray(vector<int> &array) {  | 
23、找链表环的入口。
1  | ListNode* EntryNodeOfLoop(ListNode* pHead)  | 
24、反转链表
1  | ListNode* ReverseList(ListNode* pHead) {  | 
25、合并两个有序链表
递归:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(!pHead1&&!pHead2)
            return NULL;
        if(!pHead1)
            return pHead2;
        if(!pHead2)
            return pHead1;
        
        ListNode* node=NULL;
        if(pHead1->val<pHead2->val)
        {
            node=pHead1;
            node->next=Merge(pHead1->next,pHead2);
        }
        else
        {
            node=pHead2;
            node->next=Merge(pHead1,pHead2->next);
        }
        return node;
    }
26、树的子结构
递归1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27bool HasOrNo(TreeNode* r1, TreeNode* r2)
    {
        if(!r1&&r2)
            return false;
        if(!r2)
            return true;
        if(r1->val!=r2->val)
            return false;
        
        return HasOrNo(r1->left,r2->left)&&HasOrNo(r1->right,r2->right);
    }
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(!pRoot1)
            return false;
        if(!pRoot2)
            return false;
        
        bool flag=false;
        if(pRoot1->val==pRoot2->val)
            flag=HasOrNo(pRoot1,pRoot2);
        if(!flag)
            flag=HasOrNo(pRoot1->left,pRoot2);
        if(!flag)
            flag=HasOrNo(pRoot1->right,pRoot2);
        return flag;
    }
27、二叉树的镜像
1  | void Mirror(TreeNode *pRoot) {  | 
28、对称的二叉树
1  | bool isSymmetrical(TreeNode* left,TreeNode* right);  | 
29、顺时针打印矩阵
1  | void PrintMatrixInCircle(vector<vector<int> > &matrix,const int start,vector<int>& res)  | 
30、包含min的栈
1  | class Solution {  | 
31、栈的压入弹出序列
1  | bool IsPopOrder(vector<int> pushV,vector<int> popV) {  | 
32、从上到下打印二叉树(即层次遍历,具体代码看上面树的遍历代码)
题目扩展:每一层结点占一行,换行打印1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71vector<vector<int> > Print(TreeNode* pRoot) {
            vector<vector<int> > res;
            if(!pRoot)
                return res;
            queue<TreeNode*> q;
            TreeNode* lineLast;
            TreeNode* nextLineLast;
            lineLast=nextLineLast=pRoot;
            vector<int> line;
            q.push(pRoot);
            while(!q.empty())
            {
                TreeNode* f=q.front();
                line.push_back(f->val);
                if(f->left)
                {
                    q.push(f->left);
                    nextLineLast=f->left;
                }
                if(f->right)
                {
                    q.push(f->right);
                    nextLineLast=f->right;
                }
                if(f==lineLast)
                {
                    res.push_back(line);
                    line.clear();
                    lineLast=nextLineLast;
                }
                q.pop();
            }
            return res;
        }
扩展二:之字形打印
vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int> > res;
	if (!pRoot)
		return res;
	vector<stack<TreeNode*>> stacks(2);
	int stacksIndex = 0;//stacks[0]从左到右
	stacks[0].push(pRoot);
	vector<int> line;
	while (!stacks[0].empty() || !stacks[1].empty())
	{
		TreeNode* f = stacks[stacksIndex].top();
		stacks[stacksIndex].pop();
		line.push_back(f->val);
		if (stacksIndex == 0)//下一层从右往左
		{
			if (f->right)
				stacks[1].push(f->right);
			if (f->left)
				stacks[1].push(f->left);
		}
		else{
			if (f->left)
				stacks[0].push(f->left);
			if (f->right)
				stacks[0].push(f->right);
		}
		if (stacks[stacksIndex].empty()){
			reverse(line.begin(), line.end());
			res.push_back(line);
			line.clear();
			stacksIndex = 1 - stacksIndex;
		}
	}
	return res;
    }
33、二叉搜索树的后序遍历序列
1  | bool VerifySquenceOfBST(vector<int> sequence) {  | 
34、二叉树中和为某一值的路径
1  | void backTracking(TreeNode* root,int expectNum,vector<vector<int> > &res,vector<int> &path)  | 
35、复杂链表的复制
1  | //1克隆节点  | 
36、二叉搜索树与双向链表
1  | void InOrder(TreeNode* root,TreeNode *&node)//指针的引用  | 
37、序列化二叉树
1  | //牛客  | 
38、字符串的排列
1  | void Recursive(int index,string& str,vector<string>& res)  | 
kmp算法实现:
1  | int strStr(string haystack, string needle) {  | 
39、数组中出现次数超过一半的数字
1  | int MoreThanHalfNum_Solution(vector<int> numbers) {  | 
40、最小的k个数
以下实现使用最大堆,也可用基于红黑树实现的set。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        if(k>input.size()||k<=0||input.size()<=0)
            return res;
        for(int i=0;i<k;i++)
            res.push_back(input[i]);
        make_heap(res.begin(),res.end());//构造堆
        for(int i=k;i<input.size();i++)
        {
            if(input[i]<res[0])//比堆顶数小
            {
                res.push_back(input[i]);
                push_heap(res.begin(),res.end());
                pop_heap(res.begin(),res.end());
                res.pop_back();
            }
        }
        sort_heap(res.begin(),res.end());
        return res;
    }
41、数据流中的中位数
1  | template<typename T> class DynamicArray  | 
42、连续子数组的最大和
1  | int FindGreatestSumOfSubArray(vector<int> array) {  | 
43、1~n整数中1出现的次数
1  | int NumberOf1Between1AndN_Solution(int n)  | 
44、数字序列中某一位的数字
1  | int countOfIntegers(int digits);  | 
45、把数组排成最小的数
1  | string PrintMinNumber(vector<int> numbers) {  | 
46、把数字翻译成字符串
1  | //dp  | 
47、礼物的最大价值
1  | int getMaxValue_solution1(const int* values, int rows, int cols)  | 
48.、最长不包含重复字符的子字符串
1  | int longestSubstringWithoutDuplication_2(const std::string& str)  | 
49、丑数
1  | int Min(int n1,int n2,int n3){  | 
50、第一次只出现一次的字符
1  | int FirstNotRepeatingChar(string str) {  | 
50_2、字符流中出现一次的第一个字符
1  | class Solution  | 
51、数组中的逆序对
1  | int InversePairs(vector<int> data) {  | 
52、两个链表的第一个公共结点
1  | ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {  | 
53、数字在排序数组中出现的次数
1  | int GetNumberOfK(vector<int> data ,int k) {  | 
53_2:0~n-1中缺失的数字
1  | int GetMissingNumber(const int* numbers, int length)  | 
54、二叉搜索树的第k大节点
1  | TreeNode* Inorder(TreeNode* root,int& k){  | 
55、二叉树的深度
1  | int TreeDepth(TreeNode* pRoot)  | 
56_1:数组中只出现一次的两个数字
1  | void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {  | 
56_2:数组中唯一只出现一次的数字,其他数字出现三次
1  | int FindNumberAppearingOnce(int numbers[], int length)  | 
57_1、和为s的两个数字
1  | vector<int> FindNumbersWithSum(vector<int> array,int sum) {  | 
57_2、和为s的连续正数序列
1  | vector<vector<int> > FindContinuousSequence(int sum) {  | 
58_1、翻转单词顺序
1  | string ReverseSentence(string str) {  | 
58_2:左旋转字符串
1  | //ReverseString方法与上题相同  | 
59_1、滑动窗口的最大值
1  | vector<int> maxInWindows(const vector<int>& num, unsigned int size)  | 
60、n个骰子的点数
1  | void PrintProbability_Solution2(int number)  | 
61、扑克牌中的顺子
1  | bool IsContinuous( vector<int> numbers ) {  | 
62、圆圈中最后剩下的数字(约瑟夫环)
1  | //经典环状链表解决  | 
63、股票的最大利润
1  | int MaxDiff(const int* numbers, unsigned length)  | 
64、求1+2+3+……+n
1  | int Sum_Solution(int n) {  | 
65、不用加减乘除做加法
1  | int Add(int num1, int num2)  | 
66、构建乘积数组
1  | vector<int> multiply(const vector<int>& A) {  | 
67、字符串转换成数字
1  | class Solution {  | 
68、二叉树公共父节点
1  | bool GetNodePath(TreeNode* root, TreeNode* node, vector<TreeNode*>& path){  | 
四个string函数
1  | int my_strlen(const char* str)  | 
四个图算法
1  | //迪杰斯特拉算法  | 
常用排序算法总结
1  | //冒泡排序  |