算法:【排序】(待完善)
一、归并排序(分而治之)
模板
class Solution { // 归并排序 public int[] sortArray(int[] nums) { if(nums == null || nums.length == 0) return nums; mergesort(nums, 0, nums.length-1); return nums; } public void mergesort(int[] nums, int low, int high){ if(low < high){ int mid = low + (high-low)/2; mergesort(nums, low, mid); mergesort(nums, mid+1, high); merge(nums, low, mid, high); } } public void merge(int[] nums, int low, int mid, int high){ int[] tmp = new int[high-low+1]; int l = low, r = mid+1; int k = 0; while(l <= mid && r <= high){ if(nums[l] <= nums[r]){ tmp[k++] = nums[l++]; }else{ tmp[k++] = nums[r++]; } } while(l <= mid) tmp[k++] = nums[l++]; while(r <= high) tmp[k++] = nums[r++]; for(int i=0; i<tmp.length; i++){ nums[low+i] = tmp[i]; } } }
1.1 数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
输入: [7,5,6,4]
输出: 5
// 归并排序 public class Solution { public int reversePairs(int[] nums) { int len = nums.length; if (len < 2) { return 0; } int[] copy = new int[len]; for (int i = 0; i < len; i++) { copy[i] = nums[i]; } int[] temp = new int[len]; return reversePairs(copy, 0, len - 1, temp); } private int reversePairs(int[] nums, int left, int right, int[] temp) { if (left == right) { return 0; } int mid = left + (right - left) / 2; int leftPairs = reversePairs(nums, left, mid, temp); int rightPairs = reversePairs(nums, mid + 1, right, temp); if (nums[mid] <= nums[mid + 1]) { // 表明数组已经有序,没有逆序对了 return leftPairs + rightPairs; } int crossPairs = mergeAndCount(nums, left, mid, right, temp); return leftPairs + rightPairs + crossPairs; } private int mergeAndCount(int[] nums, int left, int mid, int right, int[] temp) { for (int i = left; i <= right; i++) { temp[i] = nums[i]; } int i = left; int j = mid + 1; int count = 0; for (int k = left; k <= right; k++) { if (i == mid + 1) { nums[k] = temp[j]; j++; } else if (j == right + 1) { nums[k] = temp[i]; i++; } else if (temp[i] <= temp[j]) { nums[k] = temp[i]; i++; } else { nums[k] = temp[j]; j++; count += (mid - i + 1); } } return count; } }
1.2 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。输入:strs = ["flower","flow","flight"]
输出:"fl"
class Solution { // 1.横向扫描 // public String longestCommonPrefix(String[] strs) { // if(strs == null || strs.length == 0) // return ""; // String prefix = strs[0]; // for(int i=1; i<strs.length; i++){ // prefix = process(prefix, strs[i]); // if(prefix == "") // return prefix; // } // return prefix; // } // 2.纵向扫描 // public String longestCommonPrefix(String[] strs) { // if(strs == null || strs.length == 0) // return ""; // int len = strs[0].length(); // for(int i=0; i<len; i++){ // char c = strs[0].charAt(i); // for(int j=0; j<strs.length; j++){ // if(i == strs[j].length() || strs[j].charAt(i) != c) // return strs[0].substring(0, i); // } // } // return strs[0]; // } // 3. 分而治之 public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; return megerprocess(strs, 0, strs.length-1); } public String megerprocess(String[] str, int left, int right){ if(left == right){ return str[left]; }else{ int mid = left + (right - left)/2; String leftInfo = megerprocess(str, left, mid); String rightInfo = megerprocess(str, mid+1, right); return process(leftInfo, rightInfo); } } public String process(String str1, String str2){ int len = Math.min(str1.length(), str2.length()); int index = 0; while(index < len && str1.charAt(index) == str2.charAt(index)) index++; return str1.substring(0, index); } }
二、快速排序
模板
class Solution { // 快速排序 public int[] sortArray(int[] nums) { if(nums == null || nums.length == 0) return nums; quicksort(nums, 0, nums.length-1); return nums; } public void quicksort(int[] nums, int low, int high){ if(low < high){ int mid = partition(nums, low, high); quicksort(nums, low, mid-1); quicksort(nums, mid+1, high); } } public int partition(int[] nums, int low, int high){ int base = nums[low]; while(low < high){ while(low < high && nums[high] >= base) high--; nums[low] = nums[high]; while(low < high && nums[low] <= base) low++; nums[high] = nums[low]; } nums[low] = base; return low; } }
2.1 把数组排成最小的数
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
输入: [10,2]
输出: "102"
解题思路:
class Solution { public String minNumber(int[] nums) { String[] strs = new String[nums.length]; for(int i = 0; i < nums.length; i++) strs[i] = String.valueOf(nums[i]); quickSort(strs, 0, strs.length - 1); StringBuilder res = new StringBuilder(); for(String s : strs) res.append(s); return res.toString(); } public void quickSort(String[] strs, int low, int high){ if(low < high){ int mid = partition(strs, low, high); quickSort(strs, low, mid-1); quickSort(strs, mid+1, high); } } public int partition(String[] strs, int low, int high){ String base = strs[low]; while(low < high){ while(low < high && (strs[high] + base).compareTo(base + strs[high]) >= 0) high--; strs[low] = strs[high]; while(low < high && (strs[low] + base).compareTo(base + strs[low]) <= 0) low++; strs[high] = strs[low]; } strs[low] = base; return low; } }