黄忠的技术博客

永不停息的战争

一些有意思的算法[续]

  • 标签:
  • tec

继上次一些有意思的算法之后,我陆续整理了一些常用算法,以及一些在面试中常见的算法,也许你胸有成竹,也许你初次了解,都知道你读一读,温故而知新。希望你有新的收获,如有问题,或者对算法有更好的优化都,请联系我。

```
import java.util.ArrayList;
import java.util.List;

 /**    
* User: chris     
* Date: 2013-07-31   
*/    
public class SomeAlgorithm {

/**
 * 打印数组
 *
 * @param arr
 */
public static void printArr(int[] arr) {
    if (validate(arr)) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }
}

/**
 * 查找数组的平衡点,使得平衡点左边的数据之和等于平衡点右边数据之和
 * <p/>
 * 思路:
 * 1. 先求出数组的总和 sum
 * 2. 遍历所有数据,记录左边的数据总和left,并记录右边的数据之和right=sum-left
 * 3. 如果在位置index出,有left = right则Index就是平衡点
 * <p/>
 * 分析:
 */
public static List<Integer> pinghengPoint(int[] arr) {
    if (arr == null && arr.length == 0) {
        return null;
    }

    int sum = 0;
    for (int i = 0; i < arr.length; i++) {
        sum += arr[i];
    }

    List<Integer> index = new ArrayList<Integer>();
    int left = 0;
    int right = sum;
    for (int i = 0; i < arr.length; i++) {
        if (left == right - arr[i]) {
            index.add(i);
            System.out.println(i + " : " + arr[i]);
        }

        left += arr[i];
        right -= arr[i];
    }
    return index;
}

/*
* 插入排序原理:
* 在前i个数据中,从末尾位置开始进行两两比较排序;i++
*
* 时间复杂度:
* 平均O(n2),最坏情况O(n2)。
*/
public static void insertSortAsc(int[] arr) {
    if (arr == null && arr.length == 0) {
        return;
    }

    for (int i = 1; i < arr.length; i++) {
        for (int j = i - 1; j >= 0; j--) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1); // 交换
            }
        }
    }
}

/*
* 冒泡排序原理:
* 在前N-i个数中,从开始位置开始进行两两比较排序;i++
*
* 时间复杂度:
* 平均O(n2),最坏情况O(n2)。
*/
public static void bubbleSortAsc(int[] arr) {
    if (arr == null && arr.length == 0) {
        return;
    }

    for (int i = 1; i < arr.length; i++) {
        for (int j = 0; j < arr.length - i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1);
            }
        }
    }
}

/*
* 简选择排序原理:
* 在后N-i个数中,选择最小的值和i进行交换
*
* 时间复杂度:
* 平均O(n2),最坏情况O(n2)
*/
public static void selectSortAsc(int[] arr) {
    if (arr == null && arr.length == 0) {
        return;
    }

    for (int i = 0; i < arr.length - 1; i++) {
        int minIndex = i;
        int min = arr[i];

        for (int j = i + 1; j < arr.length; j++) {// 在后面, 找最小的.
            if (arr[j] < min) {
                minIndex = j;
                min = arr[j];
            }
        }

        if (minIndex != i) {
            swap(arr, i, minIndex);
        }
    }
}

/*
 * 二分查找特定整数在整型数组中的位置(递归)
 * <p/>
 * 条件:
 * 查找线性表必须是有序列表
 */
public int binarySearch(int[] arr, int data, int beginIndex, int endIndex) {
    if (arr == null && arr.length == 0) {
        return -1;
    }

    //相当于mid = (low + high) / 2,但是效率会高些
    int midIndex = (beginIndex + endIndex) >>> 1;
    if (data < arr[beginIndex] || data > arr[endIndex] || beginIndex > endIndex)
        return -1;
    if (data < arr[midIndex]) {
        return binarySearch(arr, data, beginIndex, midIndex - 1);
    } else if (data > arr[midIndex]) {
        return binarySearch(arr, data, midIndex + 1, endIndex);
    } else {
        return midIndex;
    }
}

/**
 * 二分查找特定整数在整型数组中的位置(非递归)
 * <p/>
 * 条件:
 * 查找线性表必须是有序列表
 */
public int binarySearch(int[] arr, int data) {
    if (arr == null && arr.length == 0) {
        return -1;
    }

    int beginIndex = 0;
    int endIndex = arr.length - 1;
    int midIndex = -1;

    if (data < arr[beginIndex] || data > arr[endIndex] || beginIndex > endIndex) {
        return -1;
    }

    while (beginIndex <= endIndex) {
        midIndex = (beginIndex + endIndex) >>> 1;
        if (data < arr[midIndex]) {
            endIndex = midIndex - 1;
        } else if (data > arr[midIndex]) {
            beginIndex = midIndex + 1;
        } else {
            return midIndex;
        }
    }
    return -1;
}

/*
* Fibonacci数列 (递归)
*/
public static int fibonacciR(int n) {
    if (0 == n) {
        return 0;
    } else if (1 == n) {
        return 1;
    } else {
        return fibonacciR(n - 1) + fibonacciR(n - 2);
    }
}

/*
* Fibonacci数列 (非递归)
*/
public static void fibonacci(int number) {
    int nLeft = 0;
    int nRight = 1;
    for (int i = 0; i < number; i++) {
        int sum = nLeft + nRight;
        System.out.println("sum:" + sum);
        nLeft = nRight;
        nRight = sum;
    }
}

/**
 * 判断任意一个整数是否素数
 *
 * @param num
 * @return boolean
 */
public boolean isPrimeNumber(int num) {
    for (int i = 2; i <= Math.sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

/**
 * 查找字符串中第一个只出现一次的字符
 * <p/>
 * 申请一个256大小的数组来统计每个字符出现的次数(以空间换时间),
 * 我们以原数组的元素值为下表,访问统计数组,直到遇到第一个访问数组元素值为1的元素,
 * 其所在位置的字符即为第一个只出现一次的字符。
 *
 * @param str
 */
public static void onlyOne(String str) {
    int[] countArr = new int[256];
    char[] chars = str.toCharArray();
    for (char c : chars) {
        countArr[c]++;//c自动转为字符对应的整形值,会在数组为c的位置记录出现次数
    }

    for (char c : chars) {
        if (countArr[c] == 1) {//查找数组中c位置的数组,也就是出现的次数
            System.out.println(c);
        }
    }
}

/**
 * 将2个有序数合并成一个新的有序数组
 *
 * @param arra
 * @param arrb
 */
public static int[] mergerSort(int[] arra, int[] arrb) {
    int a = 0, b = 0, n = 0;
    int[] ret = new int[arra.length + arrb.length];
    while (a < arra.length && b < arrb.length) {
        if (arra[a] < arrb[b]) {
            ret[n++] = arra[a];
            a++;
        } else if (arra[a] > arrb[b]) {
            ret[n++] = arrb[b];
            b++;
        } else {
            ret[n++] = arra[a];
            ret[n++] = arrb[b];
            a++;
            b++;
        }

        if (a == arra.length) {
            while (b < arrb.length) {
                ret[n++] = arrb[b++];
            }
        }

        if (b == arrb.length) {
            while (a < arra.length) {
                ret[n++] = arra[a++];
            }
        }
    }
    return ret;
}

/**
 * 将数组arra合并到数组arrb中
 *
 * @param arra 数组长度小的数组
 * @param arrb 数组长度大的数组,且能存放arra
 */
public static void merger(int[] arrb, int jj, int[] arra, int ii) {
    int k = ii + jj - 1;//+ arrb.length - 1;
    int i = ii - 1;
    int j = jj - 1;
    while (i >= 0 && j >= 0) {
        if (arra[i] > arrb[j]) {
            arra[k--] = arra[i--];
        } else if (arra[i] < arrb[j]) {
            arra[k--] = arrb[j--];
        } else {
            arra[k--] = arra[i--];
            arra[k--] = arrb[j--];
        }
    }

    while (j >= 0) {
        arra[k--] = arrb[j--];
    }
}

public static void swap(int[] arr, int src, int dest) {
    int tmp = arr[dest];
    arr[dest] = arr[src];
    arr[src] = tmp;
}

private static boolean validate(int[] arr) {
    if (arr == null && arr.length == 0) {
        return false;
    }
    return true;
}


public static void main(String[] args) {
    int[] arr = {-7, 1, 5, 2, -4, 3, 0};
    //pinghengPoint(arr);

    //selectSortAsc(arr);
    //printArr(arr);

    //fibonacci(5);

    //onlyOne("abacd");

    int[] a = {1, 3, 6, 8, 9};
    int[] b = {2, 4, 6};
    printArr(a);
    printArr(b);
    int[] c = mergerSort(a, b);
    printArr(c);


    //--------------------
    int n = 3;
    int[] aa = {1, 3, 6, 8, 9};
    int[] bb = new int[aa.length + n];
    bb[0] = 2;
    bb[1] = 4;
    bb[2] = 6;
    printArr(aa);
    printArr(bb);

    merger(aa, aa.length, bb, n);

    printArr(bb);
} } ```       给出一张插入排序的演示图: ![insert_sort](/itec/images/insert_sort.jpg)
分享到: 返回主页