您的位置:首页 > 职场人生

算法练习--微软面试题前25题

2015-11-27 11:54 615 查看
1.transform from binary search tree into doubly linked list.

rule:can not create any new node,just change the "pointer".

10
/ \
6 14
/ \ / \
4 8 12 16

transformed into:
4=6=8=10=12=14=16。

data structure of binary search tree:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};

------------------------------------------------------------

using inorder traversal to traverse the tree,at the same time,add the node to the list.

------------------------------------------------------------

2write a function called min to get the smallest value of a stack.time complexity of min,push and pop are all O(1).

public class MinStack{
public static void main(String[] args){
/**TEST CODE**/
}
private static Stack<Integer> stack = new Stack<Integer>();
private static Stack<Integer> mini_stack = new Stack<Integer>();
public static void push(Integer value) {
stack.push(value);
if(mini_stack.isEmpty())
mini_stack.push(value);
else if( value < mini_stack.peek())
mini_stack.push(value);
}
public static Integer pop(){
if(stack.isEmpty())
return null;
Integer temp = stack.pop();
if(temp == mini_stack.peek())
mini_stack.pop();
return temp;
}
public static void min(){
System.out.print(mini_stack.peek());
}
}


------------------------------------------------------------

3.求子数组的最大和
题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。

public class MaxSubArray{
public static void main(String[] args){
int[] arr = {1, -2, 3, 10, -4, 7, 2, -5};
System.out.println(get_max_subarray(arr));
}
public static int get_max_subarray(int[] arr){
int now_max = 0 ,max =  0;
for(int i = 0; i < arr.length; i++){
now_max += arr[i];
if(now_max  < 0)
now_max = 0;
if(now_max > max)
max= now_max;
}
return max;
}
}


------------------------------------------------------------

4.在二元树中找出和为某一值的所有路径
题目:输入一个整数和一棵二元树。
从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。
打印出和与输入整数相等的所有路径。
例如 输入整数22和如下二元树
10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。

public class FixedValueBranch
{
/**
* @author 无 名
* @date 2015-12-17
* @Description:查找给定和值得二叉树路径
*/
public static void main(String[] args)
{
/** TEST CODE **/
}
private final static Integer DEMAND_SUM_VALUE = 22;
public static void print_path(BinaryTreeNode parent,Integer sum,String path)
{
Integer value = parent.getValue();
sum += value;
path += "/" + String.valueOf(value);
if(null == parent.getLeft() &&  null == parent.getRight()
&& sum== DEMAND_SUM_VALUE)
System.out.println(path);
else
{
if(null != parent.getLeft())
print_path(parent.getLeft(),sum,path);
if(null != parent.getRight())
print_path(parent.getRight(),sum,path);
}
}
}


5.查找最小的k个元素
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。

public class GetMinimals
{
/**
* @author            无           名
* @date                 2015/12/17
* @Description: 求出n个数中最小的k个数
*/
public static void main(String[] args)
{
/**TEST CODE**/
}
public static void get_minimals(int[] arr,int k){
int[] mins = new int[k];
int max_flag = 0;
for(int i = 0; i < arr.length; i++){
if(i < k)
{
mins[i] = arr[i];     //initialize mins[]
if(mins[i] > mins[max_flag])
max_flag = i;
}
else{
for(int j = 0; j < k; j++)
if(arr[i] < mins[j])
mins[max_flag] = arr[i]; //exchenge the min value with max value of mins[k]
for(int j =0; j < k; j++)        //find the max value of mins[k]
if(mins[j] > mins[max_flag])
max_flag = j;
}
}
for(int i:mins)
System.out.print(i + " ");
}
}


第6题
------------------------------------
腾讯面试题:
给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数
要求下排每个数都是先前上排那十个数在下排出现的次数。
上排的十个数如下:
【0,1,2,3,4,5,6,7,8,9】

初看此题,貌似很难,10分钟过去了,可能有的人,题目都还没看懂。

举一个例子,
数值: 0,1,2,3,4,5,6,7,8,9
分配: 6,2,1,0,0,0,1,0,0,0
0在下排出现了6次,1在下排出现了2次,
2在下排出现了1次,3在下排出现了0次....
以此类推..

