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);
}
}
};