剑指offer

文章目录

        • 02-单例模式(SIngleton)
          • 饿汉单例模式
          • 懒汉单例模式
          • 两种模式比较
          • DCLP(双检查锁的风险)
        • 03-数组中重复的元素
          • 找出数组中重复的数字
        • 04-二维数组的查找
        • 05-替换空格
        • 10-斐波那契序列
        • 11-旋转数组的最小数字
        • 12-单词搜索
        • 13-机器人的运动范围
        • 14-减绳子
          • 动态规划
          • 贪婪算法
          • 柱状图中的最大矩形
            • 暴力解法
            • 单调递增栈解法
        • 15-二进制中的1的个数
        • 16-数值的整数次幂
        • 17-打印从1到最大的n位数
        • 18-删除链表的节点
        • 19-正则表达式匹配
          • leetcode-44-通配符匹配
        • 20-表示数值的字符串
        • 21-调整数组顺序使其奇数位于偶数前面
        • 22-链表中倒数第K个节点
        • 23-链表中环的入口节点
        • 24-反转链表
        • 25-合并两个有序链表
        • 26-树的子结构
        • 27-二叉树的镜像(引入智能指针)
        • 28-对称的二叉树
        • 29-顺时针打印矩阵
        • 30-包含min函数的栈
        • 31-栈的压入和弹出序列
        • 32-从上到下打印二叉树
          • 题目1:不分行从上到下打印二叉树
          • 题目2:分行从上到下打印二叉树
          • 题目3:之字形打印二叉树
            • 解法一:利用双栈
            • 解法二:利用双边数组deque
        • 33-二叉搜索树的后序遍历序列
        • 34-二叉树中和为某一值的路径
        • 35-复杂链表的复制
        • 36-二叉搜索树与双向链表
        • 37-序列化二叉树
        • 38-1-字符串排列
        • 38-2-字符串组合
        • 39-数组中出现次数超过一半的数字
        • 40-最小的K个数
        • 41-数据流中的中位数
        • 42-连续子数组的最大和
        • 43-1~n整数中1出现的次数
        • 44-数字序列中某一位的数字
        • 45-把数组排成最小的数
        • 46-把数字翻译成字符串(动态规划)
        • 47-礼物的最大价值
        • 48-最长不含重复字符的子字符串
        • 49-丑数
        • 50-第一个只出现一次的字符
          • 50-1-字符串中第一次只出现一次的字符
          • 50-2-字符流中第一个只出现一次的字符
        • 51-数组中的逆序对
        • 52-两个链表的第一个公共节点
        • 53-在排序数组中查找数字
          • 53-1-数字在排序数组中出现的次数
          • 53-2-0~n-1中缺失的数字
          • 53-3-数组中数值和下标相等的元素
        • 54- 二叉搜索树的第k大节点
        • 55-二叉树的深度
          • 55-1-二叉树的深度
          • 55-2-平衡二叉树
        • 56-数组中数字出现的次数
          • 56-1-数组中只出现一次的两个数字
          • 56-2-数组中唯一只出现一次的数字
        • 57-和为s的数字
          • 57-1-和为s的两个数字
          • 57-2-和为s的连续正数序列
        • 58-翻转字符串
          • 58-1-翻转单词顺序
          • 58-2-左旋转字符串
        • 59-队列的最大值
          • 59-1-滑动窗口的最大值
          • 59-2-队列的最大值
        • 60-n个骰子的点数
        • 61-扑克牌中的顺子
        • 62-圆圈中最后剩下的数字
        • 63-股票的最大利润
        • 64-求1+2+...+n
        • shared_ptr引用计数智能指针
        • 拓扑排序
        • 直接插入排序
        • 冒泡排序
        • 快速排序
        • 归并排序
        • 简单选择排序
        • 堆排序

02-单例模式(SIngleton)

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
饿汉单例模式
#include 
using namespace std;

//单例饿汉模式
class Singlean {
private:
	Singlean() {
		cout << "Singlean()" << endl;
	}
	static Singlean* instance;

public:
	static Singlean* GetSinglean() {
		return instance;
	}
	static Singlean* Destroy() {
		delete instance;
		instance = NULL;
	}
};
Singlean* Singlean::instance = new Singlean();

int main1() {
	Singlean *s1 = Singlean::GetSinglean();
	Singlean *s2 = Singlean::GetSinglean();
	Singlean *s3 = Singlean::GetSinglean();

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	system("pause");
	return 0;
}
结果分析:
Singlean()
0058CC70
0058CC70
0058CC70
懒汉单例模式
#include 
using namespace std;

//懒汉单例模式
class Singlean {
private://单例模式类的构造函数是private,不能直接通过构造函数实例化对象
	Singlean() {
		cout << "懒汉单例模式" << endl;
	}
	static Singlean* instrance;

public:
	static Singlean * GetSinglean() {
		if (instrance == NULL) {
			instrance = new Singlean();
		}
		return instrance;
	}
	static Singlean* Destroy() {
		delete instrance;
		instrance = NULL;
	}
};

Singlean* Singlean::instrance = NULL;

int main() {
	Singlean * s1 = Singlean::GetSinglean();
	Singlean * s2 = Singlean::GetSinglean();//静态成员变量通过类访问
	Singlean * s3 = Singlean::GetSinglean();

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	system("pause");
	return 0;
}
结果分析:
懒汉单例模式
007FCC70
007FCC70
007FCC70
两种模式比较
饿汉式单例模式:在类加载时就完成了初始化,所以类加载比较慢、获取对象的速度快、以空间换取时间模式、线程安全、

懒汉式单例模式:在类加载时不初始化、按照需求创建实例、以时间换取空间模式
  
DCLP(双检查锁的风险)
m_instance = new Singleton; 发生了什么:
  1.分配Singleton对象所需的内存
  2.为该内存区域执行构造函数
  3.m_instance指向该内存。
  一切都似乎没有什么问题,但是有时编译器喜欢把2和3替换下(先不管编译器出于什么目的)
执行单例化构造( m_instance = new Singleton; )的顺序中,其他线程访问对象程序未加锁【lock一般不阻止CPU线程调度程序,只对俩个线程里同样上了同个锁的部分函数有阻塞作用】,直接访问会出故障【操作未定义的对象】,又不能所有地方都加锁--效率低。
解决方法:在单例化构造中先构造给临时变量,再把临时变量赋值给单例化对象的指针,注意防止编译器优化,否则前功尽弃【当然,这种方式的弊端目前尚未考虑到】。
 
Singleton* Singleton::getInstance() { 
   volatile Singleton* tmp = m_instance; 
    ...                     // insert memory barrier 
    if (tmp == NULL) { 
        Lock lock; 
        tmp = m_instance; 
        if (tmp == NULL) { 
            tmp = new Singleton; 
            ...             // insert memory barrier 
            m_instance = tmp; 
        } 
    } 
    return tmp; 
} 

//防止DCLP问题

//C++ 11版本之后的跨平台实现 (volatile)
std::atomic Singleton::m_instance;
std::mutex Singleton::m_mutex;

Singleton* Singleton::getInstance() {
    Singleton* tmp = m_instance.load(std::memory_order_relaxed);
    std::atomic_thread_fence(std::memory_order_acquire);//获取内存fence
    if (tmp == nullptr) {
        std::lock_guard lock(m_mutex);
        tmp = m_instance.load(std::memory_order_relaxed);
        if (tmp == nullptr) {
            tmp = new Singleton;
            std::atomic_thread_fence(std::memory_order_release);//释放内存fence
            m_instance.store(tmp, std::memory_order_relaxed);
        }
    }
    return tmp;
}

03-数组中重复的元素

找出数组中重复的数字
题目:在一个长度为n的数组中的所有数字都在0~n-1的范围内,找出数组中重复的元素。

#include
using namespace std;
#include 
#include 


void duplicate(int nums[],int len,vector<int>&v) {
	if (nums == NULL || len <= 0) {
		return;
	}
	int i, m;
	for (i = 0; i < len; i++) {
		m = nums[i];
		if (m == i) {
			continue;
		}
		else {
			if (nums[i] == nums[m]) {
				v.push_back(nums[i]);
			}
			else {
				swap(nums[i], nums[m]);
			}
		}
	}
}

void print(int val) {
	cout << val << " ";
}

int main() {
	int nums[] = { 2,3,1,0,2,5,3 };
	int len = sizeof(nums) / sizeof(nums[0]);
	vector<int>v;

	duplicate(nums, len, v);

	for_each(v.begin(), v.end(), print);
	cout << endl;
	system("pause");
	return 0;
}

04-二维数组的查找

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

#include 
using namespace std;

//二维数组做参数
bool Find(int arr[][4], int r, int c, int number) {
	bool ret = false;
	if (arr == NULL) {
		return ret;
	}
	int row = 0;
	int column = c - 1;
	while (row < r && column >= 0) {
		if (number < arr[row][column]) {
			--column;
		}
		else if (number > arr[row][column]) {
			++row;
		}
		else {
			ret = true;
			break;
		}
	}
	return ret;
}

int main() {
	int arr[][4] = {
		{1,2,8,9},
		{2,4,9,12},
		{4,7,10,13},
		{6,8,11,15}
	};
	
	int r = sizeof(arr) / sizeof(arr[0]);
	int c = sizeof(arr[0]) / sizeof(arr[0][0]);
	bool ret = Find(arr,r,c,7);
	cout << ret << endl;
	
	system("pause");
	return 0;

}

05-替换空格

题目:请实现一个函数,把字符串中的每个空格替换成"%20".
#include 
using namespace std;
#include 
#include 
#include 
#include 

void ReplaceBlank(char string[], int len) {
	if (string == NULL || len <= 0) {
		return;
	}
	int i = 0, numberOfBlank = 0, newLength,oldlength = 0;
	while (string[i] != '\0') {
		if (string[i] == ' ') {
			numberOfBlank++;
		}
		i++;
		oldlength++;
	}
	newLength = len + 2 * numberOfBlank;
	
	int oldindex = oldlength;
	int newindex = newLength;
	while (oldindex >= 0 && newindex > oldindex) {
		if (string[oldindex] == ' ') {
			string[newindex--] = '0';
			string[newindex--] = '2';
			string[newindex--] = '%';
		}
		else {
			string[newindex--] = string[oldindex];
		}
		oldindex--;
	}
	
	
}

void print(char val) {
	cout << val;
}
int main() {
	
	//string str = "We are happy.";
	解法一:利用string容器的replace函数
	//for (int i = 0; i < str.size(); i++) {
	//	if (str[i] == ' ') {
	//		str.replace(i, 1, "%20");
	//	}
	//}
	//for_each(str.begin(), str.end(), print);

	//第二种解法
	char str1[] = "We are happy.";
	int len = strlen(str1);
	ReplaceBlank(str1, len);
	int i = 0;
	while (str1[i] != '\0') {
		cout << str1[i];
		i++;
	}
	cout << endl;
	

	system("pause");
	return 0;

}
第一种解法时间复杂度为O(n**2);
第二种解法的时间复杂度为O(n);

10-斐波那契序列

题目:青蛙跳台阶问题
#include 
using namespace std;


long Fibonacci(int n) {

	if (n == 1|| n == 2) {
		return n;
	}
	int i = 1;
	int j = 2;
	long fib = 0;
	for (int a = 3; a <= n; a++) {
		fib = i + j;
		i = j;
		j = fib;
		
	}
	return fib;
}
class Solution {
public:
	int jumpFloor(int number) {
		int n1 = 1;
		int n2 = 2;
		number--;
		while (number--)
		{
			n2 += n1;
			n1 = n2 - n1;
		}
		return n1;
	}
};

int main() {
	//解法1
	Solution s1;
	cout << s1.jumpFloor(8) << endl;
	
    //解法二
	long ret = Fibonacci(8);
	cout << ret << endl;
	
	
	system("pause");
	return 0;

}

11-旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

#include
using namespace std;
#include 

int MinInorder(const vector&v) {
	
	for (int i = 1; i < v.size(); i++) {
		if (v[i - 1] > v[i]) {
			return v[i];
		}
	}
}

int Min(vector&v) {
	if (v.size() == 0) {
		return 0;
	}
	if (v.size() == 1) {
		return v[0];
	}
	int index1 = 0;
	int index2 = v.size() - 1;
	int indexMid = index1;
	while (v[index1] >= v[index2])
	{
		if (index2 - index1 == 1)	// 循环结束条件
		{
			indexMid = index2;
			break;
		}
		indexMid = (index1 + index2) / 2;
		// 当下标为index1,index2和indexMid的值都相等时,只能顺序查找
		if (v[index1] == v[index2] && v[index1] == v[indexMid])
			return MinInorder(v);

		if (v[indexMid] >= v[index1])	// 在前面递增子数组
			index1 = indexMid;
		else if (v[indexMid] <= v[index2])
			index2 = indexMid;
		
	}
	return v[indexMid];

}



int main() {

	vectorv;
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(1);
	v.push_back(2);

	int ret = Min(v);
	cout << ret << endl;

	system("pause");
	return 0;
}

12-单词搜索

回溯法
#include 
using namespace std;
#include
#include 
#include 
#include 

bool dfs(const vector<vector<char>>&v, const string &str, int i, int j, int index, vector<pair<int, int>>&vp, int r, int c) {
	vector<pair<int, int>>::iterator it = find(vp.begin(), vp.end(), make_pair(i, j));
	if (i < 0 || j < 0 || i >= r || j >= c or v[i][j] != str[index] || it != vp.end()) {
		return false;
	}
	else if (v[i][j] == str[index] and index == str.size() - 1) {
		return true;
	}
	vp.push_back(pair<int, int>(i, j));
	return dfs(v, str, i - 1, j, index + 1, vp, r, c) || dfs(v, str, i + 1, j, index + 1, vp, r, c) || dfs(v, str, i, j - 1, index + 1, vp, r, c) || dfs(v, str, i, j + 1, index + 1, vp, r, c);
}

bool exit(const vector<vector<char>>&v,const string &str) {
	int r = v.size();
	int c = v[0].size();

	vector<pair<int, int>>vp;
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			if (v[i][j] == str[0]) {
				if (dfs(v, str, i, j, 0, vp, r, c)) {
					return true;
				}
			}
		}
	}
	return false;
}

int main() {
	vector<vector<char>>v;

	vector<char>v1;
	v1.push_back('a');
	v1.push_back('b');
	v1.push_back('t');
	v1.push_back('g');

	vector<char>v2;
	v2.push_back('c');
	v2.push_back('f');
	v2.push_back('c');
	v2.push_back('s');

	vector<char>v3;
	v3.push_back('j');
	v3.push_back('d');
	v3.push_back('e');
	v3.push_back('h');

	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);

	//cout << v.size() << endl;
	//cout << v[0].size() << endl;
	string str = "abfb";

	bool ret = exit(v, str);
	cout << ret << endl;

	system("pause");
	return 0;

}

13-机器人的运动范围

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

#include 
using namespace std;
#include 
#include 

void Fill(vector>&v, int m, int n) {
	vectorv1(n);
	fill(v1.begin(), v1.end(), false); //填充false
	for (int i = 0; i < m; i++) {
		v.push_back(v1);
	}
}

bool cheak(int num1,int num2,int k) {
	int sum = 0;
	while (num1)
	{
		sum += num1 % 10;
		num1 /= 10;
	}
	while (num2) {
		sum += num2 % 10;
		num2 /= 10;
	}

	return sum > k;
}

