两数之和
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
思路:
将数组所有元素与其下标构成散列表,词条就是数组中的元素,选一个词条,target减去该词条所得的结果,也是数组中的元素,即用结果词条去表中查询是否存在,因为需要创建哈希表,空间复杂度为O(n),时间复杂度:创建哈希表O(n),单次遍历O(n),总查询次数O(n),所以总时间复杂度为O(n)。
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
public:
static vector<int> twoSum(vector<int>& nums, int target) {
vector<int> rel;
unordered_map<int, int> hashMap;
for (int i = 0 ; i < nums.size(); ++i)
hashMap[nums[i]] = i;
for (int i = 0; i < nums.size(); ++i)
{
int r = target - nums[i];
if (hashMap.count(r) > 0 && hashMap[r] != i)
{
rel.push_back(i);
rel.push_back(hashMap[r]);
return rel;
}
}
return rel;
}
};
两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807
思路:
1.相加方法就是普通的两个多位数相加,只是题目把多位数以链表的形式给出,故需要引入链表的性质,返回值为链表头。
2.在进行相加时,首先对低位相加,需要记录进位符,以及进入下一个高位时的判空
3.设l1长度为m,l2长度为n,时间复杂度为O(max(m, n))
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int carry = 0;
// 记录链表头,作为返回值
ListNode* preHead = new ListNode(0);
// 将临时指针指向链表头,方便对链表进行add操作,以及位置更新
ListNode* p = preHead;
// 当l1和l2都为空,以及carry进位符为0时,不会再有高位产生,退出循环
while (l1 != NULL || l2 != NULL || carry != 0)
{
// l1或l2其中一个为空时,按值取0进行计算,相加结果需要加上进位符
int sum = (l1 != NULL ? l1->val : 0) + (l2 != NULL ? l2->val : 0) + carry;
// 当前位置相加时产生的进位
carry = sum / 10;
// 将当前位置的值作为结果,接到链表上作为链表下一个值
p->next = new ListNode(sum % 10);
// 更新计算位置
p = p->next;
l1 = l1 != NULL ? l1->next : l1;
l2 = l2 != NULL ? l2->next : l2;
}
// 去掉链表头的0
return preHead->next;
}
};
无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是"b",所以其长度为 1。
示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。
思路:
1.使用map记录字符与其下标位置,方便查找,当遇到重复字符时,快速获取上一个重复字符的下标位置
2.提前先遍历字符串,初始化各个字符的其实下标为-1
3.取start指向当前无重复字符串的其实位置
4.当字符的当前下标位置在start之后时,说明该字符已包含在当前无重复字符串中,如果再次遇到该字符,说明无重复字符串结构被破坏
5.记录无重复字符串长度,从start一直到碰到重复字符的前一个下标位置
6.遍历完整个字符串,需要记录最后一段无重复字符串长度
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.empty())
return 0;
// 提前先遍历字符串,初始化各个字符的其实下标为-1
map<char, int> rel;
for (int i = 0; i < s.length(); ++i)
rel[s[i]] = -1;
int maxLen = 0;
// 记录单词开始位置,重复时,指向该重复字符位置的下一个
int start = 0;
for (int i = 0; i < s.length(); ++i)
{
if (rel[s[i]] >= start)
{
int len = i - start;
start = rel[s[i]] + 1;
if (maxLen < len)
maxLen = len;
}
rel[s[i]] = i;
}
// 记录扫描到末尾的最后一段长度,与maxLen比较
int len = s.length() - start;
if (maxLen < len)
maxLen = len;
return maxLen;
}
};