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 | //冒泡排序 |