一些可用于排序的函数(2542. 最大子序列的分数)

​​​​​​2542. 最大子序列的分数

题目要求两个数组(nums1、nums2)选k个数后经过运算得到的最大值

运算:nums1中k个数之和 * min(nums2中对应下标元素)

一开始准备用类似于找第k大的数的快排划分方法写,后来发现min(nums2中对应下标元素)不一定就是这个第k大的数,因为num1和部分的运算也有影响。×

后来参考别人的代码,用最小堆枚举nums2元素,将nums2元素的下标按nums2值从大到小排序,num1下标与num2下标关联起来,找前k个和最大的值。代码如下:

  1. ids存数组下标
  2. 对下标按nums2的值从大到小排序
  3. 初始化结果,ans = 前k大的下标的nums1之和*第k大的nums2
  4. 枚举:ans = max(前k+i下标的nums1最大k个之和*第k+i大的nums2,ans)
cpp 复制代码
class Solution {
public:
    long long maxScore(vector<int> &nums1, vector<int> &nums2, int k) {
        int n = nums1.size();
        vector<int> ids(n);//ids存两个数组关联的下标
        //1.初始化下标
        iota(ids.begin(), ids.end(), 0);

        //2.对下标按nums2的值排序,不影响原数组的顺序
        //当 nums2[i] 大于 nums2[j] 时,i 排在 j 前面(降序)
        ranges::sort(ids, [&](int i, int j) { return nums2[i] > nums2[j]; });

        //3.最小堆
        priority_queue<int, vector<int>, greater<>> pq;
        long long sum = 0;
        for (int i = 0; i < k; i++) 
        {
            //前k个求和
            sum += nums1[ids[i]];
            // pq.top()存这k个里面最小的值
            pq.push(nums1[ids[i]]);
        }
        //初始结果
        long long ans = sum * nums2[ids[k - 1]];
        //枚举
        for (int i = k; i < n; i++) {
            int x = nums1[ids[i]];
        //如果num1这个值比之前求和最小的大
            if (x > pq.top()) 
            {//把这个值放入求和中,之前求和最小值删除
                sum += x - pq.top();
                pq.pop();
                pq.push(x);
               //重新计算结果              
                ans = max(ans, sum * nums2[ids[i]]);
            }
        }
        return ans;
    }
};

一、 iota函数

头文件: <numeric>

iota函数用于生成连续递增的序列

cpp 复制代码
template< class ForwardIt, class T >
void iota( ForwardIt first, ForwardIt last, T value );
  • value 开始,为**[** first, last**)**范围内的元素依次赋上连续递增的值
  • 第一个元素被赋值为 value
  • 第二个元素被赋值为 value + 1
  • 第三个元素被赋值为 value + 2
  • 以此类推,直到填充完整个范围

特点

  1. 效率高:时间复杂度为 O (n),n 是范围中的元素数量
  2. 灵活性强:可以用于任何支持正向迭代器的容器(如 array、list 等)
  3. 支持多种数据类型:只要支持 ++ 运算符的类型都可以使用(如整数、字符等)

二、 ranges::sort

头文件:<ranges>

C++20 引入的范围库中的排序函数

与传统的 std::sort 相比,它可以直接对容器进行排序**(无需传入迭代器对)。**

三、priority_queue(优先队列)

头文件:<queue>

priority_queue(优先队列)是 C++ 标准库中的一个容器适配器,它提供了一种自动排序的队列功能,每次从队列中取出的元素都是当前队列中优先级最高的元素。

核心特性

  1. 默认行为 :默认情况下是最大堆(max-heap),即每次取出的元素是当前队列中最大的。
  2. 底层容器 :默认使用 vector 作为底层存储容器,也可以指定为 deque
  3. 排序规则 :通过比较函数(或函数对象)控制排序,默认使用 less<Type>降序排序)。

基本用法

less<>(默认,最大堆)和 greater<>(最小堆)

cpp 复制代码
#include <queue>
using namespace std;

// 定义一个存储int类型的优先队列(默认是最大堆)
priority_queue<int> pq;

// 定义最小堆(需指定比较函数)
priority_queue<int, vector<int>, greater<int>> min_pq;

操作

操作 功能描述 时间复杂度
pq.push(value) 插入元素到队列 O(log n)
pq.top() 获取队首元素(优先级最高) O(1)
pq.pop() 删除队首元素 O(log n)
pq.empty() 判断队列是否为空 O(1)
pq.size() 获取队列中元素的个数 O(1)

自定义排序规则

方法 1:使用函数对象(functor)

priority_queue 的比较逻辑与常规排序相反, 默认最大堆思想,大的放后面。

cpp 复制代码
#include <queue>
#include <string>

// 自定义比较规则:按字符串长度升序排序
struct StrCompare {
    bool operator()(const string& a, const string& b) {
        return a.size() > b.size(); 
    }
};

int main() {
    priority_queue<string, vector<string>, StrCompare> pq;
    pq.push("apple");    // 长度5
    pq.push("banana");   // 长度6
    pq.push("pear");     // 长度4
    
    while (!pq.empty()) {
        cout << pq.top() << " ";  // 输出:pear apple banana
        pq.pop();
    }
    return 0;
}
方法 2:使用 lambda 表达式(C++11 及以上)

定义一个存储pair的优先队列,按pair的第二个元素升序排序

cpp 复制代码
auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) {
    return a.second > b.second;  // 小的second值优先级高
};

priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);

适用场景

  1. 需要频繁获取最大值 / 最小值的场景(如 Top K 问题)
  2. 贪心算法的实现(如霍夫曼编码、活动选择问题)
  3. 图算法(如 Dijkstra 最短路径算法、Prim 最小生成树)
  4. 任务调度(按优先级处理任务)

注意事项

  1. priority_queue 没有迭代器,无法遍历所有元素(只能通过 top() 获取顶部元素,再 pop() 删除)。
  2. 插入和删除操作的时间复杂度是 O (log n),效率较高。
  3. 自定义排序时,比较函数的返回值含义是:return true 表示第一个参数的优先级低于第二个参数(即第二个参数应该排在前面)。
相关推荐
colus_SEU4 小时前
【编译原理笔记】2.1 Programming Language Basics
c++·算法·编译原理
人工智能培训4 小时前
大模型-去噪扩散概率模型(DDPM)采样算法详解
算法
Excuse_lighttime4 小时前
只出现一次的数字(位运算算法)
java·数据结构·算法·leetcode·eclipse
liu****4 小时前
笔试强训(二)
开发语言·数据结构·c++·算法·哈希算法
无限进步_5 小时前
扫雷游戏的设计与实现:扫雷游戏3.0
c语言·开发语言·c++·后端·算法·游戏·游戏程序
qq_433554545 小时前
C++ 完全背包
开发语言·c++·算法
lingran__5 小时前
算法沉淀第二天(Catching the Krug)
c++·算法
im_AMBER6 小时前
杂记 15
java·开发语言·算法
爱coding的橙子6 小时前
每日算法刷题Day70:10.13:leetcode 二叉树10道题,用时2h
算法·leetcode·深度优先