题目:https://leetcode.cn/problems/find-the-middle-index-in-array/description/
C语言官方答案
/**
* 查找中间索引的函数
* @param nums 指向整数数组的指针
* @param numsSize 整数数组的大小
* @return 如果找到中间索引,则返回该索引;否则返回-1
*/
int findMiddleIndex(int* nums, int numsSize) {
// 首先,计算数组中所有元素的总和
int total = 0;
for (int i = 0; i < numsSize; ++i) {
total += nums[i];
}
// 初始化左侧元素之和(包括当前索引的元素)
int sum = 0;
// 遍历数组,查找中间索引
for (int i = 0; i < numsSize; ++i) {
// 检查当前索引是否满足条件:左侧元素之和的两倍加上当前元素等于总和
// 这意味着左侧元素之和等于右侧元素之和
if (2 * sum + nums[i] == total) {
return i; // 找到中间索引,返回其索引值
}
// 将当前元素添加到左侧元素之和中
sum += nums[i];
}
// 如果没有找到满足条件的索引,则返回-1
return -1;
}
#for之中使用i++和++i没有区别
#include <iostream>
int main(){
for(int i=0;i<=9;i++){
printf("%d",i);
}
printf("\n");
for(int i=0;i<=9;++i){
printf("%d",i);
}
printf("\n");
}
/*
0123456789
0123456789
*/
C++官方答案
// Solution类定义
class Solution {
public:
// 查找中间索引的函数
// 参数:nums是一个整数类型的vector的引用,用于存储要查找的数组
// 返回值:如果找到中间索引,则返回该索引;否则返回-1
int findMiddleIndex(vector<int>& nums) {
// 使用accumulate函数计算nums中所有元素的总和
int total = accumulate(nums.begin(), nums.end(), 0);
// 初始化sum为0,用于累加当前索引左侧(包括当前索引)的元素之和
int sum = 0;
// 遍历nums中的每个元素
for (int i = 0; i < nums.size(); ++i) {
// 检查当前索引是否满足条件:左侧元素之和的两倍加上当前元素等于总和
// 这意味着左侧元素之和等于右侧元素之和
if (2 * sum + nums[i] == total) {
// 如果满足条件,则返回当前索引
return i;
}
// 将当前元素加到sum上,以计算下一个索引左侧的元素之和
sum += nums[i];
}
// 如果没有找到满足条件的索引,则返回-1
return -1;
}
};
// 注意:此代码段使用了<numeric>头文件中的accumulate函数来计算总和
// 请确保在代码顶部包含了相应的头文件:#include <numeric>
// 以及包含了<vector>头文件来支持vector类型:#include <vector>
针对int findMiddleIndex(vector<int>& nums) {
C++模板类是C++模板编程的一个重要组成部分,它允许程序员编写与类型无关的代码。通过使用模板,可以创建出能够处理多种数据类型的类或函数,而无需为每种数据类型都编写单独的代码。模板是C++泛型编程的基石,它提高了代码的重用性、灵活性和可维护性。
在C++中,vector<int>& nums 的声明表示 nums 是一个对 vector<int> 类型对象的引用。
-
vector<int>:这是C++标准模板库(STL)中的一个模板类,用于存储一个动态大小的整数数组。vector提供了许多成员函数来操作数组,如添加、删除元素,访问元素等。 -
引用(&):在C++中,引用是另一个变量的别名。当你声明一个引用时,它必须被初始化,并且一旦初始化,它就不能再指向另一个对象。引用的主要用途是作为函数参数或返回值,以避免复制大型对象(如
vector)的开销。 -
vector<int>& nums:因此,vector<int>& nums表示nums是一个引用,它引用了某个vector<int>类型的对象。这意味着当你通过nums访问或修改数据时,你实际上是在访问或修改它所引用的那个vector<int>对象。
这种声明方式在函数参数中特别有用,因为它允许函数直接修改传入的 vector 对象,而不是修改它的一个副本。例如:
void modifyVector(vector<int>& nums) {
// 这里可以直接修改 nums 指向的 vector 对象
nums.push_back(42); // 向 nums 引用的 vector 中添加一个元素
}
int main() {
vector<int> myVector = {1, 2, 3};
modifyVector(myVector); // myVector 现在包含 {1, 2, 3, 42}
return 0;
}
vector<int> myVector = {1, 2, 3}; 这行代码是C++语言中的一段代码,它执行了以下几个操作:
-
声明了一个名为
myVector的变量:这个变量是一个vector容器,用于存储元素。vector是C++标准模板库(STL)中的一个序列容器,它可以存储相同类型的元素,并且大小可以动态变化。 -
指定了
vector中元素的类型为int:这意味着myVector这个vector容器将只存储整型(int)数据。 -
使用初始化列表
{1, 2, 3}初始化了myVector:在声明myVector的同时,通过花括号{}内的初始化列表,为这个vector容器初始化了三个元素,分别是1、2和3。这意味着在程序执行到这一行时,myVector已经包含了这三个整数,并且它们的顺序也是按照初始化列表中的顺序来排列的。
综上所述,vector<int> myVector = {1, 2, 3}; 这行代码的意思是:声明了一个名为myVector的整型vector容器,并使用初始化列表{1, 2, 3}为其初始化了三个元素,分别是整数1、2和3。
在这个例子中,modifyVector 函数接收一个对 vector<int> 的引用作为参数。因此,当我们在函数内部修改 nums 时,我们实际上是在修改传入的 myVector 对象。注意,由于 nums 是一个引用,我们不需要(也不能)在函数内部返回它,因为它已经是对原始对象的直接引用。
针对int total = accumulate(nums.begin(), nums.end(), 0);
int total = accumulate(nums.begin(), nums.end(), 0); 这行代码是C++中使用标准库函数accumulate的一个例子,用于计算nums(一个vector<int>或任何其他随机访问迭代器支持的容器,这里假设为vector<int>)中所有元素的总和,并将这个总和赋值给变量total。
具体来说:
-
accumulate是定义在<numeric>头文件中的一个函数模板,用于计算给定范围内所有元素的总和(或更一般地,通过给定的二元操作累积范围内的元素)。 -
nums.begin()和nums.end()分别是nums容器的开始迭代器和结束迭代器,它们定义了accumulate函数要遍历的元素范围。注意,end()迭代器指向的是范围之外的第一个位置,因此实际上它并不包含在任何累加操作中。 -
第三个参数
0是累加操作的初始值,即在这个例子中,累加的总和从0开始。 -
accumulate函数遍历从nums.begin()到nums.end()(不包括nums.end())的所有元素,将它们依次加到初始值0上,最终返回累加的总和。 -
这个总和被赋值给变量
total。
因此,如果nums是一个包含整数{1, 2, 3, 4, 5}的vector<int>,那么int total = accumulate(nums.begin(), nums.end(), 0);执行后,total的值将会是15,即1+2+3+4+5的结果。
C++优化方法
class Solution {
public:
// 函数用于找到数组中的一个索引,使得该索引左侧的元素之和等于右侧的元素之和
// 参数:nums是一个整数类型的vector的引用,用于存储要查找的数组
// 返回值:如果找到中间索引,则返回该索引;否则返回-1
int findMiddleIndex(vector<int>& nums) {
int n = nums.size(); // 获取数组的长度
int sum_l = 0; // 用于存储当前索引左侧的元素之和
int sum_r = accumulate(nums.begin(), nums.end(), 0); // 初始时,sum_r存储整个数组的元素之和
// 遍历数组中的每个元素
for (int i = 0; i < n; ++i) {
// 从sum_r中减去当前元素的值,因为当前元素现在被视为右侧元素的一部分
sum_r -= nums[i];
// 检查当前索引是否满足条件:左侧元素之和等于右侧元素之和
if (sum_l == sum_r) {
return i; // 如果满足条件,则返回当前索引
}
// 将当前元素加到sum_l上,因为在下一次迭代中,它将成为左侧元素的一部分
sum_l += nums[i];
}
// 如果没有找到满足条件的索引,则返回-1
return -1;
}
};
注意,这个算法的关键在于,它不需要在每次迭代中都重新计算左侧和右侧的元素之和。相反,它维护了两个变量sum_l和sum_r,分别表示当前索引左侧和右侧的元素之和。在遍历数组时,它逐步从sum_r中减去当前元素的值(因为当前元素现在被视为右侧元素的一部分),并将其加到sum_l上(因为在下一次迭代中,它将成为左侧元素的一部分)。这样,每次迭代时,只需要进行常数时间的操作来更新sum_l和sum_r,从而提高了算法的效率。

241





