文章目录

Two Sum

  • 题意

    给定一个数组,和指定一个目标和。从数组中选择两个数满足和为目标和。保证有且只有一个解。每个元素只可以用一次。
  • 思路

    Hash表快速查询值是否在数组中存在。

    枚举一个数,查询另一个数是否存在。

    注意:虽然一个元素只可以使用一次,但是数组中可以出现重复的元素。
  • 复杂度

    T(N)=O(N),M(N)=O(N)T(N)=O(N),M(N)=O(N)T(N)=O(N),M(N)=O(N)
  • 结果

    Runtime: 5 ms, faster than 70.02% of Java online submissions for Two Sum.

    Memory Usage: 37.5 MB, less than 100.00% of Java online submissions for Two Sum.

    即(5ms, 70.02%, 37.5MB, 100.0%)
  • 源码
class Solution {
public int[] twoSum(int[] nums, int target) {
int []ans = new int[2];
Map<Integer,Integer> m = new HashMap<Integer,Integer>();
for (int i = 0;i < nums.length; ++i) {
if (m.containsKey(nums[i])) {
if (nums[i]*2 == target) {
ans[0] = m.get(nums[i]);
ans[1] = i;
return ans;
}
} else {
m.put(nums[i], i);
}
}
for (int i = 0;i < nums.length; ++i)
if (nums[i]*2 != target && m.containsKey(target-nums[i])) {
ans[0] = i;
ans[1] = m.get(target-nums[i]);
break;
}
return ans;
}
}

Two Sum II

  • 题意

    题意不变。只是输入数组有序。另外返回的下标是基于1。
  • 思路

    由于有序,维护一左一右两个指针,所指数的和过小,则左指针右移一格;过大,右指针左移一格;等于则返回结果。
  • 复杂度

    T(N)=O(N),M(N)=O(1)T(N)=O(N),M(N)=O(1)T(N)=O(N),M(N)=O(1)
  • 结果

    (0ms, 100.0%, 36.9 MB, 100.0%)
  • 源码
class Solution {
public int[] twoSum(int[] nums, int target) {
// twoSumWithSortedArr
// 已经确保了答案存在
int l = 0;
int r = nums.length-1;
int t;
while (true) {
t = nums[l]+nums[r];
if (t < target)
++l;
else if (t > target)
--r;
else
return new int[] {l+1,r+1};
}
}
}

3Sum

  • 题意

    给定一个数组,从中选三个元素a,b,c.使得a+b+c=0.给出所有的可能的三元组(unique triplets)的集合。
  • 思路1

    原数组分为负数和非负数两个数组。则答案只有这些可能:

    1. 负+非负+非负
    2. 非负+负+负
    3. 非负+非负+非负(实际上这个只能是3个0)

      3个0的特殊判断。

      情况1枚举负数,转换为非负数数组中的two Sum问题。

      情况2同理。
  • 思路2

    先排序,直接枚举一个数。转化为Two Sum II问题。
  • 复杂度

    思路1T(N)=O(N2),M(N)=O(N)T(N)=O(N^2),M(N)=O(N)T(N)=O(N2),M(N)=O(N)

    思路2T(N)=O(N2),M(N)=O(1)T(N)=O(N^2),M(N)=O(1)T(N)=O(N2),M(N)=O(1)

    且考虑到思路2变成复杂度更低。毫无疑问选思路2.
  • 结果

    (37ms, 99.61%, 48.5MB, 100.00%)
  • 源码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int target = 0;
List<List<Integer>> ans = new ArrayList<List<Integer>>();
Arrays.sort(nums);
int len = nums.length;
for (int i = 0; i+3 <= len; ++i) {
if (nums[i]*3 > target)
break;
if (i > 0 && nums[i] == nums[i-1])
continue;
int part_target = target-nums[i];
int range[] = {i+1,len-1};
while (range[0] < range[1]) {
twoSum(nums,part_target,range);
if (range[0] >= range[1])
break;
// found a ans
List<Integer> l = new ArrayList<Integer>();
l.add(nums[i]);
l.add(nums[range[0]]);
l.add(nums[range[1]]);
ans.add(l);
// move
do{
++range[0];
}while(range[0] < range[1] && nums[range[0]] == nums[range[0]-1]);
}
}
return ans;
}
public void twoSum(int[] nums, int target, int []range) {
int t;
while (range[0] < range[1]) {
t = nums[range[0]]+nums[range[1]];
if (t < target)
++range[0];
else if (t > target)
--range[1];
else
return;
}
}
}

