代码01_02

131 阅读2分钟

归并排序

package class02;
import java.util.Arrays;
 
public class Code01_MergeSort {
 
    public static void mergeSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        process(arr, 0, arr.length - 1);
    }
 
    public static void process(int[] arr, int L, int R) {
        if (L == R) {
            return;
        }
        int mid = L + ((R - L) >> 1);
        process(arr, L, mid);
        process(arr, mid + 1, R);
        merge(arr, L, mid, R);
    }
 
    public static void merge(int[] arr, int L, int M, int R) {
        int[] help = new int[R - L + 1];
        int i = 0;
        int p1 = L;
        int p2 = M + 1;
        while (p1 <= M && p2 <= R) {
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
        }
        while (p1 <= M) {
            help[i++] = arr[p1++];
        }
        while (p2 <= R) {
            help[i++] = arr[p2++];
        }
        for (i = 0; i < help.length; i++) {
            arr[L + i] = help[i];
        }
    }
}

小和问题

package class02;
public class Code02_SmallSum {
    public static int smallSum(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        return process(arr, 0, arr.length - 1);
    }
 
    // arr[L..R]既要排好序,也要求小和
    public static int process(int[] arr, int l, int r) {
        if (l == r) {
            return 0;
        }
        int mid = l + ((r - l) >> 1);
        return process(arr, l, mid) + process(arr, mid + 1, r) + merge(arr, l, mid, r);
    }
 
    public static int merge(int[] arr, int L, int m, int r) {
        int[] help = new int[r - L + 1];
        int i = 0;
        int p1 = L;
        int p2 = m + 1;
        int res = 0;
        while (p1 <= m && p2 <= r) {
            res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
            // 要找左边数比他小的,因此相同的时候,要把右边的数加进来
            help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
        while (p1 <= m) {
            help[i++] = arr[p1++];
        }
        while (p2 <= r) {
            help[i++] = arr[p2++];
        }
        for (i = 0; i < help.length; i++) {
            arr[L + i] = help[i];
        }
        return res;
    }
}

逆序对问题

class Solution {
    public int merge(int[] arr, int L, int mid, int R){
        int p1 = L;
        int p2 = mid + 1;
        int[] help = new int[R-L+1];
        int ans = 0;
        int i = 0;

        while (p1 <= mid && p2 <= r) {
            ans += nums[p1] > nums[p2] ? (mid - p1 + 1) : 0;
            // !!! 一定要是<=,当两个数相同时,要让左边的数进来
            /*
            举个例子:1313
            要是第二个1先进来的话,第一个3就无法跟第二个1比较了
            要找的是右边比当前数小的,这样肯定是不行的。
            */
            help[index++] = nums[p1] <= nums[p2] ? nums[p1++] : nums[p2++];
        }
        while(p1<=mid){
            help[i++] = arr[p1++];
        }
        while(p2<=R){
            help[i++] = arr[p2++];
        }

        for(i=0; i<R-L+1; i++){
            arr[L+i] = help[i];
        }
        return ans;
    }
    public int process(int[] arr, int L, int R){
        if(L == R){
            return 0;
        }
        int mid = L + (R-L)/2;
        return process(arr, L, mid) + process(arr, mid+1, R) + merge(arr, L, mid, R);
    }
    public int reversePairs(int[] nums) {
        int n = nums.length;
        if(n<2){
            return 0;
        }
        return process(nums, 0, n-1);
    }
}

堆排序

public static void heapSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    for (int i = 0; i < arr.length; i++) { // O(N)
        heapInsert(arr, i); // O(logN)
    }
    // for(int i = arr.length -1; i >=0; i--) {
    // heapify(arr, i, arr.length);
    // }
    int heapSize = arr.length;
    swap(arr, 0, --heapSize);
    while (heapSize > 0) { // O(N)
        heapify(arr, 0, heapSize); // O(logN)
        swap(arr, 0, --heapSize); // O(1)
    }
}

// 某个数现在处在index位置,往上继续移动
public static void heapInsert(int[] arr, int index) {
    while (arr[index] > arr[(index - 1) / 2]) {
        swap(arr, index, (index - 1) / 2);
        index = (index - 1) / 2;
    }
}

// 某个数在index位置,能否往下移动
public static void heapify(int[] arr, int index, int heapSize) {
    int left = index * 2 + 1; // 左孩子的下标
    while (left < heapSize) { // 下方还有孩子的时候
        // 两个孩子中,谁的值大,把下标给largest
        int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
        // 父和较大的孩子之间,谁的值大,把下标给largest
        largest = arr[largest] > arr[index] ? largest : index;
        if (largest == index) {
            break;
        }
        swap(arr, largest, index);
        index = largest;
        left = index * 2 + 1;
    }
}

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

荷兰国旗问题

// 荷兰国旗问题
public static int[] partition(int[] arr, int L, int R, int p) {
    int less = L - 1; // <区的右边界
    int more = R + 1; // >区的左边界
    while (L < more) { // L是当前数的下标
        if (arr[L] < p) {
            swap(arr, ++less, L++);
        } else if (arr[L] > p) {
            swap(arr, --more, L);
        } else {
            L++;
        }
    }
    return new int[] { less + 1, more - 1 };
}

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

快速排序

public static void qSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    quickSort(arr, 0, arr.length - 1);
}

// arr[l..r]排好序
public static void quickSort(int[] arr, int L, int R) {
    if (L < R) {
        swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
        int[] p = partition(arr, L, R);
        quickSort(arr, L, p[0] - 1); // < 区
        quickSort(arr, p[1] + 1, R); // > 区
    }
}

// 这是一个处理arr[l..r]的函数
// 默认以arr[r]做划分,arr[r] -> p     <p   ==p   >p
// 返回等于区域(左边界,右边界), 所以返回一个长度为2的数组res, res[0] res[1]
public static int[] partition(int[] arr, int L, int R) {
    int less = L - 1; // <区右边界
    int more = R; // >区左边界
    while (L < more) { // L表示当前数的位置   arr[R]  ->  划分值
        if (arr[L] < arr[R]) { // 当前数   <  划分值
            swap(arr, ++less, L++);
        } else if (arr[L] > arr[R]) { // 当前数   >  划分值
            swap(arr, --more, L);
        } else {
            L++;
        }
    }
    swap(arr, more, R);
    return new int[] { less + 1, more };
}

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