int movingCountCore(vector>&v,int r,int c,int rows,int cols,int k) {
	int count = 0;
	if (r >= 0 && c >= 0 && r < rows && c < cols && !cheak(r, c, k) && !v[r][c] ){
		v[r][c] = true;
		count = 1 + movingCountCore(v, r + 1, c, rows, cols, k) + movingCountCore(v, r - 1, c, rows, cols, k)
			+ movingCountCore(v, r, c + 1, rows, cols, k) + movingCountCore(v, r, c - 1, rows, cols, k);
	}
	
	return count;

}

int main() {
	vector>v;
	int m = 50;
	int n = 50;
	Fill(v, m, n);
	int k = 18;
	int ret = movingCountCore(v, 0, 0, m, n, k);
	cout << ret << endl; // 2200
	

	/*for (vector>::iterator it = v.begin(); it != v.end(); it++) {
		for (vector::iterator jt = (*it).begin(); jt != (*it).end(); jt++) {
			cout << *jt << " ";
		}
		cout << endl;
	}*/

	system("pause");
	return 0;
	
}

14-减绳子

动态规划
动态规划问题的特点:
	1.求一个问题的最优解
	2.整体最优解是依赖与各个子问题的最优解
	3.把大问题分解成若干个小问题
	4.从上往下分析问题,从下往上求解问题
本题中由于我们实现不知道剪在哪个位置是最优解,只好把所有的可能都尝试一遍,然后比较得出最优的剪法。数学语言表示的话就是 f(n) = max(f(i)*f(n-i))
    
#include 
using namespace std;
#include 

int maxProductAfterCutting(int length) {
	if (length < 2) {
		return 0;
	}
	else if (length == 2) {
		return 1;
	}
	else if (length == 3) {
		return 2;
	}
	int *products = new int[length + 1];
	products[0] = 0;
	products[1] = 1;
	products[2] = 2;
	products[3] = 3; //此上几位为占位,无用

	int max = 0;
	for (int i = 4; i <= length; i++) {
		max = 0;
		for (int j = 1; j <= i / 2; j++) {
			int product = products[j] * products[i - j];
			if (product > max) {
				max = product;
			}
			products[i] = max;
		}
	}
	max = products[length];
	return max;
}

int main() {

	int length = 10;

	int ret = maxProductAfterCutting(length);
	cout << ret << endl; //36

	system("pause");
	return 0;
}

贪婪算法
当 n>=5时,我们尽可能多地去剪长度为3的绳子段;当当剩下的长度为4时,把绳子剪成两段长度为2的绳子

#include 
using namespace std;

int maxProductAfterCutting_solution2(int length) {
	if (length < 2) {
		return 0;
	}
	else if (length == 2) {
		return 1;
	}
	else if (length == 3) {
		return 2;
	}
	//尽可能多地去剪长度为3的绳子段
	int timeof3 = length / 3;

	//当剩下的长度为4时,把绳子剪成两段长度为2的绳子
	if (length - timeof3 * 3 == 1) {
		timeof3--;
	}
	int timeof2 = (length - timeof3 * 3) / 2;
	return (pow(3, timeof3)*pow(2, timeof2));
}

int main() {
	int  length = 5;
	int ret = maxProductAfterCutting_solution2(length);
	cout << ret << endl;
	system("pause");
	return 0;
}

柱状图中的最大矩形
暴力解法
#include 
using namespace std;

int largestRectangleArea(int nums[], int length) {
	if (length == 0) {
		return NULL;
	}
	int maxare = nums[0];
	for (int i = 1; i < length - 1; i++) {
		int left = i - 1;
		int right = i + 1;
		while (left >= 0 && nums[left] >= nums[i]) {
			left--;
		}
		while (right < length && nums[right] >= nums[i]) {
			right++;
		}
		int midare = (right - left - 1) * nums[i];
		if (midare > maxare) {
			maxare = midare;
		}
	}
	return maxare;
}

int main() {

	int nums[] = { 0,2,1,5,6,2,3,0 };
	int length = sizeof(nums) / sizeof(nums[0]);
	//cout << length << endl;
	int ret = largestRectangleArea(nums, length);
	cout << ret << endl;
	system("pause");
	return 0;
}



单调递增栈解法
#include
#include 
using namespace std;
#include 
#include 
#include;
int largestRectangleArea(vector&v) {
	int length = v.size();
	stacks;
	int Max = 0;
	for (int i = 0; i < length; i++) {
		while (!s.empty() && v[s.top()] >= v[i]) {
			
			int temp = s.top();
			s.pop();
			int l;
			if (s.empty()) {
				l = i;
			}
			else {
				l = i - s.top() - 1;
			}
			Max = max(Max, l * v[temp]);
		}
		s.push(i);
	}
	while (!s.empty()) {
		int temp = s.top();
		s.pop();
		int l = 0;
		if (s.empty()) {
			l = length;
		}
		else {
			l = length - s.top() - 1;
		}
		Max = max(Max, l * v[temp]);
	}
	return Max;
}

int main() {
	vectorv = { 2,1,5,6,2,3 };
	int length = largestRectangleArea(v);
	cout << length << endl;
	system("pause");
	return 0;
}

15-二进制中的1的个数

题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
思路:把一个整数减去1,再和原来的整数做与运算,会把该整数最右边的1变为0.那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的运算。

#include 
using namespace std;

int numberof1(int num) {
	int count = 0;
	while (num) {
		count++;
		num = num & (num - 1);
	}
	return count;
}

int main() {

	int num = 9;
	int ret = numberof1(num);
	cout << ret << endl;

	system("pause");
	return 0;
	
}

总结:把一个整数减去1之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的1变为0.

16-数值的整数次幂

#include 
using namespace std;

double Power(int m,int n) {
	if (n == 0) {
		return 1;
	}
	if (m == 0 && n < 0) {
		cout << "输入有误" << endl;
		return 0.0;
	}
	double result = 1.0;
	if (n > 0) {
		for (int i = 1; i <= n; i++) {
			result *= m;
		}
	}
	else if (n < 0) {
		for (int i = 1; i <= -n; i++) {
			result *= m;
		}
		result = 1.0 / result;
	}
	return result;
}


int main() {
	int m = 0;
	int n = -1;
	double ret = Power(m,n);

	cout << m << "^" << n << "=" <<  ret << endl;

	system("pause");
	return 0;
}

17-打印从1到最大的n位数

利用递归

#include 
#include 
using namespace std;

void PrintNumber(char *number);
void Print1TOMaxOfNDigitsRecursively(char *number, int length, int index);

void Print1TOMaxOfNDigits(int n) {
	if (n <= 0) {
		return;
	}
	char *number = new char[n + 1];
	number[n] = '\0';
	for (int i = 0; i < 10; i++) {
		number[0] = i + '0';// '0' 会把i转化成字符类型,然后赋值给nunber
		Print1TOMaxOfNDigitsRecursively(number, n, 0);
	}
	delete[] number;
}

void Print1TOMaxOfNDigitsRecursively(char *number, int length, int index) {
	if (index == length - 1) {
		PrintNumber(number);
		return;
	}
	for (int i = 0; i < 10; i++) {
		number[index + 1] = i + '0';
		Print1TOMaxOfNDigitsRecursively(number, length, index + 1);
	}
}

void PrintNumber(char *number) {
	bool isBeginning0 = true;
	int nLength = strlen(number);

	for (int i = 0; i < nLength; i++) {
		if (isBeginning0 && number[i] != '0') {
			isBeginning0 = false;
		}
		if (!isBeginning0) {
			cout << number[i];
		}
	}
	cout << "\t";
}

int main() {

	Print1TOMaxOfNDigits(2);

	system("pause");
	return 0;
}

18-删除链表的节点

#include 
using namespace std;

struct ListNode {
	int m_nValue;
	ListNode *m_pNext;
};

void DeleteNode(ListNode ** pListHead, ListNode *pToBedeleted) {
	if (!pListHead || !pToBedeleted) {
		return;
	}
	//要删除的节点不是尾节点
	if (pToBedeleted->m_pNext != nullptr) {
		ListNode *pNext = pToBedeleted->m_pNext;
		pToBedeleted->m_nValue = pNext->m_nValue;
		pToBedeleted->m_pNext = pNext->m_pNext;

		delete pNext;
		pNext = nullptr;
	}
	//链表只有一个节点,删除头节点(也是尾节点)
	else if (*pListHead == pToBedeleted) {
		delete pToBedeleted;
		pToBedeleted = nullptr;
		*pListHead = nullptr;
	}
	//链表中有很多节点,删除尾节点
	else {
		ListNode *pNode = *pListHead;
		while (pNode->m_pNext != pToBedeleted) {
			pNode = pNode->m_pNext;
		}
		pNode->m_pNext = nullptr;
		delete pToBedeleted;
		pToBedele ted = nullptr;
	}
}

int main() {
	ListNode *head = new ListNode();
	head->m_nValue = 0;
	ListNode *head1 = head;
	ListNode * p = new ListNode();
	for (int i = 1; i < 10; i++) {
		ListNode *l = new ListNode();
		l->m_nValue = i;
		head->m_pNext = l;
		head = head->m_pNext;
		if (i == 5) {
			p = l;
		}
	}

	DeleteNode(&head1, p);//删除m_nValue为5的节点

	while (head1) {
		cout << head1->m_nValue << endl;
		head1 = head1->m_pNext;
	}
    // 0 1 2 3 4 6 7 8 9 


	system("pause");
	return 0;
}

19-正则表达式匹配

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

思路:当模式中第二个字符不是'*'时:字符串中的第一个字符和模式中的第一个字符想匹配,那么在字符串和模式上都向			后移动一个字符,然后匹配剩余字符串和模式。如果第一个字符不相匹配则直接返回false;

	 当模式中第二个字符是'*'时:
	 	其一:选择是在模式上向后移动两个字符(匹配0字符),
	 	其二:如果模式中的第一字符和字符串中的第一个字符相匹配,则在字符串上向后移动一个字符,而在模式上上			  有两种选择:
	 					其一:模式上向后移动两个字符(只匹配一个字符,例如,aa*a匹配aaa)
	 					其二:模式上保持不变(匹配多个字符,例如,aa*b匹配aaaaab)
#include 
using namespace std;

bool matchCore(const char* str, const char* pattern);

bool match(const char* str, const char* pattern)
{
	if (str == nullptr || pattern == nullptr)
		return false;

	return matchCore(str, pattern);
}

bool matchCore(const char* str, const 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 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;
}


int main() {

	char str[] = "aaa";
	char pattern[] = "aa*a";
	bool ret = match(str, pattern);

	cout << ret << endl;

	system("pause");
	return 0;
}


leetcode-44-通配符匹配
#include 
using namespace std;


bool matchCore(char* str,char* p) {
	if (*str == '\0' && *p == '\0')
		return true;
		
	if (*str != '\0' && *p == '\0')
		return false;
    
	if (*str == '\0' && *p != '\0')
		return false;
    
	if (*str == *p || *p == '?') {
		return matchCore(str + 1, p + 1);
	}
	if (*p == '*') {
		return matchCore(str+1, p) || matchCore(str+1, p+1) || matchCore(str, p+1);
	}
	return false;
}


bool isMatch(char* s,char* p) {
	if (s == nullptr || p == nullptr) {
		return false;
	}
	if (*p == '*') {
		return true;
	}
	return matchCore(s, p);
}

int main() {
	
		
	char str[] = "tedrgfdg";
	char pattern[] = "*?g";

	bool res = isMatch(str, pattern);
	cout << res << endl;

	system("pause");
	return 0;
}

20-表示数值的字符串

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

注意:
小数可以没有整数部分,例如.123等于0.123;
小数点后面可以没有数字,例如233.等于233.0;
小数点前面和后面可以有数字,例如233.666;
当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1;
当e或E后面没有整数时,整个字符串不能表示数字,例如12e、12e+5.4;

思路:
	1.先去除行首行尾的空格
	2.行首如果有一个正负号,则直接忽略
	3.如果字符串为空或只有一个'.',则不是一个合法数
	4.循环整个字符串,去除一下几种情况:
		1. '.' 或 'e' 个数多于 1 个;
		2. '.' 在 'e'后面出现;
		3. 'e' 后面或前面为空;
		4. 'e'后面紧跟着正负号,但正负号后面为空;
		
#include 
using namespace std;
#include 

bool isNumeric(string s) {
    //去除行首行尾空格
	int i = 0;
	while (i < s.size() && s[i] == ' ') {
		i++;
	}
	int j = s.size() - 1;
	while (j >= 0 && s[j] == ' ') {
		j--;
	}
	if (i > j) {
		return false;
	}
	s = s.substr(i, j - i + 1);//获取子串
    
    //忽略正负号
	if (s[0] == '-' || s[0] == '+') {
		s.substr(1);
	}
    //判断字符串为空或者字符串是否只有'.'
	if (s.empty() || (s[0] == '.' && s.size() == 1)) {
		return false;
	}
	int dot = 0, e = 0;
	for (int i = 0; i < s.size(); i++) {
		if (s[i] >= '0' && s[i] <= '9') {
			continue;
		}
		else if (s[i] == '.') {
			dot++;
            //判断 '.' 个数多于 1 个 或者 '.' 在 'e'后面出现
			if (e || dot > 1) {
				return false;
			}
		}
		else if (s[i] == 'e' || s[i] == 'E') {
			e++;
            // 判断'e' 后面或前面为空 或者 'e'的前面是'.'而'.'的前面为空
			if (i + 1 == s.size() || !i || e > 1 || (i == 1 && s[0] == '.')) {
				return false;
			}
            //判断'e'后面是否紧跟着正负号 
			if (s[i + 1] == '+' || s[i + 1] == '-') {
                // 正负号后面是否为空
				if (i + 2 == s.size()) {
					return false;
				}
				//i++;
			}
		}
		else {
			return false;
		}
	}
	return true;
}



int main() {

	string str = "45645.e2";
	bool res = isNumeric(str);
	cout << res << endl;
	
	system("pause");
	return 0;
}

21-调整数组顺序使其奇数位于偶数前面

题目:输入一个整数数组,实现一个函数来调整该数组数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

#include 
using namespace std;
//利用函数接偶
bool isEven(int n) {
	return (n % 2) == 0;
}

void ReorderOddEven(int arr[],int length) {
	if (length == 0) {
		return;
	}
	int i = 0;
	int j = length - 1;

	int temp = arr[0];
	while (i < j) {
		while (i < j && !isEven(arr[i])) {
			i++;
		}
		temp = arr[i];
		while(i < j && isEven(arr[j])) {
			j--;
		}
		arr[i] = arr[j];
		arr[j] = temp;
	}

}

