转自点击打开链接
题目:
1.把二元查找树转变成排序的双向链表,要求输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
题目来自:http://topic.csdn.net/u/20101023/20/5652ccd7-d510-4c10-9671-307a56006e6d.html
思路:
一看到这样的问题首先想到的是二叉树的遍历问题,具体是前序,中序,后序遍历主要是看问题如何描述,而这里刚好可以用中序遍历,在遍历的过程中不断的调整Left,Right指针,使之满足要求.
下面给出算法的实现:
- /*
- ---------------------------------------------
- 原作者tree_star
- 2010年 10月18日下午 July
- Modified by yuucyf 2011.04.21
- ---------------------------------------------
- 1.把二元查找树转变成排序的双向链表
- 题目:
- 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
- 要求不能创建任何新的结点,只调整指针的指向。
- 10
- / /
- 6 14
- / / / /
- 4 8 12 16
- / /
- 7 9
- 转换成双向链表
- 4=6=7=8=9=10=12=14=16。
- */
- #include "stdafx.h"
- #include <assert.h>
- #include <iostream>
- using namespace std;
- typedef struct tagTreeNode
- {
- int nValue;
- tagTreeNode *psLeftNode;
- tagTreeNode *psRightNode;
- tagTreeNode()
- {
- nValue = 0;
- psLeftNode = psRightNode = NULL;
- }
- }S_BSTreeNode;
- typedef S_BSTreeNode S_DoubleListNode;
- S_DoubleListNode * g_psListIndex = NULL;
- //创建二叉查找树.
- void AddBSTreeNode(S_BSTreeNode * &psCurNode, int nValue)
- {
- if (NULL == psCurNode)
- {
- S_BSTreeNode *psNode = new S_BSTreeNode;
- assert(NULL != psNode);
- psNode->nValue = nValue;
- psNode->psLeftNode = NULL;
- psNode->psRightNode = NULL;
- psCurNode = psNode;
- }
- else
- {
- if (psCurNode->nValue > nValue)
- {
- AddBSTreeNode(psCurNode->psLeftNode, nValue);
- }
- else if (psCurNode->nValue < nValue)
- {
- AddBSTreeNode(psCurNode->psRightNode, nValue);
- }
- else
- {
- cout << "不允许插入重复值" << endl;
- }
- }
- }
- //把二叉查找树转换为Double List.
- void ConvertBSTree2DoubleList(S_BSTreeNode *psCurNode)
- {
- if (NULL == psCurNode) return;
- psCurNode->psLeftNode = g_psListIndex;
- if (NULL != g_psListIndex)
- g_psListIndex->psRightNode = psCurNode;
- g_psListIndex = psCurNode;
- cout << psCurNode->nValue << endl;
- }
- //以中序遍历二叉查找树.
- void ErgodicBSTree(S_BSTreeNode *psCurNode)
- {
- if (NULL == psCurNode) return;
- if (psCurNode->psLeftNode)
- ErgodicBSTree(psCurNode->psLeftNode);
- ConvertBSTree2DoubleList(psCurNode);
- if (psCurNode->psRightNode)
- ErgodicBSTree(psCurNode->psRightNode);
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- S_BSTreeNode *psRoot = NULL;
- AddBSTreeNode(psRoot, 10);
- AddBSTreeNode(psRoot, 4);
- AddBSTreeNode(psRoot, 6);
- AddBSTreeNode(psRoot, 8);
- AddBSTreeNode(psRoot, 12);
- AddBSTreeNode(psRoot, 14);
- AddBSTreeNode(psRoot, 15);
- AddBSTreeNode(psRoot, 16);
- AddBSTreeNode(psRoot, 7);
- AddBSTreeNode(psRoot, 9);
- ErgodicBSTree(psRoot);
- return 0;
- }
java 版:
public class BSTreeNode {
private Integer value;
private BSTreeNode left;
private BSTreeNode right;
private BSTreeNode Llist;
static BSTreeNode head;
static BSTreeNode temp;
/*
* 插入节点
*/
public void add(int insertValue)
{
if(null==value)
value=insertValue;
else if(insertValue<=value)
{
if(null==left)
{
left = new BSTreeNode();
left.setValue(insertValue);
}
else
left.add(insertValue);
}
else
{
if(null==right)
{
right = new BSTreeNode();
right.setValue(insertValue);
}
else
right.add(insertValue);
}
}
/*
* 中序遍历打印二叉树
*/
public void list()
{
if(null==this.value)
return;
if(null!=left)
left.list();
System.out.println(value);
if(null!=right)
right.list();
}
/*
* 中序遍历链表
*/
public BSTreeNode convertToLinkList()
{
if(null!=left)
left.convertToLinkList();
addNodeToList(this);
if(null!=right)
right.convertToLinkList();
return null;
}
/*
*
* 添加节点到双向链表尾部
*/
public void addNodeToList(BSTreeNode node)
{
node.left=temp;
if(null!=temp)
{
temp.right=node;
}
else
{
head=node;
}
temp=node;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public BSTreeNode getLeft() {
return left;
}
public void setLeft(BSTreeNode left) {
this.left = left;
}
public BSTreeNode getRight() {
return right;
}
public void setRight(BSTreeNode right) {
this.right = right;
}
public static void main(String args[])
{
BSTreeNode tree = new BSTreeNode();
tree.add(10);
tree.add(6);
tree.add(8);
tree.add(4);
tree.add(16);
tree.add(12);
tree.add(14);
tree.add(2);
tree.list();
tree.convertToLinkList();
BSTreeNode node = tree.head;
System.out.println("Linklist:");
while(null!=node)
{
System.out.println(node.getValue());
node = node.getRight();
}
}
}
2.
题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)
#define STACK_LEN 50
typedef struct
{
int data;
int min;
} StackItem;
typedef struct
{
StackItem data[ STACK_LEN ];
int top;
} Stack;
void push( stack *S, int val )
{
S->data[ S->top ].data = val;
if ( ( S->top )> 0 ) // 保证栈顶元素中的min始终为当前栈中最小值
{
if ( val < ( S->data[ S->top - 1 ].min ) ) // 如果当前push进的元素小于栈中最小元素值
S->data[ S->top ].min = val; // 把当前元素置为栈中最小元素值
else // 否则,不更新
S->data[ S->top ].min = S->data[ S->top - 1 ].min;
}
else
S->data[ S->top ].min = val;
S->top++;
}
int pop( stack *S )
{
return S->data[ S->top-- ].data;
}
int min( stack *S )
{
return S->data[ S->top ].min;
}
3.求子数组的最大和
- 题目:
- 输入一个整形数组,数组里有正数也有负数。
- 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
- 求所有子数组的和的最大值。要求时间复杂度为O(n)。
- 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
- 因此输出为该子数组的和18。
package beautyOfCoding;
public class MaxSubArraySum {
/**
* 3.求子数组的最大和
题目描述:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。
下面的解法:数组元素全是负数时,认为子数组最大和为0
*/
public static void main(String[] args) {
int[] a={-1,-2,-3,-10};
// int[] a={1, -2, 3, 10, -4, 7, 2, -5};
maxSubArraySum3(a);
maxSubArraySum2(a);
maxSubArraySum(a);
}
/*2012-07-29 编程之美书上的这个分析比较好理解,因此我写了maxSubArraySum2。其实maxSubArraySum2可以轻易地转换成maxSubArraySum。这两个方法本质是一样的。
假设A[0],A[1],...A(n-1)的最大子段为A[i],...,A[j],则有以下3种情况
1)当0=i=j的时候,元素A[0]本身构成和最大的一段
2)当0=i<j的时候,和最大的一段以A[0]开头
3)当0<i时候,元素A[0]跟和最大的一段没有关系
Start[i]表示从第i个元素开始(包括第i个元素)的子数组和最大值,All[i]表示A[i]A[i+1]...A[n-1]这个数组的子数组和的最大值
则原始问题A[0],A[1],...A(n-1)的解All[0]=max{A[0],A[0]+Start[1],ALL[1]}
*/
static void maxSubArraySum2(int[] a){
//略去参数检查
int Start=0;
int All=0;
for(int i=0,len=a.length;i<len;i++){
All=max(a[i],Start+a[i],All);
Start=max(a[i],a[i]+Start); //if start<0, start=a[i]
}
System.out.println("maxSubArraySum="+All);
}
static int max(int x,int...y){
int max=x;
for(int i:y){
if(i>max){
max=i;
}
}
return max;
}
static void maxSubArraySum(int[] a){
int len=a.length;
int sum=0;
int max=0;
int lastIndex=-1;
for(int i=0;i<len;i++){
if(sum<=0){
sum=a[i];
}else{
sum+=a[i];
}
if(sum>max){
max=sum;
lastIndex=i;
}
}
System.out.println("maxSubArraySum="+max);
if(lastIndex!=-1){
System.out.println("and the subArray is:");
//print the sub array
int i=lastIndex;
while(i>=0&&sum>=0){
sum-=a[i];
i--;
}
for(int j=i;j<=lastIndex;j++){
System.out.print(a[j]+" ");
}
}
}
/*下面这个方法是编程之美里面在讲二维数组的子数组最大和时候提到的:
p[0]=a[0],
p[i]=p[i-1]+a[i]=a[0]+a[1]+...a[i],1<=i<=(n-1)
那么
a[i]+a[i+1]+...a[j]=p[j]-p[i-1]
子数组和最大值为max(p[j]-p[i]),0<=(i,j)<=(n-1)
*/
static void maxSubArraySum3(int[] a){
//略去参数检查
boolean allNegative=true;
int len=a.length;
int[] p=new int[len];
for(int i=0;i<len;i++){
if(allNegative){
if(a[i]>0){
allNegative=false;
}
}
if(i==0){
p[0]=a[0];
}else{
p[i]=p[i-1]+a[i];
}
}
if(allNegative){
System.out.println("maxSubArraySum=0");
}else{
int max=p[0];
int min=p[0];
for(int i=0;i<len;i++){
if(p[i]>max){
max=p[i];
}
if(p[i]<min){
min=p[i];
}
}
System.out.println("maxSubArraySum="+(max-min));
}
}
}