力扣顺序表12题通关

顺序表的索引

4.猜数字
5.拿硬币
6.值相等的最小索引

顺序表的大小

7.最大连续1的个数
8.差的绝对值为K的数对数目9.数组中两元素的最大乘积 (暴力枚举(双重循环))
9.数组中两元素的最大乘积 (暴力枚举(双重循环))
10.数组元素和与数字和的绝对差11.K个元素的最大和
12.算术三元组的数目
13.移除元素 (双指针)

顺序表的插入

14.基于排列构建数组
15.数组串联
16.拥有最多糖果的孩子

力扣官网: https://leetcode.cn/


顺序表的索引

4.猜数字

在这里插入图片描述

解题思路

这道题是一道非常基础的数组遍历题,核心逻辑就是:

1.遍历两个数组,按索引位置一一对比。
2.每当 guess[i] 与 answer[i] 相等时,计数器加 1。
3.因为题目限定了数组长度恒为 3,直接循环 3 次即可,无需处理其他边界情况。

  • 时间复杂度:O (1)(固定循环 3 次,和输入规模无关)
  • 空间复杂度:O (1)(仅使用常数额外空间)

C++ 代码实现

class Solution{
public:
	int game(vector<int>& guss, vrctor<int>& answer){
		int ret = 0; // 计数器
		for(int i = 0; i < 3; i++){
			if(guess[i] == answer[i]){
				++ret;
			}
		}
		return ret;
	}
};	

5.拿硬币

在这里插入图片描述

解题思路

这道题的核心逻辑非常直观:
1.每次最多拿 2 枚硬币,所以要拿完一堆硬币,最少次数就是 硬币数量除以2向上取整。
2.用公式表示就是:(coins[i] + 1) / 2,这是利用整数除法实现向上取整的常用技巧。
3.把每一堆硬币的最少次数相加,就是拿完所有硬币的总次数。

  • 时间复杂度:O (n),n 为硬币堆数,遍历一次数组即可
  • 空间复杂度:O (1),仅使用常数额外空间

C++ 代码实现

class Solution {
public:
    int minCount(vector<int>& coins) {
        int ret = 0;
        for(int i = 0; i < coins.size(); i++){
            ret += (coins[i] + 1) / 2;
        }
        return ret;
    }
};

6.值相等的最小索引

在这里插入图片描述

解题思路

这道题是一道非常直接的线性遍历题,核心逻辑:
1.从下标 0 开始遍历数组(保证找到的第一个就是最小的下标)。
2.对每个下标 i,判断 i % 10 是否等于 nums[i]。
3.一旦找到满足条件的下标,直接返回 i(因为是顺序遍历,第一个就是最小的)。
4.遍历结束都没找到,返回 -1。

  • 时间复杂度:O (n),n 为数组长度,最坏情况遍历一次数组
  • 空间复杂度:O (1),仅使用常数额外空间

C++ 代码实现

class Solution {
public:
    int smallestEqual(vector<int>& nums) {
        for(int i = 0; i < nums.size(); i++){
            if(i % 10 == nums[i]){
                return i;
            }
        }
        return -1;
    }
};

顺序表的大小

7.最大连续1的个数

解题思路

这是一道典型的数组遍历题,核心逻辑:
1.定义两个变量:ret 记录当前连续 1 的个数,Max 记录遇到过的最大连续 1 的个数。
2.遍历数组:

  • 若当前元素为 1,则 ret++,并更新 Max = max(Max, ret)。
  • 若当前元素为 0,则重置 ret = 0。

3.遍历结束后,Max 即为数组中最大连续 1 的个数。

  • 时间复杂度:O (n),n 为数组长度,仅需遍历一次数组
  • 空间复杂度:O (1),仅使用常数额外空间

C++ 代码实现

#include <vector>
using namespace std;

class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        // ret:当前连续1的个数;Max:最大连续1的个数
        int ret = 0;
        int Max = 0;
        for(int i = 0; i < nums.size(); ++i){
            if(nums[i] == 1){
                // 遇到1,当前连续计数+1
                ++ret;
                // 更新最大值
                if(ret > Max) Max = ret;
            }else{
                // 遇到0,重置当前连续计数
                ret = 0;
            }
        }
        return Max;
    }
};

8.差的绝对值为K的数对数目 (暴力枚举(双重循环))

在这里插入图片描述

解题思路

  1. 使用双重循环枚举所有满足 i < j 的数对。
  2. 对于每一对数字,计算它们的绝对值之差。
  3. 如果绝对值之差等于 k,计数器加一。
  4. 遍历完成后返回计数器的值。
  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)