int main() {
	
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	//int arr[] = { 1 };
	int length = sizeof(arr) / sizeof(arr[0]);
	ReorderOddEven(arr, length);

	for (int i = 0; i < length; i++) {
		cout << arr[i] << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

22-链表中倒数第K个节点

#include 
using namespace std;

struct ListNode {
	int m_nValue;
	ListNode *m_pNext;
};

ListNode *FindKthToTail(ListNode *head, int k) {
	if (head == NULL || k == 0) {
		return NULL;
	}

	ListNode *pAhead = head;
	ListNode *pbehind = head;
	int i = 0;
	while (i < k - 1) {
		if (pbehind->m_pNext != NULL) {
			pbehind = pbehind->m_pNext;
		}
		else {
			return NULL;
		}
		i++;
	}
	while (pbehind->m_pNext != NULL) {
		pAhead = pAhead->m_pNext;
		pbehind = pbehind->m_pNext;
	}
	return pAhead;
}

int main() {
	//创建链表
	ListNode *head = new ListNode();
	head->m_nValue = 0;
	ListNode *head1 = head;
	for (int i = 1; i < 10; i++) {
		ListNode *l = new ListNode();
		l->m_nValue = i;
		head->m_pNext = l;
		head = head->m_pNext;
	}
	//head1依次为0 1 2 3 4 5 6 7 8 9
	//返回倒数第5个节点
	ListNode * KNode = FindKthToTail(head1->m_pNext, 2);
	if (KNode != NULL) {
		cout << KNode->m_nValue << endl;
	}
	else {
		cout << "该节点不存在" << endl;
	}

	system("pause");
	return 0;
}

23-链表中环的入口节点

/判断是否有环,如果快慢指针相遇的节点
ListNode *MeetingNode(ListNode *pHead) {
	if (pHead == nullptr) {
		return nullptr;
	}
	ListNode *pShow = pHead->m_pNext;
	if (pShow == nullptr) {
		return nullptr;
	}
	ListNode *pFast = pShow->m_pNext;
	
	while (pShow != nullptr && pFast != nullptr) {
		if (pShow == pFast) {
			return pFast;
		}
		pShow = pShow->m_pNext;
		//快指针一次走两步
		pFast = pFast->m_pNext;
		if (pFast != nullptr) {
			pFast = pFast->m_pNext;
		}
	}
	return nullptr;
}

ListNode *EntryNodeOfLoop(ListNode *pHead) {
	ListNode *meetingNode = MeetingNode(pHead);
	if (meetingNode == nullptr) {
		return nullptr;
	}
	//得到环中节点的数目
	int nodesInLoop = 1;
	ListNode *pNode1 = meetingNode;
	while (pNode1->m_pNext != meetingNode) {
		pNode1 = pNode1->m_pNext;
		nodesInLoop++;
	}
	//先移动pNode1,次数为环中节点的数目
	pNode1 = pHead;
	for (int i = 0; i < nodesInLoop; i++) {
		pNode1 = pNode1->m_pNext;
	}
	//在移动pNode1和pNode2
	ListNode *pNode2 = pHead;
	while (pNode1 != pNode2) {
		pNode1 = pNode1->m_pNext;
		pNode2 = pNode2->m_pNext;
	}
	return pNode1;
}

int main() {

	//创建循环链表 循环入口为5节点
	ListNode *head = new ListNode();
	ListNode *head1 = head;
	ListNode *p = new ListNode();
	for (int i = 1; i <= 10; i++) {
		ListNode *l = new ListNode();
		l->m_nValue = i;
		head->m_pNext = l;
		head = head->m_pNext;
		if (i == 1) {
			p = l;
		}
	}
	//head->m_pNext = p;注销即没有环
	head->m_pNext = p;
	ListNode * ph = EntryNodeOfLoop(head1);
	if (ph != nullptr) {
		cout << ph->m_nValue << endl;
	}
	else {
		cout << "没有环" << endl;
	}

	system("pause");
	return 0;
}

#include
using namespace std;

struct ListNode {
	int m_nValue;
	ListNode *m_pNext;
};
ListNode *MeetingNode(ListNode *pHead) {
	if (pHead == nullptr) {
		return nullptr;
	}
	ListNode *pShow = pHead;
	ListNode *pFast = pShow->m_pNext;
	while (pShow != nullptr && pFast != nullptr) {
		if (pShow == pFast) {
			return pFast;
		}
		pShow = pShow->m_pNext;
		//快指针走两步
		pFast = pFast->m_pNext;
		if (pFast != nullptr) {
			pFast = pFast->m_pNext;
		}
	}
	return nullptr;
}

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
	ListNode* meetingNode = MeetingNode(pHead);
	if (meetingNode == nullptr)
		return nullptr;

	// 得到环中结点的数目
	int nodesInLoop = 1;
	ListNode* pNode1 = meetingNode;
	while (pNode1->m_pNext != meetingNode)
	{
		pNode1 = pNode1->m_pNext;
		++nodesInLoop;
	}

	// 先移动pNode1,次数为环中结点的数目
	pNode1 = pHead;
	for (int i = 0; i < nodesInLoop; ++i)
		pNode1 = pNode1->m_pNext;

	// 再移动pNode1和pNode2
	ListNode* pNode2 = pHead;
	while (pNode1 != pNode2)
	{
		pNode1 = pNode1->m_pNext;
		pNode2 = pNode2->m_pNext;
	}

	return pNode1;
}

int main() {

	//创建循环链表 循环入口为5节点
	ListNode *head = new ListNode();
	ListNode *head1 = head;
	ListNode *p = new ListNode();
	for (int i = 1; i <= 1; i++) {
		ListNode *l = new ListNode();
		l->m_nValue = i;
		head->m_pNext = l;
		head = head->m_pNext;
		if (i == 1) {
			p = l;
		}
	}
	head->m_pNext = p;
	ListNode * ph = EntryNodeOfLoop(head1->m_pNext);
	if (ph != nullptr) {
		cout << ph->m_nValue << endl;
	}
	else {
		cout << "没有环" << endl;
	}

	system("pause");
	return 0;
}

24-反转链表

辅助指针:定义三个用于翻转链表的辅助指针和一个用于表示翻转链表头结点的指针,node指向当前节点、left指向当前节点的前一个节点、right指向当前节点的下一个节点、ReverseHead指向翻转链表的头结点。

翻转链表过程:循环翻转链表,每次循环翻转一个结点。判断node是否是最后一个结点,如果是最后一个节点,则reverseHead指向node(确定翻转链表表头节点),然后node指向left(翻转链表),退出循环;如果不是最后一个节点,则node指向left(翻转链表),移动left和node指针。

#include 
using namespace std;
struct ListNode {
	int m_nValue;
	ListNode *m_pNext;
};

ListNode *ReverseList(ListNode* pHead) {
	ListNode *pReversedHead = NULL;
	ListNode *pNode = pHead;
	ListNode *pPrev = NULL;

	while (pNode != NULL) {
		//pNext当前节点的原链表后一节点
		ListNode *pNext = pNode->m_pNext;
		if (pNext == NULL) {
			pReversedHead = pNode;
		}
		pNode->m_pNext = pPrev;

		pPrev = pNode;
		pNode = pNext;
	}
	return pReversedHead;
}

int main() {
	
	//创建单链表 
	ListNode *head = new ListNode();
	ListNode *head1 = head;
	int i = 1;
	for (i; i <= 10; i++) {
		ListNode *l = new ListNode();
		l->m_nValue = i;
		head->m_pNext = l;
		head = head->m_pNext;
	}
	//反转链表
	ListNode *Reversehead = ReverseList(head1->m_pNext);
	cout << "链表反转后:";
	while (Reversehead != NULL) {
		cout << Reversehead->m_nValue << " ";
		Reversehead = Reversehead->m_pNext;
	}//10 9 8 7 6 5 4 3 2 1 
	cout << endl;
	system("pause");
	return 0;
}

25-合并两个有序链表

递归法:
#include 
using namespace std;

struct ListNode {
	int m_nValue;
	ListNode *m_pNext;
};

ListNode *Merge(ListNode *pHead1, ListNode *pHead2) {
	if (pHead1 == nullptr) {
		return pHead2;
	}
	else if (pHead2 == nullptr) {
		return pHead1;
	}
	
	ListNode *pMergedHead = nullptr;
	if (pHead1->m_nValue < pHead2->m_nValue) {
		pMergedHead = pHead1;
		pMergedHead->m_pNext = Merge(pHead1->m_pNext, pHead2);
	}
	else {
		pMergedHead = pHead2;
		pMergedHead->m_pNext = Merge(pHead1, pHead2->m_pNext);
	}
	return pMergedHead;
}

int main() {
	
	//创建两个单链表
	ListNode *head = new ListNode();
	ListNode *head1 = head;
	int i = 1;
	while(i < 10) {
		ListNode *nl = new ListNode();
		nl->m_nValue = i;
		head->m_pNext = nl;
		head = head->m_pNext;
		i += 2;
	}
	/*while (head1->m_pNext) {
		cout << head1->m_pNext->m_nValue << " ";
		head1 = head1->m_pNext;
	}*/
	ListNode *head2 = new ListNode();
	ListNode *head3 = head2;
	i = 0;
	while (i < 10) {
		ListNode *nl1 = new ListNode();
		nl1->m_nValue = i;
		head2->m_pNext = nl1;
		head2 = head2->m_pNext;
		i += 2;
	}
	/*while (head3->m_pNext) {
		cout << head3->m_pNext->m_nValue << " ";
		head3 = head3->m_pNext;
	}*/
	ListNode *MergeHeadNode = Merge(head1->m_pNext, head3->m_pNext);
	while (MergeHeadNode != NULL) {
		cout << MergeHeadNode->m_nValue << " ";
		MergeHeadNode = MergeHeadNode->m_pNext;
	}

	system("pause");
	return 0;
}

//非递归
ListNode *Merge(ListNode *pHead1, ListNode *pHead2) {
	ListNode *p = new ListNode();
	ListNode *pMergeHead = p;
	while (pHead1 && pHead2) {
		if (pHead1->m_nValue < pHead2->m_nValue) {
			pMergeHead->m_pNext = pHead1;
			pHead1 = pHead1->m_pNext;
		}
		else {
			pMergeHead->m_pNext = pHead2;
			pHead2 = pHead2->m_pNext;
		}
		pMergeHead = pMergeHead->m_pNext;
	}
	if (pHead1) {
		pMergeHead->m_pNext = pHead1;
	}
	if (pHead2 != NULL) {
		pMergeHead->m_pNext = pHead2;
	}
	return p->m_pNext;
}

26-树的子结构

输入两颗二叉树A和B,判断B是不是A的子结构。

#include 
using namespace std;

//二叉树节点
struct BinaryTreeNode {
	double m_dbValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

bool Equal(double num1, double num2) {
	if (num1 - num2 > -0.0000001 && num1 - num2 < 0.0000001) {
		return true;
	}
	else {
		return false;
	}
}

bool DoerTree1HaveTree2(BinaryTreeNode *pRoot1, BinaryTreeNode *pRoot2) {
	if (pRoot2 == nullptr) {
		return true;
	}
	if (pRoot1 == nullptr) {
		return false;
	}
	
	if (!Equal(pRoot1->m_dbValue, pRoot2->m_dbValue)) {
		return false;
	}
	return DoerTree1HaveTree2(pRoot1->m_pLeft, pRoot2->m_pLeft) && DoerTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight);
}

bool HasSubtree(BinaryTreeNode *pRoot1,BinaryTreeNode *pRoot2) {
	bool result = false;
	if (pRoot1 != nullptr && pRoot2 != nullptr) {
		if (Equal(pRoot1->m_dbValue, pRoot2->m_dbValue)) {
			result = DoerTree1HaveTree2(pRoot1, pRoot2);
		}
		if (!result) {
			result = HasSubtree(pRoot1->m_pLeft, pRoot2);
		}
		if (!result) {
			result = HasSubtree(pRoot1->m_pRight, pRoot2);
		}
	}
	return result;
}

int main() {
	
	//创建二叉树
	BinaryTreeNode *HeadTreeNodeA = nullptr;
	
	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_dbValue = 4;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_dbValue = 2;
	Node3->m_pLeft = Node1;
	Node3->m_pLeft = Node2;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_dbValue = 9;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_dbValue = 8;
	Node5->m_pLeft = Node4;
	Node5->m_pRight = Node3;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_dbValue = 7;
	Node6->m_pLeft = nullptr;
	Node6->m_pRight = nullptr;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	//二叉树A的头结点
	HeadTreeNodeA = Node7;

	//*****************************************************

	BinaryTreeNode *HeadTreeNodeB = nullptr;
	BinaryTreeNode *Node8 = new BinaryTreeNode();
	Node8->m_dbValue = 2;
	Node8->m_pLeft = nullptr;
	Node8->m_pRight = nullptr;

	BinaryTreeNode *Node9 = new BinaryTreeNode();
	Node9->m_dbValue = 9;
	Node9->m_pLeft = nullptr;
	Node9->m_pRight = nullptr;

	BinaryTreeNode *Node10 = new BinaryTreeNode();
	Node10->m_dbValue = 8;
	Node10->m_pLeft = Node9;
	Node10->m_pRight = Node8;

	//二叉树B的头节点
	HeadTreeNodeB = Node10;

	bool res = HasSubtree(HeadTreeNodeA, HeadTreeNodeB);
	cout << res << endl;

	system("pause");
	return 0;
}

27-二叉树的镜像(引入智能指针)

题目:请完成一个函数,输入一颗二叉树,该函数输出它的镜像。

#include 
using namespace std;

struct BinaryTreeNode {
	double m_dbValue;
	std::tr1::shared_ptrm_pLeft;
	std::tr1::shared_ptrm_pRight;
};

void MirrorRecursively(std::tr1::shared_ptrpNode) {
	if (pNode == nullptr) {
		return;
	}
	if (pNode->m_pLeft == nullptr && pNode->m_pRight == nullptr) {
		return;
	}
	std::tr1::shared_ptrtemp = pNode->m_pLeft;
	pNode->m_pLeft = pNode->m_pRight;
	pNode->m_pRight = temp;
	if (pNode->m_pLeft) {
		MirrorRecursively(pNode->m_pLeft);
	}
	if (pNode->m_pRight) {
		MirrorRecursively(pNode->m_pRight);
	}
}

//先序遍历
void PreOrder(std::tr1::shared_ptrpNode) {
	if (pNode != nullptr) {
		cout << pNode->m_dbValue << " ";
		PreOrder(pNode->m_pLeft);
		PreOrder(pNode->m_pRight);
	}
}

int main(){
	//创建二叉树
	std::tr1::shared_ptrNode1(new BinaryTreeNode);
	Node1->m_dbValue = 5;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	std::tr1::shared_ptrNode2(new BinaryTreeNode);
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	std::tr1::shared_ptrNode3(new BinaryTreeNode);
	Node3->m_dbValue = 9;
	Node3->m_pLeft = nullptr;
	Node3->m_pRight = nullptr;

	std::tr1::shared_ptrNode4(new BinaryTreeNode);
	Node4->m_dbValue = 11;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;
	
	std::tr1::shared_ptrNode5(new BinaryTreeNode);
	Node5->m_dbValue = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	std::tr1::shared_ptrNode6(new BinaryTreeNode);
	Node6->m_dbValue = 10;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	std::tr1::shared_ptrNode7(new BinaryTreeNode);
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	MirrorRecursively(Node7);

	PreOrder(Node7);
	
	system("pause");
	return 0;
}

28-对称的二叉树

题目:请实现一个函数,用来判断一颗二叉树是不是对称的(与其镜像一样)

#include 
using namespace std;

struct BinaryTreeNode {
	int m_dbValue;
	std::tr1::shared_ptrm_pLeft;
	std::tr1::shared_ptrm_pRight;
};

bool isSymmetrical(std::tr1::shared_ptrpNode1, std::tr1::shared_ptrpNode2) {
	if (pNode1 == nullptr && pNode2 == nullptr) {
		return true;
	}
	if (pNode1 == nullptr || pNode2 == nullptr) {
		return false;
	}
	if (pNode1->m_dbValue != pNode2->m_dbValue) {
		return false;
	}
	return isSymmetrical(pNode1->m_pLeft, pNode2->m_pRight) && isSymmetrical(pNode1->m_pRight, pNode2->m_pLeft);
}

int main() {
	//创建二叉树
	std::tr1::shared_ptrNode1(new BinaryTreeNode);
	Node1->m_dbValue = 5;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	std::tr1::shared_ptrNode2(new BinaryTreeNode);
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	std::tr1::shared_ptrNode3(new BinaryTreeNode);
	Node3->m_dbValue = 7;
	Node3->m_pLeft = nullptr;
	Node3->m_pRight = nullptr;

	std::tr1::shared_ptrNode4(new BinaryTreeNode);
	Node4->m_dbValue = 5;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	std::tr1::shared_ptrNode5(new BinaryTreeNode);
	Node5->m_dbValue = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	std::tr1::shared_ptrNode6(new BinaryTreeNode);
	Node6->m_dbValue = 6;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	std::tr1::shared_ptrNode7(new BinaryTreeNode);
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	bool res = isSymmetrical(Node7, Node7);
	cout << res << endl;

	system("pause");
	return 0;
}

29-顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
思路:将其看作一圈一圈打印
    开始:(start, start)坐标,(0, 0), (1, 1),(2,2)…
    终止打印一圈的条件:cols > start * 2 && rows > start * 2
    如何打印一圈?
    从左到右:总需要
    从上到下:起始行号 < 终止行号
    从右到左:圈内至少两行两列 ,起始行号 < 终止行号 && 起始列号 < 终止列号
    从下到上:至少三行两列,起始行号 < 终止行号 - 1 && 起始列号 < 终止列号

#include 
using namespace std;

void PrintMatriInCircle(int arr[][4], int columns, int rows, int start) {
	//终止列号
	int endC = columns - start - 1;
	//终止行号
	int endR = rows - start - 1;

	//从左到右打印一行
	for (int i = start; i <= endC; i++) {
		int number = arr[start][i];
		cout << number << " ";
	}

	//从上到下打印一列
	if (endR > start) {
		for (int i = start + 1; i <= endR; i++) {
			int number = arr[i][endC];
			cout << number << " ";
		}
	}

	//从右到左打印一行
	if (endR > start && endC > start) {
		for (int i = endC - 1; i >= start; i--) {
			int number = arr[endR][i];
			cout << number << " ";
		}
	}

	//从下往上打印一列
	if (endR - 1 > start && endC > start) {
		for (int i = endR - 1; i >= start + 1; i--) {
			int number = arr[i][start];
			cout << number << " ";
		}
	}
	cout << endl;
}

void PrintMAtrixClockwisely(int arr[][4], int rows, int columns) {
	if (arr == NULL || columns <= 0 || rows <= 0) {
		return;
	}
	int start = 0;
	while (columns > start * 2 && rows > start * 2) {
		PrintMatriInCircle(arr, columns, rows, start);
		start++;
	}

}

int main() {
	
	int arr[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
	int rows = sizeof(arr) / sizeof(arr[0]);
	PrintMAtrixClockwisely(arr, rows, 4);

	system("pause");
	return 0;  
}

30-包含min函数的栈

题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min,push及pop时间复杂度都是1.

#include 
using namespace std;
#include

template 
class StackWithMin
{
public:
	StackWithMin() {}
	virtual ~StackWithMin() {}
	T& top();
	const T& top() const;
	void push(const T& value);
	void pop();
	const T& min() const;
	bool empty() const;
	size_t size() const;

private:
	stack   m_data;     // 数据栈,存放栈的所有元素
	stack   m_min;      // 辅助栈,存放栈的最小元素
};

template
void StackWithMin::push(const T&value) {
	m_data.push(value);
	if (m_min.size() == 0 || value < m_min.top()) {
		m_min.push(value);
	}
	else {
		m_min.push(m_min.top());
	}
}

template
void StackWithMin::pop() {
	if (m_data.size() > 0 && m_min.size() > 0) {
		m_data.pop();
		m_min.pop();
	}
	else {
		exit(0);
	}
}

template
const T& StackWithMin::min() const {
	if (m_data.size() > 0 && m_min.size() > 0) {
		return m_min.top();
	}
	else {
		exit(0);
	}
}

template 
T& StackWithMin::top()
{
	return m_data.top();
}

template 
const T& StackWithMin::top() const
{
	return m_data.top();
}

template 
bool StackWithMin::empty() const
{
	return m_data.empty();
}

template 
size_t StackWithMin::size() const
{
	return m_data.size();
}

int main() {

	StackWithMinswm;
	swm.push(3);
	swm.push(4);
	swm.push(2);
	swm.push(1);

	cout << swm.min() << endl;
	system("pause");
	return 0;
}

31-栈的压入和弹出序列

如果下一个弹出的数字刚好的栈顶数字,那么直接弹出,如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。如果所有的数字都压入栈了,仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。

#include 
#include 
using namespace std;

bool validateStackSequences(vector& pushed, vector& popped) {
        stackhelpStack;
        for(int i = 0, j = 0; i < pushed.size(); i++) {
            helpStack.push(pushed[i]);
            while (j < popped.size() && !helpStack.empty() && helpStack.top() == popped[j]) {
                helpStack.pop();
                j++;
            }
        }
        return helpStack.empty();
    }

32-从上到下打印二叉树

题目1:不分行从上到下打印二叉树
从上到下打印二叉树的每个节点,同一层的节点打印按照从左往右的顺序打印。

#include 
using namespace std;
#include 
#include

struct BinaryTreeNode {
	int m_dbValue;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};

void PrintFromTopToBottom(BinaryTreeNode* pRoot)
{
	if (pRoot == nullptr)
		return;

	deque dequeTreeNode;

	dequeTreeNode.push_back(pRoot);

	while (dequeTreeNode.size())
	{
		BinaryTreeNode *pNode = dequeTreeNode.front();
		dequeTreeNode.pop_front();

		cout << pNode->m_dbValue << " ";

		if (pNode->m_pLeft)
			dequeTreeNode.push_back(pNode->m_pLeft);

		if (pNode->m_pRight)
			dequeTreeNode.push_back(pNode->m_pRight);
	}
}

int main() {
	
	//创建二叉树

	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_dbValue = 5;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_dbValue = 9;
	Node3->m_pLeft = Node1;
	Node3->m_pLeft = Node2;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_dbValue = 11;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_dbValue = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_dbValue = 10;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	PrintFromTopToBottom(Node7);

	system("pause");
	return 0;

}

题目2:分行从上到下打印二叉树
#include 
#include 
using namespace std;

struct BinaryTreeNode {
	int m_dbValue;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};


void Print(BinaryTreeNode *pRoot) {
	if (pRoot == NULL) {
		return;
	}
	queuenodes;
	nodes.push(pRoot);
	int nextLevel = 0;//下一层节点的数目
	int toBePrinted = 1;//当前层需要打印的点数

	while (nodes.size()) {
		BinaryTreeNode *pNode = nodes.front();
		cout << pNode->m_dbValue << " ";
		if (pNode->m_pLeft != NULL) {
			nodes.push(pNode->m_pLeft);
			nextLevel++;
		}
		if (pNode->m_pRight != NULL) {
			nodes.push(pNode->m_pRight);
			nextLevel++;
		}
		nodes.pop();
		toBePrinted--;
		if (toBePrinted == 0) {
			cout << endl;
			toBePrinted = nextLevel;
			nextLevel = 0;
		}
	}
}

int main() {

	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_dbValue = 5;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_dbValue = 9;
	Node3->m_pLeft = nullptr;
	Node3->m_pLeft = nullptr;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_dbValue = 11;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_dbValue = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_dbValue = 10;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	Print(Node7);
	//8
	//6 10
	//5 7 9 11

	system("pause");
	return 0;
}

题目3:之字形打印二叉树
解法一:利用双栈
思路:如果当前打印的是偶数层(0层,2层...),则先保存左结点再保存右节点到第一个栈里;
	 如果当前的银的是奇数层(1层,3层...),则先保存右节点再保存左结点到第二个栈里。
#include 
using namespace std;
#include 

struct BinaryTreeNode {
	int m_dbValue;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};

void Print(BinaryTreeNode *pRoot) {
	if (pRoot == nullptr) {
		return;
	}
	stacklevels[2];
	int current = 0;
	int next = 1;

	levels[current].push(pRoot);

	while (!levels[0].empty() || !levels[1].empty()) {
		BinaryTreeNode *pNode = levels[current].top();
		cout << pNode->m_dbValue << " ";
		levels[current].pop();

		if (current == 0) {
			if (pNode->m_pLeft) {
				levels[next].push(pNode->m_pLeft);
			}
			if (pNode->m_pRight) {
				levels[next].push(pNode->m_pRight);
			}
		}
		else {
			if (pNode->m_pRight) {
				levels[next].push(pNode->m_pRight);
			}
			if (pNode->m_pLeft) {
				levels[next].push(pNode->m_pLeft);
			}
		}
		if (levels[current].empty()) {
			cout << endl;
			current = 1 - current;
			next = 1 - next;
		}
	}
}

int main() {
	
	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_dbValue = 5;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_dbValue = 9;
	Node3->m_pLeft = nullptr;
	Node3->m_pLeft = nullptr;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_dbValue = 11;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_dbValue = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_dbValue = 10;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	Print(Node7);
    //8
    //10 6
    //5 7 9 11

	system("pause");
	return 0;
}

解法二:利用双边数组deque
思路:当前打印的层数为偶数层(0,2...),从前面出,后面进。先进左子树,后进右子树;
	 当前打印的层数为奇数层(1,3...),从前面进,后面出。先进右子树,后进左子树。
#include 
using namespace std;
#include 
#include 

struct BinaryTreeNode {
	int m_dbValue;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};

void Print(BinaryTreeNode *pRoot) {
	if (pRoot == nullptr) {
		return;
	}
	dequenodes;
	nodes.push_back(pRoot);
	int currentLevel = 0;
	int nextLevel = 0;
	int toBeprinted = 1;
	while (!nodes.empty()) {
		BinaryTreeNode *pNode;
		if (currentLevel == 0) {
			pNode = nodes.front();
			nodes.pop_front();
			toBeprinted--;
			cout << pNode->m_dbValue << " ";
			if (pNode->m_pLeft != nullptr) {
				nodes.push_back(pNode->m_pLeft);
				nextLevel++;
			}
			if (pNode->m_pRight != nullptr) {
				nodes.push_back(pNode->m_pRight);
				nextLevel++;
			}
			if (toBeprinted == 0) {
				cout << endl;
				toBeprinted = nextLevel;
				nextLevel = 0;
				currentLevel = 1 - currentLevel;
			}
		}
		else {
			pNode = nodes.back();
			nodes.pop_back();
			toBeprinted--;
			cout << pNode->m_dbValue << " ";
			if (pNode->m_pRight != nullptr) {
				nodes.push_front(pNode->m_pRight);
				nextLevel++;
			}
			if (pNode->m_pLeft) {
				nodes.push_front(pNode->m_pLeft);
				nextLevel++;
			}
			if (toBeprinted == 0) {
				cout << endl;
				toBeprinted = nextLevel;
				nextLevel = 0;
				currentLevel = 1 - currentLevel;
			}
		}
	}
}

int main() {
	
	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_dbValue = 5;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_dbValue = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_dbValue = 9;
	Node3->m_pLeft = nullptr;
	Node3->m_pLeft = nullptr;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_dbValue = 11;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_dbValue = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_dbValue = 10;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_dbValue = 8;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	Print(Node7);
	//8
    //10 6
    //5 7 9 11
	system("pause");
	return 0;
}

33-二叉搜索树的后序遍历序列

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。
分析:在后序遍历二叉搜索树得到的序列中,最后一个数字是树的根节点的值。数组中前面的数字可以分为两部分:第一部分是左子树的值,他们都比根节点的值小;第二部分是右子数的值,它们都比根节点的值大。如果满足该条件,则是某二叉搜索树的后序遍历序列,否则不是。

#include 
using namespace std;

bool VerifySquenceOfBST(int sequence[], int length) {
	if (sequence == nullptr || length <= 0) {
		return false;
	}

	int root = sequence[length - 1];

	//在二叉树搜索树中左子树节点的值小于根节点的值
	int i = 0;
	for (; i < length - 1; i++) {
		if (sequence[i] > root) {
			break;
		}
	}
	//在二叉搜索树种右子树节点的值大于根节点的值
	int j = i;
	for (; j < length - 1; j++) {
		if (sequence[j] < root) {
			return false;
		}
	}

	//判断左子树是不是二叉搜索树
	bool left = true;
	if (i > 0) {
		left = VerifySquenceOfBST(sequence, i);
	}
	//判断右子数是不是二叉搜索树
	bool right = true;
	if (i < length - 1) {
		right = VerifySquenceOfBST(sequence + i, length - i - 1);
	}

	return (left && right);
}

int main() {

	int arr[] = { 5,7,6,9,11,10,8 };
	int length = sizeof(arr) / sizeof(arr[0]);
	bool res = VerifySquenceOfBST(arr, length);
	cout << res << endl;

	system("pause");
	return 0;
}

34-二叉树中和为某一值的路径

题目:输入二叉树和一个整数,打印二叉树中的节点值得的和为输入整数的所有路径。

#include  
using namespace std;
#include 

struct BinaryTreeNode {
	int m_Value;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};

void FindPath(BinaryTreeNode *pRoot, int sum, vector&path, int currentSum);

void FindPath(BinaryTreeNode *pRoot, int sum) {
	if (pRoot == nullptr) {
		return;
	}
	vectorpath;
	int currentSum = 0;
	FindPath(pRoot, sum, path, currentSum);
}

void FindPath(BinaryTreeNode *pRoot, int sum, vector&path, int currentSum) {
	currentSum += pRoot->m_Value;
	path.push_back(pRoot->m_Value);
	//如果是叶子节点,并且路径上的节点值的和等于输入的值,则打印出这条路径
	bool isLeaf = pRoot->m_pLeft == nullptr && pRoot->m_pRight == nullptr;
	if (currentSum == sum && isLeaf) {
		cout << "A path is found:" << " ";
		vector::iterator it = path.begin();
		for (; it != path.end(); it++) {
			cout << *it << " ";
		}
		cout << endl;
	}

	//如果不是叶子节点,则遍历它的叶子节点
	if (pRoot->m_pLeft != nullptr) {
		FindPath(pRoot->m_pLeft, sum, path, currentSum);
	}
	if (pRoot->m_pRight != nullptr) {
		FindPath(pRoot->m_pRight, sum, path, currentSum);
	}
	path.pop_back();
}

int main() {

	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_Value = 4;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_Value = 7;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_Value = 5;
	Node3->m_pLeft = Node1;
	Node3->m_pLeft = Node2;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_Value = 12;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_Value = 10;
	Node5->m_pLeft = Node3;
	Node5->m_pRight = Node4;

	FindPath(Node5, 22);

	delete Node1;
	delete Node2;
	delete Node3;
	delete Node4;
	delete Node5;

	system("pause");
	return 0;
}

35-复杂链表的复制

题目:请实现函数ComplexListNode* Clone(ComplexListNode *pHead),复制一个复杂链表。在复杂链表中,每个节点除了一个m_pNext指针指向下一个节点,还有一个m_pSibling指针指向链表中的任意节点或者nullptr。

#include 
using namespace std;

struct ComplexListNode {
	int m_nValue;
	ComplexListNode *m_pNext;
	ComplexListNode *m_pSibling;
};
//第一步:根据原始链表的每个节点N创建对应的N',且把N'放在N的后面
void CloneNodes(ComplexListNode *pHead) {
	ComplexListNode *pNode = pHead;
	while (pNode != nullptr) {
		ComplexListNode *pCloned = new ComplexListNode();
		pCloned->m_nValue = pNode->m_nValue;
		pCloned->m_pNext = pNode->m_pNext;
		pCloned->m_pSibling = nullptr;

		pNode->m_pNext = pCloned;
		pNode = pCloned->m_pNext;
	}
}
//第二步:设置复制出来的节点的m_pSibling指向S,则它对应的复制节点N'的m_pSibling指向S的复制节点S'。
void ConnectSiblingNodes(ComplexListNode *pHead) {
	ComplexListNode *pNode = pHead;
	while (pNode != nullptr) {
		ComplexListNode *pCloned = pNode->m_pNext;
		if (pNode->m_pSibling != nullptr) {
			pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
		}
		pNode = pCloned->m_pNext;
	}
}
//第三步:把这个长链表拆分成两个链表
ComplexListNode *ReconnectNodes(ComplexListNode *pHead) {
	ComplexListNode *pNode = pHead;
	ComplexListNode *pClonedHead = nullptr;
	ComplexListNode *pClonedNode = nullptr;

	if (pNode != nullptr) {
		pClonedHead = pClonedNode = pNode->m_pNext;
		pNode->m_pNext = pClonedNode->m_pNext;
		pNode = pNode->m_pNext;
	}
	while (pNode != nullptr) {
		pClonedNode->m_pNext = pNode->m_pNext;
		pClonedNode = pClonedNode->m_pNext;
		pNode->m_pNext = pClonedNode->m_pNext;
		pNode = pNode->m_pNext;
	}
	return pClonedHead;
}

ComplexListNode *Clone(ComplexListNode *pHead) {
	CloneNodes(pHead);
	ConnectSiblingNodes(pHead);
	return ReconnectNodes(pHead);
}


int main() {

	ComplexListNode *L1 = new ComplexListNode();
	L1->m_nValue = 5;
	L1->m_pNext = nullptr;

	ComplexListNode *L2 = new ComplexListNode();
	L2->m_nValue = 4;
	L2->m_pNext = L1;

	ComplexListNode *L3 = new ComplexListNode();
	L3->m_nValue = 3;
	L3->m_pNext = L2;
	
	ComplexListNode *L4 = new ComplexListNode();
	L4->m_nValue = 2;
	L4->m_pNext = L3;
	
	ComplexListNode *L5 = new ComplexListNode();
	L5->m_nValue = 1;
	L5->m_pNext = L4;
	
	L5->m_pSibling = L3;
	L4->m_pSibling = L1;
	L3->m_pSibling = nullptr;
	L2->m_pSibling = L4;
	L1->m_pSibling = nullptr;

	ComplexListNode *ret = Clone(L5);
	while (ret != nullptr) {
		if (ret->m_pSibling != nullptr) {
			cout << ret->m_pSibling->m_nValue << " ";
		}
		else {
			cout << "NULL" << " ";
		}
		ret = ret->m_pNext;
	}
	cout << endl;

	delete L1;
	delete L2;
	delete L3;
	delete L4;
	delete L5;

	system("pause");
	return 0;
}

36-二叉搜索树与双向链表

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

#include 
using namespace std;

struct BinaryTreeNode {
	int m_Value;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};

void ConverNode(BinaryTreeNode *pNode, BinaryTreeNode **pLastNodeInList);

BinaryTreeNode *Conver(BinaryTreeNode *pRootOfTree) {
	if (pRootOfTree == nullptr) {
		return nullptr;
	}
	BinaryTreeNode *pLastNodeInList = nullptr;
	ConverNode(pRootOfTree, &pLastNodeInList);

	BinaryTreeNode *pHeadOfList = pLastNodeInList;
	while (pHeadOfList != nullptr && pHeadOfList->m_pLeft != nullptr) {
		pHeadOfList = pHeadOfList->m_pLeft;
	}
	return pHeadOfList;
}

void ConverNode(BinaryTreeNode *pNode, BinaryTreeNode **pLastNodeInList) {
	if (pNode == nullptr) {
		return;
	}
	BinaryTreeNode *pCurrent = pNode;
	if (pCurrent->m_pLeft != nullptr) {
		ConverNode(pCurrent->m_pLeft, pLastNodeInList);
	}
	pCurrent->m_pLeft = *pLastNodeInList;
	if (*pLastNodeInList != nullptr) {
		(*pLastNodeInList)->m_pRight = pCurrent;
	}
	*pLastNodeInList = pCurrent;
	if (pCurrent->m_pRight != nullptr) {
		ConverNode(pCurrent->m_pRight, pLastNodeInList);
	}
}

int main() {
	
	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_Value = 4;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_Value = 8;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_Value = 12;
	Node3->m_pLeft = nullptr;
	Node3->m_pLeft = nullptr;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_Value = 16;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_Value = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_Value = 14;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_Value = 10;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	BinaryTreeNode* res = Conver(Node7);
	while (res) {
		cout << res->m_Value << " ";
		res = res->m_pRight;
	}

	delete Node1;
	delete Node2;
	delete Node3;
	delete Node4;
	delete Node5;
	delete Node6;
	delete Node7;

	system("pause");
	return 0;
}

37-序列化二叉树

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

#include 
using namespace std;
#include
#include 
#include 

struct BinaryTreeNode {
	int m_Value;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
};

//前序序列化
void Serialize(BinaryTreeNode *pHead, deque&v) {
	if (pHead == nullptr) {
		v.push_back("$");
	}
	else {
		v.push_back(to_string(pHead->m_Value));//to_string字符串转整数
		Serialize(pHead->m_pLeft, v);
		Serialize(pHead->m_pRight, v);
	}
}
//字符串转整型
int string2int(string str) {
	stringstream ss;
	ss << str;
	int result;
	ss >> result;
	return result;
}

//反序列化
BinaryTreeNode* Deserialize(deque&v) {
	if (v.empty()) {
		return nullptr;
	}
	deque::iterator it = v.begin();
	if (*it == "$") {
		v.pop_front();
		return nullptr;
	}
	BinaryTreeNode *root = new BinaryTreeNode();
	root->m_Value = string2int((*it));
	v.pop_front();
	root->m_pLeft = Deserialize(v);
	root->m_pRight = Deserialize(v);
	return root;
}

void ProInder(BinaryTreeNode *pHead) {
	if (pHead == nullptr) {
		return;
	}
	cout << pHead->m_Value << " ";
	ProInder(pHead->m_pLeft);
	ProInder(pHead->m_pRight);
}

int main() {

	BinaryTreeNode *Node1 = new BinaryTreeNode();
	Node1->m_Value = 4;
	Node1->m_pLeft = nullptr;
	Node1->m_pRight = nullptr;

	BinaryTreeNode *Node2 = new BinaryTreeNode();
	Node2->m_Value = 8;
	Node2->m_pLeft = nullptr;
	Node2->m_pRight = nullptr;

	BinaryTreeNode *Node3 = new BinaryTreeNode();
	Node3->m_Value = 12;
	Node3->m_pLeft = nullptr;
	Node3->m_pLeft = nullptr;

	BinaryTreeNode *Node4 = new BinaryTreeNode();
	Node4->m_Value = 16;
	Node4->m_pLeft = nullptr;
	Node4->m_pRight = nullptr;

	BinaryTreeNode *Node5 = new BinaryTreeNode();
	Node5->m_Value = 6;
	Node5->m_pLeft = Node1;
	Node5->m_pRight = Node2;

	BinaryTreeNode *Node6 = new BinaryTreeNode();
	Node6->m_Value = 14;
	Node6->m_pLeft = Node3;
	Node6->m_pRight = Node4;

	BinaryTreeNode *Node7 = new BinaryTreeNode();
	Node7->m_Value = 10;
	Node7->m_pLeft = Node5;
	Node7->m_pRight = Node6;

	dequev;
    //序列化
	Serialize(Node7, v);
	for (int i = 0; i < v.size(); i++) {
		cout << v[i] << " ";
	}
	cout << endl;
	//反序列化
	BinaryTreeNode *pHead = Deserialize(v);
	//反序列化之后的二叉树前序序列
	ProInder(pHead);
	cout << endl;

	delete Node1;
	delete Node2;
	delete Node3;
	delete Node4;
	delete Node5;
	delete Node6;
	delete Node7;

	system("pause");
	return 0;
}


38-1-字符串排列

题目:输入一个字符串,打印出该字符串中字符的所有排列。
#include 
using namespace std;
#include 
#include 
#include 


void Permutation(string str, int begin, vector&res) {
	if (begin >= str.size()) {
		res.push_back(str);
	}
	for (int i = begin; i < str.size(); i++) {
		//如果出现重复元素跳过
		if (str[begin] == str[i] && begin != i) {
			continue;
		}
		//将首元素和后面元素交换
		char temp = str[begin];
		str[begin] = str[i];
		str[i] = temp;

		Permutation(str, begin + 1, res);

		//将交换恢复
		temp = str[begin];
		str[begin] = str[i];
		str[i] = temp;
	}
}

vector Permutation(string str) {
	if (str.empty()) {
		return vector();
	}
	if (str.size() == 1) {
		return vector{str};
	}
	vector res;
	Permutation(str, 0, res);
	return res;
}

void print(string str) {
	cout << str << " ";
}

int main() {

	string str = "abc";
	vectorres = Permutation(str);
	for_each(res.begin(), res.end(), print);
	cout << endl;

	system("pause");
	return 0;
}

38-2-字符串组合

思路:如果组合中包含第一个字符,则下一步在剩余的字符中选取m-1个字符;如果字符里不包含第一个字符,则下一步在剩余的n-1字符里选取m个字符。

#include 
using namespace std;
#include 
#include 

void combination(char *ptr, int n, vector&result);

void combination(char *ptr) {
	if (ptr == nullptr) {
		return;
	}
	vectorresult;
	int i, length = strlen(ptr);
	for (i = 1; i <= length; i++) {
		combination(ptr, i, result);
	}
}

void combination(char *ptr, int n, vector&result) {
	if (ptr == nullptr) {
		return;
	}
	if (n == 0) {
		vector::iterator iter = result.begin();
		for (; iter != result.end(); iter++) {
			cout << *iter;
		}
		cout << endl;
		return;
	}
	if (*ptr == '\0') {
		return;
	}
	result.push_back(*ptr);
	combination(ptr + 1, n - 1, result);
	result.pop_back();
	combination(ptr + 1, n, result);
}

int main() {
	char str[] = "abc";
	combination(str);

	system("pause");
	return 0;
}


39-数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
思路:在遍历数组的时候保存两个值:一个是数组中的一个数字,另一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则字数加1;如果下一个数字和我们之前保存的数字不同,则次数减1.如果次数为0,那么我们需要保存下一个数字,并把次数设为1。
#include
#include
using namespace std;
#include 
using namespace std;
void MoreHalfOfNum(int num[], int length, int &ret) {
	if (num == nullptr || length <= 0) {
		return;
	}
	int result = num[0];
	int times = 1;
	for (int i = 1; i < length; i++) {
		if (times == 0) {
			result = num[i];
			times = 1;
		}
		else if (num[i] == result) {
			times++;
		}
		else {
			times--;
		}
	}
	if (times >= 1) {
		int count = 0;
		for (int i = 0; i < length; i++) {
			if (result == num[i]) {
				count++;
			}
		}
		if (count * 2 > length) {
			ret = result;
		}
		else {
			ret = 0;
		}
	}
}

int main() {

	int num[] = { 0,0,3,0,2,0,5,4,0 };
	int length = sizeof(num) / sizeof(num[0]);
	int result = 0xffffffff;
	MoreHalfOfNum(num, length, result);

	cout << result << endl;

	system("pause");
	return 0;
}



40-最小的K个数

题目:输入n个整数,找出其中最小的k个数。

#include 
using namespace std;
#include 
#include 

void GetLeastNumber(int arr[], multiset&ms, int length, int k) {
	if (arr == nullptr || length < k || k < 1) {
		return;
	}
	for (int i = 0; i < length; i++) {
		if (i < k) {
			ms.insert(arr[i]);
		}
		else {
			multiset::iterator it = --ms.end();
			if (arr[i] < *it) {
				ms.erase(it);
				ms.insert(arr[i]);
			}
		}
	}
}

void print(int val) {
	cout << val << " ";
}

int main() {

	int arr[] = { 4,5,1,6,2,7,3,8 };
	int length = sizeof(arr) / sizeof(arr[0]);
	multisetms;
	int k = 4;
	GetLeastNumber(arr, ms, length, k);
	for_each(ms.begin(), ms.end(), print);
	cout << endl;

	system("pause");
	return 0;
}

41-数据流中的中位数

思路:在数据总数目是偶数时把新数据插入最小堆,否则插入最大堆。
还要保证最大堆中的所有数据都要小于最小堆的数据。
当数据的总数是偶数时,按照前面的分配规则会把新的数据插入最小堆,如果新数据比原最小堆中最小的数据大,则先把这个新数据插入最小堆,再把原最小堆中的最小值取出放入最大堆中。
当数据的总数是奇数时,按照前面的分配规则会把新的数据插入最大堆,如果新数据比原最大堆中最大的数据小,则先把这个新数据插入最大堆,再把原最大堆中的最大值取出放入最小堆中。
#include
using namespace std;
#include
# include 

template
class DynamicArray {
public:
	void Insert(T num) {	
		if (((min.size() + max.size()) & 1) == 0) {
			//成立说明数据总和是奇数
			if (max.size() > 0 && num < max[0]) {
				max.push_back(num);
				push_heap(max.begin(), max.end(), less());//最大堆 类似于降序

				num = max[0];

				pop_heap(max.begin(), max.end(), less());
				max.pop_back();
			}
			min.push_back(num);
			push_heap(min.begin(), min.end(), greater());//最小堆
		}
		else {
			if (min.size() > 0 && min[0] < num) {
				min.push_back(num);
				push_heap(min.begin(), min.end(), greater());//最小堆

				num = min[0];

				pop_heap(min.begin(), min.end(), greater());
				min.pop_back();
			}
			max.push_back(num);
			push_heap(max.begin(), max.end(), less());
		}
	}
	T GetMedian() {
		int size = min.size() + max.size();
		if (size == 0) {
			throw exception("NO numbers are available");
		}
		T median = 0;
		if ((size & 1) == 1) {
			median = min[0];
		}
		else {
			median = (min[0] + max[0]) / 2;
		}
		return median;
	}
private:
	vectormin;
	vectormax;
};

// 方法二:
class Solution {
public:
    void Insert(int num)
    {
        // lower_bound(begin, end,num):从数组中begin的位置到end-1位置
        // 二分查找第一个大于等于num的数字位置,不存在返回end
        // upper_bound(begin,end,num):从数组中begin的位置到end-1位置
        // 二分查找第一个大于num的数字位置,不存在返回end
        auto it = upper_bound(array.begin(), array.end(), num);
        array.insert(it, num);
    }

    double GetMedian()
    { 
        int length = array.size();
        if (length % 2 == 1) {
            return array[length / 2];
        }
        else {
            return 1.0 * (array[length / 2 - 1] + (array[length / 2])) / 2;
        }
    }
private:
    vectorarray;
};
void print(int val) {
	cout << val << " ";
}
int main() {
	
	DynamicArrayda;
	da.Insert(5);
	da.Insert(1);
	da.Insert(2);
	da.Insert(6);
	da.Insert(3);
	da.Insert(7);
	da.Insert(8);

	cout << da.GetMedian() << endl;;

	system("pause");
	return 0;
}

42-连续子数组的最大和

#include 
using namespace std;

bool g_InvalidInput = false;

int FindGreatestSumOfSubArray(int arr[], int length) {
	if (arr == nullptr || length <= 0) {
		g_InvalidInput = true;
		return 0;
	}
	g_InvalidInput = false;
	int nCurSum = 0;
	int nGretestSum = 0x80000000;
	for (int i = 0; i < length; i++) {
		if (nCurSum <= 0) {
			nCurSum = arr[i];
		}
		else {
			nCurSum += arr[i];
		}
		if (nCurSum > nGretestSum) {
			nGretestSum = nCurSum;
		}
	}
	return nGretestSum;
}
//动态规划解法
int FindGreatestSumOfSubArray(int arr[], int length) {
	if (arr == nullptr || length <= 0) {
		g_InvalidInput = true;
		return 0;
	}
	g_InvalidInput = false;
	int *dp = new int[length];
	dp[0] = arr[0];
	int maxSum = dp[0];
	for (int i = 1; i < length; i++) {
		if (dp[i - 1] >= 0) {
			dp[i] = dp[i - 1] + arr[i];
		}
		else {
			dp[i] = arr[i];
		}
		if (dp[i] > maxSum) {
			maxSum = dp[i];
		}
	}
	delete dp;
	return maxSum;
}


int main() {

	int arr[] = { 1,-2,3,4,10,-4,7,2,-5 };
	int length = sizeof(arr) / sizeof(arr[0]);
	int ret = FindGreatestSumOfSubArray(arr, length);
	cout << ret << endl;

	system("pause");
	return 0;
}

43-1~n整数中1出现的次数

传统解法:
#include 
using namespace std;

int Number(int n) {
	int number = 0;
	while (n) {
		if (n % 10 == 1) {
			number += 1;
		}
		n = n / 10;
	}
	return number;
}

int NumberOfOne(int n) {
	int number = 0;
	for (int i = 1; i <= n; i++) {
		number += Number(i);
	}
	return number;
}

int main() {

	int res = NumberOfOne(111);
	cout << res << endl;
	system("pause");
	return 0;
}

// ====================方法二====================
#include 
#include 
#include 
#include 
using namespace std;

int NumberOf1(const char* strN);
int PowerBase10(unsigned int n);

int NumberOf1Between1AndN_Solution2(int n)
{
	if (n <= 0)
		return 0;

	char strN[50];
	sprintf_s(strN, "%d", n);

	return NumberOf1(strN);
}

int NumberOf1(const char* strN)
{
	if (!strN || *strN < '0' || *strN > '9' || *strN == '\0')
		return 0;

	int first = *strN - '0';
	unsigned int length = static_cast(strlen(strN));
	if (length == 1 && first == 0)
		return 0;

	if (length == 1 && first > 0)
		return 1;

	// 假设strN是"21345"
	// numFirstDigit是数字10000-19999的第一个位中1的数目
	int numFirstDigit = 0;
	if (first > 1)//首位元素大于1
		numFirstDigit = PowerBase10(length - 1);
	else if (first == 1)
		numFirstDigit = atoi(strN + 1) + 1;
		cout << numFirstDigit<< endl;

	// numOtherDigits是01346-21345除了第一位之外的数位中1的数目
	int numOtherDigits = first * (length - 1) * PowerBase10(length - 2);
	// numRecursive是1-1345中1的数目
	int numRecursive = NumberOf1(strN + 1);

	return numFirstDigit + numOtherDigits + numRecursive;
}

int PowerBase10(unsigned int n)
{
	int result = 1;
	for (unsigned int i = 0; i < n; ++i)
		result *= 10;

	return result;
}
int main() {

	int res = NumberOf1Between1AndN_Solution2(12);
	cout << res << endl;
	system("pause");
	return 0;
}

44-数字序列中某一位的数字

题目:数字0123456789101112131415...的格式序列化到一个字符序列中。

#include 
using namespace std;
#include 

//计算digits位的数字总共有多少个
int countOfIntegers(int digits) {
	if (digits == 1) {
		return 10;
	}
	int count = (int)std::pow(10, digits - 1);
	return 9 * count;
}
//计算dights位数的第一个数,例如三位数的第一个数100
int beginNumber(int dights) {
	if (dights == 1) {
		return 0;
	}
	return std::pow(10, dights - 1);
}

//知道要找的那一位位于某m位数之后,求出具体是哪一位数字
int digitAtIndex(int index, int dights) {
	int number = beginNumber(dights) + index / dights;
	//int yu = index % dights;
	string numbers = to_string(number);//整型转字符串
	char res = numbers[index % dights];
	number = res - '0';//字符型转整型
	return number;
	/*int indexFromRight = dights - index % dights;
	for (int i = 1; i < indexFromRight; i++) {
		number /= 10;
	}
	return number % 10;*/
}

int digitAtIndex(int index) {
	if (index < 0) {
		return -1;
	}
	int digits = 1;
	while (true) {
		int numbers = countOfIntegers(digits);//计算digits位的数一共有几个
		if (index < numbers * digits) {
			return digitAtIndex(index, digits);
		}
		index -= digits * numbers;
		digits++;
	}
	return -1;
}

int main() {

	int ret = digitAtIndex(0);
	cout << ret << endl;

	system("pause");
	return 0;
}

45-把数组排成最小的数

题目:输入一个正整数组,把数组里所有数字拼接起来排成一个数,打印能拼接出来的所有数字中最小的一个。
#include                       
#include                       
#include                     
#include                    

using namespace std;

//定义一个新的比较规则                 
//这里必须声明为静态函数               
static bool compare(int item1, int item2)
{
	//使用to_string把int转换成为string
	string m = to_string(item1);
	string n = to_string(item2);
	//使用string的好处之一就是可以直接用加号(+)来进行拼接       
	string mn = m + n;
	string nm = n + m;

	return mn < nm;
}

//按照新的比较规则对数组进行排序       
//然后按照排序的顺序进行输出           
string PrintMinNumber(vector numbers)
{
	string resu;
	if (numbers.size() <= 0)return resu;

	sort(numbers.begin(), numbers.end(), compare);
	for (vector::iterator it = numbers.begin(); it != numbers.end(); it++) {
		cout << *it << endl;
	}
	//使用范围for循环
	for (auto num : numbers) {
		resu += to_string(num);
	}
	system("pause");
	return resu;
}

int main() 
{
	vector test{ 3,32,321 };
	cout << PrintMinNumber(test) << endl;

	return 0;
}

46-把数字翻译成字符串(动态规划)

#include 
using namespace std;
#include 

int GetTranslation(const string & number) {
	int length = number.size();
	int *counts = new int[length];
	int count = 0;

	for (int i = length - 1; i >= 0; i--) {
		count = 0;
		if (i < length - 1) {
			count = counts[i + 1];
		}
		else {
			count = 1;
		}
		if (i < length - 1) {
			int digit1 = number[i] - '0';
			int digit2 = number[i + 1] - '0';
			int converted = digit1 * 10 + digit2;
			if (converted >= 10 && converted <= 25) {
				if (i < length - 2) {
					count += counts[i + 2];
				}
				else {
					count += 1;
				}
			}
			
		}
		counts[i] = count;
	}
	count = counts[0];
	delete[] counts;
	return count;
}


int GetTranslation(int number) {
	if (number < 0) {
		return 0;
	}
	string numberInString = to_string(number);
	return GetTranslation(numberInString);
}


int main() {
	int res = GetTranslation(12258);
	cout << res << endl;
	system("pause");
	return 0;
}


47-礼物的最大价值

#include 
using namespace std;
#include
#include 

int max(int val1,int val2) {
	if (val1 > val2) {
		return val1;
	}
	return val2;
}
int getMaxVulue(vector>&v) {
	if (v.empty()) {
		return 0;
	}
	int rows = v.size();
	int clos = v[0].size();
	vector>maxValues;
	vectorv1;
	v1.resize(clos);
	fill(v1.begin(), v1.end(), 0);
	for (int i = 0; i < rows; i++) {
		maxValues.push_back(v1);
	}
	
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < clos; j++) {
			int up = 0, left = 0;
			if (i > 0) {
				up = maxValues[i - 1][j];
			}
			if (j > 0) {
				left = maxValues[i][j - 1];
			}
			maxValues[i][j] = max(up, left) + v[i][j];
		}
	}
	return maxValues[rows - 1][clos - 1];

}

