C++小白修仙记_LeetCode刷题_数组

数组(难度:easy)

2011. 执行操作后的变量值

存在一种仅支持 4 种操作和 1 个变量 X 的编程语言:

  • ++X 和 X++ 使变量 X 的值 加 1
  • --X 和 X-- 使变量 X 的值 减 1
    最初,X 的值是 0

给你一个字符串数组 operations ,这是由操作组成的一个列表,返回执行所有操作后, X 的 最终值 。

示例

输入:operations = ["--X","X++","X++"]

输出:1

解释:操作按下述步骤执行:

最初,X = 0
--X:X 减 1 ,X = 0 - 1 = -1

X++:X 加 1 ,X = -1 + 1 = 0

X++:X 加 1 ,X = 0 + 1 = 1

解法:

class Solution {
public:
    int finalValueAfterOperations(vector<string>& operations) {
        int x = 0;
        for(vector<string>::iterator it = operations.begin(); it != operations.end(); it++)
        {
            if(*it == "--X" || *it == "X--")
            {
                x -= 1;
            }
            else
            {
                x += 1;
            }

        }
        return x;
    }
};

//增强for循环 C++11
class Solution {
public:
    int finalValueAfterOperations(vector<string>& operations) {
        int x = 0;
        for(string &op : operations)
        {
            if(op == "--X" || op == "X--")
            {
                x -= 1;
            }
            else
            {
                x += 1;
            }

        }
        return x;
    }
};

1929. 数组串联

给你一个长度为 n 的整数数组 nums 。请你构建一个长度为 2n 的答案数组 ans ,数组下标 从 0 开始计数 ,对于所有 0 <= i < n 的 i ,满足下述所有要求:

ans[i] == nums[i]

ans[i + n] == nums[i]

具体而言,ans 由两个 nums 数组 串联 形成。

返回数组 ans 。

示例

输入:nums = [1,2,1]

输出:[1,2,1,1,2,1]

解释:数组 ans 按下述方式形成:

  • ans = [nums[0],nums[1],nums[2],nums[0],nums[1],nums[2]]
  • ans = [1,2,1,1,2,1]

解法:

class Solution {
public:
    vector<int> getConcatenation(vector<int>& nums) {
        int n = nums.size();
        //vector<int>v(2*n);
        for(int i = 0; i < n; i++)
        {
            //v[i] = nums[i % n];
            nums.push_back(nums[i]);

        }

        //return v;
        return nums;
    }
};

// push_back函数 展开
void Push_Back(const T& val)
{
    //先判断数组容量是否足够
    if(this->m_capacity == this.m_Size)
    {
        cout << "数组已满" << endl;
        return;
    }

    this->pAddress[this->m_Size] = val;//在数组末尾插入数据
    this->m_Size++;//更新大小

}


1720. 解码异或后的数组

未知 整数数组 arr 由 n 个非负整数组成。

经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。

给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。

请解码返回原数组 arr 。可以证明答案存在并且是唯一的。

示例

输入:encoded = [1,2,3], first = 1

输出:[1,0,2,1]

解释:若 arr = [1,0,2,1] ,那么 first = 1 且 encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3]

解法:

class Solution {
public:
    vector<int> decode(vector<int>& encoded, int first) {
        int size = encoded.size();
        vector<int> arr;
         arr.push_back(first);
        for(int i = 0; i < size; i++)
        {
            int x = first ^ encoded[i];
            first = x;
            arr.push_back(x);
        }
        return arr;
    }
};

2574. 左右元素和的差值

给你一个下标从 0 开始的长度为 n 的整数数组 nums。

定义两个数组 leftSum 和 rightSum,其中:

leftSum[i] 是数组 nums 中下标 i 左侧元素之和。如果不存在对应的元素,leftSum[i] = 0 。
rightSum[i] 是数组 nums 中下标 i 右侧元素之和。如果不存在对应的元素,rightSum[i] = 0 。
返回长度为 n 数组 answer,其中 answer[i] = |leftSum[i] - rightSum[i]|。

示例

输入:nums = [10,4,8,3]

输出:[15,1,11,22]