昨天,用c++实现了此题。(*^__^*)

第7题
------------------------------------
微软亚院之编程判断俩个链表是否相交
给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。
为了简化问题,我们假设俩个链表均不带环。

问题扩展:
1.如果链表可能有环列?
2.如果需要求出俩个链表相交的第一个节点列?

第8题
------------------------------------
此贴选一些 比较怪的题,,由于其中题目本身与算法关系不大,仅考考思维。特此并作一题。
1.有两个房间,一间房里有三盏灯,另一间房有控制着三盏灯的三个开关,这两个房间是 分割开的,
从一间里不能看到另一间的情况。
现在要求受训者分别进这两房间一次,然后判断出这三盏灯分别是由哪个开关控制的。
有什么办法呢?

2.你让一些人为你工作了七天,你要用一根金条作为报酬。金条被分成七小块,每天给出一块。
如果你只能将金条切割两次,你怎样分给这些工人?

3  ★用一种算法来颠倒一个链接表的顺序。现在在不用递归式的情况下做一遍。
  ★用一种算法在一个循环的链接表里插入一个节点,但不得穿越链接表。
  ★用一种算法整理一个数组。你为什么选择这种方法?
  ★用一种算法使通用字符串相匹配。
  ★颠倒一个字符串。优化速度。优化空间。
  ★颠倒一个句子中的词的顺序,比如将“我叫克丽丝”转换为“克丽丝叫我”,实现速度最快,移动最少。
  ★找到一个子字符串。优化速度。优化空间。
  ★比较两个字符串,用O(n)时间和恒量空间。
  ★假设你有一个用1001个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1到1000(包括1000)之间。此外,除一个数字出现两次外,其他所有数字只出现一次
。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。
如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?
  ★不用乘法或加法增加8倍。现在用同样的方法增加7倍。

第9题
-----------------------------------
判断整数序列是不是二元查找树的后序遍历结果
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11
因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。

第10题
---------------------------------
翻转句子中单词的顺序。
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。
为简单起见,标点符号和普通字母一样处理。
例如输入“I am a student.”,则输出“student. a am I”。

public class SentenceReversal {
/**
* @author              无       名
* @date                2015/12/19
* @description 翻转句子单词
*/
public static void main(String[] args){
/**TEST CODE**/
String str_input = "I will be the King.";
String[] sub_strs = str_input.split(" ");
int len = sub_strs.length;
String[] target_strs = new String[len];
for(int i = len-1; i >= 0; i--){
target_strs[len - i -1] = sub_strs[i];
}
for(int i = 0; i < len; i++){
System.out.print(target_strs[i] + " ");
}
}
}


第11题

------------------------------------
求二叉树中节点的最大距离...

如果我们把二叉树看成一个图,
父子节点之间的连线看成是双向的,
我们姑且定义"距离"为两节点之间边的个数。
写一个程序,
求一棵二叉树中相距最远的两个节点之间的距离。

第12题
题目:求1+2+…+n,
要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)。

转载于http://blog.csdn.net/shoulinjun/article/details/20564095



第13题:
题目:输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};

引自:http://blog.csdn.net/philofly/article/details/4852392



第14题:
题目:输入一个已经按升序排序过的数组和一个数字,
在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。

public static void get_two_num(int[] arr,int target_value){
int r_pointer = arr.length - 1;            //pointed to the stack of small values
int l_pointer = 0;                                     //pointed to the stack of big values
while(true){
if(l_pointer == r_pointer){
System.out.print("do not exit");
break;
}
if(arr[r_pointer] + arr[l_pointer] < target_value)
l_pointer++;
else if(arr[r_pointer] + arr[l_pointer] > target_value)
r_pointer--;
else{
System.out.print(arr[l_pointer] +"+"+ arr[r_pointer]+"="+ target_value);
break;
}
}


第15题:求二叉树镜像

即在转换后的二元查找树中,左子树的结点都大于右子树的结点。
用递归和循环两种方法完成树的镜像转换。
例如输入:
8
/ \
6 10
/\ /\
5 7 9 11

输出:
8
/ \
10 6
/\ /\
11 9 7 5

定义二元查找树的结点为:
struct BSTreeNode // a node in the binary search tree (BST)
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};