int main() {

	vector>v = { {1,10,3,8},{12,2,9,6},{5,7,4,11},{3,7,16,5} };
	//vector>v = { {1,10,3,8} };
	int res = getMaxVulue(v);
	cout << res << endl;


	system("pause");
	return 0;
}

改进:
int getMaxVulue(vector>&v) {
	if (v.empty()) {
		return 0;
	}
	int rows = v.size();
	int clos = v[0].size();
	vectormaxValues;
	maxValues.resize(clos);
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < clos; j++) {
			int up = 0, left = 0;
			if (i > 0) {
				up = maxValues[j];
			}
			if (j > 0) {
				left = maxValues[j - 1];
			}
			maxValues[i][j] = max(up, left) + v[i][j];
		}
	}
	return maxValues[clos - 1];

}

48-最长不含重复字符的子字符串

题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该字符串长度。

#include 
using namespace std;
#include 

int longestSubstringWithoutDuplication(const string & str) {
	if (str.empty()) {
		return 0;
	}
	int curLength = 0;
	int maxLength = 0;
	
	int length = str.size();
	int *arr = new int[26];
	for (int i = 0; i < 26; i++) {
		arr[i] = -1;
	}
	for (int i = 0; i < length; i++) {
		int prevIndex = arr[str[i] - 'a'];//prevIndex表示str[i]字符上次在字符串中出现的位置,-1表示没有出现过
		if (prevIndex < 0 || i - prevIndex > curLength) {
			curLength++;
		}
		else {
			if (curLength > maxLength) {
				maxLength = curLength;
			}
			curLength = i - prevIndex;
		}
		arr[str[i] - 'a'] = i;
	}
	if (curLength > maxLength) {
		maxLength = curLength;
	}
	delete[] arr;
	return maxLength;
}

