面试题1

#ifndef _MS_1_
#define _MS_1_

void TestMS_1();

/*
	1.把二元查找树转变成排序的双向链表
	输入一颗二元查找树,将其转变成一个排序的双向链表,
	不能穿件任何新的节点,只能调整指针的指向
	双向链表的顺序是按照中序遍历的顺序生成
*/

// 二叉查找树节点
struct TreeNode
{
	int num;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int _num, TreeNode *_left = 0, TreeNode *_right = 0) : num(_num), left(_left), right(_right){}

};

// 双向链表节点
struct ListNode
{
	int num;
	ListNode *pre;
	ListNode *next;

	ListNode(int _num, ListNode *_pre = 0, ListNode *_next = 0) : num(_num), pre(_pre), next(_next){}
	ListNode() 
	{
		ListNode(0);
	}

	bool operator= (const ListNode & right)
	{
		if (this == &right)
		{
			return true;
		}
		if (this->num == right.num && this->next == right.next)
		{
			return true;
		}
		return false;
	}
};

void TestBinaryTreeToDoubleList();

ListNode *BinaryTreeToDoubleList(TreeNode *root);

void MiddleSearch(TreeNode *root, ListNode * &pListNode);

void DestroyDbList(ListNode *pDbList);

/*
	2.设计包含Min函数的栈
		定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素
		要求min、push、pop的时间复杂度都是O(1)
	这道题做错了!
*/
// 不用数组,用指针

const unsigned DEFAULT_STACK_CAPACITY = 10;
template <typename T>
struct MyStack
{
	MyStack();
	MyStack(unsigned capacity);
	virtual ~MyStack();

	void Push(T tmp);
	T Pop();
	T Top();
	bool IsEmpty();
	T Min();

	T *arr;
	// 默认情况下capacity个数最少为4,不够时,翻倍加1
	unsigned capacity;
	unsigned size;
	T min;
};

/*
	3:子数组最大和:有正数也有负数
*/
void MaxSubSum(const int *arr, unsigned size, int &sum, unsigned &start, unsigned &end);
void TestMaxSumSum();

/*
	4:在二叉树中找出和为某一值的所有路径
	输入一个整数和一棵树
	从根节点开始往下访问一直到叶节点,所经过的所有节点形成的
	一条路径。打印输出所有的路径
*/
// TreeNode已经定义好...
/*
	1.搜索:计算以某个节点为根的所有值,然后与num对比
	
*/
// 以该节点为根,且经过该节点
// 递归计算:先计算子节点,最后一步加上根节点的值, 并将结果保存到result中
// 用堆栈,还好吧...
// 我鄙视用堆栈,自己可以构造干嘛用别人的
// 以后结果不好呈现时,可以考虑用一下堆栈。
// 这里用了个链表,还是用数组吧...
void CalNode(TreeNode *root, int num, ListNode *&result);
void PrintListNode(ListNode *pListNode);

// 数组
void CalNode_2(TreeNode *root, int num, int result[], int count);
void PrintVecInt(int result[], unsigned count);

void TestCalNode();
// 广度优先呢?但是结果不好呈现啊

/*
	查找最小的k个元素(数组)
	输入一个数组,输出其中的k个最小的元素
*/
// 前k个小元素
void FindKSmallest(int *arr, unsigned start, unsigned end, unsigned k, int *result, unsigned resultSize);
unsigned PivotQuickSort(int *arr, unsigned start, unsigned end, unsigned middle);
void TestFindKSmallest();

/*
	上排十个数,在下排给出其出现的次数:
	0 1 2 3 4 5 6 7 8 9
	6 2 1 0 0 0 1 0 0 0
	
	本来是想考虑其数学特性,看是否能简单给出答案的,看了不行啊
	还是用回溯法搜索靠谱啊!!!
*/
bool IsNumOK(int *arr, unsigned size, int *nextArr);
const int NUM_LEN = 9;
// 类似于八皇后的搜索过程

