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

BAT、网易、蘑菇街面试题整理-7

2016-04-06 22:31 561 查看
数据结构与算法

1. 链表与数组。

2. 队列和栈,出栈与入栈。

3. 链表的删除、插入、反向。

4. 字符串操作。
http://blog.csdn.net/WINCOL/article/details/4795369
5. Hash表的hash函数,冲突解决方法有哪些。

6. 各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。









      package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

/**

 * 冒泡排序

 * @author jianina

 *

 */

public class BubbleSort extends Sort{

    /**

     * 简单冒泡排序

     */
@Override
public void sort(int[] array) {
for (int i = 0; i < array.length-1; i++) {
for (int j = i+1; j < array.length; j++) {
if(array[j]<array[i]){
int temp =array[i];
array[i]=array[j];
array[j]=temp;
}
}

}

}

/**
* 优化算法2
* 优化不明显 ,反而比算法1还要慢
* @param array
*/
public void sort2(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j =array.length-2; j >=i; j--) {
if(array[j]>array[j+1]){
int temp =array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}

}

}

/**
* 优化算法3
* 只有当每个内循环排序完之后,便可以得出正确的排序结果,则后面的循环不再进行,
* 否则和算法1、算法2在时间上没有多大差别
* @param array
*/
public void sort3(int[] array) {
boolean flag=true;
for (int i = 0; i < array.length&&flag; i++) {
flag=false;

for (int j =array.length-2; j >=i; j--) {
if(array[j]>array[j+1]){
int temp =array[j];
array[j]=array[j+1];
array[j+1]=temp; 
flag=true;
}
}

}

}



package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

public class SimpleSelectionSort  extends  Sort{

    

/**
* 选择排序算法
* 每个位置看准了最小的才进行转换位置,减少了多余的交换位置
* 20万条数据量,冒泡50秒,选择15秒
*/
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
int min;
for (int i = 0; i < array.length-1; i++) {
 
min=i;
for (int j = i+1; j < array.length; j++) {

if(array[j]<array[min]){
min=j;
}
}

 
if(i!=min){
  int temp=array[i];
  array[i]=array[min];
  array[min]=temp;


}
}

}

   package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

/**

 * 插入排序

 * @author jianina

 *

 */

public class InsertSort extends Sort{

@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
for (int i = 1; i < array.length; i++) {
for (int j = i; j>0&&compare(array[j], array[j-1]); j--) {
changePostion(j,j-1, array);
}
}
}

public  void  sort2(int[] array){
int j;
for (int i = 2; i < array.length; i++) {

if(array[i]<array[i-1]){
array[0]=array[i];
for (j = i-1;array[j]>array[0]; j--) {
array[j+1]=array[j];
}

array[j+1]=array[0];

}

}
}

public void sort3(int[] array){

for (int i =1; i < array.length; i++) {
int key=array[i];
int j=i-1;
while(j>=0&&array[j]>key){
array[j+1]=array[j];
j-=1;

}

array[j+1]=key;
}
}

/**
* 递归实现
* @param array
*/
public void sort4(int[] array,int n){
if(n>1){
sort4(array,n-1);
}

if(array
<array[n-1]){
changePostion(n, n-1,array);
sort4(array, n-1);
}

}

}

package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

/**

 * 希尔排序

 * @author jianina

 *

 */

public class ShellSort extends Sort{

@Override
public void sort(int[] array) {
int length=array.length;

   int i, j, gap;  
 
   for (gap = length / 2; gap > 0; gap /= 2)  
       for (i = gap; i <length; i++)  
           for (j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap)  
              changePostion(j, j + gap, array);

}

public void sort2(int[] array){
int length=array.length;
int i,j,gap;

for (gap= length/2;gap>0; gap/=2) {
for (i = gap; i<length; i++) {
for (j= i-gap; j>=0&&array[j]>array[j+gap]; j-=gap) {
changePostion(j, j+gap, array);
}
}

}

}

}

package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

/**

 * 归并排序

 * @author jianina

 *

 */

public class MergeSort extends Sort{

   public static void main(String[] args) {
int[] array=new int[]{1,3,4,5,2,4,6,8};
merge(array, 0, 3, 7);
for (int i : array) {
System.out.println(i);
}

}
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
     sort(array,0,array.length-1);
}