int main() {

	string str = "arabcacfr";
	int res = longestSubstringWithoutDuplication(str);
	cout << res << endl;
	system("pause");
	return 0;
    
}

49-丑数

题目:我们把只包含因子2、3、5的数称作丑数。也即如果一个数能被2整除,就连续除以2;能被3整除就连续除以3;如果能被5整除就连续除以5.如果最后得到的是1,那么这个数就是丑数,否则不是。

#include 
using namespace std;

bool IsUgly(int number) {
	while (number % 2 == 0) {
		number /= 2;
		return number;
	}
	while (number % 3 == 0) {
		number /= 3;
	}
	while (number % 5 == 0) {
		number /= 5;
	}
	return (number == 1);
}

int GetUglyNumber(int n) {
	if (n <= 0) {
		return 0;
	}
	int i = 0;
	int CurCount = 0;
	while (CurCount < n) {
		i++;
		if (IsUgly(i)) {
			CurCount++;
		}
	}
	return i;
}

int main() {

	int ret = GetUglyNumber(1500);
	cout << ret << endl;

	system("pause");
	return 0;
}

方法二:

#include 
using namespace std;

int min(int val1, int val2) {
	return val1 > val2 ? val2 : val1;
}

int GetUglyNumber(int n) {
	if (n <= 0) {
		return 0;
	}
	if (n < 7) {
		return n;
	}
	int T2 = 0;
	int T3 = 0;
	int T5 = 0;
	int *arr = new int[n];
	arr[0] = 1;
	for (int i = 1; i < n; i++) {
		arr[i] = min(arr[T2] * 2, min(arr[T3] * 3, arr[T5] * 5));
		if (arr[i] == arr[T2] * 2) {
			T2++;
		}
		if (arr[i] == arr[T3] * 3) {
			T3++;
		}
		if (arr[i] == arr[T5] * 5) {
			T5++;
		}
	}
	int uglyofn = arr[n - 1];
	delete[] arr;
	arr = nullptr;
	return uglyofn;
}


