Java面试题数据结构

xiaoxiao2021-02-28  122

136、给出下面的二叉树先序、中序、后序遍历的序列?

答:先序序列:ABDEGHCF;中序序列:DBGEHACF;后序序列:DGHEBFCA。

补充:二叉树也称为二分树,它是树形结构的一种,其特点是每个结点至多有二棵子树,并且二叉树的子树有左右之分,其次序不能任意颠倒。二叉树的遍历序列按照访问根节点的顺序分为先序(先访问根节点,接下来先序访问左子树,再先序访问右子树)、中序(先中序访问左子树,然后访问根节点,最后中序访问右子树)和后序(先后序访问左子树,再后序访问右子树,最后访问根节点)。如果知道一棵二叉树的先序和中序序列或者中序和后序序列,那么也可以还原出该二叉树。

例如,已知二叉树的先序序列为:xefdzmhqsk,中序序列为:fezdmxqhks,那么还原出该二叉树应该如下图所示:

 

137、你知道的排序算法都哪些?用Java写一个排序系统。

答:稳定的排序算法有:插入排序、选择排序、冒泡排序、鸡尾酒排序、归并排序、二叉树排序、基数排序等;不稳定排序算法包括:希尔排序、堆排序、快速排序等。

下面是关于排序算法的一个列表:

下面按照策略模式给出一个排序系统,实现了冒泡、归并和快速排序。

Sorter.java

[java]  view plain  copy package com.jackfrued.util;       import java.util.Comparator;       /**   * 排序器接口(策略模式: 将算法封装到具有共同接口的独立的类中使得它们可以相互替换)   * @author   *   */   public interface Sorter {           /**      * 排序      * @param list 待排序的数组      */      public <T extends Comparable<T>> void sort(T[] list);           /**      * 排序      * @param list 待排序的数组      * @param comp 比较两个对象的比较器      */      public <T> void sort(T[] list, Comparator<T> comp);   }    

BubbleSorter.java

[java]  view plain  copy package com.jackfrued.util;       import java.util.Comparator;       /**   * 冒泡排序   * @author   *   */   public class BubbleSorter implements Sorter {          @Override      public <T extends Comparable<T>> void sort(T[] list) {         boolean swapped = true;         for(int i = 1; i < list.length && swapped;i++) {           swapped= false;           for(int j = 0; j < list.length - i; j++) {              if(list[j].compareTo(list[j+ 1]) > 0 ) {                 T temp = list[j];                 list[j]= list[j + 1];                 list[j+ 1] = temp;                 swapped= true;              }           }         }      }          @Override      public <T> void sort(T[] list,Comparator<T> comp) {         boolean swapped = true;         for(int i = 1; i < list.length && swapped; i++) {           swapped = false;           for(int j = 0; j < list.length - i; j++) {              if(comp.compare(list[j], list[j + 1]) > 0 ) {                 T temp = list[j];                 list[j]= list[j + 1];                 list[j+ 1] = temp;                 swapped= true;              }           }         }      }    }    

MergeSorter.java

