为了能到远方,脚下的每一步都不能少.|

Lxx-123

园龄:1年粉丝:8关注:0

2月13日

前置知识

begin();end()正序迭代器
cbegin();cend() 返回 const 的begin();end()
rbegin();rend() 逆序迭代器
crbegin();crend() 返回 const 的 rbegin();rend()

begin();end()分别返回指向容器头的迭代器、指向容器尾的迭代器

示例代码:

int main ()
{
std::vector<int> a{1,2,3,4,5};
for (std::vector<int>::iterator iter=a.begin(); iter!=a.end(); ++iter){
std::cout << "old element:" << *iter;// 打印元素
(*iter) += 1;// 通过迭代器修改对应元素
std::cout << ", new:" << *iter << std::endl;
}
}

结果:
打印结果:
old element:1, new:2
old element:2, new:3
old element:3, new:4
old element:4, new:5
old element:5, new:6

rbegin(); rend() 返回逆序迭代器

例题:

1.假如一个数组里面,有一个数只出现一次,其余都出现两次,那么如何找出那个出现一次的数

1)异或法:

思路:
异或运算符(^):任何数和自己异或的结果是 0,任何数和 0 异或的结果是它本身。因此,可以通过异或运算将所有数字依次异或,最终剩下的就是只出现一次的数字。

#include <iostream>
using namespace std;
int main() {
int z[7] = { 1,2,3,4,2,3,1 };
int d=0;
for (int nums : z) {
d = d^nums;
}
cout << d;
}

2)使用哈希表

思路:
统计每个数字出现的次数,最后找到出现次数为 1 的数字。

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int singleNumber(vector<int>& nums) {
unordered_map<int, int> countMap;
for (int num : nums) {
countMap[num]++;
}
for (auto& pair : countMap) {
if (pair.second == 1) {
return pair.first;
}
}
return -1; // 如果没有找到,返回一个默认值
}
int main() {
vector<int> nums = {4, 1, 4, 6, 1};
cout << "The single number is: " << singleNumber(nums) << endl;
return 0;
}

2.给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

思路:

使用哈希表,读取数组时,检查哈希表中是否存在 target - current_element,若存在,则返回这两个元素的索引,没有就将当前元素及其索引存入哈希表。

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> mp;
for (int i = 0; i < nums.size(); i++) {
int s = target - nums[i];
if (mp.find(s) != mp.end()) {
return {mp[s], i};
}
mp[nums[i]] = i;
}
return {};
}
};

3.罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。

示例 1:

输入: s = "III"
输出: 3
示例 2:

输入: s = "IV"
输出: 4
示例 3:

输入: s = "IX"
输出: 9
示例 4:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

提示:

1 <= s.length <= 15
s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
关于罗马数字的详尽书写规则,可以参考 罗马数字 - 百度百科。

思路:

首先用哈希表,存储各个符号所对应的值
这一题是计算时,先对比该字符的值是否小于下一位的值,小于就取负数,反之正数

class Solution {
public:
int romanToInt(string s) {
unordered_map<char, int> symbol = {
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
int result=0;
for(int i=0;i<s.size();++i){
if(symbol[s[i]]<symbol[s[i+1]]){
result-=symbol[s[i]];
}else{
result+=symbol[s[i]];
}
}
return result;
}
};

4.回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数
是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

例如,121 是回文,而 123 不是。

示例 1:

输入:x = 121
输出:true
示例 2:

输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:

输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。

提示:

-231 <= x <= 231 - 1

进阶:你能不将整数转为字符串来解决这个问题吗?

思路:反转字符串,对比两者是否相同;或者反转一半

class Solution {
public:
bool isPalindrome(int x) {
string s=to_string(x);
return s==string(s.rbegin(),s.rend());
}
};

5.两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

思路:
1.直接想法,转化成整数,这样无法实现,会溢出
2.直接在链表上相加,并用一个变量存储进位

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(-1); // 哑节点
ListNode* cur = head;
int carry=0;
while(l1||l2){
int sum = carry;
if (l1) {
sum += l1->val;
l1 = l1->next;
}
if (l2) {
sum += l2->val;
l2 = l2->next;
}
carry=sum/10;
cur->next=new ListNode(sum % 10);
cur = cur->next;
}
if(carry>0){
cur->next = new ListNode(carry);
}
return head->next;
}
};

3.递归法

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
return add(l1, l2, 0);
}
ListNode* add(ListNode* l1, ListNode* l2, int carry) {
if (!l1 && !l2 && carry == 0) {
return nullptr;
}
int sum = carry;
if (l1) sum += l1->val;
if (l2) sum += l2->val;
ListNode* node = new ListNode(sum % 10);
carry = sum / 10;
// 递归处理下一位
node->next = add(
l1 ? l1->next : nullptr,
l2 ? l2->next : nullptr,
carry
);
return node;
}
};

本文作者:Lxx-123

本文链接:https://www.cnblogs.com/l-xx123/p/18713151

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Lxx-123  阅读(2)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起