1.赋值运算符重载
- 赋值运算符函数的参数为const引用类型;----->若类型为类,会产生临时对象,调用复制构造函数。
- 赋值运算符函数的返回值为引用类型;----->若类型为类,则连续赋值语句编译不通过(类型不匹配)、会产生临时对象,调用复制构造函数。
- 检查赋值的对象是否和this是同一个;----->
- 赋值的对象和this不是同以对象,则需要先释放原有对象;----->以防内存泄漏
//==================================================================
// author:pb
// date:2019-06-04
//==================================================================
#include "pch.h"
#include <iostream>
class CData {
public:
CData(const char* data);
CData(const CData& data);
CData& operator =(const CData& data);
char* GetData();
~CData();
private:
char* m_data;
};
CData::CData(const char* data = nullptr)
{
std::cout << "this is construction function" << std::endl;
if (data == nullptr)
{
m_data = new char[1];
*m_data = '\0';
}
else
{
m_data = new char[strlen(data) + 1];
strcpy(m_data, data);
}
}
CData::~CData()
{
delete[] m_data;
}
CData::CData(const CData& data)
{
std::cout << "this is copy constructor function" << std::endl;
m_data = new char[strlen(data.m_data) + 1];
strcpy(m_data, data.m_data);
}
CData& CData::operator =(const CData& data)
{
std::cout << "this is assignment operator function" << std::endl;
if (&data == this)
return *this;
delete[] m_data;
m_data = nullptr;
m_data = new char[strlen(data.m_data) + 1];
strcpy(m_data, data.m_data);
return *this;
}
char* CData::GetData()
{
return m_data;
}
void test1()
{
const char* str = "you are a nice man!";
CData d1(str);
std::cout << "test1 d1.m_data:" << d1.GetData() << std::endl;
CData d2 = d1;//调用复制构造函数
std::cout << "test1 d2.m_data:" << d2.GetData() << std::endl;
CData d3;
d3 = d1;//调用运输算符重载函数
std::cout << "test1 d3.m_data:" << d3.GetData() << std::endl;
d3 = d3;
d1 = d2 = d3;
}
int main()
{
test1();
getchar();
}
2.单例模式实现(Singleton)
- 构造函数为private或protected(即不能实例化)
- Instance的类型为静态的CSingleton
- _instance指针为static
//==================================================================
// author:pb
// date:2019-06-05
//==================================================================
#include "stdafx.h"
class CSingleton {
public:
int m_data;
public:
static CSingleton* Instance()
{
return _instance;
}
private:
CSingleton() {};//必须有函数体
static CSingleton* _instance;
};
CSingleton* CSingleton::_instance = new CSingleton();
int main()
{
CSingleton *sg = CSingleton::Instance();
sg->m_data = 10;
return 0;
}
3.数组中重复的数字
题目一:找出数组中重复的数字(数字范围0~n-1),如{2,3,1,0,2,5,3}则输出2,3
思路一:排序再遍历,时间复杂度为O(nlogn)
思路二:哈希表,时间复杂度为O(n),空间复杂度为O(n)
思路三:交换
bool duplicate(int numbers[], int length, int* duplication)
{
if (numbers == nullptr || length <= 0)
return false;
for (int i = 0; i < length; ++i)
{
if (numbers[i] < 0 || numbers[i] > length-1)
return false;
}
int *tmp_arr = new int[length]();//1.new,每个元素都初始化为0
for (int i = 0; i < length; ++i)
{
tmp_arr[numbers[i]]++;
}
if (tmp_arr[*duplication] > 1)
{
delete[] tmp_arr;
return true;
}
else
{
delete[] tmp_arr;
return false;
}
}
题目一:找出数组中重复的数字(数字范围0~n,数组长度为n+1,即至少有一个数字重复),要求不能改变原有数组
思路:利用二分查找的思想,时间复杂度O(nlogn)
4.二维数组查找
题目:二维数组如下从向右、向下递增,判断某值在不在该二维数组
思路一:遍历,时间复杂度为O(n*m)
思路二:首先选取右上角的数字和目标值比较,如果目标值小于右上角的值(图中的9),就剔除该列,依次右上角(图中的8)比较,直到小于目标值时,停止列比较,换行比较,选左上角(图中的1),往下依次剔除。
5.替换字符串中的空格
题目:字符串中的空格替换为“%20”,如“We are harry.”---->"We%20are%20harry."
思路一:遍历,1个字符替换成3个字符,需要移动后面的字符串,时间复杂度O(n2)
思路一:先遍历一遍,计算出空格的个数,从而计算出替换后字符串的总长度,然后用双指针,从后往前,依次填充、移动,时间复杂度为O(n)
6.从尾到头打印单链表
思路一:翻转链表,再打印,但是会改变结构
思路二:使用栈
思路三:使递归(和栈同样的思想),但递归的方法会有栈溢出的风险(链表过长的话)
void PrintReversedOrder(ListNode* head)
{
std::stack<int> slist;
while (nullptr != head)
{
slist.push(head->val);
head = head->next;
}
while (!slist.empty())
{
std::cout << slist.top() << " ";
slist.pop();
}
std::cout << "\n";
}
void PrintReversedOrderByRecurisive(ListNode* head)
{
if (nullptr == head)
return;
PrintReversedOrderByRecurisive(head->next);
std::cout << head->val << " ";
}
7.重建二叉树
题目:根据前序、中序的结果来构建二叉树,输出根节点(数字不重复),如前序{1,2,4,7,3,5,6,8},中序{4,7,2,1,5,3,8,6},返回该二叉树的根节点
思路:根据前序的第一个节点为根节点的特性(例子中的数字1),再从中序中找出该数字的位置,则该位置的前面都为左子树的部分(4,7,2),该节点的后面都为右子树的部分(5,3,8,6);然后是递归的调用。
// 007_ConstructBinaryTree.cpp: 定义控制台应用程序的入口点。
//==================================================================
// author:pb
// date:2019-06-06
//==================================================================
#include "stdafx.h"
#include<vector>
#include<iostream>
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
};
TreeNode* _Construct(std::vector<int> &preOrder,
int preStart,
int preEnd,
std::vector<int> &inOrder,
int inStart,
int inEnd)
{
TreeNode* root = new TreeNode(preOrder[preStart]);
if (preStart == preEnd) return root;
int partion = preStart;
for (int i = inStart; i <= inEnd; ++i)
{
if (inOrder[i] == preOrder[preStart])
{
partion = i;
break;
}
}
std::cout << "preStart=" << preStart << " preEnd=" << preEnd << " inStart=" << inStart << " inEnd=" << inEnd << " partion="<< partion <<std::endl;
int len = partion - inStart;
//if (preStart < preEnd && partion > inStart)
if(len > 0)
{
//root->left =_Construct(preOrder, preStart+1, partion, inOrder, inStart, partion-1);
root->left = _Construct(preOrder, preStart + 1, preStart+len, inOrder, inStart, partion - 1);
}
//if (inStart < inEnd && partion < inEnd)
if(len < preEnd - preStart)
{
//root->right = _Construct(preOrder, partion + 1, preEnd, inOrder, partion + 1, inEnd);
root->right = _Construct(preOrder, preStart + len + 1, preEnd, inOrder, partion + 1, inEnd);
}
return root;
}
TreeNode* Construct(std::vector<int> &preOrder, std::vector<int> &inOrder)
{
if (preOrder.size() <= 0 || inOrder.size() <= 0)
return nullptr;
return _Construct(preOrder, 0, preOrder.size() - 1, inOrder, 0, inOrder.size()-1);
}
void Test()
{
std::vector<int> preOrder{ 1, 2, 4, 7, 3, 5, 6, 8 };
std::vector<int> inOrder{ 4, 7, 2, 1, 5, 3, 8, 6 };
TreeNode* root = Construct(preOrder, inOrder);
}
int main()
{
Test();
getchar();
return 0;
}
8.二叉树的下一个节点
题目:给出二叉树和一个节点,找出中序遍历的下一个节点
9.用两个栈实现一个队列
注意:注意实现队列的入队、出队,用第一个栈s1入队,出队的时候从第二个栈s2弹出,关键一点是:出队是检测s2是否为空,若为空要把s1的元素以此弹出,压入s2,然后s2栈顶的元素为要出队的元素。
另:怎么用两个队列实现一个栈?
// 009_QueueWithTwoStack.cpp: 定义控制台应用程序的入口点。
//==================================================================
// author:pb
// date:2019-06-06
//==================================================================
#include "stdafx.h"
#include<stack>
#include<queue>
#include<assert.h>
template<typename T>
class squeue {
public:
squeue() {}
~squeue() {}
void spush(T &val)
{
s1.push(val);
}
T sfront()
{
if (s2.empty())
{
while (!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
assert(!s2.empty());
return s2.top();
}
void spop()
{
if (s2.empty())
{
while (!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
assert(!s2.empty());
return s2.pop();
}
private:
std::stack<T> s1;
std::stack<T> s2;
};
void Test1()
{
squeue<int> sq;
int a = 1;
int b = 2;
int c = 3;
sq.spush(a);
sq.spush(b);
sq.spush(c);
//sq.spop();
int ret = sq.sfront();
}
void Test2()
{
squeue<char> sq;
char a = 'a';
char b = 'b';
char c = 'c';
sq.spush(a);
sq.spush(b);
sq.spush(c);
sq.spop();
char ret = sq.sfront();
}
int main()
{
Test1();
Test2();
return 0;
}
10.斐波那契数列
// 010_Fibonacci.cpp: 定义控制台应用程序的入口点。
//==================================================================
// author:pb
// date:2019-06-06
//==================================================================
#include "stdafx.h"
#include<iostream>
//递归
int Fibonacci(int n)
{
if (n <= 1)
return n;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
//非递归
int Fibonacci1(int n)
{
if (n <= 1)
return n;
int last_one = 1;
int last_two = 0;
int ret = 0;
for (int i = 2; i <= n; ++i)
{
ret = last_one + last_two;
last_two = last_one;
last_one = ret;
}
return ret;
}
int main()
{
std::cout<< "Fibonacci(" << 10 << ")=" << Fibonacci(10) << std::endl;
std::cout << "Fibonacci1(" << 10 << ")=" << Fibonacci1(10) << std::endl;
std::cout << "Fibonacci1(" << 100 << ")=" << Fibonacci1(40) << std::endl;
std::cout << "Fibonacci(" << 100 << ")=" << Fibonacci(40) << std::endl;
getchar();
return 0;
}
11.旋转数组的最小值
题目:给出一个递增旋转过的数组,输出数组的最小值,如数组{3,4,5,1,2},最小值为1
思路一:遍历一遍,时间复杂度为O(n),不是本题所考察的点。
思路二:二分查找的思想
12.矩阵中的路径
13.机器人的运动范围
14.剪绳子
15.二进制中1的个数
思路一:按位右移,然后和1按位与。但遇到负数就会死循环
思路二:使用tmp=1和n按位与,然后按位左移,循环操作,直到tmp左移溢出变为0为止。
// 015_BinaryBit.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//==================================================================
// author:pb
// date:2019-06-06
//==================================================================
#include "pch.h"
#include <iostream>
int BinaryBit(int n)
{
int cnt = 0;
unsigned int tmp = 1;
while (tmp)
{
if (n & tmp)
++cnt;
tmp <<= 1;
}
return cnt;
}
void Test()
{
int ret = BinaryBit(1);
ret = BinaryBit(3);
ret = BinaryBit(0xFF88);
ret = BinaryBit(0x9999);
}
int main()
{
Test();
}