bool FindNextLineNum(int *arr, unsigned size, int *result, unsigned resultSize);
void TestFindNextLineNum();

/*
	判断整数序列是不是二叉查找树的后序遍历结果
	输入一个数组
*/
//  判断一个数组是不是后序遍历结果:
// 考虑用递归
// 考虑左边、右边。。。
// 我考虑的。。。
bool IsNextBinarySearch(int *arr, unsigned start, unsigned end);

bool IsNextBinarySearch_2(int *arr, unsigned start, unsigned end);
// 判断一个数组是否可能是后序遍历:存在某一个节点,前面的都小于root,后面的都大于root,
// 存在偏树的情况,左偏树返回end-1,右偏树返回start
bool IsMayBeNextBinary(int *arr, unsigned start, unsigned end, unsigned &middle);

void TestIsNextBinarySearch();

/*
	翻转句子中单词的顺序,单词内的字符顺序不变
	I am a student.-> student. a am I
*/
const int WORD_LEN = 128;

void ReverseWords(char words[][WORD_LEN], unsigned wordNum, char *result);
void ReverseWords_2(const char *str, char *result);

void ParseWord(const char *str, char words[][WORD_LEN], unsigned &wordNum);

void TestReverseWords();

#endif
#include <algorithm>
#include <assert.h>
#include <iostream>
#include <string>

#include "MS_1.h"

using namespace std;

void TestMS_1()
{
	TestBinaryTreeToDoubleList();
	TestMaxSumSum();
	TestCalNode();
	TestFindKSmallest();
	TestFindNextLineNum();
	TestIsNextBinarySearch();
	TestReverseWords();

}

void TestBinaryTreeToDoubleList()
{
	TreeNode node4(4, 0, 0);
	TreeNode node8(8, 0, 0);
	TreeNode node6(6, &node4, &node8);

	TreeNode node12(12, 0, 0);
	TreeNode node16(16, 0, 0);
	TreeNode node14(14, &node12, &node16);

	TreeNode node10(10, &node6, &node14);

	ListNode *dList = BinaryTreeToDoubleList(&node10);

}
ListNode *BinaryTreeToDoubleList(TreeNode *root)
{
	// 中序遍历树,每得到一个节点,就新建一个List节点,并挂在
	// 链表的末尾
	ListNode *dList = 0;	
	// 以递归的方式中序遍历树
	MiddleSearch(root, dList);
	while (dList->pre)
	{
		dList = dList->pre;
	}
	return dList;
}

void MiddleSearch(TreeNode *root, ListNode * &pListNode)
{
	if (!root)
	{
		return;
	}
	if (root->left)
	{
		MiddleSearch(root->left, pListNode);
	}
	if (!pListNode)
	{
		pListNode = new ListNode(root->num, 0, 0);
	}
	else
	{
		ListNode *pListTmp = new ListNode(root->num, pListNode, 0);
		pListNode->next = pListTmp;
		pListNode = pListTmp;
	}
	if (root->right)
	{
		MiddleSearch(root->right, pListNode);
	}
}

void DestroyDbList(ListNode *pDbList)
{
	ListNode *pTmp = pDbList;
	while (pDbList)
	{
		pDbList = pDbList->next;
		delete pTmp;
		pTmp = pDbList;
	}
}

// 2:
template <typename T>
MyStack<T>::MyStack()
{
	arr = new T[DEFAULT_STACK_CAPACITY];
	capacity = DEFAULT_STACK_CAPACITY;
	size = 0;
	min = T();
}

template <typename T>
MyStack<T>::MyStack(unsigned capa)
{
	capacity = capa;
	arr = new T[capacity];
	size = 0;
	min = T();
}

template <typename T>
void MyStack<T>::Push(T tmp)
{
	if (size == capacity)
	{
		capacity = capacity * 2 + 1;
		T tmpArr = new T[capacity];
		copy(arr, arr + size, tmpArr);
		delete arr;
		arr = tmpArr;
	}
	arr[size++] = tmp;
	if (tmp < min)
	{
		min = tmp;
	}
}