4Sum

  • 题意

    类似于3Sum.只是变成4个数了。并且目标和不是固定的0,而是通过输入参数指定。
  • 思路

    直接循环枚举,注意控制条件以免重复。

    其实应该写搜索的,但是枚举更加无脑暴力,就直接敲了。
  • 复杂度

    T(N)=O(N3),M(N)=O(1)T(N)=O(N^3),M(N)=O(1)T(N)=O(N3),M(N)=O(1)
  • 结果

    (19ms, 89.95%, 40MB, 100.00%)
  • 源码
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
Arrays.sort(nums);
int len = nums.length;
for (int i = 0; i+4 <= len; ++i) {
if (nums[i]*4 > target)
break;
if (i > 0 && nums[i] == nums[i-1])
continue;
for (int j = i+1; j+3 <= len; ++j) {
if (nums[i]+nums[j]*3 > target)
break;
if (j > i+1 && nums[j] == nums[j-1])
continue; // 前一个数并非是a,[j]和前一个数相同,则没必要用[j]再当b
int part_target = target-nums[i]-nums[j];
int range[] = {j+1,len-1};
while (range[0] < range[1]) {
twoSum(nums,part_target,range);
if (range[0] >= range[1])
break;
// found a ans
List<Integer> l = new ArrayList<Integer>();
l.add(nums[i]);
l.add(nums[j]);
l.add(nums[range[0]]);
l.add(nums[range[1]]);
ans.add(l);
// move
do{
++range[0];
}while(range[0] < range[1] && nums[range[0]] == nums[range[0]-1]);
}
}
}
return ans;
}
public void twoSum(int[] nums, int target, int []range) {
int t;
while (range[0] < range[1]) {
t = nums[range[0]]+nums[range[1]];
if (t < target)
++range[0];
else if (t > target)
--range[1];
else
return;
}
}
}

最新文章

  1. CentOS 7 环境配置
  2. Cocos2d-x 3.X 事件分发机制
  3. 把一个英语句子中的单词次序颠倒后输出。例如输入“how are you”,输出“you are how”;
  4. 创建javascript对象的几种方式
  5. MVVM架构~knockoutjs系列之文本框数符长度动态统计功能
  6. scanf中的[]
  7. 框架设计——MVC IOC
  8. MyBatis开发Dao
  9. http返回状态代码及含义
  10. &lt;转&gt;机器学习笔记之奇异值分解的几何解释与简单应用
  11. Atitit.软件GUIbutton与仪表盘--db数据库区--导入mysql sql错误的解决之道
  12. Mysql了解及安装
  13. [Cpp] 面向对象程序设计 C++
  14. [luogu4309][最长上升子序列]
  15. MySQL Backup mysqldump备份流程学习
  16. Golang字符串函数认识(二)
  17. X86汇编语言实现的贪吃蛇游戏
  18. 启发式搜索A-Star算法 【寻找 最短路径 算法】【地理几何位置 可利用的情况】
  19. simple Terracotta session 同步
  20. CSS属性之padding

热门文章

  1. pinpoint 修改hbase表TTL值
  2. String实例 (练习)
  3. C语言低级I/O(UNIX接口)
  4. Girlfreind:1 Vulnhub Walkthrough
  5. iOS闪退日志的收集和解析
  6. Kong 系列【六】添加插件---ip-restriction之黑白名单
  7. Java实体对象为什么要实现Serializable接口?
  8. R语言矩阵维度“消失”的问题
  9. win2012 挂载硬盘即增加新硬盘方法
  10. 如何获取 iOS APP 的 scheme URL ?