首页 > 编程语言 >蓝桥杯算法集训 - Week 2:双指针、归并排序、多路归并

蓝桥杯算法集训 - Week 2:双指针、归并排序、多路归并

时间:2024-03-16 19:33:21浏览次数:42  
标签:Week queue 归并 int 蓝桥 static import new

蓝桥杯算法集训 - Week 2

本系列随笔用于整理AcWing题单——《蓝桥杯集训·每日一题2024》的系列题型及其对应的算法模板。

一、双指针

Ⅰ、代码模板

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

for (int i = 0, j = 0; i < n; i++)
{
    while (j < i && check(i, j)) j++;

    // 具体问题的逻辑
    // ...
}

Ⅱ、无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣

无重复字符的最长子串

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 哈希集合,记录每个字符是否出现过
        Set<Character> occ = new HashSet<Character>();
        int n = s.length();
        // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        int ans = 0;
        for (int i = 0, rk = -1; i < n; ++i) {
            if (i != 0) {
                // 左指针向右移动一格,移除一个字符
                occ.remove(s.charAt(i - 1));
            }
            while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
                // 不断地移动右指针
                occ.add(s.charAt(rk + 1));
                ++rk;
            }
            // 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = Math.max(ans, rk - i + 1);
        }
        return ans;
    }
}

二、归并排序

归并排序原理复习参考:归并排序 - Hello 算法

Ⅰ、代码模板

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);

    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];
}

Ⅱ、超快速排序

107. 超快速排序 - AcWing题库

超快速排序

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static final int N = 500010;
	static int n;
	static long res;
	static int[] a = new int[N], temp = new int[N];

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		while (n != 0) {
			res = 0;
			for (int i = 0; i < n; i++)
				a[i] = Integer.parseInt(br.readLine());
			mergeSort(a, 0, n - 1);
			System.out.println(res);
			
			n = Integer.parseInt(br.readLine());
		}
		br.close();
	}

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

		int mid = l + (r - l) / 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])
				temp[k++] = q[i++];
			else { // 顺序需要调整
				res += mid - i + 1; // 记录逆序对
				temp[k++] = q[j++];
			}
		}

		while (i <= mid)
			temp[k++] = q[i++];
		while (j <= r)
			temp[k++] = q[j++];

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

三、多路归并

多路归并复习参考:多路归并排序的原理和Java实现

Ⅰ、代码模板

// 多路归并模板——基于优先队列
public static List<Integer> kMergeSort(int[][] data) {
	if (data == null || data.length == 0) {
		return null;
	}
	List<Integer> result = new ArrayList<>();

	// 建立一个优先队列,指定比较器为升序
	PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> a[0] - b[0]);
	// 将每个子序列的第一个元素加入优先队列中
	for (int i = 0; i < data.length; i++) {
		if (data[i].length > 0) {
			// 每个元素是一个数组,包含三个信息:值,所在行号,所在列号
			queue.offer(new int[]{data[i][0], i, 0});
		}
	}
	// 当优先队列不为空时循环执行
	while (!queue.isEmpty()) {
		// 弹出队列顶元素,并将其值添加到结果集合中
		int[] min = queue.poll();
		result.add(min[0]);
		// 如果该元素所在子序列还有下一个元素,则将其加入优先队列中
		if (min[2] + 1 < data[min[1]].length) {
			queue.offer(new int[]{data[min[1]][min[2] + 1], min[1], min[2] + 1});
		}
	}
	// 返回结果集合
	return result;
}

Ⅱ、鱼塘钓鱼

1262. 鱼塘钓鱼 - AcWing题库

鱼塘钓鱼

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;

public class Main {
	static final int N = 110;
	static int n, t;
	static int[] c = new int[N], d = new int[N], prefix = new int[N];

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		String[] split = br.readLine().split(" ");
		for (int i = 0; i < n; i++) {
			c[i] = Integer.parseInt(split[i]);
		}
		split = br.readLine().split(" ");
		for (int i = 0; i < n; i++) {
			d[i] = Integer.parseInt(split[i]);
		}
		split = br.readLine().split(" ");
		for (int i = 1; i <= n - 1; i++) {
			prefix[i] = prefix[i - 1] + Integer.parseInt(split[i - 1]);
		}
		t = Integer.parseInt(br.readLine());
		br.close();
		
