剑指Offer算法精炼
Posted WQP_Ya_Ping
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer算法精炼相关的知识,希望对你有一定的参考价值。
//FileName :: Algorithm.cpp(剑指Offer)
//Author :: Weiqp
//Date :: 2016-6-14
/*1. 输出链表倒数第K个节点
思想:使用两个指针p1,p2,起初同时指向链表头节点,先让p1向前走K-1步,然后两个指针同时向后移动,
当p1指向链表末尾,即p1->next为空时,p2此时正好指向倒数第K个节点
*/
# if 0
# include <iostream>
using namespace std;
//链表节点定义
typedef struct ListNode
int value;
ListNode *next;
;
//查找倒数第K个节点
ListNode* FindKthToTail(ListNode *head, unsigned int k)
//安全性检查
if(head == NULL || k == 0)
return NULL;
ListNode *p1 = head;
ListNode *p2 = NULL;
for(unsigned int i = 0; i < k-1; i++)
//检查K是否大于链表的实际长度
if(p1 ->next != NULL)
p1 = p1 ->next ;
else
return NULL;
ListNode *p2 = head;
while(p1 ->next != NULL)
p1 = p1 ->next ;
p2 = p2 ->next ;
return p2;
# endif
/*2. 链表反转
思想:三个指针,分别指向当前节点、前一个和后一个节点。
*/
# if 0
# include <iostream>
using namespace std;
//链表节点定义
typedef struct ListNode
int value;
ListNode *next;
;
//反转
ListNode* ReverseList(ListNode *head)
ListNode* pReverseHead = NULL;
ListNode* pNode = head;
ListNode* pPrev = NULL;
while(pNode != NULL)
ListNode* pNext = pNode ->next ;
if(pNext == NULL)
pReverseHead = pNode;
else
pNode ->next = pPrev;
//往后依次反转
pPrev = pNode;
pNode = pNode ->next ;
return pReverseHead;
# endif
/*3. 合并两个有序链表
思想:先比较两个链表的第一个节点的值value1和value2,如果value1小,则它作为合并后链表的头节点,
接着比较value1节点的next->value和value2,,小的作为合并头节点的next,依次进行。否则反之。
*/
# if 0
# include <iostream>
using namespace std;
//链表节点定义
typedef struct ListNode
int value;
ListNode *next;
;
//合并
ListNode * MergeList(ListNode *head1, ListNode *head2)
if(head1 == NULL && head2 == NULL)
return NULL;
else if(head1 != NULL)
return head1;
else
return head2;
ListNode* pMergeHead = NULL;
if(head1 ->value >= head2 ->value )
pMergeHead = head2;
pMergeHead ->next = MergeList(head1, head2 ->next);
else
pMergeHead = head1;
pMergeHead ->next = MergeList(head1 ->next , head2);
return pMergeHead;
# endif
/*4.判断B树是不是A树的子结构*/
# if 0
# include <iostream>
using namespace std;
//二叉树节点定义
typedef struct BinaryTree
int value;
BinaryTree* left;
BinaryTree* right;
;
//是否有B结构的树
bool IsTree1HaveTree2(BinaryTree* root1, BinaryTree* root2)
if(root2 == NULL)
return true;
if(root1 == NULL)
return false;
//以root1为根节点的树无子结构Tree2
if(root1 ->value != root2 ->value )
return false;
return IsTree1HaveTree2(root1 ->left , root2 ->left ) &&
IsTree1HaveTree2(root1 ->right , root2 ->right );
bool HasSubTree(BinaryTree* root1, BinaryTree* root2)
bool result = false;
if(root1 != NULL && root2 != NULL)
if(root1 ->value == root2 ->value )
result = IsTree1HaveTree2(root1, root2);
if(!result)
result = HasSubTree(root1 ->left ,root2);
if(!result)
result = HasSubTree(root1 ->right ,root2);
return result;
# endif
/*5.求一个树的镜像
思想::交换子节点
*/
# if 0
# include <iostream>
using namespace std;
//二叉树节点定义
typedef struct BinaryTree
int value;
BinaryTree* left;
BinaryTree* right;
;
void MirrorRecursively(BinaryTree* p)
if((p == NULL) ||(p ->left == NULL && p ->right == NULL))
return ;
BinaryTree* temp = p->left ;
p ->left = p ->right ;
p ->right = temp;
if(p ->left)
MirrorRecursively(p ->left );
if(p ->right )
MirrorRecursively(p ->right );
# endif
/*6.顺时针打印方阵
思想:从外圈向内圈一圈一圈的打印,每一圈的打印步骤为:从左到右打印一行,从上往下打印一列,
从右往左打印一行,从下往上打印一列(注意避免重复打印)。假设最后一圈左上角坐标为(startX, startY),
则终止条件是::列数columns > startX * 2; 行数rows > startY * 2;
*/
# if 0
# include <iostream>
using namespace std;
//一圈的打印过程
void PrintMatrixInCircle(int **numbers, int columns, int rows, int start);
//循环打印矩阵
void PrintMatrixClockWisely(int **numbers, int columns, int rows)
if(NULL == numbers || 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];
cout<<number<<" ";
//从上到下
if(start < endY)
for(int i = start + 1; i < endY; i++)
int number = numbers[i][endX];
cout<<number<<" ";
//从右到左
if(start < endX && start < endY)
for(int i = endX - 1; i >= start; i--)
int number = numbers[endY][i];
cout<<number<<" ";
//从下到上
if(start < endX && start < endY - 1)
for(int i = endY - 1; i >= start + 1; i--)
int number = numbers[i][start];
cout<<number<<" ";
# endif
/*7.打印蛇形矩阵*/
# if 0
#include<stdio.h>
int row,col;
int matrix[100][100]=0;
void UpFillNum(int);
void DownFillNum(int);
int main()
int n;
int i,j;
printf("请输入矩阵的阶数:(0<n<=100)");
scanf("%d",&n);
matrix[0][0]=1;
matrix[1][0]=2;
row=1;
col=0;
UpFillNum(n-1);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
printf("%d ",matrix[i][j]);
printf("\\n");
return 0;
//从上向下填充
void DownFillNum(int n)
for(;col>0 && row<n;row++,col--)
matrix[row+1][col-1]=matrix[row][col]+1;
if(row<n)
row++;
matrix[row][col]=matrix[row-1][col]+1;
else if(row==n)
col++;
matrix[row][col]=matrix[row][col-1]+1;
if(matrix[n][n]!=((n+1)*(n+1)))
UpFillNum(n);
//从下向上填充
void UpFillNum(int n)
for(;row>0 && col<n;col++,row--)
matrix[row-1][col+1]=matrix[row][col]+1;
if(col<n)
col++;
matrix[row][col]=matrix[row][col-1]+1;
else if(col==n)
row++;
matrix[row][col]=matrix[row-1][col]+1;
if(matrix[n][n]!=((n+1)*(n+1)))
DownFillNum(n);
# endif
/*8.包含最小值函数min()的栈
数据栈::m_data
辅助栈::m_min,用于保存最小值
*/
# if 0
# include <iostream>
using namespace std;
# include <stack>
//push()
template <typename T> void StackWithMin<T>:: push(const T &value)
m_data.push(value);
if(m_min.size() == 0 || value < m_min.top())
m_min.push(value);
else
m_min.push(m_min.top());
//pop
template <typename T> void StackWithMin<T>:: pop()
assert(m_data.size > 0 && m_min.size > 0);
m_data.pop();
m_min.pop();
//min()
template <typename T> void StackWithMin<T>:: min() const
assert(m_data.size > 0 && m_min.size > 0);
return m_min.top();
# endif
/*9.判断一个序列是不是栈的弹出序列*/
/*
思想::建立一个辅助栈。
比如压栈序列为1,2,3,4,5,,判断序列4,3,5,1,2是不是出栈序列
1.第一个弹出的数是4,,所以依次将1,2,3,4压入辅助栈,此时4位于栈顶可弹出。
2.下一个弹出3,此时辅助栈3位于栈顶,可弹出。
3.下来弹出的是5, 把5压入辅助栈,,位于栈顶,可弹出。
4.此时要求弹出1,因为此时辅助栈剩下1,2,且2位于栈顶。所以无法直接弹出1.
5.所以4,3,5,1,2不是一个弹出序列。
*/
/*10.从上往下打印二叉树*/
# if 0
//二叉树结点定义
/*思想::每次打印一个节点时,将他的子节点放入队列的尾部,从队列头开始打印节点,打印完为止*/
struct BinaryTreeNode
int m_value;
BinaryTreeNode *m_Left;
BinaryTreeNode *m_Right;
;
//打印
void PrintFromTopToBottom(BinaryTreeNode * pTreeRoot)
if(!pTreeRoot)
return ;
std::deque<BinaryTreeNode *> dequeTreeNode;
dequeTreeNode.push_back(pTreeRoot);
while(dequeTreeNode.size())
BinaryTreeNode *pNode = dequeTreeNode.front();
dequeTreeNode.pop_front();
printf("%d ", pNode->m_value );
if(pNode ->m_Left )
dequeTreeNode.push_back(pNode ->m_Left);
if(pNode ->m_Right )
dequeTreeNode.push_back(pNode ->m_Right );
# endif
以上是关于剑指Offer算法精炼的主要内容,如果未能解决你的问题,请参考以下文章