开始刷刷题吧,顺应互联网大潮,强迫没学过JAVA的自己用JAVA解题,一是学习算法,而是了解一下JAVA的基本语句。
第一个题,本来以为会很简单,这道题让我自己觉得自己太渣。
于是乎,决定写篇笔记来记录一下。
题干还是很简单的,地址:https://leetcode-cn.com/problems/two-sum/
但是呢,一是自己之前没学过JAVA对很多语法不熟悉,二呢,发现对数据结构的理解真的只是一点书本的东西,完全应用不起来。
看了官方解答,感觉很牛,看了第一题的解答,牛上天了。
先说官方解答吧,之前一直做底层开发的我,以为C语言编程就很神奇了,但是搞JAVA呢,让我有一种很美妙的东西,凭啥C语言里很繁琐的功能,现在通过一个预先内置的方法就都能搞定了。
官方例子:
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> m1 = new HashMap();
for(int i=0;i<nums.length;i++){
int val = target - nums[i];
if(m1.containsKey(val)){
return new int[] {m1.get(val),i};
}
m1.put(nums[i],i);
}
return null;
}
}
比遍历好的地方就是算一个数就把这个数对应的补数(姑且这样称呼吧)顺带着求了然后并存下来。
然后后面直接用哈希表自带的方法直接找自己位置。
这个思想还是比较简单的,再深入想一下。怎么找东西最快呢?真正的哈希表又是什么呢?
看运行最快的算法
class Solution {
//Solution 2 by best solution
private int size = 2048;
public int[] twoSum(int[] nums, int target) {
int[] map = new int[size]; //定义一个超大数组能涵括大部分数
int index; //index 引用nums中得values 做map的数组下标
for(int i = 0; i < nums.length; i++) {
index = nums[i] & (size - 1); //1)先定义第一个numes元素的数为 map的下标
if(map[index] != 0) {
return new int[]{map[index] - 1, i}; //4) 如果发现index数值为3)计算过的数字,能表明当前数组有求和为target的数字,返回index为下标map的元素值-1
// 为3)步时index的位置,和当前nums的下标位置。
}else { // 2) 因为map为新建数组,所以其所有元素初始状态一定为0, 因此先执行else部分
map[(target - index) & (size - 1)] = i + 1; // 3) 计算target的另一个数字,并以其为map的下标,并以当前nums的下标i+1为其数值
// 不可直接用i,因为i已经是index数的下标
}
}
throw new IllegalArgumentException("No two sum solution");
}
}
不用现成的哈希表方法,直接用一个数组,每个数的补数的位置先都给他算好了。后面找到某个数,直接看这个数的补数之前有没有被算过了。通过数组直接访问还是更快的。
认真学语言,认真学算法。