/**
*@author           无                 名
*@date                2015/12/25
* @Description:二叉树镜像转换
*/
public static void tree_turn(BinaryTreeNode root){
Queue<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>();
queue.add(root);
while(!queue.isEmpty()){
BinaryTreeNode node = queue.poll();
reset_childs(node);
if(null != node.getLeft())
queue.add(node.getLeft());
if(null != node.getRight())
queue.add(node.getRight());
}
}
public static void reset_childs(BinaryTreeNode parent){
BinaryTreeNode temp = parent.getLeft();
parent.setLeft(parent.getRight());
parent.setRight(temp);
}


第16题:
题目(微软):
输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。
例如输入
8
/ \
6 10
/ \ / \
5 7 9 11

输出8 6 10 5 7 9 11。

/**
* @author 无名
* @date 2015/12/21
* @Description: 层次遍历
*/
public static void level_traverse(BinaryTreeNode root)
{
if(null == root)
return;
Queue<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>();
queue.add(root);
while (!queue.isEmpty())
{
BinaryTreeNode temp = queue.peek().getLeft();
if (null != temp)
queue.add(temp);
temp = queue.peek().getRight();
if (null != temp)
queue.add(temp);
System.out.print(queue.poll().getValue() + " ");
}
}


第17题:
题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
分析:这道题是2006年google的一道笔试题。
entity:

package com.entity;

public class ChIntNode {
private char ch;
private int occur_num;
public char getCh() {
return ch;
}
public void setCh(char ch) {
this.ch = ch;
}
public int getOccur_num() {
return occur_num;
}
public void setOccur_num(int occur_num) {
this.occur_num = occur_num;
}
}


algorithm:

package com.micro;

import java.util.ArrayList;
import java.util.List;

import com.entity.ChIntNode;

public class Question17 {
/**
* @author           无        名
* @date             2015/12/20
*/
public static void main(String[] args) {
char[] arr = {'a','b','a','c','c','d','e','f','f'};
get_the_only_char(arr);
}
public static void get_the_only_char(char[] arr){
if(null == arr || 0==arr.length)
return;
List<ChIntNode> list =  new ArrayList<ChIntNode>();
for(int i = 0; i < arr.length;i++){
if(list.isEmpty()){
ChIntNode cin = new ChIntNode();
cin.setCh(arr[i]);
cin.setOccur_num(1);
list.add(cin);
}
Boolean flag = Boolean.TRUE;
for(ChIntNode cin:list){
if(arr[i] == cin.getCh()){
cin.setOccur_num(cin.getOccur_num()+1);
flag = Boolean.FALSE;
}
}
if(flag){
ChIntNode cin = new ChIntNode();
cin.setCh(arr[i]);
cin.setOccur_num(1);
list.add(cin);
}
}
for(ChIntNode cin: list){
if(1 == cin.getOccur_num()){
System.out.print(cin.getCh());
break;
}
}
}
}


第18题:
题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,
每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。
当一个数字删除后,从被删除数字的下一个继续删除第m个数字。
求出在这个圆圈中剩下的最后一个数字。
July:我想,这个题目,不少人已经 见识过了。

#include<stdio.h>
#include<malloc.h>
#define NULL 0
#define LEN sizeof(struct Josephus)
struct Josephus
{
int num;
struct Josephus *next;
};
void main()
{
printf("约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在");
printf("一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开");
printf("始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。");
printf("\n");
int m,n,k;
int i;
printf("Please input the values of m,n,k.");
scanf("%d,%d,%d",&m,&n,&k);
struct Josephus *p0,*p,*head;
head=NULL;
for(i=0;i<n;i++)
{
p=(struct Josephus*)malloc(LEN);
p->num=i;
if(head==NULL)
{
head=p;
p0=p;
}
else
{
p0->next=p;
p0=p;
}
}
p->next=head;
p=head;
for(i=0;i<k;i++)
{
p0=p;
p=p->next;
}
while(p->next!=p)
{
for(i=0;i<m-1;i++)
{
p0=p;
p=p->next;
}
p0->next=p->next;
printf("被删除的元素:%4d ",p->num);
p=p0->next;
}
printf("\n最后被删除的元素是:%4d",p->num);
}