public void sort(int[] array,int p,int r) {
// TODO Auto-generated method stub
     if(p<r){
     int q=(p+r)/2;
     sort(array,p,q);
     sort(array,q+1,r);
     merge2(array, p, q, r);
     }
}

public static void merge(int[] array,int p,int q,int r){
int n1=(q-p)+1;
int n2=r-q;

int[] d1=new int[n1+1];
int[] d2=new int[n2+1];

for(int i=0;i<n1;i++){
d1[i]=array[p+i];

}

for(int i=0;i<n2;i++){
d2[i]=array[q+i+1];

}

d1[n1]=Integer.MAX_VALUE;
d2[n2]=Integer.MAX_VALUE;

int i=0;
int j=0;
for(int k=p;k<=r;k++){
if(d1[i]<=d2[j]){
array[k]=d1[i];
i++;
}else{
array[k]=d2[j];
j++;
}
}

}

public static void merge2(int[] array,int p,int q,int r){
int n1=(q-p)+1;
int n2=r-q;

int[] d1=new int[n1];
int[] d2=new int[n2];

for(int i=0;i<n1;i++){
d1[i]=array[p+i];

}

for(int i=0;i<n2;i++){
d2[i]=array[q+i+1];

}

int i=0;
int j=0;
for(int k=p;k<=r;k++){

if(i>=n1){
array[k]=d2[j++];
continue;
}else if(j>=n2){
array[k]=d1[i++];
continue;
}

if(d1[i]<=d2[j]){
array[k]=d1[i];
i++;
continue;
}

if(d1[i]>d2[j]){
array[k]=d2[j];
j++;
continue;
}

}

}

       

}

 package com.algorithmz.sort.imple;

 

package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

/**

 * 快速排序

 * @author jianina

 *

 */

public class QuickSortM  extends Sort{

   public int changeCount;
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
sort(array, 0, array.length-1);
}

public void sort(int[] array,int low,int high) {
// TODO Auto-generated method stub
if(low<high){
int mid=partition(array, low, high);
sort(array,low,mid-1);
sort(array,mid+1,high);

}
}

/**while循环判断条件加不加等号情况分析:
* 不加双等 交换次数:378次,但是不加等号的速度最快
* 加一个双等 交换次数:174, 
* 条件加双等 交换次数149, 


*/

public int partition(int[] array,int low,int high){
int pivotkey=array[low];

while(low<high){

while(low<high&&array[high]>pivotkey){
high--;
}

if(low<high){
array[low]=array[high];
changeCount++;
low++;
}

while(low<high&&pivotkey>array[low]){
low++;
}
if(low<high){
array[high]=array[low];
changeCount++;
high--;
}

}

array[low]=pivotkey;
return low;
}

}

7. 快排的partition函数与归并的Merge函数。

归并Merge

public static void merge2(int[] array,int p,int q,int r){
int n1=(q-p)+1;
int n2=r-q;

int[] d1=new int[n1];
int[] d2=new int[n2];

for(int i=0;i<n1;i++){
d1[i]=array[p+i];

}

for(int i=0;i<n2;i++){
d2[i]=array[q+i+1];

}

int i=0;
int j=0;
for(int k=p;k<=r;k++){

if(i>=n1){
array[k]=d2[j++];
continue;
}else if(j>=n2){
array[k]=d1[i++];
continue;
}

if(d1[i]<=d2[j]){
array[k]=d1[i];
i++;
continue;
}

if(d1[i]>d2[j]){
array[k]=d2[j];
j++;
continue;
}

}

}

快拍parttition

public int partition(int[] array,int low,int high){
int pivotkey=array[low];

while(low<high){

while(low<high&&array[high]>pivotkey){
high--;
}

if(low<high){
array[low]=array[high];
changeCount++;
low++;
}

while(low<high&&pivotkey>array[low]){
low++;
}
if(low<high){
array[high]=array[low];
changeCount++;
high--;
}

}

array[low]=pivotkey;
return low;
}

8. 对冒泡与快排的改进。

冒泡优化:冒泡优化加上flag标识

package com.algorithmz.sort.imple;

import com.algorithmz.sort.Sort;

/**

 * 快速排序

 * @author jianina

 *

 */

public class QuickSortM  extends Sort{

   public int max_length_insert_sort=7;

   public InsertSort insertSort=new InsertSort();
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
sort(array, 0, array.length-1);
}

