单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
#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
饿汉式单例模式:在类加载时就完成了初始化,所以类加载比较慢、获取对象的速度快、以空间换取时间模式、线程安全、
懒汉式单例模式:在类加载时不初始化、按照需求创建实例、以时间换取空间模式
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;
}
题目:在一个长度为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;
}
// 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按
// 照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个
// 整数,判断数组中是否含有该整数。
#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;
}
题目:请实现一个函数,把字符串中的每个空格替换成"%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);
题目:青蛙跳台阶问题
#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;
}
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{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;
}
回溯法
#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;
}
题目:地上有一个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;
}
动态规划问题的特点:
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;
}
题目:请实现一个函数,输入一个整数,输出该数二进制表示中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.
#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;
}
利用递归
#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;
}
#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;
}
题目:请实现一个函数用来匹配包括’.’和’‘的正则表达式。模式中的字符’.’表示任意一个字符,而’‘表示它前面的字符可以出现任意次(包含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;
}
#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;
}
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
例如,字符串"+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;
}
题目:输入一个整数数组,实现一个函数来调整该数组数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
#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;
}
#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;
}
/判断是否有环,如果快慢指针相遇的节点
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;
}
辅助指针:定义三个用于翻转链表的辅助指针和一个用于表示翻转链表头结点的指针,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;
}
递归法:
#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;
}
输入两颗二叉树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;
}
题目:请完成一个函数,输入一颗二叉树,该函数输出它的镜像。
#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;
}
题目:请实现一个函数,用来判断一颗二叉树是不是对称的(与其镜像一样)
#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;
}
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
思路:将其看作一圈一圈打印
开始:(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;
}
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的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;
}
如果下一个弹出的数字刚好的栈顶数字,那么直接弹出,如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。如果所有的数字都压入栈了,仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。
#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();
}
从上到下打印二叉树的每个节点,同一层的节点打印按照从左往右的顺序打印。
#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;
}
#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;
}
思路:如果当前打印的是偶数层(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;
}
思路:当前打印的层数为偶数层(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;
}
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。
分析:在后序遍历二叉搜索树得到的序列中,最后一个数字是树的根节点的值。数组中前面的数字可以分为两部分:第一部分是左子树的值,他们都比根节点的值小;第二部分是右子数的值,它们都比根节点的值大。如果满足该条件,则是某二叉搜索树的后序遍历序列,否则不是。
#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;
}
题目:输入二叉树和一个整数,打印二叉树中的节点值得的和为输入整数的所有路径。
#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;
}
题目:请实现函数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;
}
题目:输入一个搜索二叉树,将该二叉搜索树转化成一个排序的双向链表。要求不能创建任何新的节点指针,只能调整树中节点指针的指向。
#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;
}
题目:请实现两个函数,分别用来序列化和反序列化二叉树。
#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;
}
题目:输入一个字符串,打印出该字符串中字符的所有排列。
#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;
}
思路:如果组合中包含第一个字符,则下一步在剩余的字符中选取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;
}
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
思路:在遍历数组的时候保存两个值:一个是数组中的一个数字,另一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则字数加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;
}
题目:输入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;
}
思路:在数据总数目是偶数时把新数据插入最小堆,否则插入最大堆。
还要保证最大堆中的所有数据都要小于最小堆的数据。
当数据的总数是偶数时,按照前面的分配规则会把新的数据插入最小堆,如果新数据比原最小堆中最小的数据大,则先把这个新数据插入最小堆,再把原最小堆中的最小值取出放入最大堆中。
当数据的总数是奇数时,按照前面的分配规则会把新的数据插入最大堆,如果新数据比原最大堆中最大的数据小,则先把这个新数据插入最大堆,再把原最大堆中的最大值取出放入最小堆中。
#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;
}
#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;
}
传统解法:
#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;
}
题目:数字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;
}
题目:输入一个正整数组,把数组里所有数字拼接起来排成一个数,打印能拼接出来的所有数字中最小的一个。
#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;
}
#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;
}
#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];
}
题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该字符串长度。
#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;
}
题目:我们把只包含因子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;
}
#include
using namespace std;
#include
#include
#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;
}
题目:输入两个链表,找出他们的第一个公共节点。
#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;
}
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{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;
}
#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;
}
#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;
}
#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;
}
#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;
}
#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;
}
题目:在一个数组中除两个数字只出现一次之外,其他数字都出现了两次。
#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;
}
题目:在一个数组中除一个数字只出现一次之外,其他数字都出现了三次。
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;
}
};
#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;
}
#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;
}
#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;
}
#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;
}
#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;
}
#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;
}
题目:把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;
}
};
题目:从扑克牌中随机抽取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;
}
#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;
}
#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;
}
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;
}