		int res = 0;
		for (int i = 1; i <= n; i++) {
			// 枚举经过鱼塘数从 1 到 n 的最大鱼数
			res = Math.max(res, kMerge(Arrays.copyOfRange(c, 0, i)).stream().reduce(Integer::sum).orElse(0));
		}
		System.out.println(res);
	}

	// 多路归并获取最大 res 集合
	static List<Integer> kMerge(int[] a) {
		if (a == null || a.length == 0) {
			return null;
		}

		List<Integer> res = new ArrayList<Integer>();
		PriorityQueue<int[]> queue = new PriorityQueue<>((arr1, arr2) -> Integer.compare(arr2[0], arr1[0]));
		for (int i = 0; i < a.length; i++) {
			queue.offer(new int[] { a[i], i });
		}

		int time = t - prefix[a.length - 1]; // 贪心:最优路线总是从前往后而不折返,即减去当前子结构的消耗时间(前缀和)
		while (time > 0 && !queue.isEmpty()) {
			int[] max = queue.poll();
			res.add(max[0]);
			a[max[1]] -= d[max[1]]; // 衰减鱼塘的鱼量
			
			if (a[max[1]] > 0) {
				queue.offer(new int[] { a[max[1]], max[1] }); // 将收益不为零的鱼塘加入队列
			}

			time--;
		}

		return res;
	}
}

标签:Week,queue,归并,int,蓝桥,static,import,new
From: https://www.cnblogs.com/tfiyuenlau/p/18077471

相关文章

  • 会议室预约系统优化(蓝桥杯)
    文章目录会议室预约系统优化问题描述差分会议室预约系统优化问题描述假设你是一家大型企业的IT工程师,企业内有n个会议室,每天都有多个部门预约会议室进行会议。你的任务是优化现有的会议室预约系统。你需要设计一个程序来支持以下两种操作:预约会议室:给定一......
  • 蓝桥杯 递增三元组
    Problem:蓝桥杯递增三元组文章目录思路解题方法复杂度前缀和Code二分Code双指针Code思路这是一个关于数组的问题,我们需要找到一个递增的三元组。这个三元组由三个数组中的元素组成,每个数组提供一个元素,并且这三个元素满足递增的关系。解题方法我们可以使用......
  • [蓝桥杯 2017 国 C] 合根植物(P8654)
    #include<bits/stdc++.h>#defineendl'\n'usingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();intn,m;map<int,int>fa;intfindB(intx){if(fa[x]==x)returnx;returnfa[x]=findB(......
  • 【Coursera GenAI with LLM】 Week 3 Reinforcement Learning from Human Feedback Cl
    Helpful?Honest?Harmless?MakesureAIresponseinthose3ways.Ifnot,weneedRLHFisreducethetoxicityoftheLLM.Reinforcementlearning:isatypeofmachinelearninginwhichanagentlearnstomakedecisionsrelatedtoaspecificgoalbytakin......
  • 贪心算法(算法竞赛、蓝桥杯)--均分纸牌
    1、B站视频链接:A30贪心算法P1031[NOIP2002提高组]均分纸牌_哔哩哔哩_bilibili题目链接:[NOIP2002提高组]均分纸牌-洛谷#include<bits/stdc++.h>usingnamespacestd;intn,a[101],av,cnt;intmain(){ scanf("%d",&n); for(inti=1;i<=n;i++){ scanf("%d&quo......
  • 贪心算法(算法竞赛、蓝桥杯)--奶牛晒衣服
    1、B站视频链接:A28贪心算法P1843奶牛晒衣服_哔哩哔哩_bilibili题目链接:奶牛晒衣服-洛谷#include<bits/stdc++.h>usingnamespacestd;priority_queue<int>q;//用大根堆维护湿度的最大值intn,a,b;inttim,maxn;intmain(){ scanf("%d%d%d",&n,&a,&b); for......
  • 蓝桥杯刷题(七)
    [蓝桥杯2023省A]平方差题目描述输入格式输出格式样例#1样例输入#1样例输出#1提示【样例说明】【评测用例规模与约定】代码题目描述输入格式输出格式样例#1样例输入#1样例输出#1样例#2样例输入#2样例输出#2提示代码题目描述输入格式输出格式样例#1样......
  • 第八届蓝桥杯省赛 分巧克力(二分)
    题目描述:  思路:给出N个长方形的长和宽,可以分别看长能被分成多少块,宽能被分为多少块,也就是(h/mid)*(w/mid),使其大于等于K所以我们可以通过二分去找,最大的边长是多少AC代码: #include<iostream>usingnamespacestd;typedeflonglongLL;constintN=1......
  • 蓝桥杯 3.14 三国问题
    #include<bits/stdc++.h>usingnamespacestd;constintN=1e5+100;inta1[N],b1[N],c1[N],w[N];longlongn,m;longlongs;intsheng(inta[],intb[],intc[]){memset(w,0,sizeof(w));//数组初始化为0,只有在定义时才可以用{0}//cout<<'$';for(int......
  • 14届蓝桥杯省赛E题——颜色平衡树
    一、题目描述二、题目分析设颜色平衡树的节点有n个,颜色种类为p种,每种颜色的出现次数均为q,则n=p*q。换句话说,如果一棵树的出现次数最多的颜色们的出现次数之和等于该树的节点个数,那么这棵树是颜色平衡树。为了降低遍历次数,采用树上启发式合并,定义树中节点最多的子树为重子树......