template <typename T>
T MyStack<T>::Pop()
{
	assert(!IsEmpty());
	return arr[--size];
}


template <typename T>
T MyStack<T>::Top()
{
	assert(!IsEmpty());
	return arr[size - 1];
}

template <typename T>
bool MyStack<T>::IsEmpty()
{
	return size == 0;
}

template <typename T>
T MyStack<T>::Min()
{
	assert(!IsEmpty());
	return min;
}

void MaxSubSum(const int *arr, unsigned size, int &sum, unsigned &start, unsigned &end)
{
	assert(arr);
	sum = 0;
	int tmpSum = 0;
	sum = 0x80000000;
	unsigned tmpStart = 0;
	unsigned tmpEnd = 0;

	for (unsigned i = 0; i < size; ++i)
	{
		tmpSum += arr[i];
		if (tmpSum < 0)
		{
			tmpSum = 0;
			tmpStart = i + 1;
			tmpStart = i + 1;
		}
		else if (tmpSum >= 0) // 这里要的是最长的!
		{
			tmpEnd = i;
		}

		if (tmpSum > sum)
		{
			sum = tmpSum;
			start = tmpStart;
			end = tmpEnd;
		}
	}
}

void TestMaxSumSum()
{
	int max = -(1 << 31);
	int max2 = 0x80000000;
	int max4 = -max2;
	int max3 = 1 << 31;
	int max5 = 1 << 30;
	int max6 = -max5;
}

// 4:
// 深度优先搜索,是否应该广度优先?
void CalNode(TreeNode *root, int num, ListNode *&result)
{
	if (!root)
	{
		return;
	}
	if (root->num > num)
	{
		return;
	}
	else if (root->num == num)
	{		
		PrintListNode(result);
		cout << num << " ";
		cout << endl;
		return;
	}
	else
	{
		if (!result)
		{
			result = new ListNode(root->num, 0, 0);
		}
		else 
		{
			ListNode *tmp = new ListNode(root->num, result, 0);
			result->next = tmp;
			result = tmp;
		}

		if (root->left)
		{
			CalNode(root->left, num - root->num, result);
		}
		if (root->right)
		{
			CalNode(root->right, num - root->num, result);
		}

		if (result)
		{
			ListNode *pTmp = result;
			result = result->pre;
			delete pTmp;
		}
	}	
}

void PrintListNode(ListNode *pListNode)
{	
	if (pListNode && pListNode->pre)
	{
		PrintListNode(pListNode->pre);
	}
	cout << pListNode->num << " ";
}

void TestCalNode()
{
	TreeNode node4(4, 0, 0);
	TreeNode node7(7, 0, 0);
	TreeNode node5(5, &node4, &node7);

	TreeNode node12(12, 0, 0);
	TreeNode node10(10, &node5, &node12);

	ListNode *pList = 0;
	CalNode(&node10, 22, pList);
}

void CalNode_2(TreeNode *root, int num, int result[], int count)
{
	if (num == 0)
	{
		PrintVecInt(result, count);
		return;
	}
	else
	{
		if (!root)
		{
			return;
		}
		result[count++] = root->num;
		if (root->left)
		{
			CalNode_2(root->left, num - root->num, result, count);
		}
		if (root->right)
		{
			CalNode_2(root->right, num - root->num, result, count);
		}
		count--;
	}
}

void PrintVecInt(int result[], unsigned count)
{
	assert(result);
	for (unsigned i = 0; i < count; ++i)
	{
		cout << result[i] << " ";
	}
	cout << endl;
}