解释:数组 leftSum 为 [0,10,14,22] 且数组 rightSum 为 [15,11,3,0] 。

数组 answer 为 [|0 - 15|,|10 - 11|,|14 - 3|,|22 - 0|] = [15,1,11,22] 。

解法:

class Solution {
public:
    vector<int> leftRightDifference(vector<int>& nums) {
        int n = nums.size();
        vector<int>v(n,0);
        for(int i = 1; i < n; i++)
        {
            v[i] = v[i-1] + nums[i-1]; //左侧和
        }
        int temp = 0;
        for(int i = n - 2; i >= 0; i--)
        {
            temp += nums[i+1];//右侧和
            v[i] = abs(v[i] - temp);//直接得出差值的绝对值
        }
        return v;
    }
};

LCP 01. 猜数字

小A 和 小B 在玩猜数字。小B 每次从 1, 2, 3 中随机选择一个,小A 每次也从 1, 2, 3 中选择一个猜。他们一共进行三次这个游戏,请返回 小A 猜对了几次?

输入的guess数组为 小A 每次的猜测,answer数组为 小B 每次的选择。guess和answer的长度都等于3。

示例

输入:guess = [1,2,3], answer = [1,2,3]

输出:3

解释:小A 每次都猜对了。

解法:

class Solution {
public:
    int game(vector<int>& guess, vector<int>& answer) {
        int count = 0;
        for(int i = 0; i < 3; i++)
        {
            if(guess[i] == answer[i])
            {
                count++;
            }
        }
        return count;
    }
};

LCP 06. 拿硬币

桌上有 n 堆力扣币,每堆的数量保存在数组 coins 中。我们每次可以选择任意一堆,拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数。

示例

输入:[4,2,1]

输出:4

解释:第一堆力扣币最少需要拿 2 次,第二堆最少需要拿 1 次,第三堆最少需要拿 1 次,总共 4 次即可拿完。

解法:

class Solution {
public:
    int minCount(vector<int>& coins) {
        int sum = 0;
        for(int& i: coins)
        {
            sum += (i + 1)/2;
        }
        return sum;
    }
    /*
向上取整(Ceiling)通常是指将一个数字 向上舍入 到最接近的整数。如果数字已经是整数,则返回该数字本身。
啥意思?也就是当一个数字超过它自身多出来的小数,我们 向更大值 方向取一个最接近的整数。

可以看一下 向上取整 常用于以下场景:

分页: 在分页中,向上取整用于计算需要的页数。例如,如果有 10 条数据,每页 3 条数据,实际需要 4 页来显示所有数据。
计算容器大小: 在一些算法中,当我们需要将元素分配到容器中时,可能需要向上取整来确保所有元素都能放进容器。
代码逻辑如下:

// 对于两个整数 a 和 b,我们可以通过以下方法实现 a / b 的向上取整:

int ceilDiv(int a, int b) {
    return (a + b - 1) / b;
}
// 如果 a 能被 b 整除,那么 (a + b - 1) / b 仍然等于 a / b。
// 如果 a 不能被 b 整除,(a + b - 1) / b 会将 a 向上舍入,得到正确的向上取整。


而针对这个题:
一次“动作”,有2个结果 一枚或者两枚;而从 贪心 的角度来看,除非 conis[i] 本身就 1 ,要不也不会 只取一枚;而前面说了 一枚/两枚 的动作都是一次,也就是说行动上是一样的。
那么就统一成“一次取两枚,如果还有剩余,再取一次”;那这个题转化成了 “conis[i] 是 2 的多倍,是否有余数”

这不就我上面说的 向上取整 么。直接套公式: (conis[i] + 2 - 1) / 2

    */

1365. 有多少小于当前数字的数字

给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。

换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。

以数组形式返回答案。

示例

输入:nums = [8,1,2,2,3]

输出:[4,0,1,1,3]

解释:

对于 nums[0]=8 存在四个比它小的数字:(1,2,2 和 3)。

对于 nums[1]=1 不存在比它小的数字。

对于 nums[2]=2 存在一个比它小的数字:(1)。

对于 nums[3]=2 存在一个比它小的数字:(1)。

对于 nums[4]=3 存在三个比它小的数字:(1,2 和 2)。


//暴力破解
class Solution {
public:
    vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
        vector<int>count(nums.size(),0);
        for(int i = 0; i < nums.size(); i++)
        {
            for(int j = 0; j < nums.size(); j++)
            {
                if(nums[i] > nums[j])
                {
                    count[i]++;
                }
            }
        }
    
