面试题21包括min函数的栈 

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

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

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

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

面试题26复杂链表的复制 

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

面试题28字符串的排列 

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

面试题30最小的K个数

/****************************************************/

面试题21 包括min函数的栈 :定义栈的数据结构,请在该类型中实现一个可以得到栈的最小元素的min函数。在该栈中。调用min、push及pop的时间复杂度都是O(1)

思       路:申请一个与原来栈stack大小同样的栈tmpStack。用来保存当前栈中最小元素。stack压入一个元素,tmpStack也压入一个元素,该元素与tmpStack.top比較,大则压入top 否则压入该元素。

出栈同一时候出栈。

实现例如以下:

template <typename> T;
class Stack
{
public:
Stack();
~Stack();
void pop();
void push(T &value);
T min();
private:
stack<T> m_stack;
stack<T> m_min;
};
void pop()
{
if (m_min.size() <= 0 || m_stack.size() <= 0)
{
return;
}
m_stack.pop();
m_min.pop();
}
void push(T &value)
{ if ( m_min.size() == 0 || value < m_min.top())
{
m_min.push(value); }
else
{
m_min.push(m_min.top());
} m_stack.push(value); }
T min()
{
if (m_min.size() > 0)
{
return m_min.top();
}
}

面试题22 栈的压入、弹出序列 :输入两个序列。第一个是栈的压入顺序,请推断第二个1、2、3、4、5、6则4、5、3、2、1是出栈顺序。而4、3、5、1、2就不可能是该压栈序列。

思路:

实现例如以下:

bool IsPopOrder(const int *pPush, const int *pPop, int length)
{
const int *pPushNext = pPush;
const int *pPopNext = pPop;
bool result = false; if (pPush == NULL || pPop == NULL || length <= 0)
{
return false;
} stack<const int> iStack; while(pPopNext - pPop < length)/* 弹出序列还没有到头*/
{
while(iStack.top() != *pPopNext)
{
if (pPushNext - pPush == length)
{
break;
} iStack.push(*pPushNext);
pPushNext++;
} if (iStack.top() != *pPopNext)
{
break;
} iStack.pop();
pPopNext++;
} if (iStack.empty() && pPopNext - pPop == length)
{
return true;
} return false;
}

面试题23 从上往下打印二叉树 。二叉树的层序遍历

实现例如以下:

struct BinaryTreeNode
{
int data;
BinaryTreeNode *lchild;
BinaryTreeNode *rchild;
};
void LevelOrder(BinaryTreeNode *root)
{
BinaryTreeNode *pNode;
if (root == NULL)
{
return;
}
queue<BinaryTreeNode> iQueue;
iQueue.push(root);
while(!iQueue.empty())
{
pNode = iQueue.front();
if (pNode->lchild != NULL)
{
iQueue.push(pNode->lchild);
}
if (pNode->rchild != NULL)
{
iQueue.push(pNode->rchild);
} printf("%d",pNode->data);
iQueue.pop();
}
}

面试题24 二叉搜索树的后序遍历序列 ,给出一个数组,推断是否是二叉搜索树的后序遍历序列

思路:最后一个结点的值大于左子树的随意值。小于右子树的随意值

实现例如以下:

int  IsSerchTree(int *squeue, int length)
{
int i,j; if (squeue == NULL || length <= NULL)
{
return false;
} for (i = 0; i < length; i++)
{
if (squeue[i] > squeue[length-1])
{
break;
}
} for (j = i, j <length; j++)
{
if (squeue[j] < squeue[length -1])
{
return false;
}
} if ((true == IsSerchTree(squeue, i)
&& (true == IsSerchTree(squeue + i,length - i - 1))) {
return true;
} }

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

注意:vector 与 stack和queue的差别

vector能够从头部删除节点,也能够从尾部遍历整个结构

实现例如以下:

struct BinaryTreeNode
{
int data;
BinaryTreeNode *lchild;
BinaryTreeNode *rchild;
};
void SumPathTree(BinaryTreeNode *root, int expectSum, vector<int> &iPath, int currentSum)
{
if (root == NULL)
{
return;
} /* 採用前序遍历的方式,先处理根节点 */
currentSum += root->data;
iPatch.push_back(root->data); if ((currentSum == expectSum)
&& (root->lchild == NULL && root->rchild == NULL)
{
for (iterator iter = iPath.begin(); iter < iPath.end(); iter++)
{
printf("%d", *iter);
}
printf("\n");
} if (root->lchild != NULL)
{
SumPathTree(root->lchild,expectSum,iPath,currentSum);
} if (root->rchild != NULL)
{
SumPathTree(root->rchild,expectSum,iPath,currentSum);
} /* 假设以上路径都没有期望的值。则回溯到调用之前的结点 递归结束之后,一定回到根结点 */
iPath.pop_back();
currentSum-=root->data; }

面试题26 复杂链表的复制

struct ComplexListNode

{

int data;

ComplexListNode *next;

ComplexListNode *sibling;/* 指向不论什么一个结点 */

};

第一步:每一个节点后面赋值一个同样的结点

第二步:遍历偶数结点。将新结点中sibling指针指向该指的结点

第三步:将链表按奇数偶数。拆分成两个链表。

面试题27 二叉搜索树与双向链表 ,输入一个二叉搜索树,将一个二叉搜索树变成一个排序的双向链表

思路:採用中序遍历二叉树的方式,每次递归记录下来上次遍历到的结点,作为指针传入下次递归

实现例如以下:

struct BinaryTreeNode
{
int data;
BinaryTreeNode *lchild;
BinaryTreeNode *rchild;
};
void ConvertTree(BinaryTreeNode *root, BinaryTreeNode **lastNode)
{
if (root == NULL)
{
return;
} ConvertTree(root->lchild,lastNode); root->lchild = lastNode;
if (*lastNode != NULL)
{
(*lastNode)->rchild = root;
}
(*lastNode) = root; ConvertTree(root->rchild,lastNode);
} BinaryTreeNode *GetHeadNode(BinaryTreeNode *root)
{
BinaryTreeNode *head;
if (root == NULL)
{
return NULL;
} head = root;
while (head->lchild)
{
head = head->lchild;
}
return head;
}

面试题28 字符串的排列

比如:比如输入abc 输出abc的六种排列组合 abc  bac ……

实现例如以下:

#include <iostream>

void printOrderStr(char *str, int length, int index)
{ char temp; if (str == NULL || length == 0)
{
return;
} if (index == length)
{
for (int i = 0; i<length; i++)
printf("%c",str[i]);
printf("\n");
} for (int i = index; i < length; i++)
{
temp = str[index];
str[index] = str[i];
str[i] = temp; printOrderStr(str, length, index+1); temp = str[index];
str[index] = str[i];
str[i] = temp; }
}
int main()
{
char str[] = {'a', 'b', 'c'}; printOrderStr(str, 3, 0); }

扩展题,输入一个字符串输出字符串的各种组合,比如:输入abc 输出a、b、c、ab……abc

实现例如以下:

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
#include<assert.h> void Combination_m(char *string ,int number , vector<char> &result)
{
assert(string != NULL);
if(number == 0)
{
static int num = 1;
printf("第%d个组合\t",num++); vector<char>::iterator iter = result.begin();
for( ; iter != result.end() ; ++iter)
printf("%c",*iter);
printf("\n");
return ;
}
if(*string == '\0')
return ; result.push_back(*string);
Combination_m(string + 1 , number - 1 , result);
result.pop_back();
Combination_m(string + 1 , number , result);
} void Combination(char *string)
{
assert(string != NULL); int i , length = strlen(string);
for(i = 1 ; i <= 3 ; ++i)
{
vector<char> result;
Combination_m(string , i ,result);
}
} int main(void)
{
char str[] = "abc";
Combination(str);
getchar();
return 0;
}

面试题29 数组中出现次数超过一半的数字 。给定一个数组,当中有一个数组其个数超过一半。求该数

思路:

最简单的就是排序,求中位数。

採用一个数记录反复个数,一个数记录结果,详细实现例如以下:

int FindMoreThanHalf(int num[], int length)
{
int times = 0;
int result;
if (num == NULL || length <=0 )
{
return 0;/* 非法输入*/
} result = num[0];
times++;
for (int i = 1; i < length; i++)
{ if (num[i] == result)
{
times++;
} if (times == 0)
{
result = num[i];
} if (num[i] != result && times > 0 )
{
times--;
}
} return times;
}

面试题30 最小的K个数

#include <stdlib.h>
#include <stdio.h>
/* 求最小的K个数 */ int partition(int *psArray, int num, int startIndex, int endIndex)
{
int iTemp;
int i = startIndex;
int j = endIndex; if (psArray == NULL || num <= 0 || startIndex > endIndex || startIndex < 0 || endIndex < 0)
{
return 0;
} iTemp = psArray[0]; while (i < j)
{
while ((i < j) && (psArray[i] <= psArray[j]))
j--; if (i < j)
{
iTemp = psArray[i];
psArray[i] = psArray[j];
psArray[j] = iTemp;
} while((i < j) && (psArray[i] <= psArray[j]))
i++; if (i < j)
{
iTemp = psArray[i];
psArray[i] = psArray[j];
psArray[j] = iTemp;
}
}
return i;
}
void FindMinKNum(int *psArray, int num, int k)
{
int i;
int j;
if (k > num)
{
return;
} i = partition(psArray,num,0,num-1);
while (i != k-1)
{
if (i < k-1)
{
i = partition(psArray,num,i+1,num-1);
}
else
{
i = partition(psArray,num,0,i-1);
}
}
for (j = 0; j <= i; j++)
{
printf(" %d", psArray[j]);
}
printf("\n"); }
int main()
{
int a[]={3,4,5,1,2};
FindMinKNum(a, 5, 2); }

能够用O(n*logk)的时间复杂度加上O(k)的空间复杂度来实现。

void GetLeastNumbers(int *psArray, int length, int k)
{
if (psArray == NULL || length < 0 || k < 0 || length < k)
{
return;
} multiset<int, greater<int> > iMultiset;
multiset<int, greater<int> >::iterator iSetIterator; for (int i = 0; i < length; i++)
{
if (i < k)
{
iMultiset.insert(psArray[i]);
}
else
{
if (psArray[i] < *(iMultiset.begin()))
{
iMultiset.erase(iMultiset.begin());
iMultiset.insert(psArray[i]);
}
}
}
for (iSetIterator = iMultiset.begin(); iSetIterator != iMultiset.end(); iSetIterator++ )
{
printf(" %d", *iSetIterator);
}
printf("\n");
}

【剑指Offer】俯视50题之21 - 30题的更多相关文章

  1. 【好书推荐】《剑指Offer》之硬技能(编程题12~16)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword <[好书推荐]& ...

  2. 【好书推荐】《剑指Offer》之硬技能(编程题7~11)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword <[好书推荐]& ...

  3. 【好书推荐】《剑指Offer》之硬技能(编程题1~6)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword 前一篇<[好书推 ...

  4. 剑指offer(第2版)刷题 Python版汇总

    剑指offer面试题内容 第2章 面试需要的基础知识 面试题1:赋值运算符函数 面试题2:实现Singleton模式  解答 面试题3:数组中重复的数字 解答 面试题4:二维数组中的查找 解答 面试题 ...

  5. 《剑指Offer》第二章(一)题3-8

    为春招实习做准备,记录一下<剑指Offer>里面的面试题 第二章 面试题3:数组之中的重复数字. 这个题吧,虽然不难,但是不知道为什么就是看了很久,可能很久没有做算法题了.最后面一句话说的 ...

  6. 【剑指Offer】50、数组中重复的数字

      题目描述:   在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果 ...

  7. 剑指 Offer 61. 扑克牌中的顺子 + 简单题 + 思维

    剑指 Offer 61. 扑克牌中的顺子 Offer_61 题目描述 java代码 package com.walegarrett.offer; /** * @Author WaleGarrett * ...

  8. 剑指 Offer 58 - II. 左旋转字符串 + 简单题

    剑指 Offer 58 - II. 左旋转字符串 Offer_58_2 题目描述 java代码 package com.walegarrett.offer; /** * @Author WaleGar ...

  9. 剑指offer(50)数组中重复的数字

    题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为 ...

随机推荐

  1. Linux-fuser

    Linux-fuser 1. 描述 2. 选项3. EXAMPLES4. RESTRICTIONS 限制5. SIGNAL 可用信号 fuser - 使用文件或套接字识别进程 1. 描述 fuser使 ...

  2. Python打包成exe,pyc

    D:\mypython\path\ C:\Python27\Scripts\pyinstaller.exe -w mypython.py # Python打包成exe D:\mypython\path ...

  3. p1036 选数(不详细勿看,递归)

    题目:传送门 这题,不会做,而且看了好久才看懂题解的,然后在题解的基础上补了一个 if(start>end) return 0 感觉这样对于我更直观 转载自:大神博客的传送门,点击进入 先声明, ...

  4. luogu P1364 医院设置

    题目描述 设有一棵二叉树,如图: 其中,圈中的数字表示结点中居民的人口.圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为1.如上 ...

  5. [JOYOI] 1071 LCIS

    拖了好久的LCIS f[i][j]表示a串前i个,b串以b[j]结尾的LCIS长度. 转移时考虑a[i]和b[j]是否相等,如果不等: 那么既然是以j结尾,说明a串前i-1位有一个字符和b匹配了,所以 ...

  6. Linux基础学习-命令行与图形界面切换

    命令行模式和图形界面模式切换 打开文件 vim /etc/inittab # systemd uses 'targets' instead of runlevels. By default, ther ...

  7. python基础知识05-控制流程

    控制流程 1.条件判断 python中的代码从上到下执行. if 条件: 缩进 语句1 elif 条件2: 缩进 语句2 (…或者写pass关键字.不写任何代码的时候,防止报错.) ... else: ...

  8. Django框架基础知识12-中间件及上下文处理器

    Django中间件(Middleware) 是一个轻量级.底层的“插件”系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出. django 中的中间件(middleware) ...

  9. 剑指Offer(书):剪绳子

    题目:给你一根长度为n的绳子,请把绳子剪成m段,每段绳子的长度记为k[0],k[1]....,k[m].请问k[0]xk[1]x...,k[m]可能的最大乘积是多少.例如:长度为8剪成2 3 3 得到 ...

  10. HDU 1166 排兵布阵(线段树单点更新)

    题意: 给定n个兵营的士兵初始值, 然后有最多40000个操作: 操作一共有两种, 一个是查询给定[a,b]区间兵营的士兵总和. 另一个是增加/减少指定兵营的士兵数目. 输出每次查询的值. 分析: 线 ...