// 算法:O(n),与寻找第K小元素一样
void FindKSmallest(int *arr, unsigned start, unsigned end, unsigned k, int *result, unsigned resultSize)
{
	assert(arr && (start <= end));
	assert(k <= (end - start + 1));
	unsigned middle = start + (end - start) / 2;
	// 以middle为pivot排序
	unsigned pivot = PivotQuickSort(arr, start, end, middle);
	unsigned num = pivot - start + 1;
	if (num == k)
	{
		copy(arr + start, arr + pivot + 1, result + resultSize);
	}
	else if (num < k)
	{
		copy(arr + start, arr + pivot + 1, result + resultSize);
		resultSize += num;
		FindKSmallest(arr, pivot + 1, end, k - num, result, resultSize);
	}
	else 
	{
		FindKSmallest(arr, start, pivot - 1, k, result, resultSize);
	}
}

unsigned PivotQuickSort(int *arr, unsigned start, unsigned end, unsigned middle)
{
	assert(arr);
	int pivotNum = arr[middle];
	unsigned startTmp = start;
	swap<int>(arr[start], arr[middle]);
	start++;
	while(start <= end)
	{
		while (arr[start] < pivotNum)
		{
			start++;
		}
		while (arr[end] > pivotNum)
		{
			end--;
		}

		if (start < end)
		{
			swap<int>(arr[start], arr[end]);
		}
	}
	swap<int>(arr[end], arr[startTmp]);
	return end;
}

void TestFindKSmallest()
{
	int arr[] = {3, 7, 8, 4, 2, 1, 6, 5};
	int result[8];
	//FindKSmallest(arr, 0, 7, 4, result, 0);
	//FindKSmallest(arr, 0, 7, 2, result, 0);
	FindKSmallest(arr, 0, 7, 6, result, 0);
}

/*
	上排十个数,在下排给出其出现的次数:
	0 1 2 3 4 5 6 7 8 9
	6 2 1 0 0 0 1 0 0 0

*/
bool IsNumOK(int *arr, unsigned size, int *nextArr)
{
	for (unsigned i = 0; i < size; ++i)
	{
		unsigned count = 0;
		for (unsigned j = 0; j < size; ++j)
		{
			if (nextArr[j] == arr[i])
			{
				count++;
			}
		}
		if (nextArr[i] != count)
		{
			return false;
		}
	}
	return true;
}

bool FindNextLineNum(int *arr, unsigned size, int *result, unsigned resultSize)
{
	if (size == resultSize)
	{
		if (IsNumOK(arr, size, result))
		{
			PrintVecInt(result, resultSize);
			return true;
		}
		return false;
	}
	else
	{
		for (unsigned i = 0; i < NUM_LEN; ++i)
		{
			result[resultSize] = i;
			if (FindNextLineNum(arr, size, result, resultSize + 1))
			{
				return true;
			}			
		}
	}
	return false;
}

void TestFindNextLineNum()
{
	//int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
	int result[10];
	if (FindNextLineNum(arr, NUM_LEN, result, 0))
	{
		cout << "OK" << endl;
	}
	else
	{
		cout << "No result" << endl;
	}
}

//  判断一个数组是不是后序遍历结果:
bool IsNextBinarySearch(int *arr, unsigned start, unsigned end)
{
	// 后序遍历的最后一个一定是父节点
	assert(arr);
	assert(start <= end);
	if (start == end)
	{
		return true;
	}
	
	int node = arr[end];
	unsigned middle = end;
	unsigned i;
	for (i = start; i < end; ++i)
	{
		if (arr[i] > node)
		{
			middle = i;
			break;
		}
	}
	// 1.middle没被赋值:i == end
	// 2.middle == start
	for (unsigned j = middle; j < end; ++j)
	{
		if (arr[j] < node)
		{
			return false;
		}
	}
	// 说明是左子树	说明第一个就大于,都是右子树
	if (i == end || middle == start)
	{
		return IsNextBinarySearch(arr, start, end - 1);
	}
	else 
	{
		return ((IsNextBinarySearch(arr, start, middle - 1) &&
		IsNextBinarySearch(arr, middle, end - 1)));
	}	
}

