现在的位置: 首页 > 综合 > 正文

程序设计-google2012校招笔试题

2013年09月19日 ⁄ 综合 ⁄ 共 5232字 ⁄ 字号 评论关闭

第一道程序设计题

2.1 一个环,N个点,任意相邻两点有一个距离。要求写一个算法,输入为点i和点j,输出是他们之间的最短路径。
某环形公路上有N个站点,分别记为A1,...,An,从Ai到A(i+1)的距离为Di,An到A1的距离为D0。假设D0~D(n-1)保存在数组D[N]中。现在要求你写一个函数,能够高效的计算出公路上任意两点的最近距离,要求空间复杂度不能超过O(N)。

【思考】
1、问题抽象
1)环形公路可以表示为一个环,站点即为环上的点,环可以用哪种数据结构表示呢?当然是双端链表了。
2)站点如何表示呢?站点可以视为一个点对象,画出双端链表上的点,我们发现该点对象应该有3个属性:第一属性是站点名Ai,第二个属性时其到前一个站点A(i-1)的距离D(i-1),第三个属性时其到下一个站点A(i+1)的距离D(i+1)。

3)现在我们有了对题目中研究对象的抽象(环形公路抽象为双端链表,站点抽象为点对象),现在可以把原问题转变为我们程序员熟悉的问题了:
给定双端链表中的2个点对象,求该2点间的最大距离为多少?

2、解决问题
问题抽象后,解决该问题变的简单了很多,点Ai到点Aj无非就有2条路径,一条路径是按图中顺时针方向(经由下一个站点)到达点Aj,另一条路径是按图中逆时针方向(经由前一个站点)到达点Aj。我们只要比较这俩条路径得到较小的那个值即可。
3、时间复杂度分析
顺时针方向和逆时针方向遍历链表的和正好是链表的长度n,故该算法时间复杂度为O(n)。
4、JAVA语言实现

在JAVA中双端链表可以用LinkedList表示。具体代码如下

//站点对象类

public class Point{
   private String name; //站点名称,如Ai
   private double nextPointDistance; //到下一个站点的距离,D(i+1)
   private double previousPointDistance; //到前一个站点的距离,D(i-1)
   
   //constructor
   public Point(){}
   
   //get and set method
   public String getName(){
    return name;
   }//end getName()
   
   public void setName(String name){
    this.name=name;
   }//end setName()
   
   public double getnextPointDistance(){
    return nextPointDistance;
   }//end getnextPointDistance()
   
   public void setnextPointDistance(double nextPointDistance){
    this.nextPointDistance=nextPointDistance;
   }//end setnextPointDistance()
   
   public double getpreviousPointDistance(){
    return previousPointDistance;
   }//end getpreviousPointDistance()
   
   public void setpreviousPointDistance(double previousPointDistance){
    this.previousPointDistance=previousPointDistance;
   }//end setpreviousPointDistance()
   }//end setName()   
}//end class Point

主函数shortestPath

public class HighRoad{
  private LinkedList ll; //双端链表
  
  //------------------------------------------------------
  //constructor
  //------------------------------------------------------
  public HighRoad(String[] pointName,double[] distance){
      initial(pointName,distance)
  }
  
  //------------------------------------------------------
  // API
  //------------------------------------------------------
  /**
  * 求2站点间最大距离
  * @parm name1 站点i
  * @parm name2 站点j
  * @return 返回最大路径,-1代表错误
  */
  public double shortestPath(String name1,String name2){
    //输入控制
	if(ll==null)
	  return -1;
	
	int llSize=ll.size();
	if(llSize<1)  //站点数小于2
      return -1;
	  
	if(name1==null || name1=="" || name2==null || name2=""){
	    System.out.println("请输入站点名称");
	}//end if
	
	//在双端链表中获取这2个站点的位置
	Point point1=findPoint(name1,ll);
	Point point2=findPoint(name2,ll);	
	
	//顺时针方向路径
	double rightPath=rightPath(point1,point2);
    //逆时针方向路径
	double leftPath=leftPath(point1,point2);
	
	return min(rightPath,leftPath);
  }//end shortestPath()

主函数中调用的函数

  //------------------------------------------------------
  // private method
  //------------------------------------------------------
  
