乘风破浪:LeetCode真题_001_TwoSum

一、前言

沉寂了很长时间,也悟出了很多的道理,写作是一种业余的爱好,是一种自己以后学习的工具,是对自己过往的经验积累的佐证,是检验自己理解深入度的方法。在前面的模块之中,我们已经将基本的编程知识、数据结构、设计模式、应用框架、各种优化烂熟于心了,对程序开发有了一定的理解,但是编程的功力是一种水磨的功夫,需要问题,也需要思考,最重要的是需要自己用心的去打出代码,在这个过程中经验、技巧、熟练度、思考力都是非常重要的,因此我们通过LeetCode上的一些题目来锻炼一下这方面的能力。

二、LeetCode真题_001_TwoSum

2.1 题目

2.2 分析与解决

其实从问题我们就可以看出,这是类似于helloworld的一个题目,比较简单,借以引导我们从不同的角度使用不同的方法去解决问题。最简单的想法就是暴力破解方法,通过穷举所有的情况来解决问题,但是代价是时间复杂度O(n~2),空间复杂度O(1)。那么有没有其他方法呢,于是我们想到了hash表的方法,用空间换时间,通过一次遍历就能找到所有的可能结果。

  通过暴力算法来解决:

 public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}

    通过hash算法来解决,又分为两次for循环和一次for循环:

public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}

 public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}

    来看看我们的算法:

 import java.util.Arrays;

 public class Solution {
private static class Node implements Comparable<Node> {
int val;
int idx; public Node() {
} public Node(int val, int idx) {
this.val = val;
this.idx = idx;
} @Override
public int compareTo(Node o) {
if (o == null) {
return -1;
}
return this.val - o.val;
}
} /**
* 题目大意
* 给定一个整数数组,找出其中两个数满足相加等于你指定的目标数字。
* 要求:这个函数twoSum必须要返回能够相加等于目标数字的两个数的索引,且index1必须要小于index2。
* 请注意一点,你返回的结果(包括index1和index2)都不是基于0开始的。你可以假设每一个输入肯定只有一个结果。
*
* 解题思路
* 创建一个辅助类数组,对辅助类进行排序,使用两个指针,开始时分别指向数组的两端,看这两个下标对应的值是否
* 等于目标值,如果等于就从辅助类中找出记录的下标,构造好返回结果,返回。如果大于就让右边的下标向左移,
* 进入下一次匹配,如果小于就让左边的下标向右移动,进入下一次匹配,直到所有的数据都处理完
*/ public int[] twoSum(int[] nums, int target) {
int[] result = {0, 0}; Node[] tmp = new Node[nums.length];
for (int i = 0; i < nums.length; i++) {
tmp[i] = new Node(nums[i], i);
} Arrays.sort(tmp); int lo = 0;
int hi = nums.length - 1; while (lo < hi) {
if (tmp[lo].val + tmp[hi].val == target) { if (tmp[lo].idx > tmp[hi].idx) {
result[0] = tmp[hi].idx ;
result[1] = tmp[lo].idx ;
} else {
result[0] = tmp[lo].idx ;
result[1] = tmp[hi].idx ;
}
break;
} else if (tmp[lo].val + tmp[hi].val > target) {
hi--;
} else {
lo++;
}
}
return result;
}
}

    这种想法也比较巧妙,先对所有元素进行排序,然后通过定义首尾两个指针来不断地逼近最后的和,直至遍历完成,非常的巧妙,时间复杂度O(n),空间复杂度O(n)。不过也增加了额外的创建对象的空间。

三、总结

通过这个简单的问题,我们明白了对于一件事情,要么使用时间换取空间,要么使用空间换取时间,最后达到我们想要的结果,往往通过空间换取时间的比较多,因此hash算法就变得非常的重要了,当然也有其他的算法。

最新文章

  1. IO多路复用之epoll总结
  2. RabbitMQ Step by step(一) 安装
  3. js与jquery的用法
  4. Hadoop 源码编译导出
  5. bzoj3571
  6. leptonica 学习笔记2——pixBackgroundNormSimple
  7. java线程(1)-线程同步
  8. BZOJ 1007 水平可见直线
  9. java编程思想-泛型思维导图
  10. Lucene 高亮功能
  11. Android Blur效果之FastBlur
  12. ASP.NET Core 异常重试组件 Polly
  13. 2、FreeRTOS任务相关API函数
  14. 流媒体技术学习笔记之(十八)互联网草案HTTP直播流2017年5月
  15. Bootstrap3基础 btn-primary/warning... 三类按钮的六种样式
  16. CFileDialog类的详情
  17. 看看Spring的源码(一)——Bean加载过程
  18. JDBC编程之预编译SQL与防注入式攻击以及PreparedStatement的使用教程
  19. JQuery经典总结
  20. Windows Phone 解析手机型号DeviceStatus.DeviceName

热门文章

  1. ubuntu工具安装
  2. [转]Hadoop集群_WordCount运行详解--MapReduce编程模型
  3. 分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境(服务器端及客户端)(转)
  4. XML的基本概念和Android下的使用
  5. android应用执行需要root权限的shell命令
  6. Ubuntu 16.04安装测试MQTT Mosquitto
  7. [译]用R语言做挖掘数据《二》
  8. 解决:启动项目报错 java.lang.UnsatisfiedLinkError: D:\Java\apache-tomcat-8.0.17\bin\tcnative-1.dll: Can&#39;t load IA 32-bit .dll on a AMD 64-bit platform
  9. unity3d之使用技巧
  10. C#学习笔记-中英文切换(XML)