415. 字符串相加
解法一:头插
头插是指将一个新元素插入到链表的头部(即第一个位置)。
比如对于456和77,先计算两个数字的末项6+7的结果,然后往前挪动一位
头插的效率较低,每次在字符串的开头插入一个字符,所有后续的字符都需要向后移动一个位置,因此插入一个字符的时间复杂度为O(n),其中n是当前字符串的长度。如果有m个字符需要插入,整体时间复杂度为O(m * n)。在最坏情况下,当字符串长度为n,插入操作需要进行n次,总的时间复杂度为O(n^2)。
解法二:尾插
尾插是指将一个新元素插入到链表的尾部(即最后一个位置)。
尾插相较于头插来说,效率更高
在字符串的末尾追加一个字符的操作通常是O(1)时间复杂度,因为大多数情况下,这只需要将新字符添加到字符串的末尾。如果底层实现需要重新分配内存,这个操作可能会变慢,但这种情况的发生频率很低,均摊时间复杂度仍然为O(1)。如果有n个字符需要插入,总体时间复杂度为O(n)。
代码:C++
cpp
class Solution {
public:
string addStrings(string num1, string num2) {
int end1 = num1.size() - 1, end2 = num2.size() - 1;
int next = 0; // 进位
string strRet;
while (end1 >= 0 || end2 >= 0) // 两个都结束了才结束,只要有一个大于等于0就继续
{
//int val1 = num1[end1]; // 直接取有可能会越界,比如end2还没结束,end1结束了,这时候访问就会越界
int val1 = end1 >= 0 ? num1[end1] - '0' : 0; // 如果大于等于0,就给值,否则给0
int val2 = end2 >= 0 ? num2[end2] - '0' : 0; // ASCII码值
int ret = val1 + val2 + next;
next = ret > 9 ? 1 : 0; // 大于9就进位1,不然进位0
// 头插 -- 头插的效率很低
// strRet.insert(0, 1, (ret%10) + '0'); // 0这个位置插入1个字符,比如字符0加3就变成字符3了
// strRet.insert(strRet.begin(), (ret%10) + '0'); // 也可以给第一个位置的迭代器
// 尾插效率高
strRet += ('0' + ret % 10);
--end1;
--end2;
}
if (next == 1)
strRet += '1';
// 头插
// if(next) // 比如9+1,如果还有一个1
// {
// strRet.insert(strRet.begin(), '1');
// }
// 逆置
reverse(strRet.begin(), strRet.end()); // 逆置区间必须是左闭右开[)
return strRet;
}
};
21.合并两个有序链表
解法:递归
先判断l1和l2的边界条件,然后直接使用递归。
比较list1
和list2
当前节点的值:
- 如果
list1
当前节点的值小于list2
当前节点的值,将list1
的下一个节点指向合并list1
的下一个节点和list2
的结果,返回list1
。 - 否则,将
list2
的下一个节点指向合并list1
和list2
的下一个节点的结果,返回list2
。
代码:C++
cpp
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
// 1空返回2
if(list1 == nullptr)
{
return list2;
}
// 2空返回1
else if(list2 == nullptr)
{
return list1;
}
else if(list1->val < list2->val)
{
list1->next = mergeTwoLists(list1->next, list2);
return list1;
}
else
{
list2->next = mergeTwoLists(list1, list2->next);
return list2;
}
}
};
917. 仅仅反转字母
解法:双指针
begin指向开头,end指向最后一个元素
begin遇到非字母字符就++,end遇到就--
当begin和end都指向字母时,交换它们指向的字符,然后分别移动begin向右,end向左。
代码:C++
cpp
class Solution {
public:
bool IsLetter(char ch)
{
if((ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z'))
{
return true;
}
else
{
return false;
}
}
string reverseOnlyLetters(string s) {
size_t begin = 0, end = s.size()-1;
while(begin < end)
{
while(begin < end && !isalpha(s[begin])) // 也可以直接用c++里面的函数isalpha
{
// 不是字母就++
++begin;
}
while(begin < end && !isalpha(s[end]))
{
--end;
}
swap(s[begin], s[end]);
++begin;
--end;
}
return s;
}
};
387.字符串中的第一个唯一字符
387. 字符串中的第一个唯一字符 - 力扣(LeetCode)
解法:哈希表
可以直接使用一个数据模拟哈希表。
统计每个字母出现的次数,如果等于1就找到了。
因为是在循环中,所以是从前往后,找到就直接是第一个唯一字符。
代码:C++
cpp
class Solution {
public:
int firstUniqChar(string s) {
// 首先,创建一个数组存储
int count[256] = {0};
int n = s.size();
// 统计每个字符出现的次数
for(int i=0; i<n; ++i)
{
count[s[i]] += 1;
}
// 按照字符次序从前往后找只出现一次的字符
for(int i=0; i<n; ++i)
{
if(count[s[i]] == 1)
{
return i;
}
}
return -1;
}
};
哈希表实现:
cpp
class Solution {
public:
int firstUniqChar(string s) {
unordered_map<int, int> frequency;
for (char ch : s) {
++frequency[ch];
}
for (int i = 0; i < s.size(); ++i) {
if (frequency[s[i]] == 1) {
return i;
}
}
return -1;
}
};