907.子数组的最小值之和

文章介绍了一种利用单调栈优化求解给定数组中每个元素作为子数组最小值时,其贡献次数(即子数组个数)的问题。通过两次遍历和单调栈存储元素及其边界信息,避免了枚举搜索的超时问题。

单调栈 + 贡献法

  • 每个子数组的最小值的和,即对于每个元素,包含该元素的所有子数组的个数与该元素值的乘积即为所求值
  • 每个元素贡献的次数:以该元素为最小值的所有子数组的个数
  • 区间法求符合条件的包含某元素的子数组个数:左右边界均为最靠近该元素的并且小于(等于)该元素的元素所处的位置
  • 左右边界:leftBound, rightBound, 子数组个数:(i - leftBound) * (rightBound - i)
  • (1) 使用枚举查找最靠近该元素的并且小于(等于)该元素的元素所处的位置,超时。。。
  • (2) 使用单调栈,栈中保存下标,对应的元素值由小到大,以当前元素为最大值,pop掉栈中比当前元素大的值的下标,栈顶即为所要位置(边界)
class Solution {
public:
    int sumSubarrayMins(vector<int>& arr) {
        stack<int> s;
        int n = arr.size();
        vector<int> leftBound(n, -1);
        vector<int> rightBound(n, n);
        for(int i = 0; i < n; i++)
        {
            while(s.size() && arr[i] <= arr[s.top()])
                s.pop();
            leftBound[i] = s.empty() ? -1 : s.top();
            s.push(i);
        }
        s = {};
        for(int i = n - 1; i >= 0; i--)
        {
            while(s.size() && arr[i] < arr[s.top()])
                s.pop();
            rightBound[i] = s.empty() ? n : s.top();
            s.push(i);
        }
        long long ret = 0, mod = 1e9 + 7;
        for(int i = 0; i < n; i++)
        {
            ret = ( ret + 
            (long long)arr[i] * (i - leftBound[i]) * (rightBound[i] - i) ) % mod; 
        }
        return ret;
    }
};
<think>首先,用户的问题是:“我想在C++中获取数组最小值对应的下标 请问C++ 获取数组最小值的索引”。这是一个关于在C++中找到数组最小值索引的问题。 根据系统级指令,我需要: 1. 所有行内数学表达式使用$...$格式。 2. 独立公式使用$$...$$格式并单独成段。 3. LaTeX语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾自然地添加引用标识。 用户可见层指令:回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 参考站内引用:有四个引用: - 引用[1]:关于旋转数组中的最小值,涉及遍历数组找到旋转点。 - 引用[2]:关于子数组最小值之和,涉及动态规划或类似方法。 - 引用[3]:一个C++模板递归求数组元素最小值下标。 - 引用[4]:C++中找数组或Vector中最小值的索引,使用标准库函数。 用户的问题直接相关的是引用[3][4],因为它们直接涉及在C++中找到最小值的索引。 我的回答应该结构清晰,逐步解决问题。可能的步骤: 1. 介绍问题:简要说明如何在C++中获取数组最小值的索引。 2. 提供方法:给出几种方法,如使用循环、标准库函数等。 3. 代码示例:提供代码片段来演示。 4. 解释:解释代码的工作原理。 5. 生成相关问题:在后生成相关问题。 由于引用[3]是递归方法,引用[4]是使用标准库的min_element函数。我应该优先推荐标准方法,因为它更简单、高效。 核心方法: - 使用循环遍历数组,记录最小值其索引。 - 使用标准库函数std::min_element。 用户指定了数组,所以我应该处理普通数组可能的vector。 回答结构: 1. 介绍:解释如何获取最小值的索引。 2. 方法1:使用循环遍历。 3. 方法2:使用std::min_element(推荐)。 4. 代码示例:给出代码。 5. 注意事项:如处理空数组等。 6. 生成相关问题。 使用中文回答。 引用:当引用站内内容时,在段落末尾添加引用标识。如[^1]。 在回答中,我可以引用[3][4],因为它们相关。 例如: - 引用[3]展示了一个递归方法,但可能不高效。 - 引用[4]展示了使用min_element函数。 我应该确保回答真实可靠,基于C++标准知识。 终,生成相关问题。 相关问题应该基于主题,如其他查找方法、优化、应用场景等。 大纲: 1. **开头**:直接回答用户问题,概述方法。 2. **详细方法**: - 方法1:手动遍历。 - 代码示例。 - 方法2:使用std::min_element。 - 代码示例,解释。 - 提到引用[3]的递归方法作为备选,但不推荐。 3. **注意事项**:如数组为空时处理。 4. **生成相关问题**:在后添加。 使用LaTeX:用户问题中没有数学表达式,但如果有,确保使用正确格式。这里可能不需要数学公式,除非涉及算法复杂度。 例如,时间复杂度:$O(n)$。 现在,构建回答。</think>### C++ 获取数组最小值的索引 在C++中,获取数组最小值对应的索引是一个常见任务。这可以通过手动遍历数组或使用标准库函数实现。我将逐步解释方法,并提供代码示例。核心思路是:遍历数组元素,比较每个元素的值,记录当前最小值的索引。时间复杂度为$O(n)$,其中$n$是数组长度,因为需要检查所有元素[^1]。 #### 方法1: 手动遍历数组(基础方法) 这是一种直接的方式,适用于普通数组或 `std::vector`。步骤如下: 1. 初始化一个变量存储最小值的索引(如 `min_index`),通常设为0(第一个元素)。 2. 遍历数组,比较每个元素与当前最小值。 3. 如果找到更小的元素,更新 `min_index`。 4. 返回索引。 **代码示例**: ```cpp #include <iostream> #include <vector> using namespace std; // 函数:获取数组最小值索引 int findMinIndex(int arr[], int size) { if (size <= 0) return -1; // 处理空数组,返回-1表示无效索引 int min_index = 0; for (int i = 1; i < size; i++) { if (arr[i] < arr[min_index]) { min_index = i; // 更新索引 } } return min_index; } // 函数:获取vector最小值索引 int findMinIndex(const vector<int>& vec) { if (vec.empty()) return -1; // 处理空vector int min_index = 0; for (int i = 1; i < vec.size(); i++) { if (vec[i] < vec[min_index]) { min_index = i; } } return min_index; } int main() { int arr[] = {3, 1, 4, 1, 5, 9}; // 示例数组 vector<int> vec = {3, 1, 4, 1, 5, 9}; // 示例vector int arr_index = findMinIndex(arr, 6); int vec_index = findMinIndex(vec); cout << "数组最小值索引: " << arr_index << endl; // 输出: 1 (值1) cout << "vector最小值索引: " << vec_index << endl; // 输出: 1 return 0; } ``` **解释**: - 函数 `findMinIndex` 处理普通数组 `std::vector`。 - 循环从索引1开始,避免不必要的比较。 - 如果数组为空,返回-1作为错误标识。 - 此方法简单高效,适合所有C++版本。 #### 方法2: 使用标准库函数 `std::min_element`(推荐方法) C++标准库提供了 `std::min_element` 函数(在 `<algorithm>` 头文件中),它能直接返回小元素的迭代器,然后通过计算偏移量得到索引。这是更简洁、高效的方式,尤其适合 `std::vector` 或大型数组[^4]。 **代码示例**: ```cpp #include <iostream> #include <vector> #include <algorithm> // 包含 min_element using namespace std; int main() { int arr[] = {3, 1, 4, 1, 5, 9}; // 示例数组 vector<int> vec = {3, 1, 4, 1, 5, 9}; // 示例vector // 获取普通数组最小值索引 int* min_arr = min_element(begin(arr), end(arr)); int arr_index = distance(arr, min_arr); // 计算索引 // 获取vector的最小值索引 auto min_vec = min_element(vec.begin(), vec.end()); int vec_index = distance(vec.begin(), min_vec); cout << "数组最小值索引: " << arr_index << endl; // 输出: 1 cout << "vector最小值索引: " << vec_index << endl; // 输出: 1 return 0; } ``` **解释**: - `std::min_element(begin, end)` 返回一个迭代器指向小元素。 - `std::distance(begin, iterator)` 计算迭代器与起始点的偏移量,得到索引。 - 优点:代码简洁,避免手动循环;标准库优化过,通常高效。 - 注意:如果数组为空,`min_element` 返回的迭代器等于 `end()`,使用 `distance` 前需检查。 #### 注意事项 - **处理重复最小值**:以上方法返回第一个最小值的索引(如示例中的值1,索引1而非3)。如果需要所有最小值的索引,需修改代码存储多个索引。 - **空数组处理**:始终检查数组大小,避免未定义行为。返回-1是常见错误处理方式。 - **递归方法**:引用[3]展示了一个递归模板方法,但递归可能导致栈溢出,不推荐用于大数组[^3]。标准库方法更可靠。 - **性能**:所有方法时间复杂度为$O(n)$,空间复杂度$O(1)$。对于大型数据,`std::min_element` 可能略微优化。 #### 相关问题 1. 如何获取数组中所有最小值的索引(不只第一个)? 2.C++中,如何高效地同时找到数组大值最小值索引? 3. 如果数组是动态变化的,如何维护最小值索引而不重新遍历?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值