1. 程式人生 > >【Java基礎總結】-演算法題總結

【Java基礎總結】-演算法題總結

常見資料結構和演算法程式設計題

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;
    }
}