2017去哪网春招编程题详解


1: 题目描述

给定一棵二叉树的前序(根、左、右)和中序(左、根、右)的打印结果,输出此二叉树按层(从左往右)打印结果。

例如一棵二叉树前序:1 2 4 5 3;中序:4 2 5 1 3。可以构建出下图所示二叉树:

按层打印的结果则为:1 2 3 4 5。

输入

第一行只有一个数字,表示二叉树的节点数n(1<=n<=1000);

第二行由a1,a2,...,an(1<=ai<=1000)组成的整数序列(用空格分隔)—表示前序打印结果;

第三行由b1,b2,...,bn(1<=bi<=1000)组成的整数序列(用空格分隔)—表示中序打印结果。


样例输入

5

1 2 4 5 3

4 2 5 1 3


输出

c1,c2,...,cn,用空格分隔—表示按层打印的结果。


样例输出

1 2 3 4 5

输入

第一行只有一个数字,表示二叉树的节点数n(1<=n<=1000);

第二行由a1,a2,...,an(1<=ai<=1000)组成的整数序列(用空格分隔)—表示前序打印结果;

第三行由b1,b2,...,bn(1<=bi<=1000)组成的整数序列(用空格分隔)—表示中序打印结果。


样例输入

5

1 2 4 5 3

4 2 5 1 3


输出

c1,c2,...,cn,用空格分隔—表示按层打印的结果。


样例输出

1 2 3 4 5

分析:这道题目和剑指offer上的面试题6:重建二叉树基本相似,只是在重建完二叉树后,再完成对树的层次遍历而已。基本思想就是先找到先序便利的第一个数字,它对应的是树的根节点;然后在树的中序遍历中找到此根节点,则对应中序遍历根节点位置的左边数字都为此根节点的左子树结点的值,位于根结点后面的数字都是右子树节点的值。接下来的动作就是重复上述的行为,这样就可以递归的构建出这颗二叉树了。

至于树的层次遍历就不多说了,这是基本功,唯一要注意的就是大家在用到栈,队列这类基本数据结构时,如果有可能,尽量自己写出他们的数据结构,用自己定义的栈和队列,这样使我们对这些基本的数据结构有更深的了解,笔者面试的时候就曾经被要求写一个链栈和循环队列,实现基本的功能;所以平时用Java中定义好的Stack,ArrayDeque,LinkListed等等的同学要多多注意啦,毕竟基础还是最重要的。下面直接上代码吧。

import java.util.Arrays;
import java.util.Scanner;
class linkNode{
	public TreeNode val;
	public linkNode next;	
}
class TreeNode{
public int val;
  public TreeNode left;
  public TreeNode right;
  public TreeNode(int val)
  {
    this.val=val;
  }
}
//自定义队列
class Squeue{
	TreeNode[] data=new TreeNode[100];
	int front;
	int rear;
	public boolean isEmpty()
	{
		return front==rear;	
	}
	public void InQueue(TreeNode val) throws Exception
	{
		if((rear+1)%100==front)
		{
			throw new Exception("队列已满");
		}
		else
		{
		   rear=(rear+1)%100;
		   data[rear]=val;
		}
	}
	public TreeNode EnQueue() throws Exception
	{     
		if(front==rear)
			throw new Exception("队列为空");
		else
		{
			front=(front+1)%100;
			TreeNode val=data[front];
			return val;
		}		
	}
}
class LinkQueue{   //li
  public int size;
  linkNode front;
  linkNode rear;
  public LinkQueue()
  {
	  linkNode temp=new linkNode();
	  front=temp;
	  rear=temp;
  }
  public boolean isEmpty()
  {
	  return size==0;
  }
	public TreeNode EnQueue() throws Exception
	{
		if(isEmpty()==true)
			throw new Exception("队列空");
		TreeNode val=front.next.val;
		front.next=front.next.next;
		if(front.next==null)
		{
			rear=front;
		}
		size--;
		return val;
		
	}
	public void InQueue(TreeNode t)
	{   
		linkNode s=new linkNode();
		   s.val=t;
		  rear.next=s;
		  rear=s;
		  size++;
	}
}

