现在的位置: 首页 > 综合 > 正文

20120811完成剑指offer所有习题

2013年12月12日 ⁄ 综合 ⁄ 共 41996字 ⁄ 字号 评论关闭

剑指offer之面试题3

#include <iostream>

using namespace std;

const int rowSize = 4;
const int colSize = 4;
int array[rowSize][colSize] = {
	1, 2, 8, 9, 
	2, 3, 9, 12,
	4, 7, 10, 13,
	6, 8, 11, 15
};

struct Position
{
	int xPos;
	int yPos;
};

bool searchArray(int array[][colSize], int destValue, Position &postion)
{
	if (array == NULL)
		return false;
	for (int i = 0; i < rowSize; i++)
	{
		if (array[i] == NULL)
			return false;
	}

	bool flag = false;

	for (int row = 0, col = colSize - 1; row < rowSize && col >= 0;)
	{
		if (array[row][col] > destValue)
		{
			col--;
		}
		else if (array[row][col] < destValue)
		{
			row++;
		}
		else
		{
			postion.xPos = row + 1;
			postion.yPos = col + 1;
			flag = true;
			break;
		}
	}

	return flag;
}

void print(int array[][colSize])
{
	for (int i = 0; i < rowSize; i++)
	{
		for (int j = 0; j < colSize; j++)
		{
			cout << array[i][j] << " ";
		}
		cout << endl;
	}
}

void main()
{
	print(array);
	Position position;
	for (int i = 1; i <= 16; i++)
	{
		bool flag = searchArray(array, i, position);
		if (flag == true)
			cout << "find " << i << " at: " << "(" << position.xPos << ", " << position.yPos << ")" << endl;
		else
			cout << "can't find " << i << endl;
	}
}

面试题4:替换空格

#include <iostream>

using namespace std;

void replace(char *source, const char *str = "%20")
{
	if (source == NULL || str == NULL)
		return;

	const int length = strlen(source);
	int count = 0;
	for (int i = 0; i < length; i++)
	{
		if (source[i] == ' ')
			count++;
	}

	if (count == 0)
		return;

	const int strLen = strlen(str);
	if (strLen == 0)
	{
		cout << "本题不考虑这个情形" << endl;
		return;
	}
	const int destLength = length + (strLen - 1) * count;
	source[destLength] = '\0';
	int destPos = destLength - 1;
	for (int i = length - 1; i >= 0; i--)
	{
		if (source[i] == ' ')
		{
			for (int j = strLen - 1; j >= 0; j--)
			{
				source[destPos--] = str[j];
			}
		}
		else
		{
			source[destPos--] = source[i];
		}
	}
}

void main()
{
	const int size = 100;
	char source[size] = " We are happy ";

	replace(source);
	cout << "after replace: " << endl;
	cout << "source: " << source << endl;
}

面试题5:从尾到头打印链表

#include <iostream>
#include <stack>

using namespace std;

struct Node
{
	Node(int i = 0, Node *next = NULL) : next(next), data(i) {}

	Node *next;
	int data;
};

void printLink(Node *head, bool flag, const char *str = "recurse")
{
	if (head == NULL)
		return;
	static bool myFlag = false;
	if (!myFlag)
	{
		cout << str << endl;
		myFlag = true;
	}

	printLink(head->next, flag, str);
	cout << head->data << " ";
}

void printLink(Node *head, const char *str = "iterator")
{
	if (head == NULL)
		return;
	static bool myFlag = false;
	if (!myFlag)
	{
		cout << str << endl;
		myFlag = true;
	}

	stack<Node *> snode;
	while (head != NULL)
	{
		snode.push(head);
		head = head->next;
	}

	while (!snode.empty())
	{
		Node *node = snode.top();
		cout << node->data << " ";
		snode.pop();
	}
}

Node *construct()
{
	Node *head = NULL;
	Node *pHead = head;
	for (int i = 1; i <= 10; i++)
	{
		Node *node = new Node(i);
		if (head == NULL)
		{
			head = node;
			pHead = head;
		}
		else
		{
			pHead->next = node;
			pHead = pHead->next;
		}
	}

	return head;
}

void main()
{
	Node *head = construct();
	printLink(head, true);
	cout << endl;
	printLink(head);
}

面试题6:重建二叉树

#include <iostream>
#include <vector>

using namespace std;

struct Node
{
	Node(int i = 0, Node *left = NULL, Node *right = NULL) : m_pLeft(left), m_pRight(right), data(i) {}

	Node *m_pLeft;
	Node *m_pRight;
	char data;
};

const char *preOrder = "12473568";
const char *inOrder = "47215386";
const int len = strlen(preOrder);

Node *constructTree(const char *preOrder, const char *inOrder, int inLen)
{
	if (preOrder == NULL || inOrder == NULL || inLen == 0)
		return NULL;

	Node *node = new Node(*preOrder);
	int pos = 0;
	while (inOrder[pos] != *preOrder)
		pos++;
	if (pos == inLen)
	{
		cerr << "wrong input" << endl;
		return NULL;
	}

	node->m_pLeft = constructTree(preOrder + 1, inOrder, pos);
	node->m_pRight = constructTree(preOrder + pos + 1, inOrder + pos + 1, inLen - pos - 1);

	return node;
}

void printLevel(Node *root)
{
	if (root == NULL)
		return;

	vector<Node *> nvec;
	nvec.push_back(root);
	int start = 0;
	int end = 1;
	int pos = end;

	while (start != end)
	{
		Node *node = nvec[start];
		cout << node->data << " ";
		start++;

		if (node->m_pLeft)
		{
			nvec.push_back(node->m_pLeft);
			end++;
		}
		if (node->m_pRight)
		{
			nvec.push_back(node->m_pRight);
			end++;
		}

		if (start == pos)
		{
			pos = end;
			cout << endl;
		}
	}
}

void PreOrder(Node *root)
{
	if (root)
	{
		cout << root->data << " ";
		PreOrder(root->m_pLeft);
		PreOrder(root->m_pRight);
	}
}

void InOrder(Node *root)
{
	if (root)
	{
		InOrder(root->m_pLeft);
		cout << root->data << " ";
		InOrder(root->m_pRight);
	}
}

void main()
{
	Node *root = constructTree(preOrder, inOrder, strlen(inOrder));
	if (root == NULL)
	{
		cerr << "construct failed" << endl;
	}
	else
	{
		printLevel(root);
		PreOrder(root);
		cout << endl;
		InOrder(root);
	}
}

面试题7:用两个栈来实现队列

#include <iostream>
#include <stack>

using namespace std;

class MyQueue
{
public:
	void add(int i)
	{
		istack2.push(i);
	}

	void del()
	{
		if (istack1.empty())
		{
			if (istack2.empty())
			{
				cout << "empty queue" << endl;
				return;
			}
			while (!istack2.empty())
			{
				int data = istack2.top();
				istack1.push(data);
				istack2.pop();
			}
		}
		istack1.pop();
	}

	int front()
	{
		if (istack1.empty())
		{
			if (istack2.empty())
			{
				cout << "empty queue" << endl;
				return -1;
			}
			while (!istack2.empty())
			{
				int data = istack2.top();
				istack1.push(data);
				istack2.pop();
			}
		}

		return istack1.top();
	}

	bool empty()
	{
		if (istack1.empty() && istack2.empty())
			return true;
		else
			return false;
	}

private:
	stack<int> istack1;
	stack<int> istack2;
};

void main()
{
	MyQueue myQueue;
	for (int i = 1; i <= 5; i++)
	{
		myQueue.add(i);
	}

	while (!myQueue.empty())
	{
		cout << myQueue.front() << endl;
		myQueue.del();
	}
}

面试题8:求旋转数组的最小值

#include <iostream>

using namespace std;

const int array[] = {7, 8, 9, 10, 1, 2, 3, 4, 5, 6};
const int size = sizeof array / sizeof *array;

int findMinValue(const int *array, int left, int right)
{
	if (array == NULL || left < 0 || left > right || right < 0)
		return -1;

	if (left == right)
		return array[left];

	int mid = left + (right - left) / 2;
	if (mid == left)
		return min(array[left], array[right]);

	int minValue;
	while (left != right - 1)
	{
		mid = left + (right - left) / 2;
		if (array[left] == array[mid] && array[mid] == array[right])
		{
			minValue = array[left];
			for (int i = left + 1; i <= right; i++)
			{
				if (array[i] < minValue)
					minValue = array[i];
			}

			return minValue;
		}

		if (array[mid] < array[right])
			right = mid;
		else if (array[mid] > array[left])
			left = mid;
	}
	minValue = min(array[left], array[right]);

	return minValue;
}