C++ 代码实现

class Solution {
public:
    int countKDifference(vector<int>& nums, int k) {
        int ret = 0;
        // 外层循环:遍历每个i
        for(int i = 0; i < nums.size(); ++i){
            // 内层循环:j从i+1开始,保证i < j
            for(int j = i + 1; j < nums.size(); ++j){
                // 计算差的绝对值是否等于k
                if(abs(nums[i] - nums[j]) == k){
                    ret++;
                }
            }
        }
        return ret;
    }
};

9.数组中两元素的最大乘积 (暴力枚举(双重循环))

在这里插入图片描述

解题思路

这道题的核心是找到数组中最大的两个数,核心逻辑:

  1. 遍历数组,找到最大元素的下标 maxIdx
  2. 再次遍历数组,找到第二大元素的下标 subMaxIdx(注意排除 maxIdx 本身)。
  3. 计算 (nums[maxIdx]-1) * (nums[subMaxIdx]-1),即为所求的最大值。
  • 时间复杂度:O(n),n 为数组长度,两次遍历数组
  • 空间复杂度:O(1),仅使用常数额外空间

C++ 代码实现

class Solution {
public:
    int maxProduct(vector<int>& nums) {
   		// 第一步:找到数组中最大元素的下标
        int maxIdx = 0;
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] > nums[maxIdx]){
                maxIdx = i;
            }
        }
        // 第二步:找到数组中第二大元素的下标(不能和maxIdx相同)
        int subMaxIdx = -1;
        for(int i = 0; i < nums.size(); i++){
            if(i != maxIdx){
                if(subMaxIdx == -1 || nums[i] > nums[subMaxIdx]){
                    subMaxIdx = i;
                }
            }
        }
        return (nums[maxIdx] - 1) * (nums[subMaxIdx] - 1);
    }
};

10.数组元素和与数字和的绝对差

在这里插入图片描述

解题思路

这道题的核心是分别计算数组的元素和与数字和,再求两者的绝对差,核心逻辑:

  1. 初始化两个变量 sum1(元素和)、sum2(数字和),初始值都为 0。
  2. 遍历数组 nums
    - 将当前元素直接加到 sum1 中,完成元素和的累加。
    - 用循环分解当前元素的每一位,将每一位数字加到 sum2 中,完成数字和的累加。
  3. 遍历结束后,返回 abs(sum1 - sum2),即两者的绝对差。
  • 时间复杂度:O(n * d),n 为数组长度,d 为数组中数字的平均位数
  • 空间复杂度:O(1),仅使用常数额外空间

C++ 代码实现

class Solution {
public:
    int differenceOfSum(vector<int>& nums) {
        int sum1 = 0, sum2 = 0;
        for(int i = 0; i < nums.size(); i++){
        	// 累加元素和
            sum1 += nums[i];
            // 分解数字并累加数字和
            while(nums[i]){
                int temp = nums[i] % 10;
                sum2 += temp;
                nums[i] /= 10;
              }
        }
        // 返回两者的绝对差
        return abs(sum1 - sum2);
    }
};

11.K个元素的最大和

在这里插入图片描述

解题思路

这道题的核心是每次都选择数组中的最大值进行操作,以最大化每次得分,核心逻辑:

  1. 初始化总得分 sum = 0
  2. 循环 k 次,每次执行以下操作:
    - 遍历数组,找到当前最大值 m
    - 将 m 累加到总得分 sum 中。
    - 将数组中该位置的值更新为 m + 1(相当于执行题目中的删除并添加新元素操作)。
  3. 循环结束后,返回总得分 sum
  • 时间复杂度:O(k * n),k 为操作次数,n 为数组长度
  • 空间复杂度:O(1),仅使用常数额外空间

C++ 代码实现

class Solution {
public:
    int maximizeSum(vector<int>& nums, int k) {
        int sum = 0;
        while(k--){ 
        	// 找到当前数组中的最大值
            int m = -1;
            for(int i = 0; i < nums.size(); i++){
                if(nums[i] > m){
                    m = nums[i];
                    // 将该位置的值更新为 m+1
                    nums[i] = m + 1;
                }
            }
            // 累加到总得分
            sum += m;
        }
        return sum;
    }
};

13.移除元素 (双指针)

在这里插入图片描述

解题思路

