其他

目录:

1、【剑指Offer学习】【面试题01:实现赋值运算符函数】

2、【剑指Offer学习】【面试题02:实现Singleton 模式——七种实现方式】

5、【剑指Offer学习】【面试题05:替换空格】

10、【剑指Offer学习】【面试题10:斐波那契数列】

12、【剑指Offer学习】【面试题12:二进制中1 的个数】

13、【剑指Offer学习】【面试题13:机器人的运动范围】

14、【剑指Offer学习】【面试题14:剪绳子】

15、【剑指Offer学习】【面试题15:二进制中1的个数】

17、【剑指Offer学习】【面试题17:打印1到最大的n位数】

19、【剑指Offer学习】【面试题19:正则表达式匹配】

29、【剑指Offer学习】【面试题29:顺时针打印矩阵】

40、【剑指Offer学习】【面试题40:最小的k个数】

41、【剑指Offer学习】【面试题41:数据流中的中位数】

47、【剑指Offer学习】【面试题47:礼物的最大价值】

49、【剑指Offer学习】【面试题49:丑数】

58、【剑指Offer学习】【面试题58:翻转单词顺序】

59、【剑指Offer学习】【面试题59:滑动窗口的最大值】

60、【剑指Offer学习】【面试题60:n个骰子的点数】

61、【剑指Offer学习】【面试题61:扑克牌的顺子】

63、【剑指Offer学习】【面试题63:股票的最大利润】

64、【剑指Offer学习】【面试题64:求1+2+…+n】

65、【剑指Offer学习】【面试题65:不用加减乘除做加法】

68、【剑指Offer学习】【面试题68:树中两个结点的最低公共祖先】

1. 面试题01:实现赋值运算符函数

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题1:赋值运算符函数
// 题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。

include

include

class CMyString
{
public:
CMyString(char* pData = nullptr);
CMyString(const CMyString& str);
~CMyString(void);

CMyString& operator = (const CMyString& str);

void Print();

private:
char* m_pData;
};

CMyString::CMyString(char *pData)
{
if(pData == nullptr)
{
m_pData = new char[1];
m_pData[0] = '\0';
}
else
{
int length = strlen(pData);
m_pData = new char[length + 1];
strcpy(m_pData, pData);
}
}

CMyString::CMyString(const CMyString &str)
{
int length = strlen(str.m_pData);
m_pData = new char[length + 1];
strcpy(m_pData, str.m_pData);
}

CMyString::~CMyString()
{
delete[] m_pData;
}

CMyString& CMyString::operator = (const CMyString& str)
{
if(this == &str)
return *this;

delete []m_pData;
m_pData = nullptr;

m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData, str.m_pData);

return *this;
}

// 测试代码
void CMyString::Print()
{
printf("%s", m_pData);
}

void Test1()
{
printf("Test1 begins:\n");

char* text = "Hello world";

CMyString str1(text);
CMyString str2;
str2 = str1;

printf("The expected result is: %s.\n", text);

printf("The actual result is: ");
str2.Print();
printf(".\n");
}

// 赋值给自己
void Test2()
{
printf("Test2 begins:\n");

char* text = "Hello world";

CMyString str1(text);
str1 = str1;

printf("The expected result is: %s.\n", text);

printf("The actual result is: ");
str1.Print();
printf(".\n");
}

// 连续赋值
void Test3()
{
printf("Test3 begins:\n");

char* text = "Hello world";

CMyString str1(text);
CMyString str2, str3;
str3 = str2 = str1;

printf("The expected result is: %s.\n", text);

printf("The actual result is: ");
str2.Print();
printf(".\n");

printf("The expected result is: %s.\n", text);

printf("The actual result is: ");
str3.Print();
printf(".\n");
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();

return 0;
}

2. 面试题02:实现Singleton 模式——七种实现方式

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题2:实现Singleton模式
// 题目:设计一个类,我们只能生成该类的一个实例。

using System;

namespace _02_Singleton
{
public sealed class Singleton1
{
private Singleton1()
{
}

private static Singleton1 instance = null;
public static Singleton1 Instance
{
get
{
if (instance == null)
instance = new Singleton1();

return instance;
}
}
}

public sealed class Singleton2
{
private Singleton2()
{
}

private static readonly object syncObj = new object();

private static Singleton2 instance = null;
public static Singleton2 Instance
{
get
{
lock (syncObj)
{
if (instance == null)
instance = new Singleton2();
}

return instance;
}
}
}

public sealed class Singleton3
{
private Singleton3()
{
}

private static object syncObj = new object();

private static Singleton3 instance = null;
public static Singleton3 Instance
{
get
{
if (instance == null)
{
lock (syncObj)
{
if (instance == null)
instance = new Singleton3();
}
}

return instance;
}
}
}

public sealed class Singleton4
{
private Singleton4()
{
Console.WriteLine("An instance of Singleton4 is created.");
}

public static void Print()
{
Console.WriteLine("Singleton4 Print");
}

private static Singleton4 instance = new Singleton4();
public static Singleton4 Instance
{
get
{
return instance;
}
}
}

public sealed class Singleton5
{
Singleton5()
{
Console.WriteLine("An instance of Singleton5 is created.");
}

public static void Print()
{
Console.WriteLine("Singleton5 Print");
}

public static Singleton5 Instance
{
get
{
return Nested.instance;
}
}

class Nested
{
static Nested()
{
}

internal static readonly Singleton5 instance = new Singleton5();
}
}

class Program
{
static void Main(string[] args)
{
// 也会打印An instance of Singleton4 is created.
Singleton4.Print();

// 不会打印An instance of Singleton5 is created.
Singleton5.Print();
}
}
}

5. 【剑指Offer学习】【面试题05:替换空格】】

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题5:替换空格
// 题目:请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入“We are happy.”,
// 则输出“We%20are%20happy.”。

include

include

/length 为字符数组str的总容量,大于或等于字符串str的实际长度/
void ReplaceBlank(char str[], int length)
{
if(str == nullptr && length <= 0)
return;

/originalLength 为字符串str的实际长度/
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(str[i] != '\0')
{
++ originalLength;

if(str[i] == ' ')
++ numberOfBlank;

++ i;
}

/newLength 为把空格替换成'%20'之后的长度/
int newLength = originalLength + numberOfBlank * 2;
if(newLength > length)
return;

int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
{
if(str[indexOfOriginal] == ' ')
{
str[indexOfNew --] = '0';
str[indexOfNew --] = '2';
str[indexOfNew --] = '%';
}
else
{
str[indexOfNew --] = str[indexOfOriginal];
}

-- indexOfOriginal;
}
}

// 测试代码
void Test(char* testName, char str[], int length, char expected[])
{
if(testName != nullptr)
printf("%s begins: ", testName);

ReplaceBlank(str, length);

if(expected == nullptr && str == nullptr)
printf("passed.\n");
else if(expected == nullptr && str != nullptr)
printf("failed.\n");
else if(strcmp(str, expected) == 0)
printf("passed.\n");
else
printf("failed.\n");
}

// 空格在句子中间
void Test1()
{
const int length = 100;

char str[length] = "hello world";
Test("Test1", str, length, "hello%20world");
}

// 空格在句子开头
void Test2()
{
const int length = 100;

char str[length] = " helloworld";
Test("Test2", str, length, "%20helloworld");
}

// 空格在句子末尾
void Test3()
{
const int length = 100;

char str[length] = "helloworld ";
Test("Test3", str, length, "helloworld%20");
}

// 连续有两个空格
void Test4()
{
const int length = 100;

char str[length] = "hello world";
Test("Test4", str, length, "hello%20%20world");
}

// 传入nullptr
void Test5()
{
Test("Test5", nullptr, 0, nullptr);
}

// 传入内容为空的字符串
void Test6()
{
const int length = 100;

char str[length] = "";
Test("Test6", str, length, "");
}

//传入内容为一个空格的字符串
void Test7()
{
const int length = 100;

char str[length] = " ";
Test("Test7", str, length, "%20");
}

// 传入的字符串没有空格
void Test8()
{
const int length = 100;

char str[length] = "helloworld";
Test("Test8", str, length, "helloworld");
}

// 传入的字符串全是空格
void Test9()
{
const int length = 100;

char str[length] = " ";
Test("Test9", str, length, "%20%20%20");
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();

return 0;
}