void main()
{
	int value = findMinValue(array, 0, size - 1);
	cout << "value: " << value << endl;
}

#include <iostream>

using namespace std;

int array[] = {1};
const int size = sizeof array / sizeof *array;

int getMinNumber(int *array, int size)
{
	if (array == NULL || size <= 0)
		return -1;

	int leftIndex = 0;
	int rightIndex = size - 1;
	while (leftIndex != rightIndex - 1)
	{
		int mid = (rightIndex - leftIndex) / 2 + leftIndex;
		if (array[leftIndex] == array[mid] && array[mid] == array[rightIndex])
		{
			int minValue = array[leftIndex];
			for (int i = leftIndex + 1; i <= rightIndex; i++)
			{
				if (array[i] < minValue)
					minValue = array[i];
			}

			return minValue;
		}
		if (array[leftIndex] < array[rightIndex])
		{
			return array[leftIndex];
		}

		if (array[mid] > array[leftIndex])
			leftIndex = mid;
		else
			rightIndex = mid;
	}

	return array[rightIndex];
}

void main()
{
	int ret = getMinNumber(array, size);
	cout << "ret = " << ret << endl;
}

面试题9:斐波那契数列

三种方法:递归、循环和log(N)级解

题目简单,不写

面试题10:求十进制中1的个数

int getNumberOne1(int number)
{
	int count = 0;

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

	return count;
}

int getNumberOne2(int number)
{
	int count = 0;

	while (number)
	{
		if (number & 0x01)
			count++;
		number = number >> 1;
	}

	return count;
}

int getNumberOne3(long long int n)
{
	int count = 0;
	unsigned int flag = 1;

	while (flag)
	{
		if (n & flag)
			count++;
		flag = flag << 1;
	}

	return count;
}

书中给出3种解法,解法2存在负数时变死循环

关于负数的二进制说明:

比如-1的二进制,首先是1, 00000000 00000000 00000000 00000001,补码:11111111 11111111 11111111 11111110,然后+1,得11111111 11111111 11111111 11111111,共计32个1

关于解法3,很奇怪的地方是居然能退出循环。。。不可思议!!!如果直接flag = flag << 32,flag的值却是1。。。oh, no!!!    %>_<%

面试题11:数值的整数次方

#include <iostream>

using namespace std;

bool equalZero(double number)
{
	if (number < 0.000001 && number > -0.000001)
		return true;
	else
		return false;
}

double _myPow(double base, int exp)
{
	if (exp == 0)
		return 1;
	if (exp == 1)
		return base;

	double result = _myPow(base, exp >> 1);
	result *= result;
	if (exp & 0x01)
		result *= base;

	return result;
}

double _myPow2(double base, int exp)
{
	if (exp == 0)
		return 1;
	
	double result = 1;
	while (exp)
	{
		if (exp & 0x01)
			result *= base;
		base *= base;
		exp = exp >> 1;
	}

	return result;
}

double myPow(double base, int exp)
{
	if (equalZero(base))
		return 0;
	if (exp == 0)
		return 1;

	bool flag = false;
	if (exp < 0)
	{
		flag = true;
		exp = -exp;
	}

	double result = _myPow2(base, exp);
	if (flag)
	{
		result = 1 / result;
	}

	return result;
}

void main()
{
	double base = -2.0;
	int exp = -5;

	double result = myPow(base, exp);
	cout << "result: " << result << endl;
}

面试题12:打印1到最大的N位数

#include <iostream>

using namespace std;

const int size = 10;
char array[size];

void printNumber(int number)
{
	int i;
	for (i = 0; i < number; i++)
	{
		if (array[i] != '0')
			break;
	}
	
	if (i == number)
		return;

	for (int j = i; j < number; j++)
	{
		cout << array[j];
	}
	cout << endl;
}

void printNumber2(int number)
{
	int i;
	for (i = 1; i <= number; i++)
	{
		if (array[i] != '0')
			break;
	}

	if (i == number + 1)
		return;

	for (int j = i; j <= number; j++)
	{
		cout << array[j];
	}
	cout << endl;
}

void recursePrint(int number, int index)
{
	if (index == number)
	{
		printNumber(number);
		return;
	}

	for (int i = 0; i < 10; i++)
	{
		array[index] = i + '0';
		recursePrint(number, index + 1);
	}
}

void iteratorPrint(int number)
{
	array[number + 1] = '\0';
	bool flag = false;
	
	while (true)
	{
		if (array[0] == '1')
			break;
		for (int i = number; i >= 0; i--)
		{
			if (i == number)
			{
				if (array[i] == '9')
				{
					array[i] = '0';
					flag = true;
				}
				else
				{
					array[i]++;
					break;
				}
			}
			else
			{
				if (flag)
				{
					if (array[i] == '9')
					{
						array[i] = '0';
						flag = true;
					}
					else
					{
						array[i]++;
						flag = false;
						break;
					}
				}
			}
		}
		printNumber2(number);
	}
}

void main()
{
	memset(array, '0', size);
	iteratorPrint(3);
}

面试题13:在O(1)时间删除链表结点

#include <iostream>

using namespace std;

struct Node
{
	Node(int i = 0, Node *p = NULL) : data(i), next(p) {}
	Node *next;
	int data;
};

Node *construct(Node *&pNode)
{
	Node *head = NULL;
	Node *pHead = head;
	for (int i = 1; i <= 10; i++)
	{
		Node *node = new Node(i);
		if (i == 10)
			pNode = node;
		if (head == NULL)
		{
			head = node;
			pHead = head;
		}
		else
		{
			pHead->next = node;
			pHead = pHead->next;
		}
	}

	return head;
}

void deleteNode(Node *&head, Node *destNode)
{
	if (head == NULL || destNode == NULL)
		return;

	if (head == destNode)
	{
		head = head->next;
		delete destNode;
		return;
	}
	if (destNode->next == NULL)
	{
		Node *pHead = head;
		while (pHead->next != destNode)
			pHead = pHead->next;
		pHead->next = NULL;
		delete destNode;
		return;
	}
	else
	{
		Node *destNodeNext = destNode->next;
		destNode->data = destNodeNext->data;
		destNode->next = destNodeNext->next;
		delete destNodeNext;
	}
}

void printLink(Node *head)
{
	if (head == NULL)
		return;

	while (head != NULL)
	{
		cout << head->data << " ";
		head = head->next;
	}
}

void main()
{
	Node *pNode = NULL;
	Node *head = construct(pNode);
	cout << "before delete: " << endl;
	printLink(head);
	deleteNode(head, pNode);
	cout << endl << "after delete: " << endl;
	printLink(head);
}

面试题14:调整数组顺序使奇数位于偶数前面

#include <iostream>
#include <algorithm>
#include <iterator>

using namespace std;

int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const int size = sizeof array / sizeof *array;

void tranverse(int *array, int size)
{
	if (array == NULL || size <= 0)
		return;

	int i = 0;
	int j = size - 1;
	while(true)
	{
		while (array[i] & 0x01)
			i++;
		while (!(array[j] & 0x01))
			j--;
		if (i > j)
			break;
		swap(array[i], array[j]);
	}
}

void main()
{
	tranverse(array, size);
	copy(array, array + size, ostream_iterator<int>(cout, " "));
}

面试题15:链表中倒数第k个结点

本题注意点:1

1. 关于k的取值范围的判定

2. 如果链表长度恰好等于k时的处理

#include <iostream>

using namespace std;

struct Node
{
	Node(int i = 0, Node *p = NULL) : data(i), next(p) {}
	Node *next;
	int data;
};

Node *construct(Node *pNode)
{
	Node *head = NULL;
	Node *pHead = head;
	for (int i = 1; i <= 10; i++)
	{
		Node *node = new Node(i);
		if (i == 10)
			pNode = node;
		if (head == NULL)
		{
			head = node;
			pHead = head;
		}
		else
		{
			pHead->next = node;
			pHead = pHead->next;
		}
	}

	return head;
}

