常用算法模板:基础算法 - Java实现

快速排序
static void quickSort(int[] q, int l, int r) {
        if (l >= r) return;

        int x = q[l + r >> 1], 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;
            }
        }
        quickSort(q, l, j);
        quickSort(q, j + 1, r);
}

归并排序
static void mergeSort(int q[], int l, int r) {
        if (l >= r) return;

        int mid = (l + r) / 2;
        mergeSort(q, l, mid);
        mergeSort(q, mid + 1, r);

        int k = 0, i = l, j = mid + 1;  
        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++];

        for (i = l, j = 0; i <= r; i++, j++)    
            q[i] = tmp[j];
}

整数二分
boolean check(int x) {/*......*/}	// 检查x是否满足某种性质

static int bSearch1(int l, int r) {
    while (l < r) {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

static int bSearch2(int l, int r) {
    while (l < r) {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}

浮点数二分
static double bSearch3(double l, double r) {
    while (r - l > 1e-8) {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

高精度计算
import java.math.BigInteger;

BigInteger add(BigInteger val);
BigInteger subtract(BigInteger val);
BigInteger multiply(BigInteger val);
BigInteger remainder(BigInteger val);

一维前缀和
s[i] = a[1] + a[2] + ... + a[i]
a[l] + ... + a[r] = s[r] - s[l - 1]

二维前缀和
s[i, j]表示第i行j列格子左上部分所有元素的和
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
s[x2, y2] - s[x2, y1 - 1] - s[x1 - 1, y2] + s[x1 - 1, y1 - 1]

一维差分
给区间[l, r]中每个数加上c:
B[l] += c, B[r + 1] -= c

二维差分
给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素都加上c:
s[x1, y1] += c;
s[x2 + 1, y1] -= c;
s[x1, y2 + 1] -= c;
s[x2 + 1, y2 + 1] + c;

位运算
求n的第k位数字:n >> k & 1
返回n的最后一位1lowbit(n) = n & -n;

双指针算法
for (int i = 0, j = 0; i < n; i++) {
    while (j < i && check(i, j)) j++;
    // 具体问题的逻辑
}

常用问题分类:
(1)对于一个序列,用两个指针维护一段区间
(2)对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

离散化
static List<Integer> alls = new ArrayList<>();	// 存储所有待离散的值
alls = new ArrayList<>(new HashSet<>(alls));// 去重
Collections.sort(alls);	// 先去重再排序

// 二分求出x对应的离散化的值
static int find(int x) {	// 找到第一个大于等于x的位置
    int l = 0, r = alls.size() - 1;
    while (l < r) {
        int mid = l + r >> 1;
        if (alls.get(mid) >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1;	// 映射到1,2,...n(有利于求前缀和)
}

区间合并
// 将所有存在交集的区间合并,并保存合并后的区间
static List<int[]> segs = new ArrayList<>();
static List<int[]> res = new ArrayList<>();

static void merge() {
    // 区间左端点排序
    segs.sort(new Comparator<int[]>() {
        public int compare(int[] o1, int[] o2) {
            return o1[0] - o2[0];
        }
    });
    // segs.sort((o1, o2) -> o1[0] - o2[0]); // 使用Lambda表达式会降低速度
    int l = Integer.MIN_VALUE, r = Integer.MIN_VALUE;
    for (int[] seg : segs) {
        if (r < seg[0]) {
            if (l != Integer.MIN_VALUE) res.add(new int[]{l, r});
            l = seg[0]; r = seg[1];
        }
        else r = Math.max(r, seg[1]);
    }
    if (l != Integer.MIN_VALUE) res.add(new int[]{l, r});	// 添加最后更新的区间
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值