持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
1. 两数之和
思路
(暴力枚举) O(n^2)
两重循环枚举下标i,j,然后判断 nums[i]+nums[j] 是否等于 target。
(哈希表) O(n)
使用C++中的哈希表unordered_map<int, int> hash
- 用哈希表存储前面遍历过的数,当枚举到当前数时,若哈希表中存在
target - nums[i]的元素,则表示已经找到符合条件的两个数。 - 若不存在
target - nums[i]的元素则枚举完当前数再把当前数放进哈希表中
时间复杂度: 由于只扫描一遍,且哈希表的插入和查询操作的复杂度是 O(1),所以总时间复杂度是 O(n).
c++代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i++){
if(hash.count(target - nums[i])){
return {i, hash[target - nums[i]]};
}
hash[nums[i]] = i;
}
return {};
}
};
2. 两数相加
思路 O(n)。
(模拟)
这是道模拟题,模拟我们小时候列竖式做加法的过程:
- 从最低位至最高位,逐位相加,如果和大于等于
10,则保留个位数字,同时向前一位进1。 - 如果最高位有进位,则需在最前面补
1。
具体实现
- 同时从头开始枚举两个链表,将
l1和l2指针指向的元素相加存到t中,再将t % 10的元素存到dummy链表中,再t / 10去掉存进去的元素,l1和l2同时往后移动一格。 - 当遍历完所有元素时,如果
t != 0,再把t存入到dummy链表中。
做有关链表的题目, 有个常用技巧:添加一个虚拟头结点:
ListNode *head = new ListNode(-1);,可以简化边界情况的判断。
时间复杂度: 由于总共扫描一遍,所以时间复杂度是 O(n)。
c++代码
/**
* 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* dummy = new ListNode(-1);
ListNode* cur = dummy;
int t = 0;
while(l1 || l2){
if(l1) t += l1->val, l1 = l1->next;
if(l2) t += l2->val, l2 = l2->next;
cur = cur->next = new ListNode(t % 10);
t /= 10;
}
if(t) cur->next = new ListNode(t);
return dummy->next;
}
};
3. 无重复字符的最长子串
思路
(双指针扫描) O(n)
定义两个指针 i,j(i<=j),表示当前扫描到的子串是 [i,j] (闭区间)。扫描过程中维护一个哈希表unordered_map <chat,int>hash,表示 [i,j]中每个字符出现的次数。
线性扫描时,每次循环的流程如下:
- 1.指针
j向后移一位, 同时将哈希表中s[j] 的计数加一,即hash[s[j]]++; - 2.假设
j移动前的区间[i,j]中没有重复字符,则j移动后,只有s[j]可能出现2次。因此我们不断向后移动i,直至区间[i,j]中s[j]的个数等于1为止; - 3.当确保
[i, j]中不存在重复元素时,更新res;
时间复杂度分析: 由于 i,j 均最多增加n次,且哈希表的插入和更新操作的复杂度都是 O(1),因此,总时间复杂度 O(n)。
c++代码
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> hash;
int res = 0;
for(int j = 0, i = 0; j < s.size(); j++){
hash[s[j]]++;
while(hash[s[j]]> 1){
hash[s[i]]--;
i++;
}
res = max(res, j - i + 1);
}
return res;
}
};