bool IsMayBeNextBinary(int *arr, unsigned start, unsigned end, unsigned &middle)
{
	// 遍历两次:第一次找出middle
	// 第二次:看middle左右两边的值是否满足条件
	int node = arr[end];
	
	return false;
}

bool IsNextBinarySearch_2(int *arr, unsigned start, unsigned end)
{
	assert(arr);
	assert(start <= end);

	int node = arr[end];
	unsigned middle = end;
	unsigned i;
	for (i = start; i < end; ++i)
	{
		if (arr[i] > node)
		{
			middle = i;
			break;
		}
	}
	// 1.middle没被赋值:i == end
	// 2.middle == start
	for (unsigned j = middle; j < end; ++j)
	{
		if (arr[j] < node)
		{
			return false;
		}
	}
	bool left = true;
	if (middle > start)
	{
		left = IsNextBinarySearch_2(arr, start, middle - 1);
	}
	bool right = true;
	if (middle < end)
	{
		right = IsNextBinarySearch_2(arr, middle, end - 1);
	}
	return left && right;
}

void TestIsNextBinarySearch()
{
	int arr[] = {5, 7, 6, 9, 11, 10, 8};
	//cout << IsNextBinarySearch(arr, 0, 6) << endl;
	cout << IsNextBinarySearch_2(arr, 0, 6) << endl;

	int arr2[] = {3, 4, 5, 6};
	cout << IsNextBinarySearch_2(arr2, 0, 3) << endl;

	int arr4[] = {10, 11, 9, 6};
	cout << IsNextBinarySearch_2(arr4, 0, 3) << endl;

	int arr3[] = {7, 4, 6, 5};
	cout << IsNextBinarySearch_2(arr3, 0, 3) << endl;
}

void ReverseWords(char words[][WORD_LEN], unsigned wordNum, char *result)
{
	unsigned pos = 0;
	for (unsigned i = wordNum; i > 0; --i)
	{
		//cout << words[i];
		strcpy(result + pos, words[i - 1]);
		pos += strlen(words[i - 1]);
		result[pos++] = ' ';		
	}
	result[pos] = '\0';
}

void ParseWord(const char *str, char words[][WORD_LEN], unsigned &wordNum)
{
	wordNum = 0;
	unsigned start = 0;
	unsigned end = 0;
	bool bFlag = false;
	unsigned i = 0;

	while (*(str + i))
	{
		if (*(str + i) == ' ')
		{
			if (bFlag)
			{
				bFlag = false;
				end = i - 1;
				strncpy(words[wordNum], str + start, end - start + 1);
				words[wordNum++][end - start + 1] = '\0';
			}						
		}
		else
		{
			if (!bFlag)
			{
				bFlag = true;
				start = i;
			}
		}
		++i;
	}
	strncpy(words[wordNum], str + start, i - start);
	words[wordNum++][i - start] = '\0';
}

void TestReverseWords()
{
	char *str = " I  am a student he is    exist OK.";
	//char *str = "Ia am";
	/*char words[128][WORD_LEN];
	unsigned wordNum;
	ParseWord(str, words, wordNum);*/

	char *result = new char[strlen(str) + 1];
	ReverseWords_2(str, result);
	cout << result << endl;
	delete result;

}

void ReverseWords_2(const char *str, char *result)
{
	// 直接一次遍历
	unsigned start = 0;
	unsigned end = 0;
	bool bFlag = false;
	unsigned i = 0;
	unsigned j = strlen(str);
	result[j--] = '\0';
	while (*(str + i))
	{
		if (*(str + i) == ' ')
		{
			if (bFlag)
			{
				bFlag = false;
				end = i - 1;
				j -= end - start;
				strncpy(result + j, str + start, end - start + 1);
				j--;
			}
			result[j--] = ' ';			
		}
		else
		{
			if (!bFlag)
			{
				bFlag = true;
				start = i;
			}
		}
		i++;
	}
	strncpy(result, str + start, i - start);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值