public class DaYinBinaryTree
{
   public static TreeNode Recons(TreeNode t, int[] pre, int[] mid) 
   {
       if(pre.length>0)
       {
         int index=find(mid,pre[0]);
         int[] mid1=Arrays.copyOfRange(mid,0,index);
         int[] mid2=Arrays.copyOfRange(mid,index+1,mid.length);
         int[] pre1=Arrays.copyOfRange(pre,1,index+1) ;
         int[] pre2=Arrays.copyOfRange(pre,index+1,pre.length);
         t=new TreeNode(pre[0]);
         t.left=Recons(t.left,pre1,mid1);
         t.right=Recons(t.right,pre2,mid2);
    
       }
       return t;
   
   }
   public static int find(int[] a, int target)
   { 
       for(int i=0;i<a.length;i++)
       {
          if(a[i]==target)
          {
            return i;
          }
         
       }
      return -1;
   }
  
  
  public static void main(String[] args) throws Exception
  {
    Scanner sc=new Scanner(System.in);
     int n=sc.nextInt();
     int[] pre=new int[n];
     int[] mid=new int[n];
 for(int i=0;i<n;i++)
 {
   pre[i]=sc.nextInt();
 }
   for(int i=0;i<n;i++)
   {
     mid[i]=sc.nextInt();
   }
    
    TreeNode t=null;
    t=Recons(t,pre,mid);
  /*  ArrayDeque<TreeNode> q=new ArrayDeque<>();
    q.offer(t);
    int count=0;
    while(q.isEmpty()!=true)
    {
       TreeNode temp=q.poll();
      count++;
      if(count==pre.length)
      System.out.print(temp.val);
      else
        System.out.print(temp.val+" ");
      if(temp.left!=null)
      {
       q.offer(temp.left);
      }
      if(temp.right!=null)
      {
      q.offer(temp.right);
      }
      
    }*/
   /* Squeue q=new Squeue();
    q.InQueue(t);
    int count=0;
    while(q.isEmpty()!=true)
    {
       TreeNode temp=q.EnQueue();
      count++;
      if(count==pre.length)
      System.out.print(temp.val);
      else
        System.out.print(temp.val+" ");
      if(temp.left!=null)
      {
       q.InQueue(temp.left);
      }
      if(temp.right!=null)
      {
      q.InQueue(temp.right);
      }
      
    }*/
    
    LinkQueue q=new LinkQueue();
    q.InQueue(t);
    int count=0;
    while(q.isEmpty()!=true)
    {
       TreeNode temp=q.EnQueue();
      count++;
      if(count==pre.length)
      System.out.print(temp.val);
      else
        System.out.print(temp.val+" ");
      if(temp.left!=null)
      {
       q.InQueue(temp.left);
      }
      if(temp.right!=null)
      {
      q.InQueue(temp.right);
      }
      
    }
  }
  

}
2:题目描述
									

用英文字母a-z来分别表示数值0-25, 形成一个26进制的数值表示法。需要你写一个方法,将用a-z表示的26进制数值的字符串,转化为对应的10进制数值。

输入

输入数据有多组,每组占一行,包含多个a-z之间的字符。

样例输入

ba

bcd

gibbon

goodboy

输出

所对应表示的10进制数。


样例输出

26

731

74962693

2026285376

分析:这也是一道比较基础的题目啦,可能有些童鞋范围不够用,但是Java里用long肯定没问题的,直接上代码了。。

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

/**
 * 
 * 进制转换(2017去哪儿网实习题)
 * 
 *
 */