  //初始化双端链表,将距离和站点名称列入双端链表
  private void initial(String[] pointName,double[] distance) throws Exception{
    if(pointName==null || distance==null){
		 throw new Exception("请输入站点名称 或 站点距离");
	
	int pointNumber=pointName.length();
	if(pointNumber!=distance.length())
	    throw new Exception("站点数目要和距离数目一致");
		
    //至少要有2个站点
	if(pointNumber< 2)
	    throw new Exception("至少要有2个站点");
	
	//第一个站点和最后一个站点要特殊处理下(数组下标对应关系可以从图中看出来)
	Point firstPoint=new Point(pointName[0],distance[0+1],distance[0]);
		ll.addLast(firstPoint);
	
	if(pointNumber>=2){ //如果多于2个剩余元素(除了第一个站点和最后一个站点)按以下规则添加
	    for(int i=1;i<pointNumber-1;i++){
	        Point point=new Point(pointName[i],distance[i+1],distance[i]);
			ll.addLast(point);
	    }//end for
	}//end if

	 //最后一个元素添加
	Point lastPoint=new Point(pointName[pointNumber-1],distance[0],distance[pointNumber-1-1]);
	ll.addLast(lastPoint);
  }//end initial()

  //------------------------------------------------------
  private Point findPoint(String name,LinkedList ll){
     Point point=null;
	 
     Iterator it=ll.iterator();
	 while(it.hasNext()){
	    point=(Point)it.next();
		if(point.getName.equels(name))
		  return point;
	 }//end while
  }//end findPoint()
  
  //------------------------------------------------------  
  //顺时针方向路径
  private double rightPath(Point point1,Point point2){
    double result=0; //存储路径值
	Point current=point1;
	
	while(current!=point2){
	  result+=current.getnextPointDistance();
	  current=current.next(); //指向下一个站点
	}//end while
	
	return result;
  }//end rightPath()

  //------------------------------------------------------   
   //逆时针方向路径
  private double leftPath(Point point1,Point point2){
    double result=0; //存储路径值
	Point current=point1;
	
	while(current!=point2){
	  result+=current.getpreviousPointDistance();
	  current=current.previous(); //指向前一个站点
	}//end while
	
	return result;
  }//end leftPath()  
  
  //获取较小值
  private double min(double a,double b){
    if(a<b)
	  return a;
	else
	  return b;
  }//end min()
      
}//end class HighRoad

测试用例设计:

1、只有一个站点
2、只有2个站点
3、多于2个站点

第二道程序设计题


算法1:利用
算法2:
1)翻转:以空格为分界符,用栈翻转每个以分界符的子串,然后将翻转后的子串拼接在一起
2)删除重复空格,拼接子串的时候
过程:
1)入栈:直到遇到第一个空格(空格不入栈)
2)出栈:将出栈的结果拼接到结果字符串中
3)并添加一个空格

//---------------------------------------------------
public class AlgorithmReverse{
Stack stack; //栈
StringBuffer sb; //保存翻转结果

public AlgorithmReverse(){
   stack=new Stack();
   sb=new StringBuffer();
}

public String reverse(String src){
   //输入控制
    if(src==null || src=="")
      return src;  
    
	else{
        for(int i=0;i<src.length(); ){
		   //入栈
		   char temp=src.getChar(i);
		   if( temp !=' ')
		      stack.push(temp);
		   //出栈
		   else{
		      if(!stack.empty()){
			     for(int j=0;j<stack.size();j++){
				    sb.append(stack.pop());
				 }//end for
			  }//end if
		   }//end else
		   //只加入一个空格
		   sb.append(' ');
		   //删除重复空格,返回下一个i的值
		   i=deleteSpace(src,i+1);
		}//end for
		
		return sb.toString();
	}//end else	
}//end reverse()
//---------------------------------------------------
		//删除重复空格,返回下一个i的值
		private int deleteSpace(src,int i){
		 while(src.getChar(i) !=' '){
		    i++;
		 }//end while
		 
		 return i;
		}//end delteSpace()

} //end class AlgorithmReverse
//------------------------------------

第三道程序设计题

X<10^6,如何用任意的100、50、20、10、5、2、1来加出X,求所有方法。

感觉是用因素分解的办法求解,希望会的同仁留言,写出您的算法。


抱歉!评论已关闭.