常见数据结构和算法编程题
1.二叉树的深度
public class Solution {
public int TreeDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(TreeDepth(root.left), TreeDepth(root.right)) + 1;
}
}
2.判断平衡二叉树
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
if (root == null)
return true;
if (Math.abs(TreeDepth(root.left) - TreeDepth(root.right)) > 1)
return false;
return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
}
//计算二叉树的深度
public int TreeDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(TreeDepth(root.left), TreeDepth(root.right)) + 1;
}
}
3.排序算法总结
排序类别 | 排序名称 (时间复杂度,空间复杂度,排序是否稳定) |
---|---|
交换类排序 | 冒泡排序 (n², 1, 是) |
快速排序 (nlogn, logn, 否) | |
插入类排序 | 直接插入排序 (n², 1, 是) |
折半插入(二分排序) ( n²,1,是) | |
希尔排序 (nlogn, 1, 否) | |
选择类排序 | 简单选择排序 (n², 1, 否) |
堆排序 (nlogn, 1, 否) | |
归并排序 | 归并排序 (nlogn, n, 是) |
基类排序 | 基类排序 (dn, n, 是) |
+++++++++
交换类排序源码
/**
* <冒泡排序>
* 根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,
* 凡扫描到违反本原则的轻气泡,就使其向上“漂浮”
*/
public static void Bubble(int[] a) {
// System.out.println("******冒泡排序******");
for (int i = 0; i < a.length - 1; i++) {
boolean exchange = false;
for (int j = a.length - 1; j > i; j--) {
if (a[j - 1] > a[j]) {
swap(a, j - 1, j);
exchange = true;
}
}
if (!exchange) {
return;
}
}
}
---------------------------------
/**
* <快速排序>
* 选取一个基准值,然后使 左边队列的值≦基准值≦右边队列的值
* 通过递归调用对左右子区间快速排序得到结果
*/
public static void QSort(int[] a, int low, int high) {
int i, j, temp;
if (low < high) {
i = low;
j = high;
temp = a[i];
while (i < j) {
while (i < j && a[j] > temp)
j--;
if (i < j) {
a[i] = a[j];
i++;
}
while (i < j && a[i] < temp)
i++;
if (i < j) {
a[j] = a[i];
j--;
}
}
a[i] = temp;
QSort(a, low, i - 1);
QSort(a, i + 1, high);
}
}
++++++
插入类排序源码
/**
* <直接插入排序>
* 从第一个元素开始,该元素可以认为已经被排好序。
* 取出下一个元素,在已经排序的元素序列中从后往前扫描
* 如果已排序的元素大于新元素,则将该元素与后一位的新元素交换位置
*/
public static void InsertSort(int[] a) {
int i, j;
// System.out.println("******插入排序******");
for (i = 1; i < a.length; i++) {
for (j = i; j > 0 && a[j] < a[j - 1]; j--) {
swap(a, j, j - 1);
}
}
}
------------------------
/**
* <折半插入排序(二分排序)>
* 在直接插入排序的基础上,取出下一个元素时,不是扫描插入,
* 而是通过二分查找的方式确定新元素要插入已排序中的位置,
* 再直接后移位置,插入新元素。
*/
public static void BinaryInsertSort(int[] a) {
int i, j, low, high, m, temp;
// System.out.println("******二分排序******");
for (i = 1; i <= a.length; i++) {
temp = a[i];
low = 1;
high = i - 1;
while (low <= high) {
m = (low + high) / 2;
if (temp < a[m])
high = m - 1;
else
low = m + 1;
} // while
for (j = i - 1; j > high; j--)
a[j + 1] = a[j];
a[high + 1] = temp;
}
}// BinaryInsertSort
-------------------------
/**
* 希尔排序
*/
public static int ShellSort(int[] a, int dlta[], int t) {
int count = 0;
for (int i = 0; i < t; i++) {
count = ShellInsert(a, dlta[i]);
}
return count;
}
public static int ShellInsert(int[] a, int dk) {
int i, j, count = 0;
for (i = dk + 1; i < a.length; i++) {
if (a[i] < a[i - dk])
a[0] = a[i];
for (j = i - dk; j > 0 && a[0] < a[j]; j -= dk) {
a[j + dk] = a[j];
count++;
}
a[j + dk] = a[0];
}
return count;
}
++++++
选择类排序源码
/**
* <选择排序>
* 首先在未排序序列中找到最小元素,存放到排序序列的起始位置,
* 然后,再从剩余未排序元素中继续寻找最小元素,放到排序序列末尾。
* 以此类推,直到所有的元素均排序完毕。
*/
public static void SelectSort(int[] a) {
// System.out.println("******选择排序******");
for (int i = 0; i < a.length; i++) {
boolean exchange = false;
for (int j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) {
swap(a, i, j);
exchange = true;
}
}
if (!exchange) {
return;
}
}
}
4.判断两个数组中是否存在相同的数字 问题
有一个 O(n)算法。因为两个数组都是排好序的。所以只要一次遍历就行了。首先设两个下标,分别初始化为两个数组的起始地址,依次向前推进。推进的规则是比较两个数组中的数字,小的那个数组的下标向前推进一步,直到任何一个数组的下标到达数组末尾时,如果这时还没碰到相同的数字,说明数组中没有相同的数字。
public class Solution {
// 判断两个已排好序的数组是否有相同的元素
public Boolean find(int[] a, int size1, int[] b, int size2){
int i=0,j=0;
while(i<size1&&j<size2){
if(a[i]==b[j])
return true;
if(a[i]>b[j])
j++;
if(a[i]<b[j])
i++;
}
return false;
}
}
5.最大子序列 问题
给定一整数序列A1, A2,… An (可能有负数),求A1~An的一个子序列Ai~Aj,使得Ai到Aj的和最大
这里运用动态规划的思想求解,可以使时间复杂度降为O(n)
public class Solution {
// 利用动态规划 查找最大子序列和
static int max_sub2(int[] a, int size) {
int i, temp_sum = 0, max = 0;
for (i = 0; i < size; i++) {
temp_sum += a[i];
if (temp_sum > max)
max = temp_sum;
}
return max;
}
}
6.按单词反转字符串/按字母反转单词
三种变换形态都将囊括
public class Solution {
// java实现字母反转 "Hello This is my house"-->"olleH sihT si ym esuoh"
public static String word_reverse(String str){
String reverse_str = "";
String[] array = null;
array = str.split(" ");
for (int i = 0; i < array.length; i++) {
StringBuffer sb = new StringBuffer(array[i]);
reverse_str +=sb.reverse().toString()+" ";
}
return reverse_str;
}
// java实现单词反转 "Hello This is my house"-->"house my is This Hello"
public static String word_reverse2(String str){
String reverse_str = "";
String[] array = null;
array = str.split(" ");
for (int i = array.length-1; i >= 0; i--) {
reverse_str +=array[i].toString()+" ";
}
return reverse_str;
}
//java实现单词+字母反转 "Hello This is my house"-->"esuoh ym si sihT olleH"
public static String word_reverse3(String str){
String reverse_str = "";
String[] array = null;
array = str.split(" ");
for (int i = array.length-1; i >= 0; i--) {
StringBuffer sb = new StringBuffer(array[i]);
reverse_str +=sb.reverse().toString()+" ";
}
return reverse_str;
}
}
7.删除数组中重复的数字
问题:一个动态长度可变的数字序列,以数字0为结束标志,要求将重复的数字用一个数字代替
public class Solution {
// Java中利用ArrayList去除重复的元素
public static List removeDuplicates(int[] a) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < a.length; i++) {
if (!list.contains(a[i])) {
list.add(a[i]);
}
}
return list;
}
}