int main() {

	int ret = GetUglyNumber(10);
	cout << ret << endl;

	system("pause");
	return 0;
}

50-第一个只出现一次的字符

50-1-字符串中第一次只出现一次的字符
#include 
using namespace std;
#include 
#include 
#include 

char FirstNotRepeating(const string & str) {
	int length = str.size();
	if (length == 0) {
		return '\0';
	}
	mapm;
	for (int i = 0; i < length; i++) {
		map::iterator it = m.find(str[i]);
		if (it != m.end()) {
			it->second++;
		}
		else {
			m.insert(make_pair(str[i], 1));
		}
	}
	char res;
	for (auto it = str.begin(); it != str.end(); it++) {
		if (m[*it] == 1) {
			res = *it;
			break;
		}
	}
	return res;
}

int main() {
	//string str = "afsdfdsfrte";
	string str;
	char res = FirstNotRepeating(str);
	cout << res << endl;

	system("pause");
	return 0;
}


50-2-字符流中第一个只出现一次的字符

51-数组中的逆序对

#include 
using namespace std;
#include 

void Merge(vector&v, int low, int mid, int high, int &count) {
	int *b = new int[high - low + 1];
	int i = mid, j = high, k = high - low;
	while (i >= low && j >= mid + 1) {
		if (v[i] > v[j]) {
			count += (j - mid);
			b[k--] = v[i--];
		}
		else {
			b[k--] = v[j--];
		}
	}
	while (i >= low) {
		b[k--] = v[i--];
	}
	while (j >= mid + 1) {
		b[k--] = v[j--];
	}
	for (int i = low, k = 0; i <= high; i++) {
		v[i] = b[k++];
	}
	delete [] b;
}

void InversePairsCount(vector&v,int low,int high, int &count) {
	if (low < high) {
		int mid = (low + high) / 2;
		InversePairsCount(v, low, mid, count);
		InversePairsCount(v, mid + 1, high, count);
		Merge(v, low, mid, high, count);
	}
}

void InversePair(vector&v,int &count) {
	if (v.size() <= 1) {
		return;
	}
	int low = 0;
	int high = v.size() - 1;
	InversePairsCount(v, low, high, count);
}

int main() {
	vectorv = { 7,5 ,6,4 };
	int count = 0;
	InversePair(v, count);
	cout << count << endl;
    
	system("pause");
	return 0;
}

52-两个链表的第一个公共节点

题目:输入两个链表,找出他们的第一个公共节点。

#include 
using namespace std;
#include 
struct ListNode {
	int m_nKey;
	ListNode *m_pNext;
};

//方法1:

ListNode *FindFirstCommonNode_solution1(ListNode *head1, ListNode*head2) {
	if (head1 == nullptr || head2 == nullptr) {
		return nullptr;
	}
	stacks1;
	while (head1 != nullptr) {
		s1.push(head1);
		head1 = head1->m_pNext;
	}
	stacks2;
	while (head2 != nullptr) {
		s2.push(head2);
		head2 = head2->m_pNext;
	}
	ListNode *m = s2.top();
	
	while (s1.size() > 0 && s2.size() > 0) {
		ListNode * s1Top = s1.top();
		ListNode * s2Top = s2.top();
		if (&s1Top->m_nKey == &s2Top->m_nKey) {
			s1.pop();
			s2.pop();
		}
		else {
			return s1Top->m_pNext;
		}
		if (s1.empty() && s2.empty()) {
			return s1Top;
		}
	}
}