10. 【剑指Offer学习】【面试题10:斐波那契数列】

/******************************************************************* Copyright(c) 2016, Harry He All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题10:斐波那契数列
// 题目:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。

include

// 方法1:递归
long long Fibonacci_Solution1(unsigned int n)
{
if(n <= 0)
return 0;

if(n == 1)
return 1;

return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);
}

// 方法2:循环
long long Fibonacci_Solution2(unsigned n)
{
int result[2] = {0, 1};
if(n < 2)
return result[n];

long long fibNMinusOne = 1;
long long fibNMinusTwo = 0;
long long fibN = 0;
for(unsigned int i = 2; i <= n; ++ i)
{
fibN = fibNMinusOne + fibNMinusTwo;

fibNMinusTwo = fibNMinusOne;
fibNMinusOne = fibN;
}

return fibN;
}

// 方法3:基于矩阵乘法
#include

struct Matrix2By2
{
Matrix2By2
(
long long m00 = 0,
long long m01 = 0,
long long m10 = 0,
long long m11 = 0
)
:m_00(m00), m_01(m01), m_10(m10), m_11(m11)
{
}

long long m_00;
long long m_01;
long long m_10;
long long m_11;
};

Matrix2By2 MatrixMultiply
(
const Matrix2By2& matrix1,
const Matrix2By2& matrix2
)
{
return Matrix2By2(
matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);
}

Matrix2By2 MatrixPower(unsigned int n)
{
assert(n > 0);

Matrix2By2 matrix;
if(n == 1)
{
matrix = Matrix2By2(1, 1, 1, 0);
}
else if(n % 2 == 0)
{
matrix = MatrixPower(n / 2);
matrix = MatrixMultiply(matrix, matrix);
}
else if(n % 2 == 1)
{
matrix = MatrixPower((n - 1) / 2);
matrix = MatrixMultiply(matrix, matrix);
matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
}

return matrix;
}

long long Fibonacci_Solution3(unsigned int n)
{
int result[2] = {0, 1};
if(n < 2)
return result[n];

Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
return PowerNMinus2.m_00;
}

// 测试代码
void Test(int n, int expected)
{
if(Fibonacci_Solution1(n) == expected)
printf("Test for %d in solution1 passed.\n", n);
else
printf("Test for %d in solution1 failed.\n", n);

if(Fibonacci_Solution2(n) == expected)
printf("Test for %d in solution2 passed.\n", n);
else
printf("Test for %d in solution2 failed.\n", n);

if(Fibonacci_Solution3(n) == expected)
printf("Test for %d in solution3 passed.\n", n);
else
printf("Test for %d in solution3 failed.\n", n);
}

int main(int argc, char* argv[])
{
Test(0, 0);
Test(1, 1);
Test(2, 1);
Test(3, 2);
Test(4, 3);
Test(5, 5);
Test(6, 8);
Test(7, 13);
Test(8, 21);
Test(9, 34);
Test(10, 55);

Test(40, 102334155);

return 0;
}

12. 面试题12:实现赋值运算符函数

/******************************************************************* Copyright(c) 2016, Harry He All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题12:矩阵中的路径
// 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H

include

include

include

using namespace std;

bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int& pathLength, bool* visited);

bool hasPath(const char* matrix, int rows, int cols, const char* str)
{
if(matrix == nullptr || rows < 1 || cols < 1 || str == nullptr)
return false;

bool *visited = new bool[rows * cols];
memset(visited, 0, rows * cols);

int pathLength = 0;
for(int row = 0; row < rows; ++row)
{
for(int col = 0; col < cols; ++col)
{
if(hasPathCore(matrix, rows, cols, row, col, str,
pathLength, visited))
{
return true;
}
}
}

delete[] visited;

return false;
}

bool hasPathCore(const char* matrix, int rows, int cols, int row,
int col, const char* str, int& pathLength, bool* visited)
{
if(str[pathLength] == '\0')
return true;

bool hasPath = false;
if(row >= 0 && row < rows && col >= 0 && col < cols
&& matrix[row * cols + col] == str[pathLength]
&& !visited[row * cols + col])
{
++pathLength;
visited[row * cols + col] = true;

hasPath = hasPathCore(matrix, rows, cols, row, col - 1,
str, pathLength, visited)
|| hasPathCore(matrix, rows, cols, row - 1, col,
str, pathLength, visited)
|| hasPathCore(matrix, rows, cols, row, col + 1,
str, pathLength, visited)
|| hasPathCore(matrix, rows, cols, row + 1, col,
str, pathLength, visited);

if(!hasPath)
{
--pathLength;
visited[row * cols + col] = false;
}
}

return hasPath;
}

// 测试代码
void Test(const char* testName, const char* matrix, int rows, int cols, const char* str, bool expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(hasPath(matrix, rows, cols, str) == expected)
printf("Passed.\n");
else
printf("FAILED.\n");
}

//ABTG
//CFCS
//JDEH

//BFCE
void Test1()
{
const char* matrix = "ABTGCFCSJDEH";
const char* str = "BFCE";

Test("Test1", (const char*) matrix, 3, 4, str, true);
}

//ABCE
//SFCS
//ADEE

//SEE
void Test2()
{
const char* matrix = "ABCESFCSADEE";
const char* str = "SEE";

Test("Test2", (const char*) matrix, 3, 4, str, true);
}

//ABTG
//CFCS
//JDEH

//ABFB
void Test3()
{
const char* matrix = "ABTGCFCSJDEH";
const char* str = "ABFB";

Test("Test3", (const char*) matrix, 3, 4, str, false);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SLHECCEIDEJFGGFIE
void Test4()
{
const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
const char* str = "SLHECCEIDEJFGGFIE";

Test("Test4", (const char*) matrix, 5, 8, str, true);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SGGFIECVAASABCEHJIGQEM
void Test5()
{
const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
const char* str = "SGGFIECVAASABCEHJIGQEM";

Test("Test5", (const char*) matrix, 5, 8, str, true);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SGGFIECVAASABCEEJIGOEM
void Test6()
{
const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
const char* str = "SGGFIECVAASABCEEJIGOEM";

Test("Test6", (const char*) matrix, 5, 8, str, false);
}

//ABCEHJIG
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS

//SGGFIECVAASABCEHJIGQEMS
void Test7()
{
const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
const char* str = "SGGFIECVAASABCEHJIGQEMS";

Test("Test7", (const char*) matrix, 5, 8, str, false);
}

//AAAA
//AAAA
//AAAA

//AAAAAAAAAAAA
void Test8()
{
const char* matrix = "AAAAAAAAAAAA";
const char* str = "AAAAAAAAAAAA";

Test("Test8", (const char*) matrix, 3, 4, str, true);
}

//AAAA
//AAAA
//AAAA

//AAAAAAAAAAAAA
void Test9()
{
const char* matrix = "AAAAAAAAAAAA";
const char* str = "AAAAAAAAAAAAA";

Test("Test9", (const char*) matrix, 3, 4, str, false);
}

//A

//A
void Test10()
{
const char* matrix = "A";
const char* str = "A";

Test("Test10", (const char*) matrix, 1, 1, str, true);
}

//A

//B
void Test11()
{
const char* matrix = "A";
const char* str = "B";

Test("Test11", (const char*) matrix, 1, 1, str, false);
}

void Test12()
{
Test("Test12", nullptr, 0, 0, nullptr, false);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
Test10();
Test11();
Test12();

return 0;
}

13. 面试题13:机器人的运动范围

/******************************************************************* Copyright(c) 2016, Harry He All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

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

include

int movingCountCore(int threshold, int rows, int cols, int row, int col, bool* visited);
bool check(int threshold, int rows, int cols, int row, int col, bool* visited);
int getDigitSum(int number);

int movingCount(int threshold, int rows, int cols)
{
if(threshold < 0 || rows <= 0 || cols <= 0)
return 0;

bool *visited = new bool[rows * cols];
for(int i = 0; i < rows * cols; ++i)
visited[i] = false;

int count = movingCountCore(threshold, rows, cols,
0, 0, visited);

delete[] visited;

return count;
}

int movingCountCore(int threshold, int rows, int cols, int row,
int col, bool* visited)
{
int count = 0;
if(check(threshold, rows, cols, row, col, visited))
{
visited[row * cols + col] = true;

count = 1 + movingCountCore(threshold, rows, cols,
row - 1, col, visited)
+ movingCountCore(threshold, rows, cols,
row, col - 1, visited)
+ movingCountCore(threshold, rows, cols,
row + 1, col, visited)
+ movingCountCore(threshold, rows, cols,
row, col + 1, visited);
}

return count;
}

bool check(int threshold, int rows, int cols, int row, int col,
bool* visited)
{
if(row >= 0 && row < rows && col >= 0 && col < cols
&& getDigitSum(row) + getDigitSum(col) <= threshold
&& !visited[row* cols + col])
return true;

return false;
}

int getDigitSum(int number)
{
int sum = 0;
while(number > 0)
{
sum += number % 10;
number /= 10;
}

return sum;
}

// 测试代码
void test(char* testName, int threshold, int rows, int cols, int expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(movingCount(threshold, rows, cols) == expected)
printf("Passed.\n");
else
printf("FAILED.\n");
}

// 方格多行多列
void test1()
{
test("Test1", 5, 10, 10, 21);
}

// 方格多行多列
void test2()
{
test("Test2", 15, 20, 20, 359);
}

// 方格只有一行,机器人只能到达部分方格
void test3()
{
test("Test3", 10, 1, 100, 29);
}

// 方格只有一行,机器人能到达所有方格
void test4()
{
test("Test4", 10, 1, 10, 10);
}

// 方格只有一列,机器人只能到达部分方格
void test5()
{
test("Test5", 15, 100, 1, 79);
}

// 方格只有一列,机器人能到达所有方格
void test6()
{
test("Test6", 15, 10, 1, 10);
}

// 方格只有一行一列
void test7()
{
test("Test7", 15, 1, 1, 1);
}

// 方格只有一行一列
void test8()
{
test("Test8", 0, 1, 1, 1);
}

// 机器人不能进入任意一个方格
void test9()
{
test("Test9", -10, 10, 10, 0);
}

int main(int agrc, char* argv[])
{
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();

return 0;
}

14. 面试题14:剪绳子

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题14:剪绳子
// 题目:给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。
// 每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]k[1]…*k[m]可能的最大乘
// 积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此
// 时得到最大的乘积18。

include

include

// 动态规划
int maxProductAfterCutting_solution1(int length)
{
if(length < 2)
return 0;
if(length == 2)
return 1;
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(max < product)
max = product;

products[i] = max;
}
}

max = products[length];
delete[] products;

return max;
}

// 贪婪算法
int maxProductAfterCutting_solution2(int length)
{
if(length < 2)
return 0;
if(length == 2)
return 1;
if(length == 3)
return 2;

// 尽可能多地减去长度为3的绳子段
int timesOf3 = length / 3;

// 当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子段。
// 此时更好的方法是把绳子剪成长度为2的两段,因为22 > 31。
if(length - timesOf3 * 3 == 1)
timesOf3 -= 1;

int timesOf2 = (length - timesOf3 * 3) / 2;

return (int) (pow(3, timesOf3)) * (int) (pow(2, timesOf2));
}

// 测试代码
void test(const char* testName, int length, int expected)
{
int result1 = maxProductAfterCutting_solution1(length);
if(result1 == expected)
std::cout << "Solution1 for " << testName << " passed." << std::endl;
else
std::cout << "Solution1 for " << testName << " FAILED." << std::endl;

int result2 = maxProductAfterCutting_solution2(length);
if(result2 == expected)
std::cout << "Solution2 for " << testName << " passed." << std::endl;
else
std::cout << "Solution2 for " << testName << " FAILED." << std::endl;
}

void test1()
{
int length = 1;
int expected = 0;
test("test1", length, expected);
}

void test2()
{
int length = 2;
int expected = 1;
test("test2", length, expected);
}

void test3()
{
int length = 3;
int expected = 2;
test("test3", length, expected);
}

void test4()
{
int length = 4;
int expected = 4;
test("test4", length, expected);
}

void test5()
{
int length = 5;
int expected = 6;
test("test5", length, expected);
}

void test6()
{
int length = 6;
int expected = 9;
test("test6", length, expected);
}

void test7()
{
int length = 7;
int expected = 12;
test("test7", length, expected);
}

void test8()
{
int length = 8;
int expected = 18;
test("test8", length, expected);
}

void test9()
{
int length = 9;
int expected = 27;
test("test9", length, expected);
}

void test10()
{
int length = 10;
int expected = 36;
test("test10", length, expected);
}

void test11()
{
int length = 50;
int expected = 86093442;
test("test11", length, expected);
}

int main(int agrc, char* argv[])
{
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
test10();
test11();

return 0;
}

15. 面试题15:二进制中1的个数

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题15:二进制中1的个数
// 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如
// 把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。

include

int NumberOf1_Solution1(int n)
{
int count = 0;
unsigned int flag = 1;
while (flag)
{
if (n & flag)
count++;

flag = flag << 1;
}

return count;
}

int NumberOf1_Solution2(int n)
{
int count = 0;

while (n)
{
++count;
n = (n - 1) & n;
}

return count;
}

// 测试代码
void Test(int number, unsigned int expected)
{
int actual = NumberOf1_Solution1(number);
if (actual == expected)
printf("Solution1: Test for %p passed.\n", number);
else
printf("Solution1: Test for %p failed.\n", number);

actual = NumberOf1_Solution2(number);
if (actual == expected)
printf("Solution2: Test for %p passed.\n", number);
else
printf("Solution2: Test for %p failed.\n", number);

printf("\n");
}

int main(int argc, char* argv[])
{
// 输入0,期待的输出是0
Test(0, 0);

// 输入1,期待的输出是1
Test(1, 1);

// 输入10,期待的输出是2
Test(10, 2);

// 输入0x7FFFFFFF,期待的输出是31
Test(0x7FFFFFFF, 31);

// 输入0xFFFFFFFF(负数),期待的输出是32
Test(0xFFFFFFFF, 32);

// 输入0x80000000(负数),期待的输出是1
Test(0x80000000, 1);

return 0;
}

17. 面试题17:打印1到最大的n位数

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题17:打印1到最大的n位数
// 题目:输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则
// 打印出1、2、3一直到最大的3位数即999。

include

include

void PrintNumber(char* number);
bool Increment(char* number);
void Print1ToMaxOfNDigitsRecursively(char* number, int length, int index);

// 方法一
void Print1ToMaxOfNDigits_1(int n)
{
if (n <= 0)
return;

char *number = new char[n + 1];
memset(number, '0', n);
number[n] = '\0';

while (!Increment(number))
{
PrintNumber(number);
}

delete[]number;
}

// 字符串number表示一个数字,在 number上增加1
// 如果做加法溢出,则返回true;否则为false
bool Increment(char* number)
{
bool isOverflow = false;
int nTakeOver = 0;
int nLength = strlen(number);

for (int i = nLength - 1; i >= 0; i--)
{
int nSum = number[i] - '0' + nTakeOver;
if (i == nLength - 1)
nSum++;

if (nSum >= 10)
{
if (i == 0)
isOverflow = true;
else
{
nSum -= 10;
nTakeOver = 1;
number[i] = '0' + nSum;
}
}
else
{
number[i] = '0' + nSum;
break;
}
}

return isOverflow;
}

// 方法二
void Print1ToMaxOfNDigits_2(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';
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);
}
}

// 公共函数
// 字符串number表示一个数字,数字有若干个0开头
// 打印出这个数字,并忽略开头的0
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)
{
printf("%c", number[i]);
}
}

printf("\t");
}

// 测试代码
void Test(int n)
{
printf("Test for %d begins:\n", n);

Print1ToMaxOfNDigits_1(n);
Print1ToMaxOfNDigits_2(n);

printf("\nTest for %d ends.\n", n);
}

int main(int argc, char* argv[])
{
Test(1);
Test(2);
Test(3);
Test(0);
Test(-1);

return 0;
}

19. 面试题19:正则表达式匹配

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

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

include

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;
}

// 测试代码
void Test(const char* testName, const char* string, const char* pattern, bool expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(match(string, pattern) == expected)
printf("Passed.\n");
else
printf("FAILED.\n");
}

int main(int argc, char* argv[])
{
Test("Test01", "", "", true);
Test("Test02", "", ".", true);
Test("Test03", "", ".", false);
Test("Test04", "", "c
", true);
Test("Test05", "a", ".", true);
Test("Test06", "a", "a.", false);
Test("Test07", "a", "", false);
Test("Test08", "a", ".", true);
Test("Test09", "a", "ab
", true);
Test("Test10", "a", "aba", false);
Test("Test11", "aa", "aa", true);
Test("Test12", "aa", "a
", true);
Test("Test13", "aa", ".", true);
Test("Test14", "aa", ".", false);
Test("Test15", "ab", ".
", true);
Test("Test16", "ab", ".", true);
Test("Test17", "aaa", "aa
", true);
Test("Test18", "aaa", "aa.a", false);
Test("Test19", "aaa", "a.a", true);
Test("Test20", "aaa", ".a", false);
Test("Test21", "aaa", "aa", true);
Test("Test22", "aaa", "ab
a", false);
Test("Test23", "aaa", "abaca", true);
Test("Test24", "aaa", "abaca", true);
Test("Test25", "aaa", ".
", true);
Test("Test26", "aab", "cab", true);
Test("Test27", "aaca", "abaca", true);
Test("Test28", "aaba", "ab
aca", false);
Test("Test29", "bbbba", ".aa", true);
Test("Test30", "bcbbabab", ".aa", false);

return 0;
}

29. 面试题29:顺时针打印矩阵

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题29:顺时针打印矩阵
// 题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

include

void PrintMatrixInCircle(int** numbers, int columns, int rows, int start);
void printNumber(int number);

void PrintMatrixClockwisely(int** numbers, int columns, int rows)
{
if(numbers == nullptr || columns <= 0 || rows <= 0)
return;

int start = 0;

while(columns > start * 2 && rows > start * 2)
{
PrintMatrixInCircle(numbers, columns, rows, start);

++start;
}
}

void PrintMatrixInCircle(int** numbers, int columns, int rows, int start)
{
int endX = columns - 1 - start;
int endY = rows - 1 - start;

// 从左到右打印一行
for(int i = start; i <= endX; ++i)
{
int number = numbers[start][i];
printNumber(number);
}

// 从上到下打印一列
if(start < endY)
{
for(int i = start + 1; i <= endY; ++i)
{
int number = numbers[i][endX];
printNumber(number);
}
}

// 从右到左打印一行
if(start < endX && start < endY)
{
for(int i = endX - 1; i >= start; --i)
{
int number = numbers[endY][i];
printNumber(number);
}
}

// 从下到上打印一行
if(start < endX && start < endY - 1)
{
for(int i = endY - 1; i >= start + 1; --i)
{
int number = numbers[i][start];
printNumber(number);
}
}
}

void printNumber(int number)
{
printf("%d\t", number);
}

// 测试代码
void Test(int columns, int rows)
{
printf("Test Begin: %d columns, %d rows.\n", columns, rows);

if(columns < 1 || rows < 1)
return;

int** numbers = new int*[rows];
for(int i = 0; i < rows; ++i)
{
numbers[i] = new int[columns];
for(int j = 0; j < columns; ++j)
{
numbers[i][j] = i * columns + j + 1;
}
}

PrintMatrixClockwisely(numbers, columns, rows);
printf("\n");

for(int i = 0; i < rows; ++i)
delete[] (int*)numbers[i];

delete[] numbers;
}

int main(int argc, char* argv[])
{
/*
1
*/
Test(1, 1);

