上回看到一道微软的算法题,题目大概是说:有一个很大的整型数组,我们怎样能够找到一个不在这个数组中的值。 假设一个数组的大小很大(比如说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) ; } } } } } } }

|