这道题采用双指针法,核心逻辑:

  1. 定义左右双指针 lrl 从数组左端开始,r 从数组右端开始。
  2. 遍历数组:
    - 若 nums[l] == val,则将 nums[l]nums[r] 交换,然后 r--(右端指针左移,相当于移除了 val)。
    - 若 nums[l] != val,则 l++(左端指针右移,继续检查下一个元素)。
  3. l > r 时循环结束,此时 r+1 就是数组中不等于 val 的元素个数。
  • 时间复杂度:O(n),n 为数组长度,只需遍历一次数组
  • 空间复杂度:O(1),仅使用常数额外空间,且在原数组上操作

C++ 代码实现

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
    	// 定义左右双指针
        int l = 0, r = nums.size() - 1;
        while(l <= r){
            if(nums[l] == val){
            	// 交换当前元素和右端元素
                int temp = nums[l];
                nums[l] = nums[r];  
                nums[r] = temp;
                // 右端指针左移,相当于移除了val
                r--;
            }else{
            	// 左端指针右移,继续检查下一个元素
                l++;
            }
        }
        // 不等于val的元素个数为r+1
        return r+1;
    }
};

顺序表的插入

14.基于排列构建数组

在这里插入图片描述

解题思路

这道题是一道直接的数组构造题,核心逻辑:

  1. 创建一个新数组 ret 用于存放结果。
  2. 遍历原数组 nums,对于每个下标 i,计算 nums[nums[i]] 的值。
  3. 将计算结果依次存入 ret 中。
  4. 遍历结束后,返回结果数组 ret
  • 时间复杂度:O(n),n 为数组长度,仅需遍历一次数组
  • 空间复杂度:O(n),需要额外的数组空间存放结果

C++ 代码实现

class Solution {
public:
    vector<int> buildArray(vector<int>& nums) {
        vector<int> ret;
        for(int i = 0; i < nums.size(); i++){
        	// 按题目要求计算并构建结果数组
            int ans = nums[nums[i]];
            ret.push_back(ans);
        }   
        return ret;
    }
};

15.数组串联

在这里插入图片描述
解题思路
这道题的核心是将数组自身拼接成两倍长度的新数组,核心逻辑:

  1. 初始化结果数组 ans,直接复制原数组 nums 的内容。
  2. 遍历原数组 nums,将每个元素依次追加到 ans 的末尾。
  3. 遍历结束后,返回长度为 2n 的结果数组 ans
  • 时间复杂度:O(n),n 为数组长度,只需遍历一次数组
  • 空间复杂度:O(n),需要额外的 2n 数组空间存放结果

C++ 代码实现

class Solution {
public:
    vector<int> getConcatenation(vector<int>& nums) {
    	// 初始化结果数组,先复制nums
        vector<int> ans = nums;
        // 遍历nums,将元素追加到ans末尾
        for(int i = 0; i < nums.size(); i++){
            int temp = nums[i];
            ans.push_back(temp);
        }
        return ans;
    }
};

16.拥有最多糖果的孩子

在这里插入图片描述

解题思路

这道题的核心是先找到糖果数的最大值,再判断每个孩子加上额外糖果后是否能达到最大值,核心逻辑:

  1. 先遍历数组 candies,找到当前糖果数的最大值。
  2. 再次遍历数组,对于每个孩子 i
    - 计算 candies[i] + extraCandies 的值。
    - 若该值大于等于最大值,则结果为 true,否则为 false
  3. 遍历结束后,返回布尔数组。
  • 时间复杂度:O(n),n 为数组长度,需要两次遍历数组
  • 空间复杂度:O(n),需要额外的布尔数组空间存放结果

C++ 代码实现

class Solution {
public:
    vector<bool> kidsWithCandies(vector<int>& candies, int extraCandies) {
        vector<bool> ans;
        // 找到当前糖果数的最大值
        for(int i = 0; i< candies.size(); i++){
            candies[i] += extraCandies;
            int maxIdx = 0;
            for(int j = 1; j < candies.size(); j++){
                if(candies[j] >= candies[maxIdx]){
                    maxIdx = j;
                }
            }
            // 遍历每个孩子,判断加上额外糖果后是否能成为最多
            if(candies[i] >= candies[maxIdx]){
                ans.push_back(true);
            }else{
                ans.push_back(false);
            }
            candies[i] -= extraCandies;
        }
        return ans;
    }
};

结语

以上就是本次整理的16道顺序表入门题解,覆盖了数组遍历、双指针、暴力枚举三大基础算法模式。

这些题目虽然简单,但却是后续学习复杂数据结构和算法的重要基石。希望这份题解能帮你理清思路,掌握核心代码写法。

后续我也会持续更新更多数据结构与算法的入门题解,欢迎关注、点赞、收藏,一起进步~

更多推荐