        return count;
    }
};

//排序
/*
我们也可以将数组排序,并记录每一个数在原数组中的位
置。对于排序后的数组中的每一个数,我们找出其左侧第一
个小于它的数,这样就能够知道数组中小于该数的数量。
*/
class Solution {
public:
    vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
        vector<pair<int,int>> data;
        int n = nums.size();
        for(int i = 0; i < n; i++)
        {
            data.emplace_back(nums[i],i);
        }
        sort(data.begin(),data.end());

        vector<int> ret(n,0);
        int prev = -1;
        for(int i = 0; i < n; i++)
        {
            if(prev == -1 || data[i].first > data[i - 1].first)
            {
                prev = i;
            }
            ret[data[i].second] = prev;
        }

        return ret;
    }
};

1732. 找到最高海拔

有一个自行车手打算进行一场公路骑行,这条路线总共由 n + 1 个不同海拔的点组成。自行车手从海拔为 0 的点 0 开始骑行。

给你一个长度为 n 的整数数组 gain ,其中 gain[i] 是点 i 和点 i + 1 的 净海拔高度差(0 <= i < n)。请你返回 最高点的海拔 。

示例

输入:gain = [-5,1,5,0,-7]

输出:1

解释:海拔高度依次为 [0,-5,-4,1,1,-6] 。最高海拔为 1 。

解法:

class Solution {
public:
    int largestAltitude(vector<int>& gain) {
        int ans = 0;
        int sum = 0;
       for(int x : gain)
       {
            sum += x;
            ans = max(ans,sum);
       }
       return ans;
    }
};
//或
class Solution {
public:
    int largestAltitude(vector<int>& gain) {
        int ans = 0;
        int sum = 0;
        for (int x : gain) {
            sum += x;
            if (sum > ans)
                ans = sum;
        }
        return ans;
    }
};

1464. 数组中两元素的最大乘积

给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。

请你计算并返回该式的最大值。

示例

输入:nums = [3,4,5,2]

输出:12

解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)(nums[2]-1) = (4-1)(5-1) = 3*4 = 12 。

解法:

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int max = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            for(int j = 0; j < nums.size(); j++)
            {
                int ans = (nums[i] - 1) * (nums[j] - 1);
                if(ans > max) max = ans;
            }
        }
        return max;
    }
};
//或 下面的方法  只遍历一次即可
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int max1 = 0, max2 =0;
        for(int x : nums)
        {
            if(x > max1)
            {
                max2 = max1;
                max1 = x;
            }else if(x > max2)
            {
                max2 = x;
            }
        }

        return (max1 - 1) * (max2 - 1);
    }
};
//或调用API sort()从小到大排序;nums.back()末尾元素;nums[nums.size() - 2]倒数第二个元素
class Solution {
public:

    int maxProduct(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        return (nums.back() - 1) * (nums[nums.size() - 2] - 1);
    }
};

2496. 数组中字符串的最大值

一个由字母和数字组成的字符串的 值 定义如下:

如果字符串 只 包含数字,那么值为该字符串在 10 进制下的所表示的数字。
否则,值为字符串的 长度 。
给你一个字符串数组 strs ,每个字符串都只由字母和数字组成,请你返回 strs 中字符串的 最大值 。

示例

输入:strs = ["alic3","bob","3","4","00000"]

输出:5

解释:

  • "alic3" 包含字母和数字,所以值为长度 5 。
  • "bob" 只包含字母,所以值为长度 3 。
  • "3" 只包含数字,所以值为 3 。
  • "4" 只包含数字,所以值为 4 。
  • "00000" 只包含数字,所以值为 0 。
    所以最大的值为 5 ,是字符串 "alic3" 的值。

