学习路线:
第一章 基础算法
一、排序
1.快排
2.归并
1.快速排序
题目:785.快速排序
c题解
java题解
import java.util.Scanner;
public class QuickSort {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = 1000000;
int[] q = new int[N + 1];
int n = sc.nextInt();
for (int i = 1; i <= n; i++) {
q[i] = sc.nextInt();
}
quick_sort(q, 0, n - 1);
for (int i = 1; i <= n; i++) {
System.out.printf("%d ", q[i]);
}
}
public static void quick_sort(int q[], int l, int r) {
if (l >= r) return;
int x = q[l], i = l - 1, j = r + 1;
while (i < j) {
do i++; while (q[i] < x);
do j--; while (q[j] > x);
if (i < j) {
int t = q[i];
q[i] = q[j];
q[j] = t;
}
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
}
2.归并排序
题目:787.归并排序
c题解
java题解
import java.util.Scanner;
public class MergeSort {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int N = 1000010;
int[] q = new int[N];
for (int i = 0; i < n; i++) {
q[i] = sc.nextInt();
}
marge_sort(q, 0, n - 1);
for (int i = 0; i < n; i++) {
System.out.printf("%d ", q[i]);
}
}
public static void marge_sort(int[] q, int l, int r) {
if (l >= r) return;
int mid = l + r >> 1;
int[] tmp = new int[1000010];
marge_sort(q, 0, mid);
marge_sort(q, mid + 1, r);
int i = l;
int j = mid + 1; // mid + 1
int k = 0;// k和tmp用来存储已经排好序的数组
while (i <= mid && j <= r) {
if (q[i] <= q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++];
}
//比完后剩下的
while (i <= mid) {
tmp[k++] = q[i++];
}
while (j <= r) {
tmp[k++] = q[j++];
}
//放回q数组中,i必须是l而不能是0,i小于等于r
for (i = l, j = 0; i <= r; i++, j++) {
q[i] = tmp[j];
}
}
}
二、二分
1.整数
2.实数
1.整数二分
有单调性一定可以二分,没有单调性也可能可以二分
更新区间l = mid 时要+1,r = mid 时不用+1
题目:789.数的范围
C语言
java题解
import java.util.Scanner;
public class ErFenZhengShu {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] q = new int[n];
for (int i = 0; i < n; i++) {
q[i] = sc.nextInt();
}
// 询问个数
while(m-- > 0) {
int x = sc.nextInt();
int l = 0;
int r = n - 1;
while (l < r) {
int mid = l + r >> 1;//要不要加一后面再说
if (q[mid] >= x) { //在右半边mid = l+r/2
r = mid;
} else {
l = mid + 1;
}
}
//循环结束后r = l
if (q[l] != x) { //此时l就是第一个x的位置了(左边界)
System.out.println("-1 -1");
} else {
System.out.printf("%d ",l);
l = 0;
r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (q[mid] <= x) l = mid; //再看右边界
else r = mid - 1;
}
System.out.printf("%d", l);
}
}
}
}
2.浮点数二分
C语言
java
import java.util.Scanner;
public class ErFenFuDian {
public static void main(String[] args) {
// 求根号x
Scanner sc = new Scanner(System.in);
double x = sc.nextDouble();
double l = 0;
double r = x; //根号一定在0-x区间内
while (r - 1 > 1e-4) { //10的-6次方可以近似看作答案了 比要求的有效位数多2
double mid = (l + r) / 2; //不能用>>1
if (mid * mid >= x) r = mid;
else l = mid;
}
System.out.printf("%f",l);
}
}
三、前缀和与差分
1.前缀和(一维)
原数组:a1, a2, a3 ,...,a4
前缀和:Si = a1+a2+a3+...+a4
问题:
1.求Si=Si-1 + ai
2.求a[l, r] -> Sr - Sl-1
注意:定义S0 = 0;[1, 10]->S10-S0
题目:795.子矩阵的和
c++题解
Java题解
import java.util.Scanner;
public class qianZhuiHe {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] a = new int[n+1];//记得定义n+1,注意越界
int[] s = new int[n+1];
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
}
for (int i = 1; i <= n ; i++) {
s[i] = s[i-1] + a[i];//i-1
}
while (m-- != 0){ //输入m行,接收要在循环内
int l = sc.nextInt();
int r = sc.nextInt();
int ans = s[r] - s[l-1];
System.out.println(ans);
}
}
}
2.前缀和(二维)
求和(求右下角面积):
求除去右下角之外的面积(Sij的推导方法):
题目:796.子矩阵的和
c++题解
import java.util.Scanner;
public class QianZhuiHe2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int q = sc.nextInt();
int[][] a = new int[n + 1][m + 1];
int[][] s = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
a[i][j] = sc.nextInt();
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
}
}
while (q-- != 0) {
int x1 = sc.nextInt();
int y1 = sc.nextInt();
int x2 = sc.nextInt();
int y2 = sc.nextInt();
int ans = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
System.out.println(ans);
}
}
}
3.差分
bl+c br+1-c