Node* findLastKNode(Node *head, int k)
{
	if (head == NULL || k <= 0)
		return NULL;

	Node *fastNode = head;
	Node *slowNode = head;
	while (fastNode != NULL && k != 0)
	{
		fastNode = fastNode->next;
		k--;
	}
	if (fastNode == NULL && k != 0)
	{
		cout << "k is too big" << endl;
		return NULL;
	}
	while (fastNode != NULL)
	{
		fastNode = fastNode->next;
		slowNode = slowNode->next;
	}

	return slowNode;
}

void printLink(Node *head)
{
	if (head == NULL)
		return;

	while (head != NULL)
	{
		cout << head->data << " ";
		head = head->next;
	}
}

void main()
{
	Node *head = construct(NULL);
	for (int i = 1; i <= 10; i++)
	{
		Node *node = findLastKNode(head, i);
		if (node)
			cout << "last " << i << " node: " << node->data << endl;
	}
}

面试题16:反转链表

#include <iostream>

using namespace std;

struct Node
{
	Node(int i = 0, Node *p = NULL) : data(i), next(p) {}
	Node *next;
	int data;
};

Node *construct(Node *pNode)
{
	Node *head = NULL;
	Node *pHead = head;
	for (int i = 1; i <= 10; i++)
	{
		Node *node = new Node(i);
		if (i == 10)
			pNode = node;
		if (head == NULL)
		{
			head = node;
			pHead = head;
		}
		else
		{
			pHead->next = node;
			pHead = pHead->next;
		}
	}

	return head;
}

Node *recursiveReverse(Node *head, Node *&newHead)
{
	if (head ->next == NULL)
		return head;

	Node *node = recursiveReverse(head->next, newHead);
	if (newHead == NULL)
	{
		newHead = node;
		node->next = head;
		node = head;
		node->next = NULL;
	}
	else
	{
		node->next = head;
		node = head;
		node->next = NULL;
	}
	return node;
}

Node *reverseLink(Node *head)
{
	if (head == NULL || head->next == NULL)
		return head;

	Node *pHead = head;
	Node *pHeadNext = head->next;
	Node dump;

	while (pHeadNext != NULL)
	{
		head->next = dump.next;
		dump.next = head;
		head = pHeadNext;
		pHeadNext = pHeadNext->next;
	}

	head->next = dump.next;
	dump.next = head;
	head = pHeadNext;

	return dump.next;
}

Node* reverse(Node *head)
{
	if(head == NULL) {
		cout << "link is null" << endl;
		return NULL;
	}

	Node *newHead = NULL, *pHeadNext = head;

	while(pHeadNext) {
		head = pHeadNext;
		pHeadNext = pHeadNext->next;
		head->next = newHead;
		newHead = head;
	}

	return newHead;
}

void printLink(Node *head)
{
	if (head == NULL)
		return;

	while (head != NULL)
	{
		cout << head->data << " ";
		head = head->next;
	}
}

void main()
{
	Node *head = construct(NULL);
	Node *pHead = NULL;
	recursiveReverse(head, pHead);
	printLink(pHead);
	Node *newHead = reverseLink(pHead);
	cout << endl;
	printLink(newHead);
	cout << endl;
	Node *newHead2 = reverse(newHead);
	printLink(newHead2);
}

递归算法

Node* recursiveReverse(Node *PreNode, Node *CurrentNode)
{
	Node* resultNode;
	if(CurrentNode == NULL)
		return NULL;
	if(CurrentNode->next == NULL)    
	{                    
		CurrentNode->next = PreNode;
		resultNode = CurrentNode;
	}
	else                
	{                    
		resultNode = recursiveReverse(CurrentNode, CurrentNode->next);
		CurrentNode->next = PreNode;
	}
	PreNode->next = NULL;
	return resultNode;
}

╮(╯▽╰)╭一天才做了这几道,哭啊。。。伤心。。。

面试题17:合并两个排序链表

题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。

链表1:    1 3 5 7

链表2:    2 4 6 8

#include <iostream>

using namespace std;

struct Node
{
	Node(int i = 0, Node *pNext = NULL) : data(i), next(pNext) {}
	int data;
	Node *next;
};

Node *construct()
{
	Node *node4 = new Node(7);
	Node *node3 = new Node(5, node4);
	Node *node2 = new Node(3, node3);
	Node *node1 = new Node(1, node2);

	return node1;
}

Node* construct2()
{
	Node *node4 = new Node(8);
	Node *node3 = new Node(6, node4);
	Node *node2 = new Node(4, node3);
	Node *node1 = new Node(2, node2);

	return node1;	
}

Node* mergeLink(Node *head1, Node *head2)
{
	if (head1 == NULL || head2 == NULL)
		return NULL;

	Node *pHead1 = head1;
	Node *pHead2 = head2;
	Node *head = NULL;
	Node *pHead = head;

	while (pHead1 != NULL && pHead2 != NULL)
	{
		if (head == NULL)
		{
			if (pHead1->data < pHead2->data)
			{
				head = pHead1;
				pHead1 = pHead1->next;
				pHead = head;
			}
			else
			{
				head = pHead2;
				pHead2 = pHead2->next;
				pHead = head;
			}
		}
		else
		{
			if (pHead1->data < pHead2->data)
			{
				pHead->next = pHead1;
				pHead1 = pHead1->next;
				pHead = pHead->next;
			}
			else
			{
				pHead->next = pHead2;
				pHead2 = pHead2->next;
				pHead = pHead->next;
			}		
		}
	}

	if (pHead1 == NULL)
		pHead->next = pHead2;
	else
		pHead->next = pHead1;

	return head;
}

void printLink(Node *head)
{
	if (head == NULL)
		return;

	Node *pHead = head;
	while (pHead != NULL)
	{
		cout << pHead->data << " ";
		pHead = pHead->next;
	}

	return;
}

void main()
{
	Node *head1 = construct();
	Node *head2 = construct2();
	cout << "two LINK: " << endl;
	printLink(head1);
	cout << endl;
	printLink(head2);
	cout << endl;
	Node *newHead = mergeLink(head1, head2);

	cout << "after merge: " << endl;
	printLink(newHead);
}

这道题目很弱,但是书上给出的解法很NB

Node *recursiveMergeLink(Node *head1, Node *head2)
{
	if (head1 == NULL)
		return head2;
	else if (head2 == NULL)
		return head1;

	Node *head;
	if (head1->data < head2->data)
	{
		head = head1;
		head->next = recursiveMergeLink(head1->next, head2);
	}
	else
	{
		head = head2;
		head->next = recursiveMergeLink(head1, head2->next);
	}

	return head;
}

面试题18:树的子结构

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

                8

         8            7

    9       2

       4         7

         8

   9         2

#include <iostream>

using namespace std;

struct Node
{
	Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft), right(pRight) {}
	int data;
	Node *left;
	Node *right;
};

Node* construct()
{
	Node *node7 = new Node(7);
	Node *node6 = new Node(4);
	Node *node5 = new Node(2, node6, node7);
	Node *node4 = new Node(9);
	Node *node3 = new Node(7);
	Node *node2 = new Node(8, node4, node5);
	Node *node1 = new Node(8, node2, node3);

	return node1;
}

Node* construct2()
{
	Node *node3 = new Node(2);
	Node *node2 = new Node(9);
	Node *node1 = new Node(8);

	return node1;
}

bool hasSubTree(Node *root1, Node *root2)
{
	if (root2 == NULL)
		return true;
	if (root1 == NULL)
		return false;

	if (root1->data != root2->data)
		return false;
	else
		return hasSubTree(root1->left, root2->left) && hasSubTree(root1->right, root2->right);
}

bool isSubTree(Node *root1, Node *root2)
{
	if (root1 == NULL || root2 == NULL)
		return false;

	bool flag = false;
	flag = hasSubTree(root1, root2);

	bool leftFlag = false;
	bool rightFlag = false;
	if (root1->left)
		leftFlag = isSubTree(root1->left, root2);
	if (root1->right)
		rightFlag = isSubTree(root1->right, root2);

	return flag || leftFlag || rightFlag;
}

void main()
{
	Node *root1 = construct();
	Node *root2 = construct2();
	bool result = isSubTree(root1, root2);
	if (result == true)
		cout << "has subtree" << endl;
	else
		cout << "no sub tree" << endl;
}

