一道微软算法题的java解法

类别:Java 点击:0 评论:0 推荐:

上回看到一道微软的算法题,题目大概是说:有一个很大的整型数组,我们怎样能够找到一个不在这个数组中的值。
假设一个数组的大小很大(比如说35000个值),我们知道整型的取值范围在某种c/c++编译器中是16位的,也就只能到65536。那么怎样才能通过最少的代价找到不在这个数组中的整型值呢?!

解答:
1、我们可以利用像数数字一样的算法,来解答这个问题。比如说我们数1到10的时候,如果1到10都是连续的话,那么我们可以肯定在这个中间是不会存在不在这个范围类的值了,具体到这个环境中,我们同样可以这样考虑,假设我们把数组遍历一遍,把其中所有能够连续的数值都去掉,那么那些连续数值中间的不连续地段,就是我们要找的值的所在。
2、因为java语言对于数据结构的良好封装,这道题的java解答很简单也容易。首先我们描述下面一个数据结构:
/*
 * Created on 2003-4-6
 *
 * To change this generated comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package bia.arithmetic;

import java.io.PrintStream;


/**
 * @author Administrator
 *
 * To change this generated comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class NumberNode {
 int value ;
 boolean hasLeft ;
 boolean hasRight ;
 
 NumberNode next,prev ;
 
 public void print(PrintStream out){
  String s = String.valueOf(value) ;
  if (hasLeft){
   s = "-" + s ;
  }
  else {
   s = " " + s ;
  }
  if (hasRight){
   s = s + "-" ;
  }
  else {
   s = s + " " ;
  }
  out.print(s) ;
 }
 
 public NumberNode(){
  value=0 ;
  hasLeft = false ;
  hasRight = false ;
 }
 /**
  * @return boolean
  */
 public boolean isHasLeft() {
  return hasLeft;
 }

 /**
  * @return boolean
  */
 public boolean isHasRight() {
  return hasRight;
 }

 /**
  * @return NumberNode
  */
 public NumberNode getNext() {
  return next;
 }

 /**
  * @return NumberNode
  */
 public NumberNode getPrev() {
  return prev;
 }

 /**
  * @return int
  */
 public int getValue() {
  return value;
 }

 /**
  * Sets the hasLeft.
  * @param hasLeft The hasLeft to set
  */
 public void setHasLeft(boolean hasLeft) {
  this.hasLeft = hasLeft;
 }

 /**
  * Sets the hasRight.
  * @param hasRight The hasRight to set
  */
 public void setHasRight(boolean hasRight) {
  this.hasRight = hasRight;
 }

 /**
  * Sets the next.
  * @param next The next to set
  */
 public void setNext(NumberNode next) {
  this.next = next;
 }

 /**
  * Sets the prev.
  * @param prev The prev to set
  */
 public void setPrev(NumberNode prev) {
  this.prev = prev;
 }

 /**
  * Sets the value.
  * @param value The value to set
  */
 public void setValue(int value) {
  this.value = value;
 }

}
然后,我们利用这个结构构造一个NumberList链表,来处理排序和依次读取的操作,在这个过程中,将中间连续的部分屏蔽掉,只留下连续的边界。

/*
 * Created on 2003-4-6
 *
 * To change this generated comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
package bia.arithmetic;

import java.io.PrintStream;

/**
 * @author Administrator
 *
 * To change this generated comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class NumberList {
 NumberNode first;

 public void print(PrintStream out){
  out.println("======Begin print List======") ;
  NumberNode p = first ;
  while (null!=p){
   p.print(out) ;
   p = p.getNext() ;
  }
  out.println("\n======End print List======") ;
 }
 
 public NumberList() {
 }

 public NumberNode getFirst() {
  return first;
 }

 public void addNumber(int number){
  NumberNode node = new NumberNode() ;
  node.setValue(number) ;
  addNode(node) ;
 }
 /**
  * 增加一个节点的方法
  * @Renzhichao
  * @param node
  */
 public void addNode(NumberNode node) {
  if (first == null) {
   first = node;
   first.setPrev(null);
   first.setNext(null);
   first.setHasLeft(false) ;
   first.setHasRight(false) ;
  }
  else {
   NumberNode tmp = first;
   NumberNode p = tmp;
   while (tmp.getValue() < node.getValue() && tmp.getNext() != null) {
    p = tmp;
    tmp = tmp.getNext();
   }
   if (tmp.getValue()<node.getValue()){
    //node插在链表的结尾。
    tmp.setNext(node) ;
    node.setPrev(tmp) ;
    node.setNext(null) ;
    if (tmp.getValue()+1==node.getValue()){     
     tmp.setHasRight(true) ;
     node.setHasLeft(true) ;
     if (tmp.isHasLeft()&&tmp.isHasRight()){
      p.setNext(node) ;
      node.setPrev(p) ;
      tmp=null ;      
     }
    }
   }
   else if (tmp.getValue()>node.getValue()){
    //node插在链表的中央。    
    if (tmp==first){
     //首先判断tmp是不是first
     first = node ;
     first.setHasLeft(false) ;
     first.setHasRight(false) ;
     first.setNext(tmp) ;
     first.setPrev(null) ; 
     tmp.setPrev(node) ;    
     if (first.getValue()+1==tmp.getValue()){      
      first.setHasRight(true) ;
      tmp.setHasLeft(true) ;
      if (tmp.isHasLeft()&&tmp.isHasRight()){
       //去掉tmp节点
       first.setNext(tmp.getNext()) ;
       tmp = null ;
      }
     }
    }
    else {     
     if (p.getValue()+2 == tmp.getValue()){
      //判断是不是p和tmp可以连续了
      p.setHasRight(true) ;
      tmp.setHasLeft(true) ;
     }
     else if (!p.isHasRight()&&!tmp.isHasLeft()){
      p.setNext(node) ;
      tmp.setPrev(node) ;
      node.setPrev(p) ;
      node.setNext(tmp) ;
      if (p.getValue()+1 == node.getValue()){
       p.setHasRight(true) ;
       node.setHasLeft(true) ;
      }
      else if (node.getValue()+1==tmp.getValue()){
       node.setHasRight(true) ;
       tmp.setHasLeft(true) ;
      }
     }
    }
   }
  }
 }
}

本文地址:http://com.8s8s.com/it/it17900.htm