【C++】OJ习题 篇1

news2024/11/24 3:11:44
头像
🚀个人主页:奋斗的小羊
🚀所属专栏:C++
很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~

动图描述

目录

  • 💥1、string
    • 💥1.1 字符串相加
    • 💥1.2 验证回文字符串
    • 💥1.3 反转字符串
    • 💥1.4 字符串最后一个单词的长度
    • 💥1.5 字符串中的第一个唯一字符
    • 💥1.6 反转字符串中的单词
  • 💥2、vector
    • 💥2.1 杨辉三角
    • 💥2.2 只出现一次的数字 II
    • 💥2.3 只出现一次的数字 III
  • 总结


💥1、string

💥1.1 字符串相加

  • Leetcode——字符串相加

请添加图片描述

有时候我们需要非常大的数据相加时,整型的范围不够,就可以将数据转换为字符串的形式运算,再将结果转回为整型。
整型相加时是从后往前加的,这里的字符串相加我们也从后往前加。不断取出两个字符串的末尾字符,转换为整形后相加,再用+=追加到字符串末尾,其中还要考虑进位的情况。
因为string类支持operator[],所以我们可以通过下标的方式遍历字符串。
其中两个字符串的第一位相加也可能有进位,所以循环结束后还需要判断进位是否为1。
因为我们是从后往前加的,所以最后还需要用reverse将字符串翻转过来。

class Solution {
public:
    string addStrings(string num1, string num2) {
        string s;
        int n = 0;
        int end1 = num1.size() - 1;
        int end2 = num2.size() - 1;
        while (end1>=0 || end2>=0)
        {
            int n1 = end1>=0 ? num1[end1--] - '0' : 0;
            int n2 = end2>=0 ? num2[end2--] - '0' : 0;
            int ret = n1 + n2 + n;
            n = ret / 10;
            ret %= 10;
            s += ret + '0';
        }
        if (n == 1)
        {
            s += '1';
        }
        reverse(s.begin(), s.end());
        return s;
    }
};

用下标的方式从后往前遍历字符串,相加得到的值追加到字符串,最后再反转字符串。


💥1.2 验证回文字符串

  • Leetcode——验证回文串

在这里插入图片描述

将字符串存到一个stack和一个queue中,循环比较top(),当栈和队列为空时则字符串回文,当某次top()不相等时则不回文。
范围for遍历字符串,如果是符合我们要求的字符就插入栈和队列中。

class Solution {
public:
    bool isPalindrome(string s) {
        for (auto e : s)
        {
            if (e >= 'a' && e <= 'z')
            {
                _st.push(e);
                _qu.push(e);
            }
            if (e >= 'A' && e <= 'Z')
            {
                e += 32;
                _st.push(e);
                _qu.push(e);
            }
            if (e >= '0' && e <= '9')
            {
                _st.push(e);
                _qu.push(e);
            }
        }
        while (!_st.empty())
        {
            if (_st.top() != _qu.front())
            {
                return false;
            }
            _st.pop();
            _qu.pop();
        }
        return true;
    }
private:
    stack<int> _st;
    queue<int> _qu;
};

💥1.3 反转字符串

  • Leetcode——反转字符串

在这里插入图片描述

只需要反转对应的区间就行,注意不能越界。

class Solution {
public:
    string reverseStr(string s, int k) {
        for (size_t i = 0; i < s.size(); i += 2*k)
        {
            size_t n = i + k > s.size() ? s.size() : i + k;
            reverse(s.begin() + i, s.begin() + n);
        }
        return s;
    }
};

💥1.4 字符串最后一个单词的长度

  • 牛客——最后一个单词的长度

在这里插入图片描述

#include <iostream>
using namespace std;

int main() {
    string s;
    getline(cin, s);
    size_t pos = s.rfind(" ");
    size_t length = s.size() - pos - 1;
    cout << length << endl;
}

💥1.5 字符串中的第一个唯一字符

  • Leetcode——字符串中的第一个唯一字符

在这里插入图片描述

这种类似计数的题可以用哈希映射的方法,首先定义一个用于计数的数组,然后将字符串映射到数组中,再通过遍历字符串得到下标间接遍历数组来找出为1的元素,返回下标。
定义数组时需要初始化为全0。

class Solution {
public:
    int firstUniqChar(string s) {
        int arr[26] = {0};
        for (auto e : s)
        {
            arr[e - 'a']++;
        }
        for (size_t i = 0; i < s.size(); i++)
        {
            if (1 == arr[s[i] - 'a'])
            {
                return i;
            }
        }
        return -1;
        }
};

💥1.6 反转字符串中的单词

  • Leetcode——反转字符串中的单词

在这里插入图片描述
reverse(s.begin(), s.end());
参数:双向迭代器,指向要反转的序列的初始和最终位置。使用的范围是[ )左闭右开。
从前往后遍历字符串,找" "空格的位置,用reverse反转单词。需要注意的是reverse的参数是左闭右开的。

class Solution {
public:
    string reverseWords(string s) {
        int pos1 = 0;
        int pos2 = s.find(" ", pos1);
        while (pos2 < s.size())
        {
            reverse(s.begin() + pos1, s.begin() + pos2);
            pos1 = pos2 + 1;
            pos2 = s.find(" ", pos1);
        }
        reverse(s.begin() + pos1, s.end());
        return s;
    }
};

💥2、vector

💥2.1 杨辉三角

  • Leetcode——杨辉三角

在这里插入图片描述

类似一个二维数组,用vector<vector<int>>会很方便。

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> vv(numRows);
        for (int i = 0; i < numRows; i++)
        {
            vv[i].resize(i + 1, 1);
        }
        for (int i = 2; i < numRows; i++)
        {
            for (int j = 1; j < vv[i].size() - 1; j++)
            {
                vv[i][j] = vv[i - 1][j - 1] + vv[i - 1][j];
            }
        }
        return vv;
    }
}; 

💥2.2 只出现一次的数字 II

  • Leetcode——只出现一次的数字

在这里插入图片描述

思路一: 第一个思路是利用映射计数来找出只出现一次的数字,首先找出最大值和最小值,用相减的值来确定用来计数的数组开多大(注意还要+1),接着遍历原数据映射,最后遍历计数数组找出只出现一次的数字。

但是这个方法只能通过少数测试用例,当数据非常不集中时空间消耗太大。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        int max = 0;
        int min = 0;
        for (int i = 1; i < nums.size(); i++)
        {
            if (nums[i] > nums[max])
            {
                max = i;
            }
            if (nums[i] < nums[min])
            {
                min = i;
            }
        }
        int n = nums[max] - nums[min];
        vector<int> count(n + 1, 0);
        for (auto e : nums)
        {
            count[e - nums[min]]++;
        }
        vector<int> v;
        for (int i = 0; i < n + 1; i++)
        {
            if (1 == count[i])
            {
                v.push_back(i + nums[min]);
            }
        }
        return v;
    }
};

思路二: 类似双指针遍历数据,得到只出现一个的数字的下标。
这个方法可以通过,但是时间复杂度是O(N^2),效率低。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        vector<int> v;
        for (int i = 0; i < nums.size(); i++)
        {
            int flag = 1;
            for (int j = 0; j < nums.size(); j++)
            {
                if (i != j && nums[i] == nums[j])
                {
                    flag = 0;
                }
            }
            if (1 == flag)
            {
                v.push_back(nums[i]);
            }
        }
        return v;
    }
};

思路三: 位运算,使用异或操作符遍历数据,得到只出现一次的两个数m和n的异或值(为了防止溢出可以用unsigned int接收异或值)。因为m和n不相等,所以这个异或值必然有个比特位上的值是1。 m和n在这个比特位上一个是0,一个是1。
接下来我们拿着这个比特位上的1再次使用异或操作符遍历数据,对于这个比特位,可以把值为1的分到一组,把值为0的分到一组,那么m和n必然被分到不同的组中,这个问题就变成了只出现一次的数字,最后再使用异或操作符遍历两个组,就能得到m和n的值了。

在这里插入图片描述

整个思路中最关键的就是:两个不相等的数异或的结果必然有个比特位的值是1,对于这个比特位,既然两个数在这个位上的值不一样,那我们就可以通过这个比特位将数据分成两组,这两个数就被分到了不同的组中。
不用担心相等的两个数被分到不同的组中,因为对于相等的两个数来说,任何一个比特位上的值都是一样的,所以它们不可能被分到两个组中。

在代码实现中还有一个问题,就是如何找到异或值中的某个值为 1 的比特位,这里有个简单的办法,计算lowbitlowbit = m & -m

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        unsigned int m = 0;
        for (auto e : nums)
        {
            m ^= e;
        }
        int lowbit = m & -m;
        vector<int> v(2);//已经知道元素个数的情况下提前全部开好,避免多次扩容
        for (auto e : nums)
        {
            v[(lowbit & e) == 0] ^= e;
        }
        return v;
    }
};

下面的方法是我从一位大佬的题解里学到的,作为小白的我当时理解了好久才想通,妙不可言,膜拜大佬!

vector<int> v(2);
for (auto e : nums)
{
    v[(lowbit & e) == 0] ^= e;
}

💥2.3 只出现一次的数字 III

  • Leetcode——只出现一次的数字

在这里插入图片描述

数组nums中都是int类型的数,有一个数只出现一次,其他的都出现了三次,如果将数组中所有的数的某一个比特位上的值加起来,再模以3,那么得到的0或1就是只出现了一次的数在这个比特位上的值。那么将所有的数对应的32个比特位上的0或1加起来模3,我们就能得到那个只出现了一次的数的2进制数。

只出现了一次的数的第 i 个二进制位就是数组中所有元素的第 i 个二进制位之和除以 3 的余数。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int sum = 0;
        for (int i = 0; i < 32; i++)
        {
            int n = 0;
            for (auto e : nums)
            {
                n += ((e >> i) & 1);
            }
            if (n % 3)
            {
                sum |= (1 << i);
            }
        }
        return sum;
    }
};

总结

  1. 首先要认真审题,有思路了切不可着急写,先在心中推敲一下看当前思路是否可行,有大概的把握了再着手实现
  2. 不要太钻牛角尖,如果某个思路迟迟实现不了,就把视角放广一点寻找新的思路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【奇某信-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

(论文解读)Domain Adaptation via Prompt Learning

摘要 无监督域适应( UDA )旨在将从带有标签的源域数据中学习到的模型适应到未标注的目标域数据集。现有的UDA方法通过对齐源域和目标域特征空间来学习领域不变特征。这种对齐是通过约束实现的&#xff0c;例如统计差异最小化或对抗学习。 然而&#xff0c;这些约束会导致语义…

【自动驾驶】控制算法(四)坐标变换与横向误差微分方程

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

浙大版循环结构程序设计 7-6-1 贪心法-找零钱

7-6-1 贪心法-找零钱 #include <stdio.h>int main(){int n5,n2,n1,money,total;int flag 1; //判断是否符合条件然后跳出循环scanf("%d",&money);if(money>100){printf("Invalid.");}for(n5money/5;(flag1)&&(n5>0);n5--){for(n2…

2-75 基于matlab的多尺度小波核svm预测

基于matlab的多尺度小波核svm预测&#xff0c;数据归一化操作&#xff0c;尺度小波核函数作为核函数进行训练&#xff0c;训练后的模型进行预测。程序已调通&#xff0c;可直接运行。 2-75 多尺度小波核 SVM预测 - 小红书 (xiaohongshu.com)

Java 认识String类

1. 创建字符串 常见的构造 String 的方式 //方式一&#xff1a;String str "hello world";//方式二&#xff1a;String str2 new String("Hello world");//方式三&#xff1a;char[] array {a,b,c};String str3 new String(array);注意事项&#xff1…

Promise学习之初步认识Promise

目录 前言 一、认识Promise (一) 含义 (二) 代码演示 二、Promise状态 三、总结 前言 在上一篇的学习中&#xff0c;我们已经认识到了同步与异步&#xff0c;异步代码在解决同步代码问题的同时&#xff0c;也会产生一些新的问题&#xff0c;比如常说的回调地狱&#xff0…

DBSCAN算法及Python实践

DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff0c;具有噪声的基于密度的空间聚类应用&#xff09;算法是一种基于密度的聚类算法&#xff0c;它在机器学习和数据挖掘领域有广泛的应用。以下是DBSCAN算法的主要原理和特点&#xff1a…

系统编程-管道

管道 目录 管道 1、管道的特点 2、无名管道的使用步骤 &#xff08;1&#xff09;在进程中使用 pipe 函数来获取管道的文件描述符 &#xff08;2&#xff09;使用 fork 函数来创建子进程 &#xff08;3&#xff09;通过获取到的文件描述符来进行数据的传输 &#xff08…

第八周:机器学习

目录 摘要 Abstract 一、注意力机制V.S.自注意力机制 1、引入 2、注意力机制 3、自注意力机制 二、自注意力机制 1、输入 2、输出 3、序列标注 4、Multi-head Self-attention 5、比较 总结 摘要 前两周学习了CNN的基本架构&#xff0c;针对全局信息的考虑问题&…

【Kotlin设计模式】Kotlin实现单例模式

前言 单例模式&#xff08;Singleton Pattern&#xff09;&#xff0c;是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。在 Android 中&#xff0c;有许多系统服务和 API 使用了单例模式&#xff0c;比如&#xff1a; Context: 通过getApplication…

SpringBoot2:创建项目及启动时相关报错整理

1、创建时报错 Initialization failed for https://start.aliyun.com/ Please check URL, network and proxy settings.Error message: Error parsing JSON response换官网地址初始化即可&#xff1a;https://start.spring.io/ 那么&#xff0c;大家肯定会疑问&#xff0c;官网…

【SpringBoot】10 日志持久化(log4j2)

介绍 日志概念 日志是系统生成的数据&#xff0c;用于记录网络、端点、物联网、应用程序、操作系统等&#xff0c;在运行时所发生事件的信息&#xff0c;便于开发人员或维护人员进行故障排查、性能优化、安全审计等工作。 日志作用 问题追踪及调试&#xff1a;当程序出现问…

C语言 | Leetcode C语言题解之第372题超级次方

题目&#xff1a; 题解&#xff1a; //计算a的b次方 int mypow(int a, int b){a a % 1337; // 防止a过大超出规模int ret 1;for(int i 0; i < b; i){ret * a;ret ret % 1337; //防止超出规模}return ret; } //整体计算 int superPow(int a, int* b, int bSize){if(a 1…

Android Jitpack制作远程仓库aar流程

开发高效提速系列目录 软件多语言文案脚本自动化方案Android Jitpack制作远程仓库aar流程 Android Jitpack制作远程仓库aar流程 背景aar制作与使用1. aar制作2. aar使用 异常解决总结 博客创建时间&#xff1a;2023.08.24 博客更新时间&#xff1a;2023.08.24 以Android stud…

leetcode刷题之二分算法

目录 简介 第一个错误的版本 算法思路 代码实现 两个数组的交集 算法思路 代码实现 两个数组的交集2 算法思路 代码实现 有效的完全平方数 算法思路 代码实现 猜数字大小 算法思路 代码实现 排列硬币 算法思路 代码实现 寻找比目标字母大的最小字母 代码实…

XTuner微调个人小助手认知实战

1 微调前置基础 本节主要重点是带领大家实现个人小助手微调&#xff0c;如果想了解微调相关的基本概念&#xff0c;可以访问XTuner微调前置基础。 2 准备工作 环境安装&#xff1a;我们想要用简单易上手的微调工具包 XTuner 来对模型进行微调的话&#xff0c;第一步是安装 XTun…

YOLO+Sort实现目标追踪

在前面的目标检测、实例分割的学习中&#xff0c;我们多是对单张图像进行处理&#xff0c;而事实上在我们的实际应用中多数需要对视频进行操作&#xff0c;当然这个操作也是讲视频转换为一帧帧的图像&#xff0c;但博主发现在ultralytics这个算法平台中&#xff0c;针对视频的处…

docker容器基本命令、docker进入容器的指令、容器的备份、镜像底层原理、使用commit命令制造镜像、将镜像推送到阿里云镜像仓库与私服仓库

除了exit 还有 ctrlpq exit退出停止 ctrlpq 退出不停止 将本地镜像推到阿里云 登入阿里云 容器镜像服务 实力列表 镜像仓库 创建镜像仓库 安装里面步骤来 这里192.168.10.145这部分用自己ifconfig地址

虚惊一场的一次事故,在事故中学习

上周日吃着晚饭时&#xff0c;“叮叮”两声&#xff0c;老板在QQ上单独M我。 “服务器好像崩了” “昨天和前天在线人数猛猛下滑 现在更是只有879人在线了” 看完消息&#xff0c;我震惊了&#xff0c;忙用筷子将碗中剩下的饭菜一股脑扒拉到嘴里&#xff0c;来到书桌前坐下&a…