Featured image of post 基础算法技巧

基础算法技巧

基础算法技巧

蓝桥杯基础算法笔记(Java 实现)

一维前缀和

✅ 作用

用于快速计算数组任意区间 [l, r] 的和。

✅ Java 实现(含注释)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 构建前缀和数组
int[] buildPrefixSum(int[] nums) {
    int n = nums.length;
    int[] prefix = new int[n + 1];
    for (int i = 1; i <= n; i++) {
        prefix[i] = prefix[i - 1] + nums[i - 1]; // 累加前缀和
    }
    return prefix;
}

// 查询区间 [l, r] 的和
int rangeSum(int[] prefix, int l, int r) {
    return prefix[r + 1] - prefix[l];
}

📘 使用场景

多次查询数组某一段的区间和,复杂度从 O(n) 降为 O(1)。


二维前缀和

✅ 作用

用于快速求二维矩阵子矩阵的和。

✅ Java 实现(含注释)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;

const int N = 1010;
int a[N][N], s[N][N];
int n, m, q;

int main() {
    scanf("%d%d%d", &n, &m, &q);
    
    // 读入矩阵并构建二维前缀和
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
            s[i][j] = a[i][j] + s[i-1][j] + s[i][j-1] - s[i-1][j-1];
        }
    }

    // 处理 q 次询问
    for (int i = 1; i <= q; i++) {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        printf("%d\n", s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1]);
    }

    return 0;
}

📘 使用场景

需要高频查询子矩阵和的问题,例如地图资源统计等。


一维差分

✅ 作用

对一个数组进行多次区间加法修改,将复杂度从 O(n) 降为 O(1)。

✅ Java 实现(含注释)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 构建差分数组
int[] buildDiff(int[] nums) {
    int n = nums.length;
    int[] diff = new int[n + 1];
    diff[0] = nums[0];
    for (int i = 1; i < n; i++) {
        diff[i] = nums[i] - nums[i - 1];
    }
    return diff;
}

// 区间 [l, r] 增加 val
void rangeAdd(int[] diff, int l, int r, int val) {
    diff[l] += val;
    if (r + 1 < diff.length) diff[r + 1] -= val;
}

// 还原原数组
int[] restore(int[] diff) {
    int[] res = new int[diff.length - 1];
    res[0] = diff[0];
    for (int i = 1; i < res.length; i++) {
        res[i] = res[i - 1] + diff[i];
    }
    return res;
}

二维差分

✅ 作用

对一个矩阵进行多次子矩阵加法修改,复杂度降为 O(1)。

✅ Java 实现(含注释)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 对子矩阵 [(x1,y1), (x2,y2)] 增加 c
void insert(int[][] diff, int x1, int y1, int x2, int y2, int c) {
    diff[x1][y1] += c;
    diff[x2 + 1][y1] -= c;
    diff[x1][y2 + 1] -= c;
    diff[x2 + 1][y2 + 1] += c;
}

// 还原矩阵
int[][] restore(int[][] diff) {
    int n = diff.length - 1, m = diff[0].length - 1;
    int[][] res = new int[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int a = diff[i][j];
            if (i > 0) a += res[i - 1][j];
            if (j > 0) a += res[i][j - 1];
            if (i > 0 && j > 0) a -= res[i - 1][j - 1];
            res[i][j] = a;
        }
    }
    return res;
}

最大公约数 GCD

✅ 作用

用于约分、判断整除性、数论题基础。

✅ Java 实现(含注释)

1
2
3
4
// 欧几里得算法(辗转相除法)
int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

最小公倍数 LCM

✅ 作用

用于周期性建模、最小公共时间点等。

✅ Java 实现(含注释)

1
2
3
4
// 最小公倍数 = a * b / gcd(a, b)
int lcm(int a, int b) {
    return a / gcd(a, b) * b;
}

DFS(深度优先搜索)

✅ 作用

用于遍历图、树、矩阵搜索等问题。

✅ Java 示例(含注释)

1
2
3
4
5
6
7
8
9
// 深度优先搜索图
void dfs(int u, boolean[] visited, List<List<Integer>> graph) {
    visited[u] = true; // 标记当前节点已访问
    for (int v : graph.get(u)) {
        if (!visited[v]) {
            dfs(v, visited, graph); // 递归访问相邻节点
        }
    }
}

📘 使用场景

图搜索、迷宫路径、连通分量统计等。


递归

✅ 作用

通过函数自身调用自身,实现重复结构或树形问题求解。

✅ Java 示例(含注释)

1
2
3
4
5
// 递归实现斐波那契数列
int fib(int n) {
    if (n <= 1) return n; // 基础情况
    return fib(n - 1) + fib(n - 2); // 递归定义
}

📘 使用场景

树结构、数学函数、回溯算法等。


动态规划(DP)

✅ 作用

解决有重叠子问题、最优子结构的问题。

✅ Java 示例(含注释)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 0-1 背包问题:给定物品重量 w、价值 v 和容量 C,求最大价值
int knapsack(int[] w, int[] v, int C) {
    int n = w.length;
    int[] dp = new int[C + 1]; // dp[i] 表示容量为 i 时的最大价值
    for (int i = 0; i < n; i++) {
        for (int j = C; j >= w[i]; j--) { // 倒序遍历防止重复使用物品
            dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);
        }
    }
    return dp[C];
}

📘 使用场景

背包问题、序列编辑、路径计数等。

二分算法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class BinarySearchTemplate {
    public int binarySearch(int[] nums, int target) {
        int left = 0, right = nums.length - 1; // 左闭右闭区间 [left, right]

        while (left <= right) {
            int mid = left + (right - left) / 2; // 防止溢出
            if (nums[mid] == target) {
                return mid; // 找到目标值
            } else if (nums[mid] < target) {
                left = mid + 1; // 去右半部分查找
            } else {
                right = mid - 1; // 去左半部分查找
            }
        }

        return -1; // 未找到目标值
    }
}

快速求回文数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    public static Boolean IsPalindrome(int x) {
        if(x < 0)   return false;
        int t = x,c = 0;
        while(t>0)
        {
            c = c*10 + t%10;
            t /= 10;
        }
        return c == x;
    }
NovaBryan的博客
使用 Hugo 构建
主题 StackJimmy 设计