【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
1. Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
作为LeetCode的首题,Two Sum的名气不小啊,正所谓平生不会TwoSum,刷尽LeetCode也枉然。记得原来在背单词的时候,总是记得第一个单词是abandon,结果有些人背来背去还在abandon,有时候想想刷题其实跟背GRE红宝书没啥太大的区别,都是一个熟练功夫,并不需要有多高的天赋,只要下足功夫,都能达到一个很不错的水平,套用一句鸡汤问来激励下吧,“有些时候我们的努力程度根本达不到需要拼天赋的地步” (来源于博客)
//问题:数组找两个和为目标值的数
//方法一:双重遍历(类似选择排序法中的方法),扫描到所有可能的组合
//O(n^2) O(1) 很慢186ms
/*
class Solution
{
public:
vector<int> twoSum(vector<int>& a, int target)
{
for(int i = 0; i < a.size()-1; i++)
{
for(int j = i+1; j<a.size(); j++)
{
if(a[i]+a[j] == target) return vector<int>{i,j};
}
}
return vector<int>{-1,-1}; //表示没有找到
}
};*/
/*
方法二:一次遍历+hash表
过程:将值+索引存储在hash表中,每次查找hash表中是否存在某个key(target-a[i],用成员函数find查找即可,每次查找花费常数时间)与当前值和为target
O(n), O(n) 14ms
*/
#include <unordered_map>
class Solution
{
public:
vector<int> twoSum(vector<int>& a, int target)
{
unordered_map <int, int> table;
vector<int> result;
for(int i = 0; i<a.size(); i++) //遍历数组
{
//先找再存,这样有先后关系,在已经存的元素中去找可以凑成2sum对的元素,防止同一个数被使用两次
int numberToFind = target - a[i]; //算出要找的值,
if(table.find(numberToFind) != table.end()) //如果找得到(当找不到的时候,find函数会返回容器的末尾迭代器)
{
result.push_back(table[numberToFind]); //push索引,因为要返回索引
result.push_back(i);
}
else //如果找不到时,存入hash表
table[a[i]] = i; //值+索引(key-value)存于hash表中,相同的元素会覆盖前面的索引
//哈希表无需手动重建空间,当调用[]符号时会自动创建空间,并赋初始值0(如果不手动赋值的话)
}
return result;
}
};
167. Two Sum II - Input array is sorted(《剑指offer》第57题)
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.
Note:
-
Your returned answers (both index1 and index2) are not zero-based.
-
You may assume that each input would have exactly one solution and you may not use the same element twice.
Example:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
/*
问题:所给数组为有序数组(递增),找和为特定值的两个数
方法:双指针法
过程:前后各一指针,当和小于target时,往中间移动左边指针,当和大于target时,往中间移动右边指针直到相遇或者等于target
O(n), O(1) (由于利用了数组有序性的特点,优于哈希表的方法)
*/
class Solution
{
public:
vector<int> twoSum(vector<int>& a, int target)
{
vector<int> result;
if(a.empty()) return result;
int left = 0, right = a.size()-1;
while(left < right)
{
if(a[left] + a[right] < target) left++;
else if(a[left] + a[right] > target) right--;
else
{
result.push_back(left+1); //题目要求索引以1开始
result.push_back(right+1);
return result;
}
}
return result;
}
};
653. Two Sum IV - Input is a BST
Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.
Example 1:
Input:
5
/
3 6
/
2 4 7
Target = 9
Output: True
Example 2:
Input:
5
/
3 6
/
2 4 7
Target = 28
Output: False
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/*
问题:在BST中找two sum的两个数,判断是否存在
方法:中序遍历后查找即可
O(n) O(n)(因为每个结点都会被访问一次,故会有n次递归,递归栈的空间复杂度为o(n))
*/
class Solution
{
public:
bool findTarget(TreeNode* root, int k)
{
vector<int> a; //用于存结点值
inorder(root, a);
int left = 0, right = a.size()-1;
while(left<right)
{
int sum = a[left] + a[right];
if(sum < k) left++;
else if(sum > k) right--;
else return true;
}
return false;
}
private:
void inorder(TreeNode* root, vector<int>& a)
{
if(root == nullptr) return;
inorder(root->left, a);
a.push_back(root->val);
inorder(root->right, a);
}
};