1、两数之和
题目:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
主要用了三种解法:
1、暴力法
2、双指针法
3、hash法
代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target){
//方法一:暴力法
/*vector<int> result;
for (int i = 0; i < nums.size(); i++)
{
for (int j = i + 1; j < nums.size(); j++)
{
if (nums[i] + nums[j] == target) {
result.push_back(i);
result.push_back(j);
return result;
}
}
}
return result;*/
//方法二:双指针法
// vector<int> result;
// vector<int> nums2;
// nums2 = nums;
// sort(nums.begin(), nums.end());
// int i = 0;
// int j = nums.size() - 1;
// while (i < j) {
// if (nums[i] + nums[j] < target) {
// i++;
// }
// else if (nums[i] + nums[j] > target)
// {
// j--;
// }
// else {
// break;
// }
// }
// for (int p = 0; p < nums2.size();p++) {
// if (nums2[p] == nums[i] || nums2[p] == nums[j]) {
// result.push_back(p);
// if (result.size() == 2) {
// return result;
// }
// }
// }
//hash法
vector<int> result;
unordered_map<int,int> hash;
for (int i = 0; i < nums.size(); i++)
{
if (hash[target - nums[i]] &&
hash[target - nums[i]] != i + 1)
{
result.push_back(hash[target - nums[i]] - 1);
result.push_back(i);
return result;
}
hash[nums[i]] = i + 1;
}
return result;
}
};
2、两数相加
题目:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
链表逐位相加,并通过变量记录进位。
代码:
/**
* 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) {
ListNode* result = nullptr;
if (!l1 && !l2) {
return result;
}
if (l1 && !l2) {
return l1;
}
if (!l1 && l2) {
return l2;
}
int sum = l1->val + l2->val;
int y = (l1->val + l2->val) % 10;
int c = (l1->val + l2->val) / 10;
result = new ListNode(y);
ListNode* copy = result;
l1 = l1->next;
l2 = l2->next;
while (l1) {
int val = l1->val;
if (l2) {
val += l2->val;
l2 = l2->next;
}
y = (val + c) % 10;
c = (val + c) / 10;
ListNode *node = new ListNode(y);
copy->next = node;
copy = copy->next;
l1 = l1->next;
}
while (l2) {
int val = l2->val;
y = (val + c) % 10;
c = (val + c) / 10;
ListNode *node = new ListNode(y);
copy->next = node;
copy = copy->next;
l2 = l2->next;
}
if(c){
ListNode* node = new ListNode(c);
copy->next = node;
}
return result;
}
};
3、无重复字符的最大长串
题目:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
滑动窗口
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//滑动窗口
unordered_set<char> window;
int max_length = 0;
int left = 0;
for (int i = 0;i < s.size(); i++)
{
while (window.find(s[i]) != window.end()) {
window.erase(s[left]);
left++;
}
window.insert(s[i]);
max_length = max(max_length, i - left + 1);
}
return max_length;
}
};
4、寻找两个正序数组的中位数
题目:
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]则中位数是 2.0
示例 2:nums1 = [1, 2]
nums2 = [3, 4]则中位数是 (2 + 3)/2 = 2.5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
1、暴力法
2、二分法
代码:
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
class Solution
{
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
{
//1暴力法
/*vector<int> num;
int i = 0;
int j = 0;
while (i < nums1.size() || j < nums2.size()) {
if (i < nums1.size() && j < nums2.size()) {
if (nums1[i] < nums2[j]) {
num.push_back(nums1[i]);
i++;
}
else if (nums1[i] > nums2[j])
{
num.push_back(nums2[j]);
j++;
}
else {
num.push_back(nums1[i]);
i++;
num.push_back(nums2[j]);
j++;
}
}
else {
if (i < nums1.size()) {
num.push_back(nums1[i]);
i++;
}
if (j < nums2.size()) {
num.push_back(nums2[j]);
j++;
}
}
}
if (num.size() % 2 == 0) {
return (num[num.size() / 2] + num[num.size() / 2 + 1]) / 2;
}
else {
return num[(num.size() + 1) / 2];
}*/
//2 二分法
if (nums1.size() > nums2.size())
{
vector<int> temp = nums1;
nums1 = nums2;
nums2 = temp;
}
int m = nums1.size();
int n = nums2.size();
int total = (m + n + 1) / 2;
int left = 0;
int right = m;
while (left < right) {
int i = left + (right - left + 1) / 2;
int j = total - i;
if (nums1[i - 1] > nums2[j])
{
right = i - 1;
}
else {
left = i;
}
}
int i = left;
int j = total - i;
int FIRST_LEFT = i == 0 ? INT_MIN : nums1[i - 1];
int FIRST_RIGHT = i == m ? INT_MAX : nums1[i];
int SECOND_LEFT = j == 0 ? INT_MIN : nums2[j - 1];
int SECOND_RIGHT = j == n ? INT_MAX : nums2[j];
if ((m + n) % 2 == 0) {
return (((double)max(FIRST_LEFT, SECOND_LEFT) + (double)min(FIRST_RIGHT, SECOND_RIGHT))/2);
}
else {
return max(FIRST_LEFT, SECOND_LEFT);
}
}
};