第19题:
题目:定义Fibonacci数列如下:
/ 0 n=0
f(n)= 1 n=1
\ f(n-1)+f(n-2) n=2

输入n,用最快的方法求该数列的第n项。
分析:在很多C语言教科书中讲到递归函数的时候,都会用Fibonacci作为例子。
因此很多程序员对这道题的递归解法非常熟悉,但....呵呵,你知道的。。

第20题:
题目:输入一个表示整数的字符串,把该字符串转换成整数并输出。
例如输入字符串"345",则输出整数345。

#include<stdio.h>
#include<math.h>
/**
*@author 无  名
*@date  2015/12/25
*/
bool str_to_int(char* str_inpt)
{
if(NULL == str_inpt)
return false;
char* p_char = str_inpt;
int final_num = 0;
int digit = 0;   int flag;
if(*p_char == '-')
{
p_char++;
flag = -1;
}
else if(*p_char == '+')
{
p_char++;
flag = 1;
}
while(*(p_char+1) != '\0')
{
p_char++;
digit++;
}
for(int i = 0; i <= digit; i++)
{
//判断是否有非法输入
if(*p_char < '0' || *p_char > '9')
return false;
int lastbit = *p_char - '0';
final_num += lastbit*pow(10,i);
p_char--;
}
if(flag == -1)
final_num = -final_num;
printf("%d",final_num);
return true;
}

void main()
{
char str[] = "-78767345";
str_to_int(str);
}


第21题
2010年中兴面试题
编程求解:
输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来.

/**
* @author   无      名
* @date      2015/12/19
*/
public static void main(String[] args) {
/** TEST CODE **/
System.out.println("1到25个数字中和为35的全部数列");
select_mins(35, 20, new ArrayList<Integer>());
}
public static void select_mins(int total, int n, List<Integer> arr) {
if (0 == total) {
System.out.println(arr);
return;
}
if (total < 0 || n < 0)
return;
select_mins(total, n - 1, arr);
List<Integer> new_arr = new ArrayList<Integer>(arr);
new_arr.add(n);
select_mins(total - n, n - 1, new_arr);
}
}


第22题:
有4张红色的牌和4张蓝色的牌,主持人先拿任意两张,再分别在A、B、C三人额头上贴任意两张牌,
A、B、C三人都可以看见其余两人额头上的牌,看完后让他们猜自己额头上是什么颜色的牌,
A说不知道,B说不知道,C说不知道,然后A说知道了。
请教如何推理,A是怎么知道的。
如果用程序,又怎么实现呢?

第23题:
用最简单, 最快速的方法计算出下面这个圆形是否和正方形相交。"
3D坐标系 原点(0.0,0.0,0.0)
圆形:
半径r = 3.0
圆心o = (*.*, 0.0, *.*)

正方形:
4个角坐标;
1:(*.*, 0.0, *.*)
2:(*.*, 0.0, *.*)
3:(*.*, 0.0, *.*)
4:(*.*, 0.0, *.*)

第24题:
链表操作,
(1).单链表就地逆置,
(2)合并链表

public static void reverse(Node root){
Node n1,n2,n3;
n1 = root;
n2 = root.getNext();
if(null == n2)
return;
n3 = n2.getNext();
n1.setNext(null);
if(null == n3){
n2.setNext(n1);
return;
}
while(null != n3.getNext()){
n2.setNext(n1);
n1 = n2; n2 = n3;
n3 = n3.getNext();
}
n3.setNext(n2);
n2.setNext(n1);
}


第25题:
写一个函数,它的原形是int continumax(char *outputstr,char *intputstr)
功能:
在字符串中找出连续最长的数字串,并把这个串的长度返回,
并把这个最长数字串付给其中一个函数参数outputstr所指内存。
例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9,
outputstr所指的值为123456789
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: