C++学习——顺序表(六)

news/2025/3/27 4:09:03

文章目录

  • 前言
  • 一、找到数组的中间位置
  • 二、有序数组中的单一元素
  • 三、杨辉三角(Ⅱ)
  • 四、超过阈值的最小操作数Ⅰ
  • 五、找出峰值
  • 六、统计已测试设备
  • 七、统计和小于目标的下标对数目
    • 1.单向遍历法
    • 2.双指针法(时间复杂度小)
  • 八、计算K置位下标元素的和
  • 九、数组能形成多少数对
  • 十、求出现两次数字的XOR值


前言

本文为《C++学习》的第篇文章,今天是顺序表的最后一篇总结,通过leetcode来练习顺序表的枚举。


一、找到数组的中间位置

1991.找到数组的中间位置

class Solution {
public:
    int findMiddleIndex(vector<int>& nums) {
        int totalSum = 0;
        for (int num : nums) {
            totalSum += num;
        }
        
        int leftSum = 0;
        for (int i = 0; i < nums.size(); ++i) {
            int rightSum = totalSum - leftSum - nums[i];
            if (leftSum == rightSum) {
                return i;
            }
            leftSum += nums[i];
        }
        
        return -1;
    }
};

二、有序数组中的单一元素

540.有序数组中的单一元素

class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        int left = 0; // 初始化左指针为数组的起始位置
        int right = nums.size() - 1; // 初始化右指针为数组的末尾位置
        
        while (left < right) { // 当左指针小于右指针时继续循环
            int mid = left + (right - left) / 2; // 计算中间位置
            
            // 确保 mid 是偶数,以便进行成对比较
            if (mid % 2 == 1) {
                mid--; // 如果 mid 是奇数,则将其减 1 变为偶数
            }
            
            if (nums[mid] == nums[mid + 1]) { // 检查 mid 和 mid+1 是否相等
                left = mid + 2; // 如果相等,说明唯一的元素在右半部分,更新左指针为 mid + 2
            } else {
                right = mid; // 如果不相等,说明唯一的元素在左半部分或就是 mid,更新右指针为 mid
            }
        }
        
        return nums[left]; // 返回左指针指向的元素,即为唯一出现一次的元素
    }
};





三、杨辉三角(Ⅱ)

119.杨辉三角(Ⅱ)

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> row(rowIndex + 1, 0); // 初始化结果数组,大小为 rowIndex + 1,初始值为 0
        row[0] = 1; // 第一行的第一个元素总是 1
        
        for (int i = 1; i <= rowIndex; ++i) { // 从第二行开始构建每一行
            for (int j = i; j > 0; --j) { // 从后向前更新当前行的元素
                row[j] += row[j - 1]; // 每个元素等于其上方和左上方元素之和
            }
        }
        
        return row; // 返回构建好的第 rowIndex 行
    }
};

四、超过阈值的最小操作数Ⅰ

3065.超过阈值的最小操作数Ⅰ

class Solution {
public:
    int minOperations(vector<int>& nums, int k) {
        int operations = 0; // 初始化操作次数为 0
        
        for (int num : nums) { // 遍历数组中的每个元素
            if (num < k) { // 如果当前元素小于 k
                operations++; // 增加操作次数
            }
        }
        
        return operations; // 返回所需的操作次数
    }
};

五、找出峰值

2951.找出峰值

class Solution {
public:
    vector<int> findPeaks(vector<int>& mountain) {
        vector<int> peaks; // 初始化一个向量来存储峰值的下标
        
        for (int i = 1; i < mountain.size() - 1; ++i) { // 从第二个元素到倒数第二个元素遍历
            if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i + 1]) { // 检查是否为峰值
                peaks.push_back(i); // 如果是峰值,记录其下标
            }
        }
        
        return peaks; // 返回所有峰值的下标
    }
};

六、统计已测试设备

2960.统计已测试设备

class Solution {
public:
    int countTestedDevices(vector<int>& batteryPercentages) {
        int testedDevices = 0; // 初始化已测试设备的计数
        
        for (int i = 0; i < batteryPercentages.size(); ++i) {
            if (batteryPercentages[i] > 0) { // 检查当前设备的电池百分比是否大于 0
                testedDevices++; // 增加已测试设备的计数
                
                // 减少后续所有设备的电池百分比,确保不会低于 0
                for (int j = i + 1; j < batteryPercentages.size(); ++j) {
                    batteryPercentages[j] = max(0, batteryPercentages[j] - 1);
                }
            }
        }
        
        return testedDevices; // 返回已测试设备的数量
    }
};

七、统计和小于目标的下标对数目

2824.统计和小于目标的下标对数目

1.单向遍历法

class Solution {
public:
    int countPairs(vector<int>& nums, int target) {
        int count = 0; // 初始化满足条件的下标对数量
        
        for (int i = 0; i < nums.size(); ++i) { // 外层循环遍历每个元素
            for (int j = i + 1; j < nums.size(); ++j) { // 内层循环遍历后续元素
                if (nums[i] + nums[j] < target) { // 检查当前两个元素之和是否小于目标值
                    count++; // 如果是,则增加满足条件的下标对数量
                }
            }
        }
        
        return count; // 返回满足条件的下标对数量
    }
};

2.双指针法(时间复杂度小)

class Solution {
public:
    int countPairs(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end()); // 对数组进行排序
        int left = 0; // 初始化左指针
        int right = nums.size() - 1; // 初始化右指针
        int count = 0; // 初始化满足条件的下标对数量
        
        while (left < right) { // 当左指针小于右指针时继续循环
            if (nums[left] + nums[right] < target) { // 检查当前左右指针所指元素之和是否小于目标值
                count += right - left; // 如果是,则增加满足条件的下标对数量
                left++; // 将左指针右移一位
            } else {
                right--; // 否则,将右指针左移一位
            }
        }
        
        return count; // 返回满足条件的下标对数量
    }
};

八、计算K置位下标元素的和

2859.计算K置位下标元素的和

class Solution {
public:
    int sumIndicesWithKSetBits(vector<int>& nums, int k) {
        int sum = 0; // 初始化结果和为 0
        
        for (int i = 0; i < nums.size(); ++i) { // 遍历每个下标
            if (__builtin_popcount(i) == k) { // 检查下标的二进制表示中是否有恰好 k 个置位
                sum += nums[i]; // 如果是,则将对应的 nums 元素加到结果和中
            }
        }
        
        return sum; // 返回结果和
    }
};

补充: 函数__builtin_popcount(i) == k
是 GCC 编译器提供的一个内置函数,用于计算一个无符号整数的二进制表示中 1 的数量。
手动计算如下:

int popcount(unsigned int x) {
    int count = 0;
    while (x) {
        count += x & 1; // 检查最低位是否为 1
        x >>= 1; // 右移一位
    }
    return count;
}

九、数组能形成多少数对

2341.数组能形成多少数对
哈希表

#include <unordered_map>
class Solution {
public:
    vector<int> numberOfPairs(vector<int>& nums) {
        unordered_map<int, int> countMap; // 哈希表用于统计每个整数出现的次数
        
        // 统计每个整数出现的次数
        for (int num : nums) {
            countMap[num]++;
        }
        
        int pairs = 0; // 形成的数对数目
        int remaining = 0; // 剩余的整数数目
        
        // 遍历哈希表,计算数对和剩余整数的数量
        for (const auto& entry : countMap) {
            int count = entry.second;
            pairs += count / 2; // 可以形成的数对数量
            remaining += count % 2; // 剩余的整数数量
        }
        
        return {pairs, remaining}; // 返回结果数组
    }
};

顺序表

#include <algorithm>
class Solution {
public:
    vector<int> numberOfPairs(vector<int>& nums) {
        sort(nums.begin(), nums.end()); // 对数组进行排序
        
        int pairs = 0; // 形成的数对数目
        int remaining = 0; // 剩余的整数数目
        int n = nums.size();
        
        for (int i = 0; i < n; ) {
            if (i + 1 < n && nums[i] == nums[i + 1]) { // 检查相邻元素是否相等
                pairs++; // 形成一个数对
                i += 2; // 跳过这两个元素
            } else {
                remaining++; // 当前元素计入剩余的整数数量
                i++;
            }
        }
        
        return {pairs, remaining}; // 返回结果数组
    }
};

十、求出现两次数字的XOR值

3158.求出现两次数字的XOR值
哈希表

#include<unordered_map>
class Solution {
public:
    int duplicateNumbersXOR(vector<int>& nums) {
        unordered_map<int, int> countMap; // 哈希表用于统计每个整数出现的次数
        
        // 统计每个整数出现的次数
        for (int num : nums) {
            countMap[num]++;
        }
        
        int xorValue = 0; // 存储出现两次的数字的按位 XOR 值
        
        // 遍历哈希表,计算出现两次的数字的按位 XOR 值
        for (const auto& entry : countMap) {
            if (entry.second == 2) { // 检查是否出现两次
                xorValue ^= entry.first; // 计算按位 XOR 值
            }
        }
        
        return xorValue; // 返回按位 XOR 值
    }
};

顺序表

#include<algorithm>
class Solution {
public:
    int duplicateNumbersXOR(vector<int>& nums) {
        sort(nums.begin(), nums.end()); // 对数组进行排序
        
        int xorValue = 0; // 存储出现两次的数字的按位 XOR 值
        int n = nums.size();
        
        for (int i = 0; i < n; ) {
            if (i + 1 < n && nums[i] == nums[i + 1]) { // 检查相邻元素是否相等
                xorValue ^= nums[i]; // 将该数字加入按位 XOR 运算中
                i += 2; // 跳过这两个元素
            } else {
                i++;
            }
        }
        
        return xorValue; // 返回按位 XOR 值
    }
};

这就是今天的全部内容了,谢谢大家的观看,不要忘了给一个免费的赞哦!


http://www.niftyadmin.cn/n/5889965.html

相关文章

游戏引擎学习第152天

仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾昨天的内容 这个节目展示了我们如何从零开始制作一款完整的游戏。我们不使用任何游戏引擎或库&#xff0c;而是从头开始创建一款游戏&#xff0c;整个开发过程都会呈现给大家。你将能够看到每一行代码的编写&#xff0c;了解…

怎么选相机分辨率、投影仪尺寸、标定板大小等硬件

选择结构光三维重建系统中的相机分辨率、投影仪尺寸、标定板大小等硬件时&#xff0c;需要综合考虑多个因素&#xff0c;以确保系统性能和测量精度。以下是具体的选择指南&#xff1a; 相机分辨率 应用需求: 根据应用的精度需求选择相机分辨率。例如&#xff0c;牙科、医学成…

如何简单获取三个月免费试用的SSL证书

刚开始我在阿里云上折腾&#xff0c;奈何验证总是无法通过&#xff0c;于是查资料&#xff0c;偶然间发现一个超级简单好用的SSL获取网站&#xff0c;免费无推广哈&#xff0c;试用了还不错。 目录 1. 网页地址&#xff1a; 2. 申请方法&#xff1a; 3. 验证步骤&#xff1a…

sap webapi接口

接到任务说学一下创建api接口&#xff0c;所以记录一下 web api的概念&#xff1a; 调用外部web api还没弄&#xff0c;到时再说&#xff0c;这次只记录SAP 发布web api 事务码 se24 创建类 在INTERFACE中输入IF_HTTP_EXTENSION 在methods输入 GET和POST 双击第一栏的IF_HTTP_…

进程(下)【Linux操作系统】

文章目录 进程的状态R状态&#xff1a;S状态&#xff1a;D状态&#xff1a;T状态t状态Z状态&#xff1a;孤儿进程X状态&#xff1a; 进程的优先级如果我们要修改一个进程的优先级重置进程优先级 进程切换进程的调度 进程的状态 在内核中&#xff0c;进程状态的表示&#xff0c…

OpenCV开发笔记(八十三):图像remap实现哈哈镜效果

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/146213444 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

铁塔倾斜监测:保障基础设施安全的关键技术

​ ​在现代社会&#xff0c;电力、通信等关键基础设施的稳定运行对于经济发展和社会生活至关重要。然而&#xff0c;这些设施中的铁塔却常常面临自然灾害和长期使用带来的安全隐患。想象一下&#xff0c;如果一座重要的通信铁塔突然倾倒&#xff0c;不仅会造成巨大的经济损…

电脑一直重启怎么解决 原因及解决方法

电脑一直重启的故障状态&#xff0c;不仅影响电脑的正常使用&#xff0c;还可能导致数据丢失或损坏。那么&#xff0c;电脑一直重启是什么原因呢&#xff1f;又该如何解决呢&#xff1f;下面将为大家介绍电脑一直重启的常见原因和解决方法&#xff0c;帮助您恢复电脑的正常工作…