剑指offer系列,个人读书记录,希望能帮助你理解。
变秃才能变强
具体的实现思路,在我的代码注释中全都有,如果还不理解可以多刷几遍。
谜底就在迷面上,就问你刺不刺激——岳云鹏
从尾到头打印链表
从尾到头打印链表github地地址
//
// Created by android on 19-8-9.
//
/* 输入一个链表,从尾到头打印链表每个节点的值
* 实现
* 思路:从前向后记录‘ ’数目,从后向前替换‘ ’。 重点:从后向前替换的时候的技巧 例如:“we are lucky”
* (1) 从头到尾输出比较简单,一种想法是反转结点的指针。但是会破坏原链表的结构,不推荐;
* (2) 从头遍历链表,先访问的后输出,后访问的先输出,“后进先出”,利用栈来实现;
* (3) 递归本质上就是一个栈的结构,可以利用递归来实现。
* 但是当链表比较长的时候,递归会导致函数调用的层级很深,有可能会导致函数调用栈的溢出,故还是推荐使用栈来实现。
* */
#include
#include
#include
#include
#include
using namespace std;
typedef int ElementType;
typedef struct ListNode {
ElementType Element; // 数据域,存放数据
ListNode *Next; // 指向下一个链表节点
};
ListNode *createListNode(int value) {
ListNode *pNode = new ListNode();
pNode->Element = value;
pNode->Next = nullptr;
return pNode;
}
void connectListNodes(ListNode *pCurrent, ListNode *pNext) {
if (pCurrent == nullptr) {
printf("Error to connect two nodes.\n");
exit(1);
}
pCurrent->Next = pNext;
}
class Solution {
public:
//using stack
void printListReversingly(ListNode *pHead) {
stack nodes;
ListNode *pNode = pHead;
while (pNode != nullptr) {
nodes.push(pNode);
pNode = pNode->Next;
}
while (!nodes.empty()) {
pNode = nodes.top();
printf("%d\t", pNode->Element);
nodes.pop();
}
}
void printListRever_Recursively(ListNode *pHead) {
if (pHead != nullptr) {
if (pHead->Next != nullptr) {
printListRever_Recursively(pHead->Next);
}
printf("%d\t", pHead->Element);
}
}
};
TEST(print, a1) {
ListNode *pNode1 = createListNode(1);
ListNode *pNode2 = createListNode(2);
ListNode *pNode3 = createListNode(3);
ListNode *pNode4 = createListNode(4);
ListNode *pNode5 = createListNode(5);
connectListNodes(pNode1, pNode2);
connectListNodes(pNode2, pNode3);
connectListNodes(pNode3, pNode4);
connectListNodes(pNode4, pNode5);
(new Solution)->printListReversingly(pNode1);
(new Solution)->printListRever_Recursively(pNode1);
}
重建二叉树
重建二叉树
//
// Created by android on 2019/8/11.
//
/*
前序遍历:
1.访问根节点
2.前序遍历左子树
3.前序遍历右子树
中序遍历:
1.中序遍历左子树
2.访问根节点
3.中序遍历右子树
后序遍历:
1.后序遍历左子树
2.后序遍历右子树
3.访问根节点
*题目:
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
* 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
*思路分析
* 根据二叉树前序遍历的特点(根-左-右),每次读取的第一个值一定是根节点,这样我们可以在中序遍历的序列中找到当前的根节点的位置。
* 根据中序遍历的特点(左-根-右),当确定了一个根节点后,其左边序列就是这个根节点的左子树,右边序列就是其右子树。
* 我们每次都需要在前序遍历中找根节点并创建一个根节点,然后在中序遍历中确定根节点位置,并确定当前根节点的左右子树,
* 然后以同样的方法去构建左右子树。
* 这整个过程其实是一个递归的过程。
*/
#include
#include
using namespace std;
typedef int ElementType;
typedef struct BinaryTreeNode {
ElementType elementType;
BinaryTreeNode *pLeftBinaryTreeNode;
BinaryTreeNode *pRightBinaryTreeNode;
};
BinaryTreeNode *CreateBinaryTreeNode(int value) {
BinaryTreeNode *pNode = new BinaryTreeNode();
pNode->elementType = value;
pNode->pRightBinaryTreeNode = pNode->pLeftBinaryTreeNode = nullptr;
return pNode;
}
void ConnectTreeNodes(BinaryTreeNode *pParent, BinaryTreeNode *pLeft, BinaryTreeNode *pRight) {
if (pParent != nullptr) {
pParent->pLeftBinaryTreeNode = pLeft;
pParent->pRightBinaryTreeNode = pRight;
}
}
BinaryTreeNode *constructCore(int *startPreOrder, int *endPreOrder, int *startInOrder, int *endInOrder) {
//前序遍历第一个书为root
int rootValue = startPreOrder[0];
BinaryTreeNode *root = new BinaryTreeNode();
root->elementType = rootValue;
root->pLeftBinaryTreeNode = root->pRightBinaryTreeNode = nullptr;
if (startPreOrder == endPreOrder) {
if (startInOrder == endInOrder && *startPreOrder == *startInOrder)
return root;
else
throw exception();
}
// 在中序遍历中找到根结点的值
int *rootInOrder = startInOrder;
while (rootInOrder <= endInOrder && *rootInOrder != rootValue)
++rootInOrder;
if (rootInOrder == endInOrder && *rootInOrder != rootValue)
throw exception();
int leftLength = rootInOrder - startInOrder;
int *leftPreOrderEnd = startPreOrder + leftLength;
if (leftLength > 0) {
// 构建左子树
root->pLeftBinaryTreeNode = constructCore(startPreOrder + 1, leftPreOrderEnd,
startInOrder, rootInOrder - 1);
}
if (leftLength < endPreOrder - startPreOrder) {
// 构建右子树
root->pRightBinaryTreeNode = constructCore(leftPreOrderEnd + 1, endPreOrder,
rootInOrder + 1, endInOrder);
}
return root;
};
BinaryTreeNode *construct(int *preOrder, int *inOrder, int length) {
if (preOrder == nullptr || inOrder == nullptr || length <= 0)
return nullptr;
return constructCore(preOrder, preOrder + length - 1,
inOrder, inOrder + length - 1);
}
class Solution {
public:
BinaryTreeNode *reConstructBinaryTree(int *preOrder, int *inOrder, int length) {
return construct(preOrder, inOrder, length);
}
};
TEST(construct, test) {
const int LENGTH = 8;
int preOrder[LENGTH] = {1, 2, 4, 7, 3, 5, 6, 8};
int inOrder[LENGTH] = {4, 7, 2, 1, 5, 3, 8, 6};
BinaryTreeNode *root = (new Solution)->reConstructBinaryTree(preOrder, inOrder, LENGTH);
EXPECT_EQ(1, root->elementType);
}