leetcode1991. 找到数组的中间位置

题目: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> 类型对象的引用。

  1. vector<int>:这是C++标准模板库(STL)中的一个模板类,用于存储一个动态大小的整数数组。vector 提供了许多成员函数来操作数组,如添加、删除元素,访问元素等。

  2. 引用(&):在C++中,引用是另一个变量的别名。当你声明一个引用时,它必须被初始化,并且一旦初始化,它就不能再指向另一个对象。引用的主要用途是作为函数参数或返回值,以避免复制大型对象(如 vector)的开销。

  3. 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++语言中的一段代码,它执行了以下几个操作:

  1. 声明了一个名为myVector的变量:这个变量是一个vector容器,用于存储元素。vector是C++标准模板库(STL)中的一个序列容器,它可以存储相同类型的元素,并且大小可以动态变化。

  2. 指定了vector中元素的类型为int:这意味着myVector这个vector容器将只存储整型(int)数据。

  3. 使用初始化列表{1, 2, 3}初始化了myVector:在声明myVector的同时,通过花括号{}内的初始化列表,为这个vector容器初始化了三个元素,分别是123。这意味着在程序执行到这一行时,myVector已经包含了这三个整数,并且它们的顺序也是按照初始化列表中的顺序来排列的。

综上所述,vector<int> myVector = {1, 2, 3}; 这行代码的意思是:声明了一个名为myVector的整型vector容器,并使用初始化列表{1, 2, 3}为其初始化了三个元素,分别是整数123

在这个例子中,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_lsum_r,分别表示当前索引左侧和右侧的元素之和。在遍历数组时,它逐步从sum_r中减去当前元素的值(因为当前元素现在被视为右侧元素的一部分),并将其加到sum_l上(因为在下一次迭代中,它将成为左侧元素的一部分)。这样,每次迭代时,只需要进行常数时间的操作来更新sum_lsum_r,从而提高了算法的效率。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值