递归的方法很简单,那么关于迭代的方法呢。。。

#include <iostream>
#include <stack>

using namespace std;

struct Node
{
	Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft), right(pRight) {}
	int data;
	Node *left;
	Node *right;
};

Node* construct()
{
	Node *node7 = new Node(7);
	Node *node6 = new Node(4);
	Node *node5 = new Node(2, node6, node7);
	Node *node4 = new Node(9);
	Node *node3 = new Node(7);
	Node *node2 = new Node(8, node4, node5);
	Node *node1 = new Node(8, node2, node3);

	return node1;
}

Node* construct2()
{
	Node *node3 = new Node(2);
	Node *node2 = new Node(9);
	Node *node1 = new Node(8, node2, node3);

	return node1;
}

bool checkSubTree(Node *root1, Node *root2)
{
	if (root1 == NULL || root2 == NULL)
		return false;

	stack<Node *> nstack1;
	stack<Node *> nstack2;
	bool result = true;
	while (!nstack2.empty() || root2 != NULL)
	{
		if (root2 != NULL)
		{
			if (root1->data == root2->data)
			{
				nstack1.push(root1);
				nstack2.push(root2);
				root1 = root1->left;
				root2 = root2->left;
			}
			else
			{
				result = false;
				break;
			}
		}
		else
		{
			root1 = nstack1.top();
			root2 = nstack2.top();
			nstack1.pop();
			nstack2.pop();

			root1 = root1->right;
			root2 = root2->right;
		}
	}

	return result;
}

bool isSubTree(Node *root1, Node *root2)
{
	if (root1 == NULL || root2 == NULL)
		return false;

	stack<Node*> nstack;
	bool result = false;
	while (!nstack.empty() || root1 != NULL)
	{
		if (root1 != NULL)
		{
			if (checkSubTree(root1, root2) == true)
			{
				result = true;
				break;
			}

			nstack.push(root1);
			root1 = root1->left;
		}
		else
		{
			root1 = nstack.top();
			nstack.pop();
			root1 = root1->right;
		}
	}

	return result;
}

void main()
{
	Node *root1 = construct();
	Node *root2 = construct2();

	if (isSubTree(root1, root2) == true)
		cout << "is subtree" << endl;
	else
		cout << "not a subtree" << endl;
}

面试题19:二叉树的镜像

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

          8

    6        10

5      7  9      11

#include <iostream>
#include <queue>

using namespace std;

struct Node
{
	Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft), right(pRight) {}
	int data;
	Node *left;
	Node *right;
};

Node* construct()
{
	//Node *node7 = new Node(11);
	Node *node6 = new Node(9);
	Node *node5 = new Node(7);
	Node *node4 = new Node(5);
	Node *node3 = new Node(10, node6);
	Node *node2 = new Node(6, node4, node5);
	Node *node1 = new Node(8, node2, node3);

	return node1;
}

void printLevel(Node *root)
{
	if (root == NULL)
		return;

	queue<Node *> qnode;
	qnode.push(root);
	int count = 1;
	int start = 0;
	int tempCount = 0;

	while (!qnode.empty())
	{
		tempCount = 0;
		while (start != count)
		{
			Node *top = qnode.front();
			
			if (top != NULL)
			{
				if (top->left)
				{
					qnode.push(top->left);
					tempCount++;
				}
				else if (top->left == NULL && top->right != NULL)
				{
					qnode.push(NULL);
					tempCount++;
				}
				if (top->right)
				{
					qnode.push(top->right);
					tempCount++;
				}
				else if (top->left != NULL && top->right == NULL)
				{
					qnode.push(NULL);
					tempCount++;
				}
			}

			start++;
			if (top != NULL)
				cout << top->data;
			else
				cout << " ";
			qnode.pop(); 
		}
		count = tempCount;
		start = 0;
		cout << endl;
	}
}

Node* swapTree(Node *root)
{
	if (root == NULL)
		return root;
	swap(root->left, root->right);
	swapTree(root->left);
	swapTree(root->right);

	return root;
}

void main()
{
	Node *root = construct();
	printLevel(root);
	Node* root2 = swapTree(root);
	printLevel(root2);
}

面试题20:顺时针打印矩阵

输入矩阵如下:

1   2    3    4

5   6    7    8

9   10  11 12

13 14 15 16

输出:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#include <iostream>

using namespace std;

const int size = 4;

int array[4][4] =
{
	1, 2, 3, 4,
	12, 13, 14, 5,
	11, 16, 15, 6,
	10, 9, 8, 7
};

void print(int (*array)[size])
{
	for (int i = 0; i < (size + 1) / 2; i++)
	{
		for (int j = i; j < size - i; j++)
			cout << array[i][j] << " ";
		for (int j = i + 1; j < size - i; j++)
			cout << array[j][size - i - 1] << " ";
		for (int j = size - i - 2; j >= i; j--)
			cout << array[size - i - 1][j] << " ";
		for (int j = size - i - 2; j >= i + 1; j--)
			cout << array[j][i] << " ";
	}
}

void main()
{
	print(array);
}

递归解法:

#include <iostream>  

using namespace std;  

const int size = 16;  

int array[size] =  
{  
	1, 2, 3, 4,  
	12, 13, 14, 5,  
	11, 16, 15, 6,  
	10, 9, 8, 7  
};  

void print(int *array, int rows, int cols, int index)
{
	if (array == NULL || rows < 0 || cols < 0 || index >= min(rows >> 1, cols >> 1))
		return;

	for (int i = index; i < cols - index; i++)
		cout << array[index * rows + i] << " ";
	for (int i = index + 1; i < rows - index; i++)
		cout << array[i * rows + cols - index - 1] << " ";
	for (int i = cols - index - 2; i >= index; i--)
		cout << array[(rows - index - 1) * rows + i] << " ";
	for (int i = rows - index - 2; i > index; i--)
		cout << array[i * rows + index] << " ";

	print(array, rows, cols, index + 1);
}

void main()
{
	print(array, 4, 4, 0);
}

面试题21:包含min函数的栈

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

本题目一定要注意,保存的是最小元素的index,而不是最小元素,因为stack里面保存的不一定是int型,有可能是类

#include <iostream>

using namespace std;

class MyStack
{
public:
	MyStack(int i = -1, int j = -1) : currentIndex(i), currentIndexMin(j) {}
	void push(int item)
	{
		if (currentIndex == size - 1)
		{
			cerr << "over flow" << endl;
			return;
		}
		
		data[++currentIndex] = item;
		if (currentIndexMin == -1)
			minIndex[++currentIndexMin] = currentIndex;
		else if (item < data[minIndex[currentIndexMin]])
		{
			minIndex[++currentIndexMin] = currentIndex;
		}
	}

	void pop()
	{
		if (currentIndex == -1)
		{
			cerr << "under flow" << endl;
			return;
		}
	
		if (currentIndex == minIndex[currentIndexMin])
		{
			currentIndexMin--;
		}
		currentIndex--;
	}

	int min()
	{
		if (currentIndexMin == -1)
		{
			cerr << "under flow" << endl;
			return -1;
		}

		return data[minIndex[currentIndexMin]];
	}

private:
	static const int size = 100;
	int data[size];
	int currentIndex;
	int currentIndexMin;
	int minIndex[size];
};

void main()
{
	MyStack myStack;
	myStack.push(3);
	myStack.push(5);
	myStack.push(1);
	myStack.push(2);
	myStack.push(4);

	cout << myStack.min() << endl;
	myStack.pop();
	cout << myStack.min() << endl;
	myStack.pop();

	cout << myStack.min() << endl;
	myStack.pop();

	cout << myStack.min() << endl;
	myStack.pop();

	cout << myStack.min() << endl;
	myStack.pop();
}

面试题22:栈的压入、弹出序列

题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该栈序列对应的一个弹出序列,但是4、3、5、1、2就不可能是该压栈序列的弹出序列。

#include <iostream>
#include <stack>

using namespace std;

int source[] = {1, 2, 3, 4, 5};
int dest[] = {4, 3, 2, 1, 5};
const int size = sizeof source / sizeof *source;

