精选微软等公司数据结构+算法面试100题带答案(86-90)

86、怎样编写一个程序,把一个有序整数数组放到二叉树中?
    分析:本题考察二叉搜索树的建树方法,简单的递归结构。关于树的算法设计一定要联想到递归,因为树本身就是递归的定义。而学会把递归改称非递归也是一种必要的技术。毕竟,递归会造成栈溢出,关于系统底层的程序中不到非不得以最好不要用。但是对某些数学问题,就一定要学会用递归去解决。

struct BTree
{
	int data;
	BTree *left;
	BTree *right;
};

BTree* array2Tree(int *array, int start, int end) 
{
	if (start > end) 
		return NULL;

	int m = start + (end-start)/2;    //中间的作为根节点
	BTree * root = new BTree;
	root->data=array[m];
	root->left = array2Tree(array, start, m-1);
	root->right = array2Tree(array, m+1, end);

	return root;
}

87、字符串和整数溢出问题
1)大整数数相乘的问题。(考虑整数溢出)

       见:http://blog.csdn.net/dazhong159/article/details/7801015
2)求最大连续递增数字串(如“ads3sl456789DF3456ld345AA”中的“456789”)

       注意问题:题目要求连续、递增,比较大小时需要考虑字符串结尾为数字的情况

#include "stdafx.h"
#include "stdlib.h"
#include <iostream.h>
#include <string.h>

int MCISubstring(char *str,char *&result)
{
	char *s1=str;
	size_t count=0,maxCount=0;
	for (size_t i=0;i<strlen(s1);i++)  //遍历str
	{
		if (s1[i]>='0'&&s1[i]<='9')
		{
			if (s1[i]<s1[i+1]||s1[i+1]=='\0')  //注意考虑字符串结尾的特殊性
			{
				count++;
			}
			else
				count=0; //重置
		}
		else
		{
			if (count>maxCount) //更新maxCount
			{
				maxCount=count;
				result=&s1[i];
			}
			count=0;  //重置count
		}
	}	
	if (count>maxCount) //字符串结尾也是数字,更新maxCount
	{
		maxCount=count;
	}	

	result=result-maxCount;   //改变result数组地址,指向最大递增数字子串
	*(result+maxCount)='\0';  //result数组内容结尾标志

	return maxCount;
}

void main()
{
	char str[]="akdh1832713ada819301ada993aaa123456789aa";
	int len=strlen(str);
	char *result=new char[len+1];

	cout<<MCISubstring(str,result)<<endl;
	cout<<result<<endl;
}

3)实现strstr功能,即在父串中寻找子串首次出现的位置。

int StrStr(const char *str,const char *substr)
{
	const char *s1=str,*s2=substr;
	size_t k=0;
	for (size_t i=0;i<strlen(s1);i++)  //遍历str
	{
		if (s1[i]==s2[0])
		{
			for (size_t j=0;j<strlen(s2);j++) //匹配substr
			{
				if (s1[i+k]!=s2[j])
					break;
				k++;
			}
			if (k==strlen(s2)) //匹配成功
			{
				break;
				k=0;
			}
		}
		k=0;  //未匹配成功,k重置
	}
	
	return i;
}

88、2005年11月金山笔试题。编码完成下面的处理函数。
函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量。
如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5。(要求使用尽量少的时间和辅助空间)

int PartitionStar(char *str)
{
	int i = strlen(str)-1;  //i用来遍历str
	int j=i,count=0;        //j存储非'*'元素
	while (i >= 0) 
	{
		if (str[i] != '*') 
		{
			swap(str, i--, j--);//将'*'和非'*'元素互换
		} 
		else 
		{
			i--; 
			count ++;
		}
	} 

	return count;
}

89、神州数码、华为、东软笔试题
1)2005年11月15日华为软件研发笔试题。实现一单链表的逆转。

       见:http://blog.csdn.net/dazhong159/article/details/7796344
2)编码实现字符串转整型的函数(实现函数atoi的功能),据说是神州数码笔试题。如将字符串 ”+123”123, ”-0123”-123, “123CS45”123, “123.45CS”123, “CS123.45”0

int atoi(const char *str)
{
	int sign=1,m=0;
	if(*str=='-'||*str=='+')  //判断符号
	{
		sign=*str=='+'?1:-1;
		str++;
	}

    while(*str!='\0')
	{
		if (*str>='0'&&*str<='9')
		{
			if(*str=='0')  //'0'的话,continue
			{
				str++;
				continue;
			}
			m=m*10+(*str-'0'); //非'0'整数,转换
			str++;
		} 
		else  //非法字符,break
		{
			break;
		}
	}
    m*=sign;

	return m;
}

3)快速排序(东软喜欢考类似的算法填空题,又如堆排序的算法等)

       见:http://blog.csdn.net/dazhong159/article/details/7793132
4)删除字符串中的数字并压缩字符串。如字符串”abc123de4fg56”处理后变为”abcdefg”。注意空间和效率。(要求不要开辟新空间,时间复杂度为O(N))。

//快慢指针典型用法
//快指针遍历原始字符串,慢指针用来删除指定字符
void PartitionStar(char *strOriginal)
{
	char *fast=strOriginal,*slow=strOriginal;
	while(*fast!='\0')
	{
		if (*fast<'0'||*fast>'9')
		{
			*slow=*fast;
			slow++;
		}
		fast++;
	}
	*slow='\0';
}

5)求两个串中的第一个最长子串(神州数码以前试题)。如"abractyeyt","dgdsaeactyey"的最大子串为"actyet"。

先写个复杂度为O(n^2),用后缀树的话复杂度为O(n),以后研究。

char * SMString(char *str1,char *str2)
{
	char *s1=str1,*s2=str2,*start; //s1、s2分别用来遍历str1和str2,start保存子串
	int len=0,maxLen=0;

	while(*s1!='\0')
	{
		s2=str2; //s2重置
		while(*s2!='\0')
		{
			if (*(s1+len)==*s2)
			{
				len++;
			}
			else    //这个是重要的地方,更新maxLen
			{
				if(len>maxLen)
				{
					maxLen=len;
					start=s1;
				}
		        len=0; //len重置
			}
			s2++;
		}
		if(len>maxLen) //字符串末尾匹配,需要更新maxLen
		{
			maxLen=len;
			start=s1;
		}
		len=0; //len重置
		s1++;
	}
	*(start+maxLen)='\0';

	return start;
}

90、字符串和链表
1)不开辟用于交换数据的临时空间,如何完成字符串的逆序 

//用异或代替交换,避免开辟新的内存空间
void ReverseString(char *str) 
{
	for(int i=0,j=strlen(str)-1; i<j; i++, j--)
	{
		str[i]^=str[j];
		str[j]^=str[i];
		str[i]^=str[j];	
	}
}

2)删除串中指定的字符

//快慢指针典型用法
//快指针遍历原始字符串,慢指针用来删除指定字符
void PartitionStar(char *strOriginal,char *toBedelete)
{
	char temp[255],*fast=strOriginal,*slow=strOriginal;
	memset(temp,'0',255);
	size_t i=0;
	for (;i<strlen(toBedelete);i++)
	{
		temp[toBedelete[i]]='1'; //利用数组标记,避免其他查找方法
	}

	while(*fast!='\0')
	{
		if (temp[*fast]=='0')
		{
			*slow=*fast;
			slow++;
		}
		fast++;
	}
	*slow='\0';
}

3)判断单链表中是否存在环。

       见:http://blog.csdn.net/dazhong159/article/details/7915603  第七题

 

文章转载于:http://blog.csdn.net/v_july_v/article/details/5975019

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值