思路总结
(1)使用哈希表空间换时间
(2)排序后使用左右指针
1. Remove Duplicates from Sorted Array
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
Given nums = [1,1,2], Your function should return length =2
, with the first two elements ofnums
being1
and2
respectively. It doesn't matter what you leave beyond the returned length.
思路:easy
只需要两个下标,一个记录不重复所在位置,一个不断遍历即可
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() < 2) return nums.size();
int i = 0;
for(int j = 1;j < nums.size();j++){
if(nums[i] != nums[j]){
i++;
nums[i] = nums[j];
}
}
return i+1;
}
};
2. Remove Duplicates from Sorted Array II
Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
Given nums = [1,1,1,2,2,3], Your function should return length =5
, with the first five elements ofnums
being1, 1, 2, 2
and 3 respectively. It doesn't matter what you leave beyond the returned length.
思路:medium
注意,这里不能改上面的代码,变成减2,会出现问题,1,1,1,2,2,3会变成1,1,2,3,因为第一个2移位之后,会变成1,1,2,2,2,3,造成误判,必须使用count去计次
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() < 3) return nums.size();
int i = 1,cnt = 1;
for(int j = 1;j < nums.size();j++){
if(nums[j] == nums[j-1]) cnt++;
else cnt = 1;
if(cnt < 3) nums[i++] = nums[j];
}
return i;
}
};
3. Longest Consecutive Sequence
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
Your algorithm should run in O(n) complexity.
Example:
Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]
. Therefore its length is 4.
思路:hard
怎样O(n)时间去检测顺序序列 -> 空间换时间,使用哈希表
思路1: 使用字典去记录边界的长度,不断更新
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
if(nums.size()<2) return nums.size();
int left = 0,right = 0;
int res = 0;
map<int,int> m;
for(int num:nums){
if(!m.count(num)){
left = (m.count(num-1) > 0)? m[num-1]:0;
right = (m.count(num+1) > 0)? m[num+1]:0;
// 更新左右边界的长度
m[num] = left+right+1;
m[num-left] = m[num];
m[num+right] = m[num];
res = max(m[num],res);
}
}
return res;
}
};
思路2:使用set,很直观的想法,当一个数的num-1不在数组中时,说明这个num是一个上升序列的起始,因此去找这个序列的右边界
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
if(nums.size()<2) return nums.size();
// 初始化set
set<int> s(nums.begin(),nums.end());
int res=1;
for(int num:s){
// 只有当当前数是一个序列的起始点的时候,去判断序列长度
if(!s.count(num-1)){
// 找到序列最长长度
int right = num+1;
while(s.count(right)) right++;
res = max(res,right-num);
}
}
return res;
}
};
4.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].
思路:easy
(1)时间复杂度O(n^2)
因为未排序需要返回下标,故可以直接O(n^2)时间复杂度遍历
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for(int i = 0;i < nums.size();i++){
for(int j = i+1;j < nums.size();j++){
if(nums[i]+nums[j] == target){
res.push_back(i);
res.push_back(j);
return res;
}
}
}
return res;
}
};
(2)空间换时间,时间复杂度O(N)
这里思路跟上一题很像,充分利用哈希表的特性
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int,int> m;
vector<int> res;
for(int i = 0;i < nums.size();i++){
m[nums[i]] = i;
}
for(int i = 0;i < nums.size();i++){
int num_j = target-nums[i];
// 注意这里m[num_j] != i,确保不会取到自己
if(m.count(num_j) && m[num_j] != i){
res.push_back(i);
res.push_back(m[num_j]);
break;
}
}
return res;
}
};
5.3Sum
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
思路:medium
(1)怎样去重:sort之后判断
(2)3 sum是2 sum的变形,排序后使用2 sum,时间复杂度O(n^2)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size() < 3) return res;
// 排序:便于去重,同时2sum时间负责度变为O(n)
sort(nums.begin(),nums.end());
for(int i = 0;i < nums.size()-2;i++){
int target = 0-nums[i];
if(i == 0 || (i > 0 && nums[i] != nums[i-1])){
int j = i+1,k = nums.size()-1;
while(j < k){
if(nums[j]+nums[k] == target){
vector<int> cur{nums[i],nums[j],nums[k]};
res.push_back(cur);
while(j < k && nums[j+1] == nums[j]) j++;
while(k > j && nums[k-1] == nums[k]) k--;
j++;k--;
}
else if (nums[j]+nums[k] < target) j++;
else k--;
}
}
}
return res;
}
};