public void sort(int[] array,int low,int high) {
// TODO Auto-generated method stub

if(low<high) {
int pivoykey=partition(array, low, high);
sort(array,low,pivoykey-1);
sort(array,pivoykey+1,high);

}

}

/**
* 优化1加上阈值,当数组长度低于阈值是采用插入排序
* @param array
* @param low
* @param high
*/

public void sort2(int[] array) {
// TODO Auto-generated method stub
sort(array, 0, array.length-1);

}

public void sort2(int[] array,int low,int high) {
// TODO Auto-generated method stub
int pivoykey;
if((high-low)>max_length_insert_sort){
pivoykey=partition(array, low, high);
sort2(array,low,pivoykey-1);
sort2(array,pivoykey+1,high);
}
else{
InsertSort.sort4(array);
}

}

public void sort3(int[] array) {
// TODO Auto-generated method stub
sort3(array, 0, array.length-1);

}

/**
* 优化2再加上阈值的同时,采用尾递归,减少递归深度
* @param array
* @param low
* @param high
*/
public void sort3(int[] array,int low,int high) {
// TODO Auto-generated method stub
int pivoykey;
if((high-low)>max_length_insert_sort){

while (low<high) {
pivoykey=partition(array, low, high);
sort3(array,low,pivoykey-1);
low=pivoykey+1;
}
}
else{
InsertSort.sort4(array);
}

}

/**while循环判断条件加不加等号情况分析:
* 不加双等 交换次数:378次,但是不加等号的速度最快
* 加一个双等 交换次数:174, 
* 条件加双等 交换次数149, 


*/

public int partition(int[] array,int low,int high){
int pivotkey=array[low];

while(low<high){

while(low<high&&array[high]>pivotkey){
high--;
}

if(low<high){
array[low]=array[high];

low++;
}

while(low<high&&pivotkey>array[low]){
low++;
}
if(low<high){
array[high]=array[low];

high--;
}

}

array[low]=pivotkey;
return low;
}

}

9. 二分查找,与变种二分查找。

package com.algorithmz.binarysearch;

public class BinarySearch {
public static void main(String[] args) {
int[] array=new int[]{1,2,53,6,4,8};
System.out.println(binarySearch(array,-1));
}

public static int binarySearch(int[] a,int key) {

        int low = 0;

        int high = a.length - 1;

        int mid = 0;

        while(low <= high){

            mid = (low + high) / 2;

            if(a[mid] == key) return mid;

            if(a[mid] > key) high = mid - 1;

            if(a[mid] < key) low = mid + 1;

        }

        return -1;

    }

10. 二叉树、B+树、AVL树、红黑树、哈夫曼树。
http://blog.sina.com.cn/s/blog_9cbb6a210102v5dc.html http://blog.csdn.net/dongdong_java/article/details/9128983 http://blog.csdn.net/quitepig/article/details/8041308
11. 二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。

package com.algorithmz.binarytree;

import java.util.HashMap;

import java.util.LinkedList;

import java.util.Map;

import java.util.Queue;

import java.util.Stack;

public class BinaryTree {

 public static void main(String[] args) {
BinaryTree binaryTree=new BinaryTree();
binaryTree.createBinaryTree();
binaryTree.levelTravel(binaryTree.root);
}

     private TreeNode root=null;

     

     public BinaryTree(){

    root=new TreeNode(1,"rootNode(A)");

     }

     

     public BinaryTree(TreeNode root){

    this.root=root;

     

     }

     

     

     public void createBinaryTree(){

    TreeNode b=new TreeNode(2,"B");

    TreeNode c=new TreeNode(3,"C");

    TreeNode d=new TreeNode(4,"D");

    TreeNode e=new TreeNode(5,"E");

    TreeNode f=new TreeNode(6,"F");

     

    root.leftNode=b;

    root.rightNode=c;

    root.leftNode.leftNode=d;

    root.leftNode.rightNode=e;

    root.rightNode.rightNode=f;

     

   

     

     }

     

     public boolean isEmpty(){

    return root==null;

     }

     

     

     public int height(){

    return height(root);

     }

     

     

     public int height(TreeNode  treeNode){

    if(treeNode==null){

    return 0;

    }

    int i=height(treeNode.leftNode);

    int j=height(treeNode.rightNode);

     

     

    return i<j?(j+1):(i+1);

     

     }

     

     