public class JinZhiZhuanHuan {

	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		List<Long> list=new ArrayList<>();
		while(sc.hasNext()){
         String s=sc.next();
         long sum=0;
         for(int i=0;i<s.length();i++)
         {
        	 sum=sum+(long)((s.charAt(i)-'a')*Math.pow(26,s.length()-i-1));
        	 
         }
        list.add(sum);
		}
		for(int i=0;i<list.size();i++)
		{
          System.out.println(list.get(i));
		}
	}

}
PS:关于输入输出的问题,这道题要求输入多行,但没说具体是几行,我们只要写成死循环即可,但是要记得输入一个,就要处理一个,然后存起来,最后统一输出,当然我们在本地运行的时候程序是停不下来的,但是不论是牛客网还是赛码网,oj系统都会自动检查测试的case,在相应的地方做停止,不需要我们操心的。比如牛客网上华为机试题库的一道ip地址分类的题,也是如此。

3:题目描述
									

有一个单词列表,一个初始单词和一个最终单词,初始单词需要通过单词列表逐步变换到最终单词,求变换所需的最短变换路径长度。

变换规则:每次只能变动1个字母(不可交换位置,如:从abc变成cba属于变动了2个字母),每次变换只能从单词列表中选取。

例如:初始单词hot,最终单词dog,单词列表[got, dot, god, dog, lot, log],最短变换路径为[hot,dot,dog],最短变换路径长度为3。

注:单词列表中包含最终单词,不包含初始单词;列表中每一项单词长度与初始单词、最终单词相同;列表中单词不重复;所有字母均为小写。

输入

输入数据有三行,第一行为初始单词;第二行为最终单词;第三行为单词列表,单词和单词之间以空格分割

输出

最短变换路径长度。

样例输入

hot

dog

got dot god dog lot log

样例输出

3

分析:拿到这个题目,大家脑海里都想到了最短路径算法,或者肯定跟图有点小关系的样子;确实如此,只不过,他需要我们将所需要的图构造出来,才能使用我们的最短路径算法,广度优先遍历算法等等去求解;

那这道题该如何构造呢,要构造一张图,首先有顶点集合V,边集合E,顶点的话,相信大家都能找到,就是题目中描述的单词列表,题目中的单词列表有6个单词,那就是6个顶点,但不要忘了这里面不包括初始单词,所以我们也要把他算上,就是7个顶点了;那么在程序中怎么定义它呢,我定义了一个类Vertex,他有两个成员变量,no和name,no代表着是节点的编号,从0开始,按着单词列表里出现的顺序,依次增加就好了,而name就是单词本身啦,这样题目中的单词列表就变成了7个Vertex的对象啦~

有了节点,接下来就是边了,哪些节点之间应该有边相连呢,再仔细读读题目,发现我们每次变动字母的时候,只能变动一个,而且顺序不能交换,比如hot-->dot, 这就是一次变化 ,那么我们就认为hot所对应的节点就和dot所对应的节点之间有一条边,其他的都是如此,这样,我们就能完整的构造一个图了,构造的图如下(画的好丑,看不下去了。。。那两条连接的线不是连在一块的,大家不要看错了,自己布局好节点)。

图构造出来了,接下来就可以用广度优先遍历或者迪杰斯特拉算法求最短路径了。这里图采用的是邻接矩阵的数据结构,在使用广度优先遍历的时候,大家注意,可以在节点类Vertex中再定义一个整型变量pre,用来存放在遍历过程中将其放入队列的前一个节点,初始节点的pre为-1,比如got,dot,lot对应节点的pre都是0,指向hot对应的节点,这样放我们遍历到目标节点,即dog时,往回寻找,知道找到某个节点的pre=-1时,所经过的节点个数即为最短路径了。

上代码:

import java.util.ArrayDeque;
import java.util.Scanner;
/**
 * 
 * 单词变换
 * 
 *
 */
