此版子转自ACwing中的java刷题模板,作者是:Lic ,https://www.acwing.com/blog/content/593/
目录
二分搜索逼近左边界,区间[left, right]被分为左区间[left, mid]和右区间[mid + 1, right]。
二分搜索逼近右边界,区间[left, right]被分为左区间[left, mid - 1]和右区间[mid, right]。
数据输入
一般我常用的数据输入方法有两种,Scanner和BufferedReader。BufferedReader可以读一行,速度比Scanner快,所以数据较多的时候使用。注意BufferedReader用完记得关。
Scanner
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt(); // String: next(), double: nextDouble()
int[] nums = new int[n];
for (int i = 0; i < n; i++)
nums[i] = scan.nextInt();
// ...
}
}
BufferedReader
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
int[] nums = new int[n];
String[] strs = reader.readLine().split(" ");
for (int i = 0; i < n; i++)
nums[i] = Integer.parseInt(strs[i]);
// ...
reader.close(); // 记得关闭
}
}
快速排序quickSort
快速排序要注意x取值的边界情况。取x = nums[left], nums分为[left, j]和[j + 1, right],或x = nums[right], nums分为[left, i - 1]和[i, right],否则会StackOverflow。
public void quickSort(int[] nums, int left, int right) {
if (left >= right)
return;
int i = left - 1, j = right + 1, x = nums[left];
while (i < j) {
do i++; while (nums[i] < x);
do j--; while (nums[j] > x);
if (i < j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
quickSort(nums, left, j);
quickSort(nums, j + 1, right);
}
例题:AcWing 785, LeetCode 912
归并排序mergeSort
mergeSort时间复杂度是稳定O(nlogn),空间复杂度O(n),稳定的。quickSort时间复杂度平均O(nlogn),最坏O(n^2),最好O(nlogn),空间复杂度O(nlogn),不稳定的。
public void mergeSort(int[] nums, int left, int right) {
if (left >= right)
return;
int mid = left + (right - left) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
int k = 0, i = left, j = mid + 1;
int[] temp = new int[right - left + 1];
while (i <= mid && j <= right)
if (nums[i] < nums[j])
temp[k++] = nums[i++];
else
temp[k++] = nums[j++];
while (i <= mid)
temp[k++] = nums[i++];
while (j <= right)
temp[k++] = nums[j++];
for (i = left, j = 0; i <= right; i++, j++)
nums[i] = temp[j];
}
例题:AcWing 787, LeetCode 912
二分搜索binarySearch
二分搜索逼近左边界,区间[left, right]被分为左区间[left, mid]和右区间[mid + 1, right]。
public int binarySearchLeft(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (check(mid))
right = mid;
else
left = mid + 1;
}
return nums[left];
}