     public int size(){

     

    return size(root);

     }

    

     

     public int size(TreeNode treeNode){

     

    if(treeNode==null){

    return 0;

    }

     

    return 1+size(treeNode.leftNode)+size(treeNode.rightNode);

     

     }

     

    

     public void visted(TreeNode subTree){

    subTree.isVisted=true;

    System.out.println("key:"+subTree.key+"  name:"+subTree.data);

     }

     

     

     

 

     /**

      * 前序遍历

      * @param subTree

      */

     public void preOrder(TreeNode subTree){

    if(subTree!=null){

    visted(subTree);

    preOrder(subTree.leftNode);

    preOrder(subTree.rightNode);

    }

     

     }

     

     

     

     /**

      * 前序遍历

      * @param subTree

      */

     public void inOrder(TreeNode subTree){

    if(subTree!=null){

   

    inOrder(subTree.leftNode);

    visted(subTree);

    inOrder(subTree.rightNode);

    }

     

     }

     

     

     public void postOrder(TreeNode subTree){

    if(subTree!=null){

    postOrder(subTree.leftNode);

    postOrder(subTree.rightNode);

    visted(subTree);

    }

     }

     

     

     /**

      * 二叉树非递归遍历实现

      * @param subTree

      */

     public void nonRecPreOrder(TreeNode subTree){

    Stack<TreeNode>  stack=new Stack<TreeNode>();

    TreeNode node=subTree;

    while(node!=null||stack.size()>0){

    while(node!=null){

    visted(node);

    stack.push(node);

    node=node.leftNode;

     

    }

     

    node=stack.pop();

    node=node.rightNode;

     

    }

     

     

     }

     

     

     

     /**

      * 二叉树中序非递归遍历

      * @param subTree

      */

     public void nonRecInOrder(TreeNode subTree){

    Stack<TreeNode> stack =new Stack<BinaryTree.TreeNode>();  

         TreeNode node =subTree;  

         while(node!=null||stack.size()>0){  

             //存在左子树  

             while(node!=null){  

                 stack.push(node);  

                 node=node.leftNode;  

             }  

             //栈非空  

             if(stack.size()>0){  

                 node=stack.pop();  

                 visted(node);  

                 node=node.rightNode;  

             }  

         }  

     

     }

     

     public  void nonRecPostOrder(TreeNode p){

     Stack<TreeNode> stack=new Stack<BinaryTree.TreeNode>();  

          TreeNode node =p;  

          while(p!=null){  

              //左子树入栈  

              for(;p.leftNode!=null;p=p.leftNode){  

                  stack.push(p);  

              }  

              //当前结点无右子树或右子树已经输出  

              while(p!=null&&(p.rightNode==null||p.rightNode==node)){  

                  visted(p);  

                  //纪录上一个已输出结点  

                  node =p;  

                  if(stack.empty())  

                      return;  

                  p=stack.pop();  

              }  

              //处理右子树  

              stack.push(p);  

              p=p.rightNode;  

          }

     

     

     }

       

       

       

     /** 

      *  

      * @param root 树根节点 

      * 层序遍历二叉树,用队列实现,先将根节点入队列,只要队列不为空,然后出队列,并访问,接着讲访问节点的左右子树依次入队列 

      */  

     public static void levelTravel(TreeNode root){  

         if(root==null)return;  

         Queue<TreeNode> q=new LinkedList<TreeNode>();  

         q.add(root);  

         while(!q.isEmpty()){  

        TreeNode temp =  q.poll();  

             System.out.println(temp.data);  

             if(temp.leftNode!=null)

            q.add(temp.leftNode);  

             if(temp.rightNode!=null)

            q.add(temp.rightNode);  

         }  

     }  

     

     

     /** 

      *  

      * @param root 树根节点 

      * 利用栈实现循环先序遍历二叉树 

      * 这种实现类似于图的深度优先遍历(DFS) 

      * 维护一个栈,将根节点入栈,然后只要栈不为空,出栈并访问,接着依次将访问节点的右节点、左节点入栈。 

      * 这种方式应该是对先序遍历的一种特殊实现(看上去简单明了),但是不具备很好的扩展性,在中序和后序方式中不适用 

      */  