[java]  view plain  copy package com.jackfrued.util;       import java.util.Comparator;       /**   * 归并排序   * 归并排序是建立在归并操作上的一种有效的排序算法。   * 该算法是采用分治法(divide-and-conquer)的一个非常典型的应用,   * 先将待排序的序列划分成一个一个的元素,再进行两两归并,   * 在归并的过程中保持归并之后的序列仍然有序。   * @author   *   */   public class MergeSorter implements Sorter {          @Override      public <T extends Comparable<T>> void sort(T[] list) {         T[] temp = (T[]) new Comparable[list.length];         mSort(list,temp, 0, list.length- 1);      }           private <T extends Comparable<T>> void mSort(T[] list, T[] temp, int low, int high) {         if(low == high) {           return ;         }         else {           int mid = low + ((high -low) >> 1);           mSort(list,temp, low, mid);           mSort(list,temp, mid + 1, high);           merge(list,temp, low, mid + 1, high);         }      }           private <T extends Comparable<T>> void merge(T[] list, T[] temp, int left, int right, int last) {           int j = 0;            int lowIndex = left;            int mid = right - 1;            int n = last - lowIndex + 1;            while (left <= mid && right <= last){                if (list[left].compareTo(list[right]) < 0){                    temp[j++] = list[left++];                } else {                    temp[j++] = list[right++];                }            }            while (left <= mid) {                temp[j++] = list[left++];            }            while (right <= last) {                temp[j++] = list[right++];            }            for (j = 0; j < n; j++) {                list[lowIndex + j] = temp[j];            }       }          @Override      public <T> void sort(T[] list, Comparator<T> comp) {         T[]temp = (T[])new Comparable[list.length];         mSort(list,temp, 0, list.length- 1, comp);      }           private <T> void mSort(T[] list, T[] temp, int low, int high, Comparator<T> comp) {         if(low == high) {           return ;         }         else {           int mid = low + ((high -low) >> 1);           mSort(list,temp, low, mid, comp);           mSort(list,temp, mid + 1, high, comp);           merge(list,temp, low, mid + 1, high, comp);         }      }           private <T> void merge(T[] list, T[]temp, int left, int right, int last, Comparator<T> comp) {           int j = 0;            int lowIndex = left;            int mid = right - 1;            int n = last - lowIndex + 1;            while (left <= mid && right <= last){                if (comp.compare(list[left], list[right]) <0) {                    temp[j++] = list[left++];                } else {                    temp[j++] = list[right++];                }            }            while (left <= mid) {                temp[j++] = list[left++];            }            while (right <= last) {                temp[j++] = list[right++];            }            for (j = 0; j < n; j++) {                list[lowIndex + j] = temp[j];            }       }       }    

QuickSorter.java

[java]  view plain  copy package com.jackfrued.util;       import java.util.Comparator;       /**   * 快速排序   * 快速排序是使用分治法(divide-and-conquer)依选定的枢轴   * 将待排序序列划分成两个子序列,其中一个子序列的元素都小于枢轴,   * 另一个子序列的元素都大于或等于枢轴,然后对子序列重复上面的方法,   * 直到子序列中只有一个元素为止   * @author    *   */   public class QuickSorter implements Sorter {          @Override      public <T extends Comparable<T>> void sort(T[] list) {         quickSort(list, 0, list.length- 1);      }          @Override      public <T> void sort(T[] list, Comparator<T> comp) {         quickSort(list, 0, list.length- 1, comp);      }          private <T extends Comparable<T>> void quickSort(T[] list, int first, int last) {         if (last > first) {           int pivotIndex = partition(list, first, last);           quickSort(list, first, pivotIndex - 1);           quickSort(list, pivotIndex, last);         }      }           private <T> void quickSort(T[] list, int first, int last,Comparator<T> comp) {         if (last > first) {           int pivotIndex = partition(list, first, last, comp);           quickSort(list, first, pivotIndex - 1, comp);           quickSort(list, pivotIndex, last, comp);         }      }          private <T extends Comparable<T>> int partition(T[] list, int first, int last) {         T pivot = list[first];         int low = first + 1;         int high = last;             while (high > low) {           while (low <= high && list[low].compareTo(pivot) <= 0) {              low++;           }           while (low <= high && list[high].compareTo(pivot) >= 0) {              high--;           }           if (high > low) {              T temp = list[high];              list[high]= list[low];              list[low]= temp;           }         }             while (high > first&& list[high].compareTo(pivot) >= 0) {           high--;         }         if (pivot.compareTo(list[high])> 0) {           list[first]= list[high];           list[high]= pivot;           return high;         }         else {           return low;         }      }          private <T> int partition(T[] list, int first, int last, Comparator<T> comp) {         T pivot = list[first];         int low = first + 1;         int high = last;             while (high > low) {           while (low <= high&& comp.compare(list[low], pivot) <= 0) {              low++;           }           while (low <= high&& comp.compare(list[high], pivot) >= 0) {              high--;           }           if (high > low) {              T temp = list[high];              list[high] = list[low];              list[low]= temp;           }         }             while (high > first&& comp.compare(list[high], pivot) >= 0) {           high--;         }         if (comp.compare(pivot,list[high]) > 0) {           list[first]= list[high];           list[high]= pivot;           return high;         }         else {           return low;         }      }        }    