//方法二

ListNode *FindFirstCommonNode_solution2(ListNode *pHead1, ListNode *pHead2) {
	if (pHead1 == nullptr || pHead2 == nullptr) {
		return nullptr;
	}
	ListNode *phead1 = pHead1;
	ListNode *phead2 = pHead2;

	int length1 = 0, length2 = 0;
	while (pHead1 != nullptr) {
		length1++;
		pHead1 = pHead1->m_pNext;
	}
	while (pHead2 != nullptr) {
		length2++;
		pHead2 = pHead2->m_pNext;
	}
	if (length1 > length2) {
		for (int i = 0; i < (length1 - length2); i++) {
			phead1 = phead1->m_pNext;
		}
	}
	else {
		for (int i = 0; i < (length2 - length1); i++) {
			phead2 = phead2->m_pNext;
		}
	}
	while (phead1 != nullptr && phead2 != nullptr) {
		//指向的是同一个地址才是公共节点,否则不是
		if (&phead1->m_nKey == &phead2->m_nKey) {
			return phead1;
		}
		else {
			phead1 = phead1->m_pNext;
			pHead2 = phead2->m_pNext;
		}
	}
	return nullptr;
}

int main() {
	
	/*ListNode *head0 = new ListNode();
	head0->m_nKey = 2;
	head0->m_pNext = nullptr;
*/
	ListNode *head1 = new ListNode();
	head1->m_nKey = 1;
	head1->m_pNext = nullptr;

	ListNode *head3 = new ListNode();
	head3->m_nKey = 2;
	head3->m_pNext = head1;


	ListNode *head2 = new ListNode();
	head2->m_nKey = 1;
	head2->m_pNext = nullptr;//没有公共节点,只是节点的值相等,但地址并不相等

	//ListNode *head2 = head1;//这样的head2是有公共节点的,因为head2与head1有公共节点

	ListNode *res = FindFirstCommonNode_solution2(head3, head2);
	if (res != nullptr) {
		cout << res->m_nKey << endl;
	}
	else {
		cout << "无公共节点" << endl;
	}

	delete head1;
	delete head3;
	//delete head2;

	system("pause");
	return 0;
}

53-在排序数组中查找数字

53-1-数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}中统计数字3的次数。

#include 
using namespace std;
#include

int getNumberOfK(vector nums, int k) {
	if (nums.empty()) return 0;
	int ret = 0;
	int left = 0, right = nums.size() - 1;

	int leftIndex = -1;  // k元素最左位置
	int rightIndex = -1; // k元素最右位置
	// 查找最左边的k元素位置
	while (left <= right) {
		int mid = (left + right) / 2;
		if (nums[mid] < k)
			left = mid + 1;
		else if (nums[mid] > k)
			right = mid - 1;
		else {
			if ((mid > 0 && nums[mid - 1] != k) || mid == 0) {
				leftIndex = mid;
				break;
			}
			else
				right = mid - 1;
		}
	}

	if (leftIndex == -1) return 0;    // 没有出现

	// 查找最右边的k元素位置
	left = 0, right = nums.size() - 1;
	while (left <= right) {
		int mid = (left + right) / 2;
		if (nums[mid] < k)
			left = mid + 1;
		else if (nums[mid] > k)
			right = mid - 1;
		else {
			if ((mid < nums.size() - 1 && nums[mid + 1] != k) || mid == nums.size() - 1) {
				rightIndex = mid;
				break;
			}
			else
				left = mid + 1;
		}
	}
	return rightIndex - leftIndex + 1;
}

int main() {

	vectorv = { 1,2,3,3,3,3,4,5 };
	int k = 3;
	int res = getNumberOfK(v, k);
	cout << res << endl;
	system("pause");
	return 0;
}

53-2-0~n-1中缺失的数字
#include  
using namespace std;

int GetMissingNumber(int arr[], int length) {
	if (arr == nullptr || length <= 0) {
		return -1;
	}
	int left = 0;
	int right = length - 1;
	while (left <= right) {
		int midIndex = (left + right) >> 1;
		if (arr[midIndex] == midIndex) {
			left = midIndex + 1;
		}
		else {
			if (midIndex == 0 || arr[midIndex - 1] == midIndex-1) {
				return midIndex;
			}
			else {
				right = midIndex - 1;
			}
		}
	}
	if (left == length) {
		return length;
	}
	return -1;
}

int main() {

	int arr[] = { 0,1,2,3,4,5,6,7,9 };
	int length = sizeof(arr) / sizeof(arr[0]);
	int res = GetMissingNumber(arr, length);
	cout << res << endl;

	system("pause");
	return 0;
}

53-3-数组中数值和下标相等的元素
#include 
using namespace std;

int GetNumberSameAsIndex(int arr[], int length) {
	if (arr == nullptr || length <= 0) {
		return -1;
	}
	int left = 0;
	int right = length - 1;
	while (left <= right) {
		int midIndex = (left + right) / 2;
		if (arr[midIndex] == midIndex) {
			return midIndex;
		}
		else if (arr[midIndex] > midIndex) {
			right = midIndex - 1;
		}
		else if (arr[midIndex] < midIndex) {
			left = midIndex + 1;
		}
	}
	return -1;
}

int main() {
 
	int arr[] = { -3,-1,1,3,5 };
	int length = sizeof(arr) / sizeof(arr[0]);
	int res = GetNumberSameAsIndex(arr, length);
	cout << res << endl;

	system("pause");
	return 0;
}

54- 二叉搜索树的第k大节点

#include 
using namespace std;
struct BinaryTreeNode {
	int m_value;
	BinaryTreeNode * m_left;
	BinaryTreeNode * m_right;
};

BinaryTreeNode *KthNodeCore(BinaryTreeNode *pRoot, int &k) {
	BinaryTreeNode *target = nullptr;
	if (pRoot->m_left != nullptr) {
		target = KthNodeCore(pRoot->m_left, k);
	}
	if (target == nullptr) {
		if (k == 1) {
			target = pRoot;
		}
		k--;
	}
	if (target == nullptr && pRoot->m_right != nullptr) {
		target = KthNodeCore(pRoot->m_right, k);
	}
	return target;
}

BinaryTreeNode *KthNode(BinaryTreeNode *pRoot, int k) {
	if (pRoot == nullptr || k <= 0) {
		return nullptr;
	}
	return KthNodeCore(pRoot, k);
}

int main() {


	system("pause");
	return 0;
}

55-二叉树的深度

55-1-二叉树的深度
#include 
using namespace std;
struct BinaryTreeNode {
	int m_value;
	BinaryTreeNode * m_left;
	BinaryTreeNode * m_right;
};

int TreeDepth(BinaryTreeNode *pRoot) {
	if (pRoot == nullptr) {
		return 0;
	}
	int left = TreeDepth(pRoot->m_left);
	int right = TreeDepth(pRoot->m_right);
	return (left >= right) ? (left + 1) : (right + 1);
}

int main() {


	system("pause");
	return 0;
}

55-2-平衡二叉树
#include 
using namespace std;

struct BinaryTreeNode {
	int m_value;
	BinaryTreeNode * m_left;
	BinaryTreeNode * m_right;
};

int Height(BinaryTreeNode *pRoot) {
	if (pRoot == nullptr) {
		return 0;
	}
	int lh = Height(pRoot->m_left);
	int rh = Height(pRoot->m_right);
	if (lh < 0 || rh < 0 || lh - rh > 1 || lh - rh < -1) {
		return -1;
	}
	else {
		return (lh > rh) ? (lh + 1) : (rh + 1);
	}
}

bool IsBalanced(BinaryTreeNode *pRoot) {
	if (pRoot == nullptr) {
		return false;
	}
	return Height(pRoot) >= 0;
}
int main() {


	system("pause");
	return 0;
}

56-数组中数字出现的次数

56-1-数组中只出现一次的两个数字
题目:在一个数组中除两个数字只出现一次之外,其他数字都出现了两次。
#include 
using namespace std;

int FindFirstBitIs1(int num) {
	int indexBit = 0;
	while (((num & 1) == 0) && (indexBit < 8 * sizeof(int))) {
		num = num >> 1;
		++indexBit;
	}
	return indexBit;
}

void FindNumsAppearOnce(int arr[],int length, int &num1, int &num2) {
	if (arr == nullptr || length < 2) {
		return;
	}
	int resultExclusive = 0;
	for (int i = 0; i < length; i++) {
		resultExclusive ^= arr[i];
	}
	int indexFirstOf1 = FindFirstBitIs1(resultExclusive);
	num1 = 0;
    num2 = 0;
	for (int i = 0; i < length; i++) {
		if ((arr[i] >> indexFirstOf1) & 1) {
			num1 ^= arr[i];
		}
		else {
			num2 ^= arr[i];
		}
	}
}

int main() {
	int arr[] = { 2,4,3,6,3,2,5,5 };
	int num1;
	int num2;
	int length = sizeof(arr) / sizeof(arr[0]);
	FindNumsAppearOnce(arr,length, num1, num2);
	cout << num1 << endl;
	cout << num2 << endl;

	system("pause");
	return 0;
}

56-2-数组中唯一只出现一次的数字
题目:在一个数组中除一个数字只出现一次之外,其他数字都出现了三次。

class Solution {
public:
    int singleNumber(vector& nums) {
        if (nums.size() <= 0) {
            return -1;
        }
        if (nums.size() == 1) {
            return nums[0];
        }
        int bitarr[32] = {0};
        for (int i = 0; i < nums.size(); i++) {
            int bitmask = 1;
            for (int j = 31; j >= 0; j--)
            {
                int bit = (nums[i] >> j) & 1;
                bitarr[j] += bit;
            }
        }
        int result = 0;
        for (int i = 31; i >= 0; i--) {
            result |= ((bitarr[i] % 3) << i);
        }
        return result;
    }
};

57-和为s的数字

57-1-和为s的两个数字
#include 
using namespace std;

bool unvilidinput = true;

void FindNumbersWithSum(int arr[], int Sum, int length,int &num1,int &num2) {
	if (arr == nullptr || Sum == 0 || length < 2) {
		return;
	}
	int start = 0;
	int end = length - 1;
	while (start < end) {
		int cursum = arr[start] + arr[end];
		if (cursum > Sum) {
			end--;
		}
		else if (cursum < Sum) {
			start++;
		}
		else {
			unvilidinput = false;
			num1 = arr[start];
			num2 = arr[end];
			break;
		}
	}
}

int main() {

	int arr[] = { 1,2,4,7,11,15 };
	int length = sizeof(arr) / sizeof(arr[0]);
	int num1, num2;
	FindNumbersWithSum(arr, 20, length,num1,num2);
	if (unvilidinput == false) {
		cout << num1 << " "  << num2 << endl;
	}
	

	system("pause");
	return 0;
}

57-2-和为s的连续正数序列
#include 
using namespace std;

void PrintContinuousSequence(int small, int big) {

	for (small; small <= big; small++) {
		cout << small << " ";
	}
	cout << endl;
}

void FindContinuousSequence(int sum) {
	if (sum < 3) {
		return;
	}
	int small = 1;
	int big = 2;
	int middle = (1 + sum) / 2;
	int curSum = small + big;
	while (small < middle) {
		if (curSum == sum) {
			PrintContinuousSequence(small, big);
		}
		while (curSum > sum && small < middle) {
			curSum -= small;
			small++;
			if (curSum == sum) {
				PrintContinuousSequence(small, big);
			}
		}
		big++;
		curSum += big;
	}

}

int main() {

	int sum = 15;
	FindContinuousSequence(sum);

	system("pause");
	return 0;
}

58-翻转字符串

58-1-翻转单词顺序
#include 
using namespace std;
#include 
#include 

void Reverse(string &str) {
	if (str.empty()) {
		return;
	}
	stackvs;
	string subStr = "";
	for (auto it = str.begin(); it != str.end(); it++) {
		if ((*it) == '.' || it == --str.end()) {
			subStr += (*it);
			vs.push(subStr);
			subStr = "";
		}
		else if ((*it) != ' ') {
			subStr +=(*it);
		}
		else {
			vs.push(subStr);
			subStr = "";
		}
	}
	while (!vs.empty()) {
		cout << vs.top() << " ";
		vs.pop();
	}
	cout << endl;
}

int main() {

	//string str = "I am a student.";
	string str = "student";
	Reverse(str);

	system("pause");
	return 0;
}

58-2-左旋转字符串
#include 
using namespace std;
#include 
#include 

void LeftRotateString(string &str,int pos) {
	if (str.empty() || pos == 0 || pos > str.size()) {
		return;
	}
	string ss = "";
	for (int i = 0; i < pos; i++) {
		ss +=str[i];
	}
	str.erase(0, pos);
	str.append(ss.begin(), ss.end());
	
}