解法:

class Solution {
public:
    int maximumValue(vector<string>& strs) {
         int max_val = 0;
        for (string& str : strs) {
            bool all_digit = all_of(str.begin(),str.end(),::isdigit);
            int current_val = 0;
                if (all_digit){ 
                   current_val = atoi(str.c_str());
                } else {
                    current_val = str.size();
                }
                if(current_val > max_val)
                {
                    max_val = current_val;
                }
                    
            }
            return max_val;
        }
};
//或
class Solution {
public:
    int all_digit(string& str) { //判断字符串是否全为数字
        int temp = 0;
        for (int i = 0; i < str.size(); i++) {
            temp = int(str[i]);
            if (temp >= 48 && temp <= 57) {
                continue;
            }else{
                return 0;
            }
        }
        return 1;
    }

    int maximumValue(vector<string>& strs) {
        int max_val = 0;
        for (string& str : strs) {
            int current_val = 0;
            if (all_digit(str)) {//是返回1 并将字符串变为数字
                current_val = atoi(str.c_str());
            } else {//不是求去字符串长度
                current_val = str.size();
            }
            if (current_val > max_val) {//找到最大值
                max_val = current_val;
            }
        }
        return max_val;
    }
};

1979. 找出数组的最大公约数

给你一个整数数组 nums ,返回数组中最大数和最小数的 最大公约数 。

两个数的 最大公约数 是能够被两个数整除的最大正整数。

示例

输入:nums = [2,5,6,9,10]

输出:2

解释:

nums 中最小的数是 2

nums 中最大的数是 10

2 和 10 的最大公约数是 2

解法:辗转相除法

class Solution {
public:
    int findGCD(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int x = nums[0];//最小值
        int y = nums[n - 1];//最大值
        int temp;
        while(x)//最小值为循环条件
        {
            temp = y % x;
            y = x;
            x = temp;
        }

        return y;
    }
};

485. 最大连续 1 的个数

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例

输入:nums = [1,1,0,1,1,1]

输出:3

解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

解法:

class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        int max = 0, count = 0;
        for (int x : nums) {
            if (x == 1) {
                count++;
            } else {
                if (count > max)
                    max = count;
                count = 0;
            }
        }
        if (count > max)
            max = count;
        return max;
    }
};

495. 提莫攻击

在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。

当提莫攻击艾希,艾希的中毒状态正好持续 duration 秒。

正式地讲,提莫在 t 发起攻击意味着艾希在时间区间 [t, t + duration - 1](含 t 和 t + duration - 1)处于中毒状态。如果提莫在中毒影响结束 前 再次攻击,中毒状态计时器将会 重置 ,在新的攻击之后,中毒影响将会在 duration 秒后结束。

给你一个 非递减 的整数数组 timeSeries ,其中 timeSeries[i] 表示提莫在 timeSeries[i] 秒时对艾希发起攻击,以及一个表示中毒持续时间的整数 duration 。

返回艾希处于中毒状态的 总 秒数。

示例

输入:timeSeries = [1,4], duration = 2

输出:4

解释:提莫攻击对艾希的影响如下:

  • 第 1 秒,提莫攻击艾希并使其立即中毒。中毒状态会维持 2 秒,即第 1 秒和第 2 秒。
  • 第 4 秒,提莫再次攻击艾希,艾希中毒状态又持续 2 秒,即第 4 秒和第 5 秒。
    艾希在第 1、2、4、5 秒处于中毒状态,所以总中毒秒数是 4 。

解法:

class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        int ans = 0;
        for(int i = 1; i < timeSeries.size(); i++)
        {
            int diff = timeSeries[i] - timeSeries[i - 1];
            //计算差值,如果差值大于等于中毒时间,先直接加一整个
            //中毒时间;如果差值小于中毒时间,先只加当前攻击与前
            //一次攻击的差值
            if(diff >= duration){
                ans += duration;
            }else{
                ans += diff;
            }
        }
        //最后无论哪种情况都需要加一整个中毒时间
        ans += duration;
        return ans;
    }
};

