【leetcode热题100】刷题记录(1-4)
1. 两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
题目解答
思路就是用num-target
作为字典的key
,然后记录对应的下标,当找到数字时,直接返回对应的两个索引即可。
python 解答
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
dic = dict()
for i, num in enumerate(nums):
if num not in dic:
dic[target - num] = i
else:
return [dic[num], i]
cpp解答
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> dic;
for (int i = 0; i < nums.size(); i ++)
{
auto it = dic.find(nums[i]);
if (it != dic.end())
return {it->second, i};
dic[target - nums[i]] = i;
}
return {};
}
};
2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
题目解答
直接模拟就可以了,注意c++用的时候,返回对象是个指针还是一个对象,指针的话,要用->
,对象用.
。
python 解答
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
adds = 0 # 进位
head = curr = ListNode(0)
while l1 or l2 or adds:
val = 0
if l1:
val += l1.val
l1 = l1.next
if l2:
val += l2.val
l2 = l2.next
val, adds = (val + adds) % 10, (val + adds) // 10
node = ListNode(val)
curr.next = node
curr = curr.next
return head.next
cpp解答
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int adds = 0;
ListNode *head = nullptr;
ListNode *curr = nullptr;
head = curr = new ListNode(0);
while (l1 || l2 || adds)
{
int val = 0;
if(l1)
{
val += l1->val;
l1 = l1->next;
}
if(l2)
{
val += l2->val;
l2 = l2->next;
}
curr->next = new ListNode((val + adds) % 10);
adds = (val + adds) / 10;
curr = curr->next;
}
return head->next;
}
};
3. 无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符
的 最长子串
的长度
。
题目解答
双指针加set
从左往右滑窗,如果遇到set
里面没有的元素,右指针一直右移动,直到不满足了,更新一下最长距离,然后加入s[r]
,删掉s[l]
,这里我还记录了final_l
,相当于如果要求最长不重复子序列的话,那就直接输出s[final_l:final_l+res]
python 解答
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
l, r = 0, 0
final_l = 0
res = 0
dic = set()
while r < len(s):
while r < len(s) and s[r] not in dic:
dic.add(s[r])
r += 1
if r - l > res:
res = r - l
final_l = l
dic.remove(s[l])
l += 1
return res
cpp解答
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int l = 0, r = 0, res = 0, final_l;
unordered_set<char> dic;
while (r < s.size())
{
while (r < s.size() and dic.find(s[r]) == dic.end())
{
dic.insert(s[r]);
r ++;
}
if (r - l > res)
{
res = r - l;
final_l = l;
}
dic.erase(s[l]);
l ++;
}
return res;
}
};
4. 寻找两个正序数组的中位数
给定两个大小分别为 m
和 n
的正序(从小到大)数组 nums1
和 nums2
。请你找出并返回这两个正序数组的 中位数
。
算法的时间复杂度应该为 O(log (m+n))
。
题目解答
二分查找
具体而言就是寻找到对两个数组的一个分割,转化成求前k小数字的问题,分割的时候主要使得分割线左右元素的值满足交叉有序关系,然后再讨论一些边界条件即可。具体的可以看官网解析
python 解答
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
if len(nums1) > len(nums2):
return self.findMedianSortedArrays(nums2, nums1)
infinty = 2**40
m, n = len(nums1), len(nums2)
left, right = 0, m
# median1:前一部分的最大值
# median2:后一部分的最小值
median1, median2 = 0, 0
while left <= right:
# 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
# // 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]
i = (left + right) // 2
j = (m + n + 1) // 2 - i
# nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]
nums_im1 = (-infinty if i == 0 else nums1[i - 1])
nums_i = (infinty if i == m else nums1[i])
nums_jm1 = (-infinty if j == 0 else nums2[j - 1])
nums_j = (infinty if j == n else nums2[j])
if nums_im1 <= nums_j:
median1, median2 = max(nums_im1, nums_jm1), min(nums_i, nums_j)
left = i + 1
else:
right = i - 1
return (median1 + median2) / 2 if (m + n) % 2 == 0 else median1
cpp解答
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
if (nums1.size() > nums2.size()) {
return findMedianSortedArrays(nums2, nums1);
}
int m = nums1.size();
int n = nums2.size();
int left = 0, right = m;
// median1:前一部分的最大值
// median2:后一部分的最小值
int median1 = 0, median2 = 0;
while (left <= right) {
// 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]
// 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]
int i = (left + right) / 2;
int j = (m + n + 1) / 2 - i;
// nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]
int nums_im1 = (i == 0 ? INT_MIN : nums1[i - 1]);
int nums_i = (i == m ? INT_MAX : nums1[i]);
int nums_jm1 = (j == 0 ? INT_MIN : nums2[j - 1]);
int nums_j = (j == n ? INT_MAX : nums2[j]);
if (nums_im1 <= nums_j) {
median1 = max(nums_im1, nums_jm1);
median2 = min(nums_i, nums_j);
left = i + 1;
} else {
right = i - 1;
}
}
return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;
}
};