138、写一个二分查找(折半搜索)的算法。

答:折半搜索,也称二分查找算法、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

[java]  view plain  copy package com.jackfrued.util;       import java.util.Comparator;       public class MyUtil {          public static <T extends Comparable<T>> int binarySearch(T[] x, T key) {         return binarySearch(x, 0, x.length- 1, key);      }           public static <T> int binarySearch(T[] x, T key, Comparator<T> comp) {         int low = 0;         int high = x.length - 1;         while (low <= high) {             int mid = (low + high) >>> 1;             int cmp = comp.compare(x[mid], key);             if (cmp < 0) {               low = mid + 1;             }             else if (cmp > 0) {               high = mid - 1;             }             else {               return mid;             }         }         return -1;      }           private static <T extends Comparable<T>> int binarySearch(T[] x, int low, int high, T key) {         if(low <= high) {             int mid = low + ((high -low) >> 1);             if(key.compareTo(x[mid]) == 0) {                 return mid;             }             else if(key.compareTo(x[mid])< 0) {                 return binarySearch(x,l ow, mid - 1, key);             }             else {                 return binarySearch(x, mid + 1, high, key);             }         }         return -1;      }   }   说明:两个版本一个用递归实现,一个用循环实现。需要注意的是计算中间位置时不应该使用(high+ low) / 2的方式,因为加法运算可能导致整数越界,这里应该使用一下三种方式之一:low+ (high – low) / 2或low + (high – low) >> 1或(low + high) >>> 1(注:>>>是逻辑右移,不带符号位的右移)

 

139、统计一篇英文文章中单词个数。

答:

[java]  view plain  copy import java.io.FileReader;       public class WordCounting {          public static void main(String[] args) {        try(FileReader fr = new FileReader("a.txt")) {           int counter = 0;           boolean state = false;           int currentChar;           while((currentChar= fr.read()) != -1) {             if(currentChar== ' ' || currentChar == '\n'                || currentChar == '\t' || currentChar == '\r') {                state = false;             }             else if(!state) {                state = true;                counter++;             }           }           System.out.println(counter);        }        catch(Exceptione) {           e.printStackTrace();        }      }   }   补充:这个程序可能有很多种写法,这里选择的是Dennis M. Ritchie和Brian W. Kernighan老师在他们不朽的著作《The C Programming Language》中给出的代码,向两位老师致敬。下面的代码也是如此。

 

140、输入年月日,计算该日期是这一年的第几天。

答:

[java]  view plain  copy import java.util.Scanner;       public class DayCounting {          public static void main(String[] args) {         int[][] data = {              {31,2831303130313130313031},              {31,2931303130313130313031}         };         Scanner sc = newScanner(System.in);         System.out.print("请输入年月日(1980 11 28): ");         int year = sc.nextInt();         int month = sc.nextInt();         int date = sc.nextInt();         int[] daysOfMonth = data[(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)?1 : 0];         int sum = 0;         for(int i = 0; i < month -1; i++) {           sum += daysOfMonth[i];         }         sum += date;         System.out.println(sum);         sc.close();      }   }    

141、约瑟夫环:15个基督教徒和15个非教徒在海上遇险,必须将其中一半的人投入海中,其余的人才能幸免于难,于是30个人围成一圈,从某一个人开始从1报数,报到9的人就扔进大海,他后面的人继续从1开始报数,重复上面的规则,直到剩下15个人为止。结果由于上帝的保佑,15个基督教徒最后都幸免于难,问原来这些人是怎么排列的,哪些位置是基督教徒,哪些位置是非教徒。

答:

[java]  view plain  copy public class Josephu {      private static final int DEAD_NUM = 9;           public static void main(String[] args) {         boolean[] persons = new boolean[30];         for(int i = 0; i < persons.length; i++) {           persons[i] = true;         }                 int counter = 0;         int claimNumber = 0;         int index = 0;         while(counter < 15) {           if(persons[index]) {              claimNumber++;              if(claimNumber == DEAD_NUM) {                 counter++;                 claimNumber= 0;                 persons[index]= false;              }           }           index++;           if(index >= persons.length) {              index= 0;            }         }         for(boolean p : persons) {           if(p) {              System.out.print("基");           }           else {              System.out.print("非");           }         }      }   }    

142、回文素数:所谓回文数就是顺着读和倒着读一样的数(例如:11,121,1991…),回文素数就是既是回文数又是素数(只能被1和自身整除的数)的数。编程找出11~9999之间的回文素数。

答:

[java]  view plain  copy public class PalindromicPrimeNumber {          public static void main(String[] args) {         for(int i = 11; i <= 9999; i++) {           if(isPrime(i) && isPalindromic(i)) {              System.out.println(i);           }         }      }           public static boolean isPrime(int n) {         for(int i = 2; i <= Math.sqrt(n); i++) {            if(n % i == 0) {              return false;           }         }         return true;      }           public static boolean isPalindromic(int n) {         int temp = n;         int sum = 0;         while(temp > 0) {           sum= sum * 10 + temp % 10;           temp/= 10;         }         return sum == n;      }   }    

143、全排列:给出五个数字12345的所有排列。

答:

[java]  view plain  copy public class FullPermutation {          public static void perm(int[] list) {         perm(list,0);      }          private static void perm(int[] list, int k) {         if (k == list.length) {           for (int i = 0; i < list.length; i++) {              System.out.print(list[i]);           }            System.out.println();         }else{           for (int i = k; i < list.length; i++) {              swap(list, k, i);              perm(list, k + 1);              swap(list, k, i);           }         }      }          private static void swap(int[] list, int pos1, int pos2) {         int temp = list[pos1];         list[pos1] = list[pos2];         list[pos2] = temp;      }          public static void main(String[] args) {         int[] x = {12345};         perm(x);      }   }       144、对于一个有N个整数元素的一维数组,找出它的子数组(数组中下标连续的元素组成的数组)之和的最大值。

答:下面给出几个例子(最大子数组用粗体表示):

1) 数组:{ 1, -2, 3,5, -3, 2 },结果是:8

2) 数组:{ 0, -2, 3, 5, -1, 2 },结果是:9

3) 数组:{ -9, -2,-3, -5, -3 },结果是:-2

可以使用动态规划的思想求解:

[java]  view plain  copy public class MaxSum {          private static int max(int x, int y) {         return x > y? x: y;      }           public static int maxSum(int[] array) {         int n = array.length;         int[] start = new int[n];         int[] all = new int[n];         all[n - 1] = start[n - 1] = array[n - 1];         for(int i = n - 2; i >= 0;i--) {           start[i] = max(array[i], array[i] + start[i + 1]);           all[i] = max(start[i], all[i + 1]);         }         return all[0];      }           public static void main(String[] args) {         int[] x1 = { 1, -235,-32 };         int[] x2 = { 0, -235,-12 };         int[] x3 = { -9, -2, -3,-5, -3 };         System.out.println(maxSum(x1));   // 8         System.out.println(maxSum(x2));   // 9         System.out.println(maxSum(x3));   //-2      }   }    

145、用递归实现字符串倒转

答:

[java]  view plain  copy public class StringReverse {          public static String reverse(String originStr) {         if(originStr == null || originStr.length()== 1) {             return originStr;         }         return reverse(originStr.substring(1))+ originStr.charAt(0);      }           public static void main(String[] args) {         System.out.println(reverse("hello"));      }   }       146、输入一个正整数,将其分解为素数的乘积。

答:

[java]  view plain  copy public class DecomposeInteger {          private static List<Integer> list = newArrayList<Integer>();           public static void main(String[] args) {          System.out.print("请输入一个数: ");          Scanner sc = newScanner(System.in);          int n = sc.nextInt();          decomposeNumber(n);          System.out.print(n + " = ");          for(int i = 0; i < list.size() - 1; i++) {              System.out.print(list.get(i) + " * ");          }          System.out.println(list.get(list.size() - 1));      }           public static void decomposeNumber(int n) {         if(isPrime(n)) {           list.add(n);           list.add(1);         }         else {           doIt(n, (int)Math.sqrt(n));         }      }           public static void doIt(int n, int div) {         if(isPrime(div) && n % div == 0) {           list.add(div);           decomposeNumber(n / div);         }         else {           doIt(n, div - 1);         }      }          public static boolean isPrime(int n) {         for(int i = 2; i <= Math.sqrt(n);i++) {           if(n % i == 0) {              return false;           }         }         return true;      }   }    

147、一个有n级的台阶,一次可以走1级、2级或3级,问走完n级台阶有多少种走法。

答:可以通过递归求解。

[java]  view plain  copy public class GoSteps {          public static int countWays(int n) {            if(n < 0) {                return 0;            }            else if(n == 0) {                return 1;            }            else {                return countWays(n - 1) + countWays(n - 2) + countWays(n -3);            }       }               public static void main(String[] args) {            System.out.println(countWays(5));   // 13        }    }    

148、写一个算法判断一个英文单词的所有字母是否全都不同(不区分大小写)。

答:

[java]  view plain  copy public class AllNotTheSame {          public static boolean judge(String str) {         String temp = str.toLowerCase();         int[] letterCounter = new int[26];         for(int i = 0; i <temp.length(); i++) {           int index = temp.charAt(i)- 'a';           letterCounter[index]++;           if(letterCounter[index] > 1) {              return false;           }         }         return true;      }           public static void main(String[] args) {         System.out.println(judge("hello"));         System.out.print(judge("smile"));      }   }  

149、有一个已经排好序的整数数组,其中存在重复元素,请将重复元素删除掉,例如,A= [1, 1, 2, 2, 3],处理之后的数组应当为A= [1, 2, 3]。

答:

[java]  view plain  copy import java.util.Arrays;       public class RemoveDuplication {          public static int[] removeDuplicates(int a[]) {            if(a.length <= 1) {                return a;            }            int index = 0;            for(int i = 1; i < a.length; i++) {                if(a[index] != a[i]) {                    a[++index] = a[i];                }            }            int[] b = new int[index + 1];            System.arraycopy(a, 0, b, 0, b.length);            return b;       }               public static void main(String[] args) {            int[] a = {11223};            a = removeDuplicates(a);            System.out.println(Arrays.toString(a));       }    }    

150、给一个数组,其中有一个重复元素占半数以上,找出这个元素。

答:

[java]  view plain  copy public class FindMost {          public static <T> T find(T[] x){         T temp = null;         for(int i = 0, nTimes = 0; i< x.length;i++) {             if(nTimes == 0) {                 temp= x[i];                 nTimes= 1;             }             else {                 if(x[i].equals(temp)) {                     nTimes++;                 }                 else {                     nTimes--;                 }             }         }         return temp;      }           public static void main(String[] args) {         String[]strs = {"hello","kiss","hello","hello","maybe"};         System.out.println(find(strs));      }   }      
转载请注明原文地址: https://www.6miu.com/read-25913.html

最新回复(0)