414. 第三大的数

给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。

示例

输入:[3, 2, 1]

输出:1

解释:第三大的数是 1 。

解法:

class Solution {
public:
    int thirdMax(vector<int>& nums) {
        sort(nums.begin(),nums.end(),greater<int>());//从大到小排序
        int n = nums.size();
        if(n < 3)
        {
            return nums[0];
        }
        int count = 1;//记录最大值现在为1
        for(int i = 1; i < n; i++)
        {
            if(nums[i] != nums[i - 1])
            {
                count++;
                if(count == 3)
                {
                    return nums[i];
                }
            }

        }
        return nums[0];
    }
};

628. 三个数的最大乘积

给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。

示例

输入:nums = [1,2,3]

输出:6

解法:

 class Solution {
public:
    int maximumProduct(vector<int>& nums) {
        //思路:先排序从大到小方式,如果全为正数或全为负数,则取number2算法,如果又有正数又有负数,则取number1算法
        int number1 = 0;
        int number2 = 0;
        int count = 0;
        sort(nums.begin(), nums.end(), greater<int>());
        int n = nums.size();

        number1 = nums[0] * nums[n-1] * nums[n - 2];
        number2 = nums[0] * nums[1] * nums[2];
        if(number1 > number2){
            return number1;
        }
        return number2;
    }
};

645. 错误的集合

集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例

输入:nums = [1,2,2,4]

输出:[2,3]

解法:

class Solution {
public:
    vector<int> findErrorNums(vector<int>& nums) {
        //哈希表法:先在map统计各个数字的个数,如果遇到数量为2的,则代表是重复数字,将下标赋给x;如果count为0,则代表缺失数字的下标赋给y。
        int n = nums.size(), x = 0, y = 0, count = 0;
        map<int,int>map;
        for(int num : nums){
            map[num]++;
        }
        for(int i = 1; i <= n; i++){
            count = map[i];
            if(count == 2){
                x = i;
            }else if(count == 0){
                y = i;
            }
        }
        return {x, y};
    }
};

697. 数组的度

给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

示例

输入:nums = [1,2,2,3,1]

输出:2

解释:

输入数组的度是 2 ,因为元素 1 和 2 的出现频数最大,均为 2 。

连续子数组里面拥有相同度的有如下所示:

[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]

最短连续子数组 [2, 2] 的长度为 2 ,所以返回 2 。

解法:

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        unordered_map<int, vector<int>> map;
        int n = nums.size();
        for (int i = 0; i < n; i++) {
            if (map.count(nums[i])) {
                map[nums[i]][0]++;
                map[nums[i]][2] = i;
            } else {
                map[nums[i]] = {1, i, i};
            }
        }
        int maxNum = 0, minLen = 0;
        for (auto& [_, vec] : map) {
            //auto& [, vec] 的意思是:对于 mp 中的每一个键值对
            // 元素(它是一个 pair),我声明一个对它的引用。然后
            // ,我将这个 pair 的第二个成员(值)解包到一个名为 
            // vec 的引用中,同时忽略它的第一个成员(键)。
            if (maxNum < vec[0]) {
                maxNum = vec[0];
                minLen = vec[2] - vec[1] + 1;
            } else if (maxNum == vec[0]) {
                if (minLen > vec[2] - vec[1] + 1) {
                    minLen = vec[2] - vec[1] + 1;
                }
            }
        }
        return minLen;
    }
};

448. 找到所有数组中消失的数字

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例

输入:nums = [4,3,2,7,8,2,3,1]

输出:[5,6]

解法:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n = nums.size();
        int count = 0;
        map<int,int>mp;//利用哈希表记录数组内的在数字个数
        vector<int> res;
        for(int num : nums){
            mp[num]++;
        }
        for(int i = 1; i <= n; i++){
            count = mp[i];
            if(count == 0)//如果个数为0 则代表数组内没有这个数,并将此数插入到res数组中
            {
                res.push_back(i); 
            }
        }

        return res;
    }
};
posted @ 2025-08-25 22:53  Jaylan  阅读(16)  评论(0)    收藏  举报