/*
1 2
3 4
*/
Test(2, 2);

/*
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
*/
Test(4, 4);

/*
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
*/
Test(5, 5);

/*
1
2
3
4
5
*/
Test(1, 5);

/*
1 2
3 4
5 6
7 8
9 10
*/
Test(2, 5);

/*
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
*/
Test(3, 5);

/*
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20
*/
Test(4, 5);

/*
1 2 3 4 5
*/
Test(5, 1);

/*
1 2 3 4 5
6 7 8 9 10
*/
Test(5, 2);

/*
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
*/
Test(5, 3);

/*
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
*/
Test(5, 4);

return 0;
}

40. 面试题40:最小的k个数

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题40:最小的k个数
// 题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8
// 这8个数字,则最小的4个数字是1、2、3、4。

include

include "..\Utilities\Array.h"

include

include

include

include

using namespace std;

// 方法1
void GetLeastNumbers_Solution1(int* input, int n, int* output, int k)
{
if(input == nullptr || output == nullptr || k > n || n <= 0 || k <= 0)
return;

int start = 0;
int end = n - 1;
int index = Partition(input, n, start, end);
while(index != k - 1)
{
if(index > k - 1)
{
end = index - 1;
index = Partition(input, n, start, end);
}
else
{
start = index + 1;
index = Partition(input, n, start, end);
}
}

for(int i = 0; i < k; ++i)
output[i] = input[i];
}

// 方法2
typedef multiset<int, std::greater > intSet;
typedef multiset<int, std::greater >::iterator setIterator;

void GetLeastNumbers_Solution2(const vector& data, intSet& leastNumbers, int k)
{
leastNumbers.clear();

if(k < 1 || data.size() < k)
return;

vector::const_iterator iter = data.begin();
for(; iter != data.end(); ++ iter)
{
if((leastNumbers.size()) < k)
leastNumbers.insert(*iter);

else
{
setIterator iterGreatest = leastNumbers.begin();

if(*iter < (leastNumbers.begin()))
{
leastNumbers.erase(iterGreatest);
leastNumbers.insert(
iter);
}
}
}
}

// 测试代码
void Test(char* testName, int* data, int n, int* expectedResult, int k)
{
if(testName != nullptr)
printf("%s begins: \n", testName);

vector vectorData;
for(int i = 0; i < n; ++ i)
vectorData.push_back(data[i]);

if(expectedResult == nullptr)
printf("The input is invalid, we don't expect any result.\n");
else
{
printf("Expected result: \n");
for(int i = 0; i < k; ++ i)
printf("%d\t", expectedResult[i]);
printf("\n");
}

printf("Result for solution1:\n");
int* output = new int[k];
GetLeastNumbers_Solution1(data, n, output, k);
if(expectedResult != nullptr)
{
for(int i = 0; i < k; ++ i)
printf("%d\t", output[i]);
printf("\n");
}

delete[] output;

printf("Result for solution2:\n");
intSet leastNumbers;
GetLeastNumbers_Solution2(vectorData, leastNumbers, k);
printf("The actual output numbers are:\n");
for(setIterator iter = leastNumbers.begin(); iter != leastNumbers.end(); ++iter)
printf("%d\t", *iter);
printf("\n\n");
}

// k小于数组的长度
void Test1()
{
int data[] = {4, 5, 1, 6, 2, 7, 3, 8};
int expected[] = {1, 2, 3, 4};
Test("Test1", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
}

// k等于数组的长度
void Test2()
{
int data[] = {4, 5, 1, 6, 2, 7, 3, 8};
int expected[] = {1, 2, 3, 4, 5, 6, 7, 8};
Test("Test2", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
}

// k大于数组的长度
void Test3()
{
int data[] = {4, 5, 1, 6, 2, 7, 3, 8};
int* expected = nullptr;
Test("Test3", data, sizeof(data) / sizeof(int), expected, 10);
}

// k等于1
void Test4()
{
int data[] = {4, 5, 1, 6, 2, 7, 3, 8};
int expected[] = {1};
Test("Test4", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
}

// k等于0
void Test5()
{
int data[] = {4, 5, 1, 6, 2, 7, 3, 8};
int* expected = nullptr;
Test("Test5", data, sizeof(data) / sizeof(int), expected, 0);
}

// 数组中有相同的数字
void Test6()
{
int data[] = {4, 5, 1, 6, 2, 7, 2, 8};
int expected[] = {1, 2};
Test("Test6", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int));
}

// 输入空指针
void Test7()
{
int* expected = nullptr;
Test("Test7", nullptr, 0, expected, 0);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();

return 0;
}

41. 面试题41:数据流中的中位数

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题41:数据流中的中位数
// 题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么
// 中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,
// 那么中位数就是所有数值排序之后中间两个数的平均值。

include

include

include

include

using namespace std;

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:
vector min;
vector max;
};

// 测试代码
void Test(char* testName, DynamicArray& numbers, double expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(abs(numbers.GetMedian() - expected) < 0.0000001)
printf("Passed.\n");
else
printf("FAILED.\n");
}

int main(int argc, char* argv[])
{
DynamicArray numbers;

printf("Test1 begins: ");
try
{
numbers.GetMedian();
printf("FAILED.\n");
}
catch(const exception&)
{
printf("Passed.\n");
}

numbers.Insert(5);
Test("Test2", numbers, 5);

numbers.Insert(2);
Test("Test3", numbers, 3.5);

numbers.Insert(3);
Test("Test4", numbers, 3);

numbers.Insert(4);
Test("Test6", numbers, 3.5);

numbers.Insert(1);
Test("Test5", numbers, 3);

numbers.Insert(6);
Test("Test7", numbers, 3.5);

numbers.Insert(7);
Test("Test8", numbers, 4);

numbers.Insert(0);
Test("Test9", numbers, 3.5);

numbers.Insert(8);
Test("Test10", numbers, 4);

return 0;
}

47. 面试题47:礼物的最大价值

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题47:礼物的最大价值
// 题目:在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值
// (价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或
// 者向下移动一格直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计
// 算你最多能拿到多少价值的礼物?

include

include

int getMaxValue_solution1(const int* values, int rows, int cols)
{
if(values == nullptr || rows <= 0 || cols <= 0)
return 0;

int** maxValues = new int*[rows];
for(int i = 0; i < rows; ++i)
maxValues[i] = new int[cols];

for(int i = 0; i < rows; ++i)
{
for(int j = 0; j < cols; ++j)
{
int left = 0;
int up = 0;

if(i > 0)
up = maxValues[i - 1][j];

if(j > 0)
left = maxValues[i][j - 1];

maxValues[i][j] = std::max(left, up) + values[i * cols + j];
}
}

int maxValue = maxValues[rows - 1][cols - 1];

for(int i = 0; i < rows; ++i)
delete[] maxValues[i];
delete[] maxValues;

return maxValue;
}

int getMaxValue_solution2(const int* values, int rows, int cols)
{
if(values == nullptr || rows <= 0 || cols <= 0)
return 0;

int* maxValues = new int[cols];
for(int i = 0; i < rows; ++i)
{
for(int j = 0; j < cols; ++j)
{
int left = 0;
int up = 0;

if(i > 0)
up = maxValues[j];

if(j > 0)
left = maxValues[j - 1];

maxValues[j] = std::max(left, up) + values[i * cols + j];
}
}

int maxValue = maxValues[cols - 1];

delete[] maxValues;

return maxValue;
}

// 测试代码
void test(const char* testName, const int* values, int rows, int cols, int expected)
{
if(getMaxValue_solution1(values, rows, cols) == expected)
std::cout << testName << ": solution1 passed." << std::endl;
else
std::cout << testName << ": solution1 FAILED." << std::endl;

if(getMaxValue_solution2(values, rows, cols) == expected)
std::cout << testName << ": solution2 passed." << std::endl;
else
std::cout << testName << ": solution2 FAILED." << std::endl;
}

void test1()
{
// 三行三列
int values[][3] = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
int expected = 29;
test("test1", (const int*) values, 3, 3, expected);
}

void test2()
{
//四行四列
int values[][4] = {
{ 1, 10, 3, 8 },
{ 12, 2, 9, 6 },
{ 5, 7, 4, 11 },
{ 3, 7, 16, 5 }
};
int expected = 53;
test("test2", (const int*) values, 4, 4, expected);
}

void test3()
{
// 一行四列
int values[][4] = {
{ 1, 10, 3, 8 }
};
int expected = 22;
test("test3", (const int*) values, 1, 4, expected);
}

void test4()
{
int values[4][1] = {
{ 1 },
{ 12 },
{ 5 },
{ 3 }
};
int expected = 21;
test("test4", (const int*) values, 4, 1, expected);
}

void test5()
{
// 一行一列
int values[][1] = {
{ 3 }
};
int expected = 3;
test("test5", (const int*) values, 1, 1, expected);
}

void test6()
{
// 空指针
int expected = 0;
test("test6", nullptr, 0, 0, expected);
}

int main(int argc, char* argv[])
{
test1();
test2();
test3();
test4();
test5();

return 0;
}

49. 面试题49:丑数

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题49:丑数
// 题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到
// 大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。
// 习惯上我们把1当做第一个丑数。

include

// 算法1的代码
bool IsUgly(int number)
{
while(number % 2 == 0)
number /= 2;
while(number % 3 == 0)
number /= 3;
while(number % 5 == 0)
number /= 5;

return (number == 1) ? true : false;
}

int GetUglyNumber_Solution1(int index)
{
if(index <= 0)
return 0;

int number = 0;
int uglyFound = 0;
while(uglyFound < index)
{
++number;

if(IsUgly(number))
++uglyFound;
}

return number;
}

// 算法2的代码
int Min(int number1, int number2, int number3);

int GetUglyNumber_Solution2(int index)
{
if(index <= 0)
return 0;

int *pUglyNumbers = new int[index];
pUglyNumbers[0] = 1;
int nextUglyIndex = 1;

int *pMultiply2 = pUglyNumbers;
int *pMultiply3 = pUglyNumbers;
int *pMultiply5 = pUglyNumbers;

while(nextUglyIndex < index)
{
int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
pUglyNumbers[nextUglyIndex] = min;

while(pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
++pMultiply2;
while(
pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
++pMultiply3;
while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
++pMultiply5;

++nextUglyIndex;
}

int ugly = pUglyNumbers[nextUglyIndex - 1];
delete[] pUglyNumbers;
return ugly;
}

int Min(int number1, int number2, int number3)
{
int min = (number1 < number2) ? number1 : number2;
min = (min < number3) ? min : number3;

return min;
}

// 测试代码
void Test(int index, int expected)
{
if(GetUglyNumber_Solution1(index) == expected)
printf("solution1 passed\n");
else
printf("solution1 failed\n");

if(GetUglyNumber_Solution2(index) == expected)
printf("solution2 passed\n");
else
printf("solution2 failed\n");
}

int main(int argc, char* argv[])
{
Test(1, 1);

Test(2, 2);
Test(3, 3);
Test(4, 4);
Test(5, 5);
Test(6, 6);
Test(7, 8);
Test(8, 9);
Test(9, 10);
Test(10, 12);
Test(11, 15);

Test(1500, 859963392);

Test(0, 0);

return 0;
}

58. 面试题58:翻转单词顺序

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题58(一):翻转单词顺序
// 题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
// 为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",
// 则输出"student. a am I"。

include

include "..\Utilities\StringUtil.h"

include

char* ReverseSentence(char *pData)
{
if(pData == nullptr)
return nullptr;

char *pBegin = pData;

char pEnd = pData;
while(
pEnd != '\0')
pEnd ++;
pEnd--;

// 翻转整个句子
Reverse(pBegin, pEnd);

// 翻转句子中的每个单词
pBegin = pEnd = pData;
while(pBegin != '\0')
{
if(
pBegin == ' ')
{
pBegin ++;
pEnd ++;
}
else if(*pEnd == ' ' || *pEnd == '\0')
{
Reverse(pBegin, --pEnd);
pBegin = ++pEnd;
}
else
pEnd ++;
}

return pData;
}

// 测试代码
void Test(const char* testName, char* input, const char* expectedResult)
{
if(testName != nullptr)
printf("%s begins: ", testName);

ReverseSentence(input);

if((input == nullptr && expectedResult == nullptr)
|| (input != nullptr && strcmp(input, expectedResult) == 0))
printf("Passed.\n\n");
else
printf("Failed.\n\n");
}

// 功能测试,句子中有多个单词
void Test1()
{
char input[] = "I am a student.";
char expected[] = "student. a am I";

Test("Test1", input, expected);
}

// 功能测试,句子中只有一个单词
void Test2()
{
char input[] = "Wonderful";
char expected[] = "Wonderful";

Test("Test2", input, expected);
}

// 鲁棒性测试
void Test3()
{
Test("Test3", nullptr, nullptr);
}

// 边界值测试,测试空字符串
void Test4()
{
Test("Test4", "", "");
}

// 边界值测试,字符串中只有空格
void Test5()
{
char input[] = " ";
char expected[] = " ";
Test("Test5", input, expected);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();

return 0;
}


/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题58(二):左旋转字符串
// 题目:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。
// 请定义一个函数实现字符串左旋转操作的功能。比如输入字符串"abcdefg"和数
// 字2,该函数将返回左旋转2位得到的结果"cdefgab"。

include

include "..\Utilities\StringUtil.h"

include <string.h>

char* LeftRotateString(char* pStr, int n)
{
if(pStr != nullptr)
{
int nLength = static_cast(strlen(pStr));
if(nLength > 0 && n > 0 && n < nLength)
{
char* pFirstStart = pStr;
char* pFirstEnd = pStr + n - 1;
char* pSecondStart = pStr + n;
char* pSecondEnd = pStr + nLength - 1;

// 翻转字符串的前面n个字符
Reverse(pFirstStart, pFirstEnd);
// 翻转字符串的后面部分
Reverse(pSecondStart, pSecondEnd);
// 翻转整个字符串
Reverse(pFirstStart, pSecondEnd);
}
}

return pStr;
}

// 测试代码
void Test(const char* testName, char* input, int num, const char* expectedResult)
{
if(testName != nullptr)
printf("%s begins: ", testName);

char* result = LeftRotateString(input, num);

if((input == nullptr && expectedResult == nullptr)
|| (input != nullptr && strcmp(result, expectedResult) == 0))
printf("Passed.\n\n");
else
printf("Failed.\n\n");
}

// 功能测试
void Test1()
{
char input[] = "abcdefg";
char expected[] = "cdefgab";

Test("Test1", input, 2, expected);
}

// 边界值测试
void Test2()
{
char input[] = "abcdefg";
char expected[] = "bcdefga";

Test("Test2", input, 1, expected);
}

// 边界值测试
void Test3()
{
char input[] = "abcdefg";
char expected[] = "gabcdef";

Test("Test3", input, 6, expected);
}

// 鲁棒性测试
void Test4()
{
Test("Test4", nullptr, 6, nullptr);
}

// 鲁棒性测试
void Test5()
{
char input[] = "abcdefg";
char expected[] = "abcdefg";

Test("Test5", input, 0, expected);
}

// 鲁棒性测试
void Test6()
{
char input[] = "abcdefg";
char expected[] = "abcdefg";

Test("Test6", input, 7, expected);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();

return 0;
}

59. 面试题59:滑动窗口的最大值

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题59(一):滑动窗口的最大值
// 题目:给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,
// 如果输入数组{2, 3, 4, 2, 6, 2, 5, 1}及滑动窗口的大小3,那么一共存在6个
// 滑动窗口,它们的最大值分别为{4, 4, 6, 6, 6, 5},

include

include

include

using namespace std;

vector maxInWindows(const vector& num, unsigned int size)
{
vector maxInWindows;
if(num.size() >= size && size >= 1)
{
deque index;

for(unsigned int i = 0; i < size; ++i)
{
while(!index.empty() && num[i] >= num[index.back()])
index.pop_back();

index.push_back(i);
}

for(unsigned 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;
}

// 测试代码
void Test(const char* testName, const vector& num, unsigned int size, const vector& expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

vector result = maxInWindows(num, size);

vector::const_iterator iterResult = result.begin();
vector::const_iterator iterExpected = expected.begin();
while(iterResult < result.end() && iterExpected < expected.end())
{
if(*iterResult != *iterExpected)
break;

++iterResult;
++iterExpected;
}

if(iterResult == result.end() && iterExpected == expected.end())
printf("Passed.\n");
else
printf("FAILED.\n");
}

void Test1()
{
int num[] = { 2, 3, 4, 2, 6, 2, 5, 1 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

int expected[] = { 4, 4, 6, 6, 6, 5 };
vector vecExpected(expected, expected + sizeof(expected) / sizeof(int));

unsigned int size = 3;

Test("Test1", vecNumbers, size, vecExpected);
}

void Test2()
{
int num[] = { 1, 3, -1, -3, 5, 3, 6, 7 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

int expected[] = { 3, 3, 5, 5, 6, 7 };
vector vecExpected(expected, expected + sizeof(expected) / sizeof(int));

unsigned int size = 3;

Test("Test2", vecNumbers, size, vecExpected);
}

// 输入数组单调递增
void Test3()
{
int num[] = { 1, 3, 5, 7, 9, 11, 13, 15 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

int expected[] = { 7, 9, 11, 13, 15 };
vector vecExpected(expected, expected + sizeof(expected) / sizeof(int));

unsigned int size = 4;

Test("Test3", vecNumbers, size, vecExpected);
}

// 输入数组单调递减
void Test4()
{
int num[] = { 16, 14, 12, 10, 8, 6, 4 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

int expected[] = { 16, 14, 12 };
vector vecExpected(expected, expected + sizeof(expected) / sizeof(int));

unsigned int size = 5;

Test("Test4", vecNumbers, size, vecExpected);
}

// 滑动窗口的大小为1
void Test5()
{
int num[] = { 10, 14, 12, 11 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

int expected[] = { 10, 14, 12, 11 };
vector vecExpected(expected, expected + sizeof(expected) / sizeof(int));

unsigned int size = 1;

Test("Test5", vecNumbers, size, vecExpected);
}

// 滑动窗口的大小等于数组的长度
void Test6()
{
int num[] = { 10, 14, 12, 11 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

int expected[] = { 14 };
vector vecExpected(expected, expected + sizeof(expected) / sizeof(int));

unsigned int size = 4;

Test("Test6", vecNumbers, size, vecExpected);
}

// 滑动窗口的大小为0
void Test7()
{
int num[] = { 10, 14, 12, 11 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

vector vecExpected;

unsigned int size = 0;

Test("Test7", vecNumbers, size, vecExpected);
}

// 滑动窗口的大小大于输入数组的长度
void Test8()
{
int num[] = { 10, 14, 12, 11 };
vector vecNumbers(num, num + sizeof(num) / sizeof(int));

vector vecExpected;

unsigned int size = 5;

Test("Test8", vecNumbers, size, vecExpected);
}

// 输入数组为空
void Test9()
{
vector vecNumbers;
vector vecExpected;

unsigned int size = 5;

Test("Test9", vecNumbers, size, vecExpected);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();

return 0;
}


/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题59(二):队列的最大值
// 题目:给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,
// 如果输入数组{2, 3, 4, 2, 6, 2, 5, 1}及滑动窗口的大小3,那么一共存在6个
// 滑动窗口,它们的最大值分别为{4, 4, 6, 6, 6, 5},

include

include

include

using namespace std;

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;
};

deque data;
deque maximums;
int currentIndex;
};

// 测试代码
void Test(const char* testName, const QueueWithMax& queue, int expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(queue.max() == expected)
printf("Passed.\n");
else
printf("FAILED.\n");
}

int main(int argc, char* argv[])
{
QueueWithMax queue;
// {2}
queue.push_back(2);
Test("Test1", queue, 2);

// {2, 3}
queue.push_back(3);
Test("Test2", queue, 3);

// {2, 3, 4}
queue.push_back(4);
Test("Test3", queue, 4);

// {2, 3, 4, 2}
queue.push_back(2);
Test("Test4", queue, 4);

// {3, 4, 2}
queue.pop_front();
Test("Test5", queue, 4);

// {4, 2}
queue.pop_front();
Test("Test6", queue, 4);

// {2}
queue.pop_front();
Test("Test7", queue, 2);

// {2, 6}
queue.push_back(6);
Test("Test8", queue, 6);

// {2, 6, 2}
queue.push_back(2);
Test("Test9", queue, 6);

// {2, 6, 2, 5}
queue.push_back(5);
Test("Test9", queue, 6);

// {6, 2, 5}
queue.pop_front();
Test("Test10", queue, 6);

// {2, 5}
queue.pop_front();
Test("Test11", queue, 5);

// {5}
queue.pop_front();
Test("Test12", queue, 5);

// {5, 1}
queue.push_back(1);
Test("Test13", queue, 5);

return 0;
}

60. 面试题60:n个骰子的点数

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

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

include

include <math.h>

int g_maxValue = 6;

// 方法一
void Probability(int number, int* pProbabilities);
void Probability(int original, int current, int sum, int* pProbabilities);

void PrintProbability_Solution1(int number)
{
if(number < 1)
return;

int maxSum = number * g_maxValue;
int* pProbabilities = new int[maxSum - number + 1];
for(int i = number; i <= maxSum; ++i)
pProbabilities[i - number] = 0;

Probability(number, pProbabilities);

int total = pow((double)g_maxValue, number);
for(int i = number; i <= maxSum; ++i)
{
double ratio = (double)pProbabilities[i - number] / total;
printf("%d: %e\n", i, ratio);
}

delete[] pProbabilities;
}

void Probability(int number, int* pProbabilities)
{
for(int i = 1; i <= g_maxValue; ++i)
Probability(number, number, i, pProbabilities);
}

void Probability(int original, int current, int sum,
int* pProbabilities)
{
if(current == 1)
{
pProbabilities[sum - original]++;
}
else
{
for(int i = 1; i <= g_maxValue; ++i)
{
Probability(original, current - 1, i + sum, pProbabilities);
}
}
}

// 方法二
void PrintProbability_Solution2(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];
}

// 测试代码
void Test(int n)
{
printf("Test for %d begins:\n", n);

printf("Test for solution1\n");
PrintProbability_Solution1(n);

printf("Test for solution2\n");
PrintProbability_Solution2(n);

printf("\n");
}

int main(int argc, char* argv[])
{
Test(1);
Test(2);
Test(3);
Test(4);

Test(11);

Test(0);

return 0;
}

61. 面试题61:扑克牌的顺子

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

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

include

include

int Compare(const void *arg1, const void *arg2);

bool IsContinuous(int* numbers, int length)
{
if(numbers == nullptr || length < 1)
return false;

qsort(numbers, length, sizeof(int), Compare);

int numberOfZero = 0;
int numberOfGap = 0;

// 统计数组中0的个数
for(int i = 0; i < length && numbers[i] == 0; ++i)
++numberOfZero;

// 统计数组中的间隔数目
int small = numberOfZero;
int big = small + 1;
while(big < length)
{
// 两个数相等,有对子,不可能是顺子
if(numbers[small] == numbers[big])
return false;

numberOfGap += numbers[big] - numbers[small] - 1;
small = big;
++big;
}

return (numberOfGap > numberOfZero) ? false : true;
}

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

// 测试代码
void Test(const char* testName, int* numbers, int length, bool expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(IsContinuous(numbers, length) == expected)
printf("Passed.\n");
else
printf("Failed.\n");
}

void Test1()
{
int numbers[] = { 1, 3, 2, 5, 4 };
Test("Test1", numbers, sizeof(numbers) / sizeof(int), true);
}

void Test2()
{
int numbers[] = { 1, 3, 2, 6, 4 };
Test("Test2", numbers, sizeof(numbers) / sizeof(int), false);
}

void Test3()
{
int numbers[] = { 0, 3, 2, 6, 4 };
Test("Test3", numbers, sizeof(numbers) / sizeof(int), true);
}

void Test4()
{
int numbers[] = { 0, 3, 1, 6, 4 };
Test("Test4", numbers, sizeof(numbers) / sizeof(int), false);
}

void Test5()
{
int numbers[] = { 1, 3, 0, 5, 0 };
Test("Test5", numbers, sizeof(numbers) / sizeof(int), true);
}

void Test6()
{
int numbers[] = { 1, 3, 0, 7, 0 };
Test("Test6", numbers, sizeof(numbers) / sizeof(int), false);
}

void Test7()
{
int numbers[] = { 1, 0, 0, 5, 0 };
Test("Test7", numbers, sizeof(numbers) / sizeof(int), true);
}

void Test8()
{
int numbers[] = { 1, 0, 0, 7, 0 };
Test("Test8", numbers, sizeof(numbers) / sizeof(int), false);
}

void Test9()
{
int numbers[] = { 3, 0, 0, 0, 0 };
Test("Test9", numbers, sizeof(numbers) / sizeof(int), true);
}

void Test10()
{
int numbers[] = { 0, 0, 0, 0, 0 };
Test("Test10", numbers, sizeof(numbers) / sizeof(int), true);
}

// 有对子
void Test11()
{
int numbers[] = { 1, 0, 0, 1, 0 };
Test("Test11", numbers, sizeof(numbers) / sizeof(int), false);
}

// 鲁棒性测试
void Test12()
{
Test("Test12", nullptr, 0, false);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
Test10();
Test11();
Test12();

return 0;
}

63. 面试题63:股票的最大利润

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题63:股票的最大利润
// 题目:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖交易该股
// 票可能获得的利润是多少?例如一只股票在某些时间节点的价格为{9, 11, 8, 5,
// 7, 12, 16, 14}。如果我们能在价格为5的时候买入并在价格为16时卖出,则能
// 收获最大的利润11。

include

int MaxDiff(const int* numbers, unsigned length)
{
if(numbers == nullptr && length < 2)
return 0;

int min = numbers[0];
int maxDiff = numbers[1] - min;

for(int i = 2; i < length; ++i)
{
if(numbers[i - 1] < min)
min = numbers[i - 1];

int currentDiff = numbers[i] - min;
if(currentDiff > maxDiff)
maxDiff = currentDiff;
}

return maxDiff;
}

// ==================== Test Code ====================
void Test(const char* testName, const int* numbers, unsigned int length, int expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

if(MaxDiff(numbers, length) == expected)
printf("Passed.\n");
else
printf("FAILED.\n");
}

void Test1()
{
int numbers[] = { 4, 1, 3, 2, 5 };
Test("Test1", numbers, sizeof(numbers) / sizeof(int), 4);
}

// 价格递增
void Test2()
{
int numbers[] = { 1, 2, 4, 7, 11, 16 };
Test("Test2", numbers, sizeof(numbers) / sizeof(int), 15);
}

// 价格递减
void Test3()
{
int numbers[] = { 16, 11, 7, 4, 2, 1 };
Test("Test3", numbers, sizeof(numbers) / sizeof(int), -1);
}

// 价格全部相同
void Test4()
{
int numbers[] = { 16, 16, 16, 16, 16 };
Test("Test4", numbers, sizeof(numbers) / sizeof(int), 0);
}

void Test5()
{
int numbers[] = { 9, 11, 5, 7, 16, 1, 4, 2 };
Test("Test5", numbers, sizeof(numbers) / sizeof(int), 11);
}

void Test6()
{
int numbers[] = { 2, 4 };
Test("Test6", numbers, sizeof(numbers) / sizeof(int), 2);
}

void Test7()
{
int numbers[] = { 4, 2 };
Test("Test7", numbers, sizeof(numbers) / sizeof(int), -2);
}

void Test8()
{
Test("Test8", nullptr, 0, 0);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();

return 0;
}

64. 面试题64:求1+2+…+n

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题64:求1+2+…+n
// 题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case
// 等关键字及条件判断语句(A?B:C)。

include

// 方法一
class Temp
{
public:
Temp() { ++ N; Sum += N; }

static void Reset() { N = 0; Sum = 0; }
static unsigned int GetSum() { return Sum; }

private:
static unsigned int N;
static unsigned int Sum;
};

unsigned int Temp::N = 0;
unsigned int Temp::Sum = 0;

unsigned int Sum_Solution1(unsigned int n)
{
Temp::Reset();

Temp *a = new Temp[n];
delete []a;
a = NULL;

return Temp::GetSum();
}

// 方法二
class A;
A* Array[2];

class A
{
public:
virtual unsigned int Sum (unsigned int n)
{
return 0;
}
};

class B: public A
{
public:
virtual unsigned int Sum (unsigned int n)
{
return Array[!!n]->Sum(n-1) + n;
}
};

int Sum_Solution2(int n)
{
A a;
B b;
Array[0] = &a;
Array[1] = &b;

int value = Array[1]->Sum(n);

return value;
}

// 方法三
typedef unsigned int (*fun)(unsigned int);

unsigned int Solution3_Teminator(unsigned int n)
{
return 0;
}

unsigned int Sum_Solution3(unsigned int n)
{
static fun f[2] = {Solution3_Teminator, Sum_Solution3};
return n + f[!!n](n - 1);
}

// 方法四
template struct Sum_Solution4
{
enum Value { N = Sum_Solution4<n - 1>::N + n};
};

template <> struct Sum_Solution4<1>
{
enum Value { N = 1};
};

template <> struct Sum_Solution4<0>
{
enum Value { N = 0};
};

// 测试代码
void Test(int n, int expected)
{
printf("Test for %d begins:\n", n);

if(Sum_Solution1(n) == expected)
printf("Solution1 passed.\n");
else
printf("Solution1 failed.\n");

if(Sum_Solution2(n) == expected)
printf("Solution2 passed.\n");
else
printf("Solution2 failed.\n");

if(Sum_Solution3(n) == expected)
printf("Solution3 passed.\n");
else
printf("Solution3 failed.\n");
}

void Test1()
{
const unsigned int number = 1;
int expected = 1;
Test(number, expected);
if(Sum_Solution4::N == expected)
printf("Solution4 passed.\n");
else
printf("Solution4 failed.\n");
}

void Test2()
{
const unsigned int number = 5;
int expected = 15;
Test(number, expected);
if(Sum_Solution4::N == expected)
printf("Solution4 passed.\n");
else
printf("Solution4 failed.\n");
}

void Test3()
{
const unsigned int number = 10;
int expected = 55;
Test(number, expected);
if(Sum_Solution4::N == expected)
printf("Solution4 passed.\n");
else
printf("Solution4 failed.\n");
}

void Test4()
{
const unsigned int number = 0;
int expected = 0;
Test(number, expected);
if(Sum_Solution4::N == expected)
printf("Solution4 passed.\n");
else
printf("Solution4 failed.\n");
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();

return 0;
}

65. 面试题65:不用加减乘除做加法

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题65:不用加减乘除做加法
// 题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、×、÷
// 四则运算符号。

include

int Add(int num1, int num2)
{
int sum, carry;
do
{
sum = num1 ^ num2;
carry = (num1 & num2) << 1;

num1 = sum;
num2 = carry;
}
while(num2 != 0);

return num1;
}

// 测试代码
void Test(int num1, int num2, int expected)
{
int result = Add(num1, num2);
if(result == expected)
printf("%d + %d is %d. Passed\n", num1, num2, result);
else
printf("%d + %d is %d. FAILED\n", num1, num2, result);
}

int main(int argc, char* argv[])
{
Test(1, 2, 3);
Test(111, 899, 1010);

Test(-1, 2, 1);
Test(1, -2, -1);

Test(3, 0, 3);
Test(0, -4, -4);

Test(-2, -8, -10);

return 0;
}

68. 面试题68:树中两个结点的最低公共祖先

/*******************************************************************
Copyright(c) 2016, Harry He
All rights reserved.

Distributed under the BSD license.
(See accompanying file LICENSE.txt at
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
*******************************************************************/

//==================================================================
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 作者:何海涛
//==================================================================

// 面试题68:树中两个结点的最低公共祖先
// 题目:输入两个树结点,求它们的最低公共祖先。

include

include "..\Utilities\Tree.h"

include

using namespace std;

bool GetNodePath(const TreeNode* pRoot, const TreeNode* pNode, list<const TreeNode*>& path)
{
if(pRoot == pNode)
return true;

path.push_back(pRoot);

bool found = false;

vector<TreeNode>::const_iterator i = pRoot->m_vChildren.begin();
while(!found && i < pRoot->m_vChildren.end())
{
found = GetNodePath(
i, pNode, path);
++i;
}

if(!found)
path.pop_back();

return found;
}

const TreeNode* GetLastCommonNode
(
const list<const TreeNode>& path1,
const list<const TreeNode
>& path2
)
{
list<const TreeNode>::const_iterator iterator1 = path1.begin();
list<const TreeNode
>::const_iterator iterator2 = path2.begin();

const TreeNode* pLast = nullptr;

while(iterator1 != path1.end() && iterator2 != path2.end())
{
if(*iterator1 == *iterator2)
pLast = *iterator1;

iterator1++;
iterator2++;
}

return pLast;
}

const TreeNode* GetLastCommonParent(const TreeNode* pRoot, const TreeNode* pNode1, const TreeNode* pNode2)
{
if(pRoot == nullptr || pNode1 == nullptr || pNode2 == nullptr)
return nullptr;

list<const TreeNode*> path1;
GetNodePath(pRoot, pNode1, path1);

list<const TreeNode*> path2;
GetNodePath(pRoot, pNode2, path2);

return GetLastCommonNode(path1, path2);
}

// 测试代码
void Test(const char* testName, const TreeNode* pRoot, const TreeNode* pNode1, const TreeNode* pNode2, TreeNode* pExpected)
{
if(testName != nullptr)
printf("%s begins: ", testName);

const TreeNode* pResult = GetLastCommonParent(pRoot, pNode1, pNode2);

if((pExpected == nullptr && pResult == nullptr) ||
(pExpected != nullptr && pResult != nullptr && pResult->m_nValue == pExpected->m_nValue))
printf("Passed.\n");
else
printf("Failed.\n");
}

// 形状普通的树
// 1
// /
// 2 3
// /
// 4 5
// / \ / |
// 6 7 8 9 10
void Test1()
{
TreeNode* pNode1 = CreateTreeNode(1);
TreeNode* pNode2 = CreateTreeNode(2);
TreeNode* pNode3 = CreateTreeNode(3);
TreeNode* pNode4 = CreateTreeNode(4);
TreeNode* pNode5 = CreateTreeNode(5);
TreeNode* pNode6 = CreateTreeNode(6);
TreeNode* pNode7 = CreateTreeNode(7);
TreeNode* pNode8 = CreateTreeNode(8);
TreeNode* pNode9 = CreateTreeNode(9);
TreeNode* pNode10 = CreateTreeNode(10);

ConnectTreeNodes(pNode1, pNode2);
ConnectTreeNodes(pNode1, pNode3);

ConnectTreeNodes(pNode2, pNode4);
ConnectTreeNodes(pNode2, pNode5);

ConnectTreeNodes(pNode4, pNode6);
ConnectTreeNodes(pNode4, pNode7);

ConnectTreeNodes(pNode5, pNode8);
ConnectTreeNodes(pNode5, pNode9);
ConnectTreeNodes(pNode5, pNode10);

Test("Test1", pNode1, pNode6, pNode8, pNode2);
}

// 树退化成一个链表
// 1
// /
// 2
// /
// 3
// /
// 4
// /
// 5
void Test2()
{
TreeNode* pNode1 = CreateTreeNode(1);
TreeNode* pNode2 = CreateTreeNode(2);
TreeNode* pNode3 = CreateTreeNode(3);
TreeNode* pNode4 = CreateTreeNode(4);
TreeNode* pNode5 = CreateTreeNode(5);

ConnectTreeNodes(pNode1, pNode2);
ConnectTreeNodes(pNode2, pNode3);
ConnectTreeNodes(pNode3, pNode4);
ConnectTreeNodes(pNode4, pNode5);

Test("Test2", pNode1, pNode5, pNode4, pNode3);
}

// 树退化成一个链表,一个结点不在树中
// 1
// /
// 2
// /
// 3
// /
// 4
// /
// 5
void Test3()

{
TreeNode* pNode1 = CreateTreeNode(1);
TreeNode* pNode2 = CreateTreeNode(2);
TreeNode* pNode3 = CreateTreeNode(3);
TreeNode* pNode4 = CreateTreeNode(4);
TreeNode* pNode5 = CreateTreeNode(5);

ConnectTreeNodes(pNode1, pNode2);
ConnectTreeNodes(pNode2, pNode3);
ConnectTreeNodes(pNode3, pNode4);
ConnectTreeNodes(pNode4, pNode5);

TreeNode* pNode6 = CreateTreeNode(6);

Test("Test3", pNode1, pNode5, pNode6, nullptr);
}

// 输入nullptr
void Test4()
{
Test("Test4", nullptr, nullptr, nullptr, nullptr);
}

int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();

return 0;
}

posted @ 2019-12-11 20:27  风御之举  阅读(70)  评论(0)    收藏  举报