//邻接矩阵表示法
class Vertex{
public int no;
public String name;
public int pre;
public Vertex(int no,String name)
 {  
	this.no=no;
	this.name=name;
	pre=-1;
 }
}
class Graph{
 public int edge[][]=new int[100][100];
 public int n;
 public int e;
 public Vertex[] vex=new Vertex[100];
  public boolean isBian(Vertex v1,Vertex v2)
  {    int count=0;
	 for(int i=0;i<v1.name.length();i++)
	 {
		 if(v1.name.charAt(i)!=v2.name.charAt(i))
		 {
			 count++;
		 }	 
	 }
	  if(count==1)
		  return true;
	  else
	  return false;
  }
  public int find(String d)
  {
	 for(int i=0;i<n;i++)
	 {
		 if(vex[i].name.equals(d))
			 return i;
	 }
	 return -1;
  }
  public int createGraph(Scanner sc)
  {	  
      String s=sc.next();
      String d=sc.next();
      sc.nextLine();
	  String s1=sc.nextLine();
     String list=s+" "+s1;
	  String[] word=list.split(" ");
	 for(int i=0;i<word.length;i++)
	  {
	     vex[i]=new Vertex(i,word[i]);
		 n++;
	  }
	 for(int i=0;i<word.length;i++)
		 for(int j=0;j<word.length;j++)
		 {
			 if(isBian(vex[i],vex[j]))
			 {
				 edge[i][j]=1;
				 e++;
			 }
			 else
			 {
				 edge[i][j]=100;
			 }			 
		 }
	 e=e/2; 	 
	 int index=find(d);
	 return index;
  }
}
public class DanCiBianHuan {
	// 广度遍历求最短路径
	public static int BFS(Graph g,Vertex v,Vertex v1)
	{
		boolean[] visited=new boolean[g.n];
		for(int i=0;i<visited.length;i++)
			 visited[i]=false;
		ArrayDeque<Vertex> q=new ArrayDeque<>();
		//System.out.println(v.name);
		visited[0]=true;
		q.offer(v);
		while(q.isEmpty()!=true)
		{
		  Vertex temp=q.poll();
		  for(int i=0;i<g.n;i++)
		  {
			  if(g.edge[temp.no][i]==1&&!visited[i])
			  {
				  visited[i]=true;
				 // System.out.println(g.vex[i].name);
				  g.vex[i].pre=temp.no;
				  if(g.vex[i].name.equals(v1.name))
				  {    int count=1;
					  while(g.vex[i].pre!=-1)
					  {
						  count++;
						  i=g.vex[i].pre;
					  }
					  return count;
				  }
				  q.offer(g.vex[i]);				  
			  }
		  }
		}
		return -1;
	}
	//迪杰斯特拉算法求最短路径
	 public static void Dijkstra(Graph g, Vertex v,Vertex v1,int dist[],int path[])
	 {  //初始化操作
		 int[] set=new int[g.n];
		 int u=0;
         for(int i=0;i<g.n;i++)
         { 
        	 dist[i]=g.edge[v.no][i];
        	 set[i]=0;
        	 if(g.edge[v.no][i]<100)
        	 {
        		 path[i]=v.no;
        	 }else
        	 {
        		 path[i]=-1;
        	 } 
         }
		 set[v.no]=1;path[v.no]=-1;//初始化结束
		for(int i=0;i<g.n;i++)
		{
			int min=100;
			for(int j=0;j<g.n;j++)
			{
				if(set[j]==0&&dist[j]<min)
				{
					u=j;
					min=dist[j];
				}
			}
		   set[u]=1;
		   for(int j=0;j<g.n;j++)
		   {
			   if(set[j]==0&&dist[u]+g.edge[u][j]<dist[j])
			   {
				   dist[j]=dist[u]+g.edge[u][j];
				   path[j]=u;
			   }		   
		   }
		   
		}
		 System.out.println(dist[v1.no]+1);
		 
	 }
	public static void main(String[] args) {	
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
		Graph g=new Graph();
		int index=g.createGraph(sc);
	    Vertex v=g.vex[0];
	    Vertex v1=g.vex[index];
	    int[] dist=new int[g.n];
	    int[] path=new int[g.n];
	    Dijkstra(g,v,v1,dist,path);
	  //  System.out.println(BFS(g,v,v1));	    
	   /* for(int i=0;i<g.n;i++)
	    {	for(int j=0;j<g.n;j++)
	    		System.out.print(g.edge[i][j]+" ");
	      System.out.println();
	    }   */
		}   
	}

}

Ok啦,就先这样吧~~啧啧啧



                
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值