bool isPopSequence(int *source, int sizeSource, int *dest, int sizeDest)
{
	if (source == NULL || dest == NULL || sizeSource != sizeDest)
		return false;

	stack<int> istack;
	int indexDest = 0;
	int indexSource = 0;
	bool flag = false;
	while (indexSource != sizeSource && indexDest != sizeDest)
	{
		istack.push(source[indexSource]);
		indexSource++;
		while (!istack.empty() && istack.top() == dest[indexDest])
		{
			istack.pop();
			indexDest++;
		}
	}

	if (indexSource == sizeSource && indexDest == sizeDest)
		flag = true;

	return flag;
}

void main()
{
	bool result = isPopSequence(source, size, dest, size);
	if (result)
		cout << "pos sequence" << endl;
	else
		cout << "not a pop sequence" << endl;
}

面试题23:从上往下打印二叉树

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

            8

      6        10

5       7  9        11

#include <iostream>
#include <queue>

using namespace std;

struct Node 
{
	Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft), right(pRight){}
	int data;
	Node *left;
	Node *right;
};

void printLevel(Node *root)
{
	if (root == NULL)
		return;

	queue<Node *> qnodes;
	qnodes.push(root);

	int indexFast = 1;
	int indexSlow = 1;
	int index = 0;
	while (!qnodes.empty())
	{
		Node *node = qnodes.front();
		qnodes.pop();

		if (node->left)
		{
			indexFast++;
			qnodes.push(node->left);
		}
		if (node->right)
		{
			indexFast++;
			qnodes.push(node->right);
		}

		index++;
		cout << node->data << " ";
		if (index == indexSlow)
		{
			indexSlow = indexFast;
			cout << endl;
		}
	}
}

Node *construct()
{
	Node *node7 = new Node(11);
	Node *node6 = new Node(9);
	Node *node5 = new Node(7);
	Node *node4 = new Node(5);
	Node *node3 = new Node(10, node6, node7);
	Node *node2 = new Node(6, node4, node5);
	Node *node1 = new Node(8, node2, node3);

	return node1;
}

void main()
{
	Node *root = construct();
	printLevel(root);
}

面试题24:二叉搜索树的后序遍历序列

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果,如果是返回true,否则返回false,假设输入数组的任意两个数字都互不相同。

比如{5, 7, 6, 9, 11, 10, 8} 则返回true

{7, 4, 6, 5}返回false

#include <iostream>

using namespace std;

//int array[] = {5, 7, 6, 9, 11, 10, 8};
//int array[] = {6, 8, 7, 5};
int array[] = {3, 5};
const int size = sizeof array / sizeof *array;

bool _isPostOrder(int *array, int start, int end)
{
	if (start > end)
		return false;
	if (start == end)
		return true;

	int index = end - 1;
	while (index >= 0 && array[index] > array[end])
		index--;
	if (index == -1 || index == end - 1)
		return _isPostOrder(array, start, end - 1);
	else
		return _isPostOrder(array, start, index) && _isPostOrder(array, index + 1, end - 1);
}

bool isPostOrder(int *array, int size)
{
	if (array == NULL || size <= 0)
		return false;

	return _isPostOrder(array, 0, size - 1);
}

void main()
{
	bool result = isPostOrder(array, size);
	if (result)
		cout << "post order" << endl;
	else
		cout << "not post order" << endl;
}

UT:

1. 空指针

2. 含有一个元素 {1}

3. 只有左子树  {2, 4, 3, 5}  {1, 2, 3, 4}

4. 只有右子树 {6, 8, 7, 5}  {4, 3, 2, 1}

5. 左右子树均有

面试题25:二叉树中和为某一值的路径

题目:输入一棵二叉树和一个整数,打印二叉树中结点值的和为输入整数的所有路径,从树的根节点开始往下一直到叶结点所经过的结点形成一条路径。

          10

       5      12

   4      7     

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

using namespace std;

struct Node
{
	Node(int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft), right(pRight) {}
	int data;
	Node *left;
	Node *right;
};

Node* construct()
{
	Node *node5 = new Node(-1);
	Node *node4 = new Node(4);
	Node *node3 = new Node(12);
	Node *node2 = new Node(13, node4, node5);
	Node *node1 = new Node(10, node2, node3);

	return node1;
}

void printSum(Node *root, int sum, vector<Node *> nvec)
{
	if (root == NULL)
		return;

	nvec.push_back(root);
	if (root ->left == NULL && root->right == NULL)
	{
		if (sum == root->data)
		{
			for (vector<Node *>::iterator iter = nvec.begin(); iter != nvec.end(); ++iter)
				cout << (*iter)->data << " ";
			cout << endl;
		}
		nvec.pop_back();
		return;
	}

	printSum(root->left, sum - root->data, nvec);
	printSum(root->right, sum - root->data, nvec);
	nvec.pop_back();
}

void main()
{
	Node *root = construct();
	vector<Node *> nvec;
	printSum(root, 22, nvec);
}

面试题26:复杂链表的复制

#include <iostream>

using namespace std;

struct Node 
{
	Node(int i = 0, Node *nextNode = NULL, Node *nextRandNode = NULL) : data(i), next(nextNode), randNext(nextRandNode) {}
	int data;
	Node *next;
	Node *randNext;
};

Node *construct()
{
	Node *node5 = new Node(5);
	Node *node4 = new Node(4, node5);
	Node *node3 = new Node(3, node4);
	Node *node2 = new Node(2, node3);
	Node *node1 = new Node(1, node2);

	node5->randNext = node1;
	node4->randNext = node2;
	node2->randNext = node5;
	node1->randNext = node3;

	return node1;
}

Node* copyLinkStepOne(Node *head)
{
	if (head == NULL)
		return head;

	Node *pHead = head;
	while (pHead != NULL)
	{
		Node *cloneNode = new Node(pHead->data);
		cloneNode->next = pHead->next;
		pHead->next = cloneNode;
		pHead = cloneNode->next;
	}

	return head;
}

Node *copyLinkStepTwo(Node *head)
{
	if (head == NULL)
		return head;

	Node *pHead = head;
	Node *pCloneHead = pHead->next;
	while (pHead != NULL)
	{
		pCloneHead->randNext = pHead->randNext;
		pHead = pCloneHead->next;
		if (pHead != NULL)
			pCloneHead = pHead->next;
	}

	return head;
}

Node *copyLinkStepThree(Node *head)
{
	if (head == NULL)
		return head;

	Node *pHead = head;
	Node *cloneHead = pHead->next;
	Node *pCloneHead = cloneHead;
	while (pHead != NULL)
	{
		pHead->next = pCloneHead->next;
		pHead = pCloneHead->next;
		if (pHead != NULL)
		{
			pCloneHead->next = pHead->next;
			pCloneHead = pCloneHead->next;
		}
		else
		{
			pCloneHead->next = NULL;
		}
	}

	return cloneHead;
}

void printLink(Node *head)
{
	if (head == NULL)
		return;

	cout << head->data << '\t';
	if (head->randNext != NULL)
		cout << head->randNext->data << endl;
	else
		cout << endl;
	printLink(head->next);
}

void printLink2(Node *head)
{
	if (head == NULL)
		return;

	Node *pHead = head;
	while (pHead != NULL)
	{
		cout << pHead->data << '\t';
		if (pHead->randNext != NULL)
			cout << pHead->randNext->data << endl;
		else
			cout << endl;
		pHead = pHead->next;
	}
}

void main()
{
	Node *head = construct();
	cout << "source link: " << endl;
	printLink(head);
	Node *tempCloneHead = copyLinkStepOne(head);
	tempCloneHead = copyLinkStepTwo(tempCloneHead);
	Node *cloneHead = copyLinkStepThree(tempCloneHead);

	cout << "After Copy!!!: Source Link" << endl;
	printLink(head);
	cout << "After Copy!!!: Clone Link" << endl;
	printLink(cloneHead);
}

UT:

1. NULL指针

2. 只有1个node

3. 普通链表

4. 正常的复杂链表

面试题27:二叉搜索树与双向链表

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

             10

      6          14

4      8    12     16

输出:4 6 8 10 12 14 16

#include <iostream>
#include <stack>

using namespace std;

struct Node 
{
	Node(int i = 0, Node *nextNode = NULL, Node *nextRandNode = NULL) : data(i), left(nextNode), right(nextRandNode) {}
	int data;
	Node *left;
	Node *right;
};

Node *construct()
{
	Node *node7 = new Node(16);
	Node *node6 = new Node(12);
	Node *node5 = new Node(8);
	Node *node4 = new Node(4);
	Node *node3 = new Node(14, node6, node7);
	Node *node2 = new Node(6, node4, node5);
	Node *node1 = new Node(10, node2, node3);

	return node1;
}

Node* convert2LinkRecursive(Node *root)
{
	if (root == NULL)
		return root;

	static Node *head = NULL;
	static Node *pHead = head;

	convert2LinkRecursive(root->left);
	if (head == NULL)
	{
		head = root;
		pHead = head;
	}
	else
	{
		pHead->right = root;
		root->left = pHead;
		pHead = root;
	}
	convert2LinkRecursive(root->right);

	return head;
}

Node* convert2LinkIterator(Node *root)
{
	if (root == NULL)
		return root;

	Node *head = NULL;
	Node *pHead = head;
	stack<Node *> snode;
	
	while (root != NULL || !snode.empty())
	{
		while (root != NULL)
		{
			snode.push(root);
			root = root->left;
		}
		root = snode.top();
		if (head == NULL)
		{
			head = root;
			pHead = head;
		}
		else
		{
			pHead->right = root;
			root->left = pHead;
			pHead = root;
		}
		root = root->right;
		snode.pop();
	}

	return head;
}

void printLink(Node *head)
{
	if (head == NULL)
		return;

	cout << head->data << " ";
	printLink(head->right);
}

void printLinkLeft(Node *head)
{
	if (head == NULL)
		return;

	Node *pHead = head;
	while (pHead->right != NULL)
	{
		pHead = pHead->right;
	}

	while (pHead != head)
	{
		cout << pHead->data << " ";
		pHead = pHead->left;
	}

	cout << pHead->data << endl;
}

void inorder(Node *root)
{
	if (root)
	{
		inorder(root->left);
		cout << root->data << " ";
		inorder(root->right);
	}
}

void main()
{
	Node *root = construct();
	inorder(root);
	cout << endl;
	Node *head = convert2LinkIterator(root);
	printLink(head);
	cout << endl;
	printLinkLeft(head);
}

面试题28:字符串的排列

题目:输入一个字符串,打印出该字符串中字符的所有排列,例如输入字符串abc,则打印出字符串a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和aba。

#include <iostream>
#include <vector>

using namespace std;

char str[] = {'a', 'b', 'c'};
const int size = sizeof str / sizeof *str;

void printCombine2(char *str, int index, int size)
{
	if (str == NULL || index < 0 || size <= 0 || index > size)
		return;

	if (index == size)
		cout << str << endl;

	for (int i = index; i < size; i++)
	{
		swap(str[i], str[index]);
		printCombine2(str, index + 1, size);
		swap(str[i], str[index]);
	}
}

bool isSolution(int index, int size)
{
	return index == size;
}

void processSolution(char *states, int statesSize)
{
	if (states == NULL || statesSize <= 0)
		return;

	for (int i = 0; i < statesSize; i++)
		cout << states[i] << " ";
	cout << endl;
}

void generateCandidates(char *str, int size, char *states, char *candidates, int *ncandidates, int index)
{
	if (str == NULL || size <= 0 || states == NULL || candidates == NULL || ncandidates == NULL)
		return;

	*ncandidates = 0;
	for (int i = 0; i < size; i++)
	{
		int j;
		for (j = 0; j < index; j++)
		{
			if (str[i] == states[j])
				break;
		}
		if (j == index)
		{
			candidates[*ncandidates] = str[i];
			*ncandidates = *ncandidates + 1;
		}
	}
}

void printCombine(char *str, int size, char *states, int statesSize, int index)
{	
	if (str == NULL || size <= 0 || states == NULL || statesSize <= 0 || index < 0 || index > statesSize)
		return;

	if (isSolution(index, statesSize) == true)
	{
		processSolution(states, statesSize);
	}
	else
	{
		int ncandidates;
		char candidates[100];
		generateCandidates(str, size, states, candidates, &ncandidates, index);
		for (int i = 0; i < ncandidates; i++)
		{
			states[index] = candidates[i];
			printCombine(str, size, states, statesSize, index + 1);
		}
	}
}

void main()
{
	char states[100];
	printCombine(str, size, states, size, 0);
}

面试题29: 数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字,例如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

int array[] = {1, 2, 3, 2, 2, 2, 5, 4, 2};
const int size = sizeof array / sizeof *array;

int myPartition1(int *array, int size)
{
	if (array == NULL || size <= 0)
		return -1;

	int pivot = array[size - 1];
	int i = -1;
	int j = 0;
	while (j < size - 1)
	{
		if (array[j] < pivot)
		{
			i++;
			swap(array[i], array[j]);
		}
		j++;
	}

	i++;
	swap(array[i], array[j]);

	return i;
}

int myPartition2(int *array, int left, int right)
{
	if (array == NULL)
		return -1;

	if (left == right)
		return left;

	int leftIndex = left;
	int rightIndex = right - 1;
	int &pivot = array[right];
	while (leftIndex <= rightIndex)
	{
		while (leftIndex < right && array[leftIndex] <= pivot)
			leftIndex++;
		while (rightIndex >= left && array[rightIndex] > pivot)
			rightIndex--;

		if (leftIndex > rightIndex)
			break;
		swap(array[leftIndex], array[rightIndex]);
	}
	swap(array[leftIndex], pivot);

	return leftIndex;
}


int partitionIndex(int *array, int size, int k)
{
	if (array == NULL || size <= 0 || k <= 0 || k > size)
		return -1;
	k = k - 1;
	int pos = -1;
	int left = 0;
	int right = size - 1;
	while (true)
	{
		pos = myPartition2(array, left, right);
		if (pos < k)
			left = pos + 1;
		else if (pos > k)
			right = pos - 1;
		else
			 break;
	}

	return array[pos];
}

void main()
{
	int result = partitionIndex(array, size, (size + 1) >> 1);
	cout << "mid value = " << result << endl;
	for (int i = 1; i <= size; i++)
	{
		int result = partitionIndex(array, size , i);
		cout << "result = " << result << endl;
	}
}

#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

int array[] = {1, 2, 3, 2, 2, 2, 5, 4, 2};
const int size = sizeof array / sizeof *array;

int findMoreThanHalf(int *array, int size)
{
	if (array == NULL || size <= 0)
		return -1;

	int candidate = array[0];
	int count = 1;

	for (int i = 1; i < size; i++)
	{
		if (count == 0)
		{
			candidate = array[i];
			count = 1;
			continue;
		}

		if (candidate == array[i])
			count++;
		else
			count--;
	}

	return candidate;
}

void main()
{
	int result = findMoreThanHalf(array, size);
	cout << "result = " << result << endl;
}

面试题30:最小的K个数

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

思路1:利用partition来求解,代码同上

思路2:利用最大堆来求解

#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

void keepHeap(int *array, int position, int size)
{
	if (array == NULL || size <= 0)
		return;

	int start = position;
	int maxPos = start;
	while (start < size / 2)
	{
		int leftChild = 2 * start + 1;
		int rightChild = 2 * start + 2;
		maxPos = start;
		if (leftChild < size)
		{
			if (array[start] < array[leftChild])
				maxPos = leftChild;
		}
		if (rightChild < size)
		{
			if (array[maxPos] < array[rightChild])
				maxPos = rightChild;
		}
		if (maxPos != start)
		{
			swap(array[start], array[maxPos]);
			start = maxPos;
		}
		else
			break;
	}
}

void buildMaxHeap(int *array, int size)
{
	if (array == NULL || size <= 0)
		return;

	for (int i = (size - 1) / 2; i >= 0; i--)
		keepHeap(array, i, size);
}

void getKMin(int *data, int size, int *array, int k)
{
	if (data == NULL || size <= 0 || array == NULL || k <= 0)
		return;

	if (k >= size)
	{
		for (int i = 0; i < size; i++)
			array[i] = data[i];
		copy(array, array + size, ostream_iterator<int>(cout, " "));
		return;
	}
	else
	{
		for (int i = 0; i < k; i++)
			array[i] = data[i];
	}
	buildMaxHeap(array, k);

	for (int i = k; i < size; i++)
	{
		if (data[i] < array[0])
		{
			array[0] = data[i];
			keepHeap(array, 0, k);
		}
	}

	copy(array, array + k, ostream_iterator<int>(cout, " "));
}

void main()
{
	const int k = 5;
	int array[k];
	int data[] = {5, 4, 1, 9, 8, 7, 6, 2, 3};
	const int size = sizeof data / sizeof *data;
	getKMin(data, size, array, k);
}

UT:

1. k的取值问题,如果k为负数、0、正数(比size小,和size一样大,比size大)

2. 数组data的值选取

思路3:利用计数排序的思想来求解

#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

const int maxNumber = 20;

void getKMin(int *data, int size, int *array, int k)
{
	if (data == NULL || size <= 0 || array == NULL || k <= 0)
		return;

	if (k >= size)
	{
		for (int i = 0; i < size; i++)
			array[i] = data[i];
		copy(array, array + size, ostream_iterator<int>(cout, " "));
		return;
	}

	int count[maxNumber];
	for (int i = 0; i < maxNumber; i++)
		count[i] = 0;

	for (int i = 0; i < size; i++)
	{
		count[data[i]]++;
	}

	int index = 0;

	for (int i = 0; i < maxNumber; i++)
	{
		for (int j = 0; j < count[i]; j++)
		{
			array[index] = i;
			index++;
			if (index == k)
				goto here;
		}
	}

here:
	copy(array, array + k, ostream_iterator<int>(cout, " "));
}

void main()
{
	const int k = 5;
	int array[k];
	int data[] = {5, 4, 1, 9, 8, 7, 6, 2, 3};
	const int size = sizeof data / sizeof *data;
	getKMin(data, size, array, 5);
}

面试题31:连续子数组的最大和

题目:输入一个整形数组,数组里有正数也有负数,数组中一个或连续的多个整数组成一个子数组,求所有子数组和的最大值,要求时间复杂度为O(N)

#include <iostream>

using namespace std;

int array[] = {-2, 5, 3, -6, 4, -8, 6};
const int size = sizeof array / sizeof *array;

bool gStatus = false;
int getMaxSum(int *array, int size)
{
	if (array == NULL || size <= 0)
	{
		gStatus = true;
		return -1;
	}

	int maxSum = -65535;
	int tempSum = 0;
	for (int i = 0; i < size; i++)
	{
		tempSum += array[i];
		if (tempSum > maxSum)
			maxSum = tempSum;
		if (tempSum < 0)
			tempSum = 0;
	}

	return maxSum;
}

int getMaxSum2(int *array, int size)
{
	if (array == NULL || size <= 0)
	{
		gStatus = true;
		return -1;
	}

	int maxInclude = array[0];
	int maxExclude = array[0];

	for (int i = 1; i < size; i++)
	{
		maxExclude = max(maxInclude, maxExclude);
		maxInclude = max(array[i] + maxInclude, array[i]);
	}

	return max(maxInclude, maxExclude);
}

void main()
{
	int result = getMaxSum2(array, size);
	cout << "result = " << result << endl;
}

面试题32:从1到n正数中1出现的次数

题目:输入一个正数n,求从1到n这n个整数的十进制表示中1出现的次数,例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1共出现了5次。

#include <iostream>

using namespace std;

int getOneNumber(int number)
{
	int count = 0;

	int currentNumber;
	int preNumber;
	int posNumber;
	int position = 1;

	while (number / position)
	{
		currentNumber = (number / position) % 10;
		preNumber = number / (position * 10);
		posNumber = number % position;

		switch (currentNumber)
		{
		case 0:
			count += preNumber * position;
			break;
		case 1:
			count += preNumber * position + posNumber + 1;
			break;
		default:
			count += (preNumber + 1) * position;
			break;
		}
		position *= 10;
	}

	return count;
}

void main()
{
	int number = getOneNumber(123);
	cout << "number = " << number << endl;
}

话说书上的递归解我就想不出来。。。

#include <iostream>

using namespace std;

const char *input = "123";

int myExp(int base, int exp)
{
	int result = 1;
	for (int i = 0; i < exp; i++)
		result *= base;

	return result;
}

int getOneNumber(const char *input)
{
	if (input == NULL || *input < '0' || *input > '9' || *input == '\0')
		return 0;
	int length = strlen(input);
	int currentNumber = input[0] - '0';

	if (length == 1)
	{
		if (currentNumber == 0)
			return 0;
		else
			return 1;
	}

	int currentCount;
	int otherCount;

	if (currentNumber == 1)
	{
		currentCount = atoi(input + 1) + 1;
	}
	else
	{
		currentCount = myExp(10, length - 1);
	}

	otherCount = currentNumber * (length - 1) * myExp(10, length - 2);

	return currentCount + otherCount + getOneNumber(input + 1);
}

void main()
{
	int result = getOneNumber(input);
	cout << "result = " << result << endl;
}

面试题33:把数组排成最小的数

题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接处的所有数字钟最小的一个。例如输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323

#include <iostream>
#include <iterator>
#include <algorithm>
#include <sstream>
#include <string>

using namespace std;

int compare(const char *lhs, const char *rhs, char *lhsCatRhs, char *rhsCatLhs)
{
	if (lhs == NULL || rhs == NULL)
		return false;

	int lenLhs = strlen(lhs);
	int lenRhs = strlen(rhs);
	
	strncpy(lhsCatRhs, lhs, lenLhs);
	strncpy(lhsCatRhs + lenLhs, rhs, lenRhs);
	lhsCatRhs[lenLhs + lenRhs] = 0;

	strncpy(rhsCatLhs, rhs, lenRhs);
	strncpy(rhsCatLhs + lenRhs, lhs, lenLhs);
	rhsCatLhs[lenLhs + lenRhs] = 0;

	return strcmp(lhsCatRhs, rhsCatLhs);
}

string myItoa(int number)
{
	stringstream ss;
	ss.str("");
	ss << number;
	string str = ss.str();

	return str.c_str();
}

int partition(int *array, int left, int right, char *lhsCatRhs, char *rhsCatLhs)
{
	if (array == NULL)
		return -1;

	int leftIndex = left;
	int& pivot = array[right];
	int rightIndex = right - 1;

	while (leftIndex < right)
	{
		while (leftIndex < right && compare(myItoa(array[leftIndex]).c_str(), myItoa(pivot).c_str(), lhsCatRhs, rhsCatLhs) <= 0)
			leftIndex++;
		while (rightIndex >= 0 && compare(myItoa(array[rightIndex]).c_str(), myItoa(pivot).c_str(), lhsCatRhs, rhsCatLhs) > 0)
			rightIndex--;

		if (leftIndex > rightIndex)
			break;
		swap(array[leftIndex], array[rightIndex]);
	}

	swap(array[leftIndex], pivot);

	return leftIndex;
}

void fastSort(int *array, int start, int end, char *lhsCatRhs, char *rhsCatLhs)
{
	if (array == NULL || start >= end)
		return;

	int pos = partition(array, start, end, lhsCatRhs, rhsCatLhs);
	fastSort(array, start, pos - 1, lhsCatRhs, rhsCatLhs);
	fastSort(array, pos + 1, end, lhsCatRhs, rhsCatLhs);
}

void getMinNumber(int *array, int size, int maxDigits)
{
	if (array == NULL || size <= 0)
		return;

	char *lhsCatRhs = new char[maxDigits + 1];
	char *rhsCatLhs = new char[maxDigits + 1];

	fastSort(array, 0, size - 1, lhsCatRhs, rhsCatLhs);
	copy(array, array + size, ostream_iterator<int>(cout, " "));
	cout << endl;

	delete []lhsCatRhs;
	delete []rhsCatLhs;
}

void main()
{
	const int size = 3;
	int array[size] = {3, 32, 321};
	const int maxDigits = 10;

	getMinNumber(array, size, maxDigits);
}

面试题34:丑数

题目:我们把只包含因子2、3和5的数称作丑数,求按从小到大的顺序的第1500个丑数。

#include <iostream>

using namespace std;

long long int findUglyNumber(int count)
{
	long long int *pUglyNumbers = new long long int[count];
	*pUglyNumbers = 1;
	long long int *pUglyNumbersTwo = pUglyNumbers;
	long long int *pUglyNumbersThree = pUglyNumbers;
	long long int *pUglyNumbersFive = pUglyNumbers;
	int i = 1;
	while (i < count)
	{
		pUglyNumbers[i] = min(min(*pUglyNumbersTwo * 2, *pUglyNumbersThree * 3), *pUglyNumbersFive * 5);
		
		while (*pUglyNumbersTwo * 2 <= pUglyNumbers[i])
			pUglyNumbersTwo++;
		while (*pUglyNumbersThree * 3 <= pUglyNumbers[i])
			pUglyNumbersThree++;
		while (*pUglyNumbersFive * 5 <= pUglyNumbers[i])
			pUglyNumbersFive++;
		++i;
	}

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

void main()
{
	long long int result = findUglyNumber(4);
	cout << "result = " << result << endl;
}

面试题35:第一个只出现一次的字符

题目:在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出b

#include <iostream>

using namespace std;

char findFirstChar(const char *str)
{
	if (str == NULL)
		return '\0';

	char result = '\0';
	const int length = strlen(str);
	const int size = 256;
	int hashBuff[size];
	for (int i = 0; i < size; i++)
		hashBuff[i] = 0;
	
	for (int i = 0; i < length; i++)
	{
		hashBuff[str[i]]++;
	}

	for (int i = 0; i <size; i++)
	{
		if (hashBuff[str[i]] == 1)
		{
			result = str[i];
			break;
		}
	}

	return result;
}

void main()
{
	const char *str = "abaccdeff";
	char result = findFirstChar(str);
	cout << "result = " << result << endl;
}

面试题36:数组中的逆序对

题目:在数组中的两个数字如果前面一个数字大于后面的数字,则两个数字组成一个逆序对,输入一个数组,求出这个数组中的逆序对总数

#include <iostream>
#include <algorithm>
#include <iterator>

using namespace std;

const int size = 4;
int tempArray[size];

int findReversePair(int *array, int leftIndex, int rightIndex)
{
	if (array == NULL)
		return -1;
	
	if (leftIndex == rightIndex)
		return 0;

	int midIndex = (leftIndex + rightIndex) >> 1;
	int count = 0;
	int leftCount = findReversePair(array, leftIndex, midIndex);
	int rightCount = findReversePair(array, midIndex + 1, rightIndex);

	for (int i = leftIndex; i <= midIndex; i++)
		tempArray[i] = array[i];
	for (int i = midIndex + 1; i <= rightIndex; i++)
		tempArray[i] = array[i];

	int i = leftIndex;
	int j = midIndex + 1;
	int k = leftIndex;
	while (i <= midIndex && j <= rightIndex)
	{
		if (tempArray[i] > tempArray[j])
		{
			array[k] = tempArray[j];
			count += midIndex - i + 1;
			j++;
			k++;
		}
		else
		{
			array[k] = tempArray[i];
			i++;
			k++;
		}
	}

	if (i == midIndex + 1)
	{
		for (int m = j; m <= rightIndex; m++)
			array[k++] = tempArray[m];
	}
	else if (j == rightIndex + 1)
	{
		for (int m = i; m <= midIndex; m++)
			array[k++] = tempArray[m];
	}

	return count + leftCount + rightCount;
}

void main()
{
	int array[] = {7, 5, 6, 4};
	int result = findReversePair(array, 0, size - 1);
	cout << "result = " << result << endl;
	copy(array, array + size, ostream_iterator<int>(cout, " "));
}

面试题37:两个链表的第一个公共结点

题目:输入连个链表,找出它们的第一个公共结点。

1 2 3

          6 7

   4 5

#include <iostream>

using namespace std;

struct Node
{
	Node(int i = 0, Node *pLeft = NULL) : data(i), next(pLeft) {}
	int data;
	Node *next;
};

void constructLink(Node *&head1, Node *&head2)
{
	Node *node7 = new Node(7);
	Node *node6 = new Node(6, node7);
	Node *node5 = new Node(5, node6);
	Node *node4 = new Node(4, node5);
	Node *node3 = new Node(3, node6);
	Node *node2 = new Node(2, node3);
	Node *node1 = new Node(1,node2);

	head1 = node1;
	head2 = node4;
}

Node *findFirstCommonNode(Node *head1, Node *head2)
{
	if (head1 == NULL || head2 == NULL)
		return NULL;

	int head1Len = 0;
	int head2Len = 0;
	Node *pHead1 = head1;
	Node *pHead2 = head2;

	while (pHead1 != NULL)
	{
		head1Len++;
		pHead1 = pHead1->next;
	}
	while (pHead2 != NULL)
	{
		head2Len++;
		pHead2 = pHead2->next;
	}

	pHead1 = head1;
	pHead2 = head2;

	if (head1Len > head2Len)
	{
		int dist = head1Len - head2Len;
		while (dist)
		{
			pHead1 = pHead1->next;
			dist--;
		}
	}
	if (head1Len < head2Len)
	{
		int dist = head2Len - head1Len;
		while (dist)
		{
			pHead2 = pHead2->next;
			dist--;
		}
	}

	while (pHead1 != NULL && pHead2 != NULL && pHead1 != pHead2)
	{
		pHead1 = pHead1->next;
		pHead2 = pHead2->next;
	}

	return pHead1;
}

void main()
{
	Node *head1;
	Node *head2;
	constructLink(head1, head2);
	Node *commonNode = findFirstCommonNode(head1, head2);
	cout << "common node: " << commonNode->data << endl;
}

面试题38:数字在排序数组中出现的次数

题目:统计一个数字在排序数组中出现的次数,例如输入排序数组{1, 2, 3, 3, 3, 3, 4, 5}和数字3,由于3在这个数组中出现4次,所有输出4

#include <iostream>

using namespace std;
int array[] = {3, 3, 3, 3, 3, 3, 3, 5};
const int size = sizeof array /sizeof *array;

int binarySearchLeftIndex(int *array, int size, int value)
{
	if (array == NULL || size <= 0)
		return -1;

	int leftIndex = 0;
	int rightIndex = size - 1;

	while (leftIndex != rightIndex)
	{
		int midIndex = (leftIndex + rightIndex) >> 1;
		if (array[midIndex] < value)
			leftIndex = midIndex + 1;
		else
			rightIndex = midIndex;
	}

	if (array[leftIndex] == value)
		return leftIndex;
	else
		return -1;
}

int binarySearchRightIndex(int *array, int size, int value)
{
	if (array == NULL || size <= 0)
		return -1;

	int leftIndex = 0;
	int rightIndex = size - 1;

	while (leftIndex != rightIndex)
	{
		int midIndex = (leftIndex + rightIndex + 1) >> 1;
		if (array[midIndex] > value)
			rightIndex = midIndex - 1;
		else
			leftIndex = midIndex;
	}

	if (array[leftIndex] == value)
		return leftIndex;
	else
		return -1;
}

void main()
{
	int indexLeft = binarySearchLeftIndex(array, size, 3);
	int indexRight = binarySearchRightIndex(array, size, 3);
	int count;
	if (indexLeft > -1 && indexRight > -1)
		count = indexRight - indexLeft + 1;
	else
		count = 0;

	cout << "count = " << count << endl;
}

 面试题39:二叉树的深度    

题目一:输入一棵二叉树的根节点,求该树的深度。从根节点到叶结点依次经历过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为数的深度。

题目二:输入一棵二叉树的根节点,判断该树是不是平衡二叉树,如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

                1

       2            3

 4        5              6

        7

#include <iostream>

using namespace std;

struct Node
{
Node (int i = 0, Node *pLeft = NULL, Node *pRight = NULL) : data(i), left(pLeft), right(pRight) {}
int data;
Node *left;
Node *right;
};

int getBinaryTreeDepth(Node *root)
{
if (root == NULL)
return 0;

int leftDepth = getBinaryTreeDepth(root->left);
int rightDepth = getBinaryTreeDepth(root->right);

return max(leftDepth, rightDepth) + 1;
}

Node *construct()
{
Node *node7 = new Node(7);
Node *node6 = new Node(6);
Node *node5 = new Node(5, node7);
Node *node4 = new Node(4);
Node *node3 = new Node(3, NULL, node6);
Node *node2 = new Node(2, node4, node5);
Node *node1 = new Node(1, node2, node3);

return node1;
}

void main()
{
Node *root = construct();
int depth =

抱歉!评论已关闭.