Two Sum:

解法一:排序后使用双索引对撞:O(nlogn)+O(n) = O(nlogn) , 但是返回的是排序前的指针。

解法二:查找表。将所有元素放入查找表, 之后对于每一个元素a,查找 target-a 是否存在。使用map实现,键是元素的值,键值是元素对应的索引。

不能把vector中所有的值放到查找表中,因为若有重复的值,前一个会被后一个覆盖。所以改善为把当前元素v前面的元素放到查找表中。

时间复杂度:O(n)

空间复杂度:O(n)

注意:这道题只有唯一解。

class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> record;
for(int i=; i<nums.size();i++){
int complement = target - nums[i];
if(record.find(complement) != record.end()){
int res[] = {i, record[complement]}; //res记录两个元素的索引
return vector<int>(res, res+);
}
record[nums[i]] = i;
}
throw invalid_argument("The input has no solution");
}
};

需要考虑不同的三元组:是要求值不同还是索引不同。

class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > res;
if(nums.size()<=){
return res;
} sort(nums.begin(), nums.end());
size_t i = ;
while(i<nums.size()-){
int target = -nums[i];
int l = i+;
int r = nums.size()-;
while(l<r){
int sum = nums[l]+nums[r];
if(sum<target)
l++;
else if(sum>target)
r--;
else{
vector<int> triplet = {nums[i], nums[l], nums[r]};
res.push_back(triplet);
//避免把重复的一组数字存入res中
while(l<r && nums[l] == triplet[])
l++;
while(l<r && nums[r] == triplet[])
r--;
}
}
int curNum = nums[i];
while(i<nums.size()- && nums[i]==curNum)
i++;
}
return res;
}
};

思路和3sum差不多,也就是多加了一层循环,即这里有两层循环,然后用一对对撞指针来计算剩下的两个数之后。

需要注意的是:int(nums.size()-3) 和 int(nums.size()-2) 一定要加 int() 因为nums.size() == 0 时,因为它是unsigned int 型 , nums.size()-2=2^32-2,循环次数就炸掉了。

class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
set<vector<int>> res;
sort(nums.begin(),nums.end());
for(int i=;i<int(nums.size()-);i++){
for(int j=i+; j<int(nums.size()-); j++){
if(j>i+ && nums[j]==nums[j-] ) continue;
int left = j+, right = nums.size()-;
while(left<right){
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if(sum==target){
vector<int> out{nums[i], nums[j], nums[left], nums[right]};
res.insert(out);
left++;
right--;
}
else if(sum < target)
left++;
else
right--;
}
}
}
return vector<vector<int>>(res.begin(), res.end());
}
};

思路:这题要求返回最接近给定值的值,所以我们要保证档期那的三个数和给定值之间的差的绝对值最小。

1)首先定义diff来记录差的绝对值,closest保存当前最小的三个数的和;

2)数组排序,以便进行左指针和右指针的移动;

3)遍历一遍数组,再使用对撞指针的思想计算三个数的和,与diff进行比较,并把较小值保存在diff中,最后返回closest。

class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int closest = nums[] + nums[] + nums[];
int diff = abs(closest - target);
sort(nums.begin(), nums.end());
for(int i=; i<nums.size()-;i++){
int left = i+, right = nums.size()-;
while(left<right){
int sum = nums[i] + nums[left] + nums[right];
int newDiff = abs(sum-target);
if(diff > newDiff){
diff = newDiff;
closest = sum;
}
if(sum<target) left++;
else right--;
}
}
return closest;
}
};

class Solution {
public:
//时间复杂度O(n^2)
//空间复杂度O(n^2)
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
unordered_map<int,int> record;
for(int i=;i<C.size();i++){
for(int j=;j<D.size();j++)
record[C[i]+D[j]] ++;
}
int res = ;
for(int i=; i<A.size();i++){
for(int j=;j<B.size();j++){
if(record.find(-A[i]-B[j]) != record.end())
res += record[-A[i]-B[j]];
}
} return res;
}
};

本题中都是小写字母。

class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> res; //返回值
unordered_map<string, vector<string>> m; //字符串与它的同构字符串之间的映射
for(string str: strs){
string t = str;
sort(t.begin(),t.end());
m[t].push_back(str);
}
for(auto a:m)
res.push_back(a.second);
return res;
}
};

思路:如下图所示,定义一个map来记录每个点到point i 的距离,和它对应的频次。然后遍历这个map,若能找到频次大于等于2的点,则把res值累加上。

注意:为了防止距离开根号出现浮点数,这里储存距离的平凡。

//时间复杂度O(n^2)
//空间复杂度O(n)
class Solution {
public:
int numberOfBoomerangs(vector<pair<int, int>>& points) {
int res = ; //记录一共有多少个符合条件的三元组
for(int i=; i<points.size(); i++){
unordered_map<int, int> record; //其余的点距离points的值,及其出现的频次
for(int j=;j<points.size();j++){
if(j!=i)
record[ dis(points[i], points[j]) ]++;
}
for(unordered_map<int,int>::iterator iter=record.begin(); iter!=record.end();iter++)
if(iter->second >=)
res += (iter->second)*(iter->second-);
}
return res;
} private:
int dis(const pair<int,int> &pa, const pair<int, int> &pb){
return (pa.first - pb.first)*(pa.first - pb.first) +
(pa.second-pb.second)*(pa.second-pb.second);
}
};

不愧是hard模式,连代码长度都是其他题目的两倍 ==

思路:1)使用map型的lines来存储直线的斜率和对应出现的频次;

2)需要注意判断两个边界条件:两个点重合的情况和两个点的x值相同也就是斜率无限大的情况;

3)求斜率的时候使用了求两个数的最大公约数的方法,分别用这两个数来除以公约数,来得到这两个数斜率的最简值(比如4/2 和 2/1的斜率最简化的值都是2/1)。然后存储到lines中。

4)最终的result保存最大的值,注意要加上重复点的个数。

/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
int maxPoints(vector<Point>& points) {
if(points.size()<) return points.size();
int result = ;
map<pair<int, int> ,int> lines;
for(int i=; i<points.size();i++){
lines.clear();
int duplicate = , vertical = ;
for(int j=i+;j<points.size();j++){
if(points[j].x == points[i].x && points[j].y == points[i].y){
duplicate++;
continue;
}
else if(points[j].x == points[i].x) vertical++;
else{
//求两点的斜率
int a = points[j].x - points[i].x;
int b = points[j].y - points[i].y;
int gcd = GCD(a,b);
a /= gcd, b /= gcd;
lines[make_pair(a,b)]++; //存储对应斜率的次数
}
}
if(result < duplicate) result = duplicate;
if(result < vertical) result = vertical;
for(auto line : lines){
int tmp = duplicate + line.second;
if(result < tmp) result = tmp;
}
}
return result;
} private:
int GCD(int a, int b){
if(b==) return a;
else return GCD(b, a%b);
}
};

查找表,Two Sum,15. 3Sum,18. 4Sum,16 3Sum Closest,149 Max points on line的更多相关文章

  1. 1. Two Sum&&15. 3Sum&&18. 4Sum

    题目: 1. Two Sum Given an array of integers, return indices of the two numbers such that they add up t ...

  2. leetcode 1.Two Sum 、167. Two Sum II - Input array is sorted 、15. 3Sum 、16. 3Sum Closest 、 18. 4Sum 、653. Two Sum IV - Input is a BST

    1.two sum 用hash来存储数值和对应的位置索引,通过target-当前值来获得需要的值,然后再hash中寻找 错误代码1: Input:[3,2,4]6Output:[0,0]Expecte ...

  3. 15. 3Sum、16. 3Sum Closest和18. 4Sum

    15 3sum Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = ...

  4. LeetCode 15. 3Sum 16. 3Sum Closest 18. 4Sum

    n数求和,固定n-2个数,最后两个数在连续区间内一左一右根据当前求和与目标值比较移动,如果sum<target,移动较小数,否则,移动较大数 重复数处理: 使i为左至右第一个不重复数:while ...

  5. 【LeetCode】18. 4Sum 四数之和

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:four sum, 4sum, 四数之和,题解,leet ...

  6. [LeetCode][Python]18: 4Sum

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 18: 4Sumhttps://oj.leetcode.com/problem ...

  7. 修改6S Fortran77 代码,建立查找表

      逐像元大气校正,常预先计算查找表(LUT,LookUp Tabel),6S大气辐射传输模式也可以用来计算LUT.但6S源程序输出信息多,且浮点数输出精度低,不利于提取关键信息生成LUT,本文描述了 ...

  8. java 实现从15位~18位的身份证号码转换,校验中国大陆公民身份证、香港居民身份证、澳门身份证和台湾身份证。

    package xidian.sl.netcredit.util; /** * Copyright (C) 2009-2010 Yichuan, Fuchun All rights reserved. ...

  9. 数据结构算法C语言实现(三十二)--- 9.1静态查找表

    一.简述 静态查找表又分为顺序表.有序表.静态树表和索引表.以下只是算法的简单实现及测试,不涉及性能分析. 二.头文件 /** author:zhaoyu date:2016-7-12 */ #inc ...

随机推荐

  1. php常用 随机数

    <?php $number =range(1,50); //shuffle 将数组顺序随即打乱. shuffle($number); print_r($number); echo '<br ...

  2. 在CentOS6.x下安装Compiz——桌面立方体,特效种种

    很多人貌似认为compiz必须要emerland,但事实上,没这个必要. compiz+gnome,实用,而又华丽,是个不错的选择. compiz需要显卡驱动,一般情况下不成问题(别忘了这是很新的ce ...

  3. Solidity字符串拼接实现oraclize动态查询

    solidity本身没有字符串拼接功能,但是如果你恰巧要用oraclize api,那么可以使用oraclize api中的字符串拼接方法(strConcat).之所以oraclize api里会有s ...

  4. Linux pkg-config命令

    一.简介 pkg-config用来检索系统中安装库文件的信息.典型的是用作库的编译和连接. 二.实例 http://blog.chinaunix.net/uid-20595934-id-1918368 ...

  5. poj1722 SUBTRACT

    应该是基础的dp练手题 线性dp最主要的就是关于阶段的划分,这个题中我没想到的一点就是开状态的时候使用了前i个数能合成的数来记录 我自己的想法就是类似于区间dp这样的记录方法,这种方法确实开了很多冗余 ...

  6. Python3 网络爬虫开发实战学习弱点书签

    1. urllib.robotparse模块对robot.txt文件的解析,can_fetch()方法和parse()方法. Page121 2. lxml.etree模块自动补全Html代码,Htm ...

  7. 第05章-构建Spring Web应用程序

    1. Spring MVC起步 1.1 跟踪Spring MVC的请求 前端控制器DispatcherServlet 请求旅程的第一站是Spring的DispatcherServlet.与大多数基于J ...

  8. Densely Connected Convolutional Networks(緊密相連卷積網絡)

    - Dense blocks where each layer is connected to every other layer in feedforward fashion(緊密塊是指每一個層與每 ...

  9. 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源

    建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...

  10. ElasticSearch 笔记(二)

    记录一些核心概念 1) Near Realtime (NRT): 近实时,包括 2 个方面,① 数据从写入 Elasticsearch 到可被搜索.分析的延迟 ( 大约 1 秒 ); ② 从 es 中 ...