int main() {

	string str = "abcdefg";
	int pos = 6;
	LeftRotateString(str,pos);
	for (int i = 0; i < str.size(); i++) {
		cout << str[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

59-队列的最大值

59-1-滑动窗口的最大值
#include 
using namespace std;
#include
#include 

vector maxInWindows(const vector&num, int size) {
	vectormaxInWindows;
	if (num.size() >= size && size >= 1) {
		dequeindex;
        //找出数组中前size个元素最大值的下标,存入index双端数组
		for (int i = 0; i < size; i++) {
			while (!index.empty() && num[i] >= num[index.back()]) {
				index.pop_back();
			}
			index.push_back(i);
		}
        //处理数组中后续其他元素值
		for (int i = size; i < num.size(); i++) {
			maxInWindows.push_back(num[index.front()]);
			while (!index.empty() && num[i] >= num[index.back()]) {
				index.pop_back();
			}
			if (!index.empty() && index.front() <= (int)(i - size)) {
				index.pop_front();
			}
			index.push_back(i);
		}
		maxInWindows.push_back(num[index.front()]);
	}
	return maxInWindows;
}

int main() {
	 
	vectornum = { 2,3,4,2,6,2,5,1 };
	vector res = maxInWindows(num, 3);
	for (vector::iterator it = res.begin(); it != res.end(); it++){
		cout << *it << " ";
	}

	system("pause");
	return 0;
}

59-2-队列的最大值
#include 
using namespace std;
#include 

template
class QueueWithMax {
public:
	QueueWithMax() :currentIndex(0) {}

	void push_back(T number) {
		while (!maximums.empty() && number >= maximums.back().number) {
			maximums.pop_back();
		}
		InternalData internalData = { number,currentIndex };
		data.push_back(internalData);
		maximums.push_back(internalData);

		currentIndex++;
	}

	void pop_front() {
		if (maximums.empty()) {
			throw new exception("queue is empty");
		}
		if (maximums.front().index == data.front().index) {
			maximums.pop_front();
		}
		data.pop_front();
	}

	T max()const {
		if (maximums.empty()) {
			throw new exception("queue is empty");
		}
		return maximums.front().number;
	}
private:
	struct InternalData {
		T number;
		int index;
	};
	dequedata;
	dequemaximums;
	int currentIndex;
};

int main() {

	system("pause");
	return 0;
}

60-n个骰子的点数

题目:把n个骰子扔在地上,所有骰子朝上的一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
#include 
using namespace std;
#include 

int g_maxValue = 6;
void PrintProbability(int number) {
	if (number < 1) {
		return;
	}
	int *pProbabilities[2];
	pProbabilities[0] = new int[g_maxValue * number + 1];
	pProbabilities[1] = new int[g_maxValue * number + 1];
	for (int i = 0; i < g_maxValue * number + 1; i++) {
		pProbabilities[0][i] = 0;
		pProbabilities[1][i] = 0;
	}
	int flag = 0;
	for (int i = 1; i <= g_maxValue; i++) {
		pProbabilities[flag][i] = 1;
	}
	for (int k = 2; k <= number; k++) {
		for (int i = 0; i < k; i++) {
			pProbabilities[1 - flag][i] = 0;
		}
		for (int i = k; i <= g_maxValue * k; i++) {
			pProbabilities[1 - flag][i] = 0;
			for (int j = 1; j <= i && j <= g_maxValue; j++) {
				pProbabilities[1 - flag][i] += pProbabilities[flag][i - j];
			}
		}
		flag = 1 - flag;
	}
	double total = pow((double)g_maxValue, number);
	for (int i = number; i <= g_maxValue * number; i++) {
		double ratio = (double)pProbabilities[flag][i] / total;
		printf("%d:%e\n", i, ratio);
	}
	delete[] pProbabilities[0];
	delete[] pProbabilities[1];

}

int main() {

	PrintProbability(5);

	system("pause");
	return 0;
}


方法二:
class Solution {
public:
    vector twoSum(int n) {
        vector>dp(n + 1, vector(6 * n + 1, 0));
        dp[0][0] = 1; //初始化:n个骰子,除了dp[0][0] = 1,其他都是0
        // dp[i][j] 表示前 i 次总和为点数为 j 的情况的次数
        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= 6 * n; j++) {
                for (int k = 1; k <= 6; k++) {
                    if (j >= k) {
                        dp[i][j] += dp[i - 1][j - k];
                    }
                }
            }
        }
        //计算每个点出现的次数
        int *times = new int[5 * n + 1];
        for (int i = n, j = 0; i <= 6 * n; i++, j++) {
            times[j] = dp[n][i];
        }
        // 计算每个次数的概率
        vectorres;
        double total = pow(6, n);
        for (int i = 0; i < 5 * n + 1; i++) {
            res.push_back(times[i] / total);
        }
        return res;
    }
};

61-扑克牌中的顺子

题目:从扑克牌中随机抽取5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。

// 方法一
只有5张牌,先排除非零对子,然后求最大和最小的牌面之差就行了,小于等于4就肯定是顺子
class Solution {
public:
    bool isStraight(vector& nums) {
        int *bucket = new int[14];
        int Min = 14, Max = -1;
        for (int i = 0; i < 14; i++) {
            bucket[i] = 0;
        }
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] == 0) continue;
            // 如果有非零的对子则直接返回false
            if (bucket[nums[i]] == 1) return false;
            bucket[nums[i]]++;
            // 记录牌面的最大和最小
            Min = min(Min, nums[i]);
            Max = max(Max, nums[i]);
        }
        // 小于等于4就行,少的用0补
        return Max - Min <= 4;
    }
};

// 方法二
#include 
using namespace std;

int compare(const void *arg1, const void *arg2) {
	return *(int *)arg1 - *(int *)arg2;
}

bool IsContinuous(int arr[], int length) {
	if (arr == nullptr || length < 1) {
		return false;
	}
	qsort(arr, length, sizeof(int), compare);
	/*for (int i = 0; i < length; i++) {
		cout << arr[i] << endl;
	}*/
	int numberOfzero = 0; //初始化0的个数
	int numberOfgap = 0; //初始化间隙的个数
	int i = 0;
	while (i < length-1)
	{
		if (arr[i] == 0) {
			numberOfzero++;
		}
		else {
			if (arr[i] == arr[i + 1]) {
				return false;
			}
			if (arr[i] + 1 != arr[i + 1]) {
				numberOfgap += arr[i + 1] - arr[i] - 1;
			}
		}
		i++;
	}
	if (numberOfgap <= numberOfzero) {
		return true;
	}
	return false;
}


int main() {
	
	int arr[] = { 0,0, 1,5 , 4 };
	int length = sizeof(arr) / sizeof(arr[0]);
	bool res = IsContinuous(arr, length);
	cout << res << endl;
	system("pause");
	return 0;
}

62-圆圈中最后剩下的数字

#include 
using namespace std;
#include 

//方法一
class Solution {
public:
    int lastRemaining(int n, int m) {
        //旧编号 0   1  ... m-1  m  m+1 ... n-1 
        //新编号 -m -m+1    m-1  0   1  ... n-1-m
        if (n == 1) {
            return 0;
        }
        // 旧编号 = 新编号 + m
        return (lastRemaining(n -1, m) + m) % n;
    }
};

// 方法二
int LastRemaining(int n, int m) {
	if (n < 1 || m < 1) {
		return -1;
	}
	listarr;
	for (int i = 0; i < n; i++) {
		arr.push_back(i);
	}
	auto it = arr.begin();
	while (arr.size() > 1)
	{
		for (int i = 1; i < 3; i++) {
			it++;
			if (it == arr.end()) {
				it = arr.begin();
			}
		}
		auto next = ++it;
		if (next == arr.end()) {
			next = arr.begin();
		}
		--it;
		arr.erase(it);
		it = next;
	}
	return *it;
}

int main() {
	int n = 5;
	int m = 3;
	int res = LastRemaining(n, m);
	cout << res << endl;
	system("pause");
	return 0;
}

63-股票的最大利润

#include 
using namespace std;

int Maxdiff(int arr[], int length) {
	if (arr == nullptr || length < 2) {
		return 0;
	}
	int min = arr[0];
	int maxDiff = arr[1] - min;
	for (int i = 2; i < length; i++) {
		if (arr[i - 1] < min) {
			min = arr[i - 1];
		}
		int currentDiff = arr[i] - min;
		if (currentDiff > maxDiff) {
			maxDiff = currentDiff;
		}
	}
	return maxDiff;
}

int main() {

	int arr[] = { 9,11,8,5,7,12,16,14 };
	int length = sizeof(arr) / sizeof(arr[0]);
	int res = Maxdiff(arr, length);
	cout << res << endl;
	system("pause");
	return 0;
}

64-求1+2+…+n


shared_ptr引用计数智能指针

shared_ptr采用引用计数,多个指针可以指向同一个对象;auto_ptr就不能,只能运行一个指针指向一个对象:如果要指针赋值,那么原来的指针要放弃对该对象的所有权。

恩,以后都用shared_ptr。

shared_ptr在最新的c++11中,已经被列入了标准指针,而auto_ptr则出局了。

说了那么多,shared_ptr采用RAII技术,是防止内存泄露的神器。

按bnu_chenshuo的说法,他最后一次看见代码中的内存泄露还是04年他做实习生的时候。

而C++沉思录的作者AndrewKoenig也极力推荐使用标准库,不用指针。

看下面的程序,我new了一个对象,并没有在程序中使用delete,但是,运行程序,其构造函数仍然运行!这就是shared_ptr,如果要预防内存泄露,它就是最佳选择!

# include 
# include 
using namespace std;
class A {
public:
	A() {
		cout << "construct A!!!" << endl;
	}
	;
	~A() {
		cout << "destruct A!!!" << endl;
	}
	;
};
class B: public A {
public:
	B() {
		cout << "construct B!!!" << endl;
	}
	;
	~B() {
		cout << "destruct B!!!" << endl;
	}
	;
};
int main() {
//	B* ptrB0 = new B();
	std::tr1::shared_ptr ptrB1(new B());
}

运行结果:
construct A!!!
construct B!!!
destruct B!!!
destruct A!!!

14

拓扑排序

leetcode 207
    
class Solution {
public:
    bool canFinish(int numCourses, vector>& prerequisites) {
        vector>Adj(numCourses,list());//邻接表
        vectorindegree(numCourses,0);//保存每个节点的入度
        stackstk;//保存当前入度为0的节点编号
        for(int i = 0;i < prerequisites.size();i++){
            Adj[prerequisites[i][1]].push_back(prerequisites[i][0]);
            indegree[prerequisites[i][0]]++;
        }
        for(int i = 0;i < numCourses;i++){
            if(indegree[i]==0){
                stk.push(i);
            }
        }
        int cnt = 0;
        while(!stk.empty()){
            int top = stk.top();
            stk.pop();
            cnt ++;
            for(list::iterator it = Adj[top].begin();it != Adj[top].end();it++){
                indegree[*it] --;
                if (indegree[*it] == 0){
                    stk.push(*it);
                }
            }
        }
        return cnt == numCourses;
    }
};

直接插入排序

#include
#include
using namespace std;

void insertSort(int a[], int length)
{
	for (int i = 1; i < length; i++) {
		int temp = a[i];
		int j = i - 1;
		while (j >= 0) {
			if (a[j] > temp) {
				a[j + 1] = a[j];
				j--;
			}
			else {
				break;
			}
		}
		a[j + 1] = temp;
	}
}

int main()
{
	int a[] = { 2,1,4,5,3,8,7,9,0,6 };

	insertSort(a, 10);

	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << " ";

	}
	cout << endl;
	system("pause");
	return 0;

}


冒泡排序

#include
#include
using namespace std;

int * BubbleSort(int *a,int len) {
	int i = 0;
	while (i < len-1 )
	{
		for (int j = 0; j < len - i - 1; j++) {
			if (a[j] > a[j + 1]) {
				int temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
			}
		}
		i++;
	}
	return a;
}

void print(int *a) {
	for (int i = 0; i < 10; i++)
	{
		cout << a[i] << " ";

	}
	cout << endl;
}

int main4()
{
	
	int a[]= { 2,1,4,52,3,8,7,9,0,6 };

	BubbleSort(a, 10);
	print(a);

	
	system("pause");
	return 0;

}


快速排序

#include 
using namespace std;

//快速排序 1
int Partition(int a[],int low,int height ) {
	int pivot = a[low];
	int i = low;
	int j = height;
	while (i!=j)
	{
		while (i pivot)
		{
			j--;
		}
		if (i < j) {
			swap(a[i++], a[j]);
		}
		
		while (i
using namespace std;
#include

void quick_sort(int arr[], int left, int right)
{
	if (left >= right) {
		return;
	}
	int i, j, temp;
	i = left;
	j = right;
	temp = arr[left];
	while (i != j) {
		while (arr[j] >= temp && i < j) {
			j--;
		}
		while (arr[i] <= temp && i < j) {
			i++;
		}
		if (i < j) {
			swap(arr[i], arr[j]);
		}
	}
	swap(arr[left], arr[i]);
	quick_sort(arr, left, i - 1);
	quick_sort(arr, i + 1, right);
}


int main() {
	int a[] = { 10,5,20,30,21,23,45,65,1 };
	int height = sizeof(a) / sizeof(a[0]) - 1;
	quick_sort(a, 0, height);
	for (int i = 0; i < height; i++) {
		cout << a[i] << " ";
	}

	system("pause");
	return 0;
}

//快速排序3
#include 
using namespace std;
#include

void quick_sort(int arr[], int left, int right)
{
	if (left >= right) {
		return;
	}
	int i, j, temp;
	i = left;
	j = right;
	temp = arr[left];
	while (i != j) {
		while (arr[j] >= temp && i < j) {
			j--;
		}
		if (i < j) {
			arr[i++] = arr[j];
		}
		while (arr[i] <= temp && i < j) {
			i++;
		}
		if (i < j) {
			arr[j--] = arr[i];
		}
		
	}
	
	arr[i] = temp;
	quick_sort(arr, left, i - 1);
	quick_sort(arr, i + 1, right);
}


int main() {
	int a[] = { 10,5,20,130,21,23,45,605,1 };
	int height = sizeof(a) / sizeof(a[0]) - 1;
	quick_sort(a, 0, height);
	for (int i = 0; i < height+1; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

//时间复杂度:O(nlog(n));
//空间复杂度:O(log(n));
//快速是不稳定的
//采用分治的思想

归并排序

#include
using namespace std;
#include

//合并a
void Merge(int a[],int low,int mid,int high) {
	int *b = new int[high - low + 1];//申请一个数组
	int i = low, j = mid+1, k = 0;
	while (i <= mid && j <= high) {
		if (a[i] <= a[j]) {
			b[k++] = a[i++];
		}
		else {
			b[k++] = a[j++];
		}
	}
	while (i<=mid)
	{
		b[k++] = a[i++];
	}
	while (j<=high)
	{
		b[k++] = a[j++];
	}
	for (int i = low,k = 0; i <= high; i++) {
		a[i] = b[k++];
	}
	delete [] b;
}

void MergeSort(int a[],int low,int high) {
	if (low < high) {
		int mid = (low + high) / 2;
		MergeSort(a, low, mid);
		MergeSort(a, mid + 1, high);
		Merge(a, low, mid, high);
	}
}

int main7() {

	int a[] = { 5,2,3,8,10,25,65,42,23,21 };
	int high = sizeof(a) / sizeof(a[0]);
	MergeSort(a, 0, high-1);

	for (int i = 0; i < high; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
	

	system("pause");
	return 0;

}

//时间复杂度 O(nlog(n))
//空间复杂度 O(log(n))
//稳定

简单选择排序

#include
using namespace std;

void SimpleSelectSort(int a[],int len) {
	for (int i = 0; i < len; i++) {
		int min = i;
		for (int j = i + 1; j < len; j++) {
			if (a[j] < a[min]) {
				min = j;
			}
		}
		if (min != i) {
			int temp = a[i];
			a[i] = a[min];
			a[min] = temp;
		}
	}
}

int main() {
	
	int a[] = { 2,5,6,4,8,9,10,2,1 };
	int len = sizeof(a) / sizeof(a[0]);
	SimpleSelectSort(a, len);

	for (int i = 0; i < len; i++) {
		cout << a[i] << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

//时间复杂度 O(n**2)
//空间复杂度O(1)
//不稳定性

堆排序

#include
#include
using namespace std;

template
void AdjustHeap(vector& a, int i, int len)
{
	while (2 * i + 1 <= len) {
		int j = 2 * i + 1;//指向左孩子
		if (j < len && a[j] < a[j + 1]) {
			j++;
		}
		if (a[i] > a[j]) {
			break;
		}
		else {
			swap(a[i], a[j]);
		}
		i = j;
	}
}
template
void HeapSort(vector& a) {
	int len = a.size() - 1;
	for (int i = len / 2 - 1; i >= 0; i--) {//构造一个大顶堆,这时的a[0]为最大值
		AdjustHeap(a, i, len);
	}
	while (len >= 0) {
		swap(a[0], a[len--]);
		AdjustHeap(a, 0, len);//调整堆,使其满足堆的定义(父节点比它的俩子节点都要大)
	}
}

int main()
{
	vector a = {18,10,6,16,20,28,30,2,16,12 };
	cout << "排序之前:" << endl;
	for (int i = 0; i < a.size(); i++) {
		cout << a[i] << " ";
	}
	cout << endl;
	HeapSort(a);
	cout << "排序之后:" << endl;
	for (int i = 0; i < a.size(); i++) {
		cout << a[i] << " ";
	}
	system("pause");
	return 0;
}


你可能感兴趣的:(笔记)