     public static void preOrderStack_1(TreeNode root){  

         if(root==null)return;  

         Stack<TreeNode> s=new Stack<TreeNode>();  

         s.push(root);  

         while(!s.isEmpty()){  

        TreeNode temp=s.pop();  

             System.out.println(temp.data);  

             if(temp.rightNode!=null) s.push(temp.rightNode);  

             if(temp.leftNode!=null) s.push(temp.leftNode);  

         }  

     }  

     /** 

      *  

      * @param root 树的根节点 

      * 利用栈模拟递归过程实现循环先序遍历二叉树 

      * 这种方式具备扩展性,它模拟递归的过程,将左子树点不断的压入栈,直到null,然后处理栈顶节点的右子树 

      */  

     public static void preOrderStack_2(TreeNode root){  

         if(root==null)return;  

         Stack<TreeNode> s=new Stack<TreeNode>();  

         while(root!=null||!s.isEmpty()){  

             while(root!=null){  

                 System.out.println(root.data);  

                 s.push(root);//先访问再入栈  

                 root=root.leftNode;  

             }  

             root=s.pop();  

             root=root.leftNode;//如果是null,出栈并处理右子树  

         }  

     }  

     /** 

      *  

      * @param root 树根节点 

      * 利用栈模拟递归过程实现循环中序遍历二叉树 

      * 思想和上面的preOrderStack_2相同,只是访问的时间是在左子树都处理完直到null的时候出栈并访问。 

      */  

     public static void inOrderStack(TreeNode root){  

         if(root==null)return;  

         Stack<TreeNode> s=new Stack<TreeNode>();  

         while(root!=null||!s.isEmpty()){  

             while(root!=null){  

                 s.push(root);//先访问再入栈  

                 root=root.leftNode;  

             }  

             root=s.pop();  

             System.out.println(root.data);  

             root=root.rightNode;//如果是null,出栈并处理右子树  

         }  

     }  

     /** 

      *  

      * @param root 树根节点 

      * 后序遍历不同于先序和中序,它是要先处理完左右子树,然后再处理根(回溯),所以需要一个记录哪些节点已经被访问的结构(可以在树结构里面加一个标记),这里可以用map实现 

      */  

     public static void postOrderStack(TreeNode root){  

         if(root==null)return;  

         Stack<TreeNode> s=new Stack<TreeNode>();  

         Map<TreeNode,Boolean> map=new HashMap<TreeNode,Boolean>();   

         s.push(root);  

         while(!s.isEmpty()){  

        TreeNode temp=s.peek();  

             if(temp.leftNode!=null&&!map.containsKey(temp.leftNode)){  

                 temp=temp.leftNode;  

                 while(temp!=null){  

                     if(map.containsKey(temp))break;  

                     else s.push(temp);  

                     temp=temp.leftNode;  

                 }  

                 continue;  

             }  

             if(temp.rightNode!=null&&!map.containsKey(temp.rightNode)){  

                 s.push(temp.rightNode);  

                 continue;  

             }  

             TreeNode t=s.pop();  

             map.put(t,true);  

             System.out.println(t.data);  

         }  

     }  

 

       

       

       

       

       

       private static class TreeNode{

      

      private int key;

      private String data;

      private boolean isVisted;

      private TreeNode leftNode;

      private TreeNode rightNode;

      

      public  TreeNode(){

      

      }

      

            public  TreeNode(int key,String data){

      this.key=key;

      this.data=data;

      

      }

            

            

            public  TreeNode(int key,String data,TreeNode leftNode,TreeNode rightNode){

        this.key=key;

        this.data=data;

        this.leftNode=leftNode;

        this.rightNode=rightNode;

        

        

        }

      

       }

}

12. 图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。

13. KMP算法。
http://blog.csdn.net/yutianzuijin/article/details/11954939
14. 排列组合问题。

15. 动态规划、贪心算法、分治算法。(一般不会问到)

16. 大数据处理:类似10亿条数据找出最大的1000个数.........等等

算法的话其实是个重点,因为最后都是要你写代码,所以算法还是需要花不少时间准备,这里有太多算法题,写不全,我的建议是没事多在OJ上刷刷题(牛客网、leetcode等),剑指offer上的算法要能理解并自己写出来,编程之美也推荐看一看。

推荐书籍:《大话数据结构》《剑指offer》《编程之美》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: