Skip to content

基础算法

1.输入和输出

java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            System.out.println(a + b);
        }
    }
}
java
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException { // 记得抛异常
        StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
        while (st.nextToken() != StreamTokenizer.TT_EOF){
            // String str = st.sval; //读取String类型数据
            int a = (int) st.nval;  // 读取第一个数字a
            st.nextToken();      // 读取下一个token
            double b = (double) st.nval;   // 读取第二个数字b
            pw.println(a + b);
        }
        pw.flush(); // 最后flush

    }
}

2.map计数

java
for (int num : nums){
    map.put(num, map.getOrDefault(num, 0) + 1);
}

3.快速排序

java
// 调用:quick_sort(a, 0, n - 1)
void quick_sort(int[] q, int l, int r){
    if (l >= r)
        return;
    // i从左往右扫描找比x大的,j从右往左扫描找比x小的
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j){
        while (q[++i] < x);
        while (q[--j] > x);
        if (i < j){
            int temp = q[i];
            q[i] = q[j];
            q[j] = temp;
        }
    }
    // 从上到下分治
    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}

4.归并排序

java
    int[] temp = new int[n]; // 辅助数组
    // 将[l, r]排好序
    void merge_sort(int[] q, int l, int r){
        if (l >= r)
            return;
        int mid = l + r >> 1;
        // 从下到上
        // 分
        merge_sort(q, l, mid);
        merge_sort(q, mid + 1, r);
        // 治
        // k:辅助数组的索引, i:左数组索引, j:右数组索引
        int k = 0, i = l, j = mid + 1;
        while (i <= mid && j <= r){
            if (q[i] <= q[j])
                temp[k++] = q[i++];
            else
                temp[k++] = q[j++];
        }
        // 左数组不为空
        while (i <= mid)
            temp[k++] = q[i++];
        // 右数组不为空
        while (j <= r)
            temp[k++] = q[j++];
        // 复制到原数组
        for (i = l, k = 0; i <= r; i++, k++){
            q[i] = temp[k];
        }
    }

5.二分

java
    // 是否满足条件
    boolean check(int x){/*....*/}
    // 找左边界(满足条件的最小的那个)
    int bsearch(int l, int r){
        while (l < r){
            int mid = l + r >> 1;
            if (check(mid))
                r = mid;
            else
                l = mid + 1;
        }
        return r;
    }
    // 找右边界(满足条件的最大的那个)
    int bsearch(int l, int r){
        while (l < r){
            int mid = l + r + 1 >> 1;
            if (check(mid))
                l = mid;
            else
                r = mid - 1;
        }
        return l;
    }

6.一维前缀和

java
    //S(i+1) = S(i) + a(i)
    // a(l)+a(l+1)+...+a(r) = S(r+1)-S(l)
    for (int i = 0; i < n; i++){
        s[i + 1] = s[i] + a[i];
    }

7.一维差分

java
    // 给区间[l, r]中的每个数加上c
    void insert(int l, int r, int c){
        B[l] += c;
        B[r + 1] -= c;
    }
    // 初始化差分数组
    for (int i = 0; i < n; i++) {
        insert(i, i, a[i]);
    }
    // 输出前缀和数组
    for (int i = 0; i < n; i++){
        B[i + 1] += B[i];
    }

8.双指针

java
    // i从头到尾,j不回头
    for (int i = 0, j = 0; i < n; i++){
        while (j < i && check(i, j))
            j++;
    }

9.位运算

  1. 求n的右数第k位二进制数
java
n >> k & 1;
  1. 返回n的最后一位1
java
// 101100返回100
int lowbit(int x){
    return x & -x; // -x是x的反码加1
}
  1. 清除最右边的1
java
// 101100变为101000
n % (n - 1);
  1. 统计一个数的二进制有多少个1
java
Integer.bitCount(int x);

10.最大公约数

java
int gcd(int a, int b){
    return b != 0 ? gcd(b, a % b) : a;
}

11.求最大子数组之和(Kadane算法)

java
public int maxSubArray(int[] nums) {
    int pre = 0, maxAns = nums[0];
    for (int x : nums) {
        pre = Math.max(pre + x, x);
        maxAns = Math.max(maxAns, pre);
    }
    return maxAns;
}