https://leetcode-cn.com/problems/two-sum/
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
/*
var twoSum = function(nums, target) {
var i, j;
for (i = 0; i < nums.length; i++) {
for (j = i+1; j < nums.length; j++) {
var c = target - nums[i];
if (nums[j] == c) {
return [i, j];
}
}
}
return [-1, -1];
};
*/
/*
var twoSum = function(nums, target) {
var map = new Map();
// 创建map value => index
for (var i = 0; i < nums.length; i++) {
map.set(nums[i], i);
}
// 遍历1个数a, 从map中根据key找另外一个数b = target-a
for (i = 0; i < nums.length; i++) {
var complement = target - nums[i];
if (map.has(complement) && map.get(complement) != i) {
return [i, map.get(complement)];
}
}
// No two sum solution
return [-1, -1];
};
*/
// 创建map的同时, 找这个数跟map中已存在的数之和是不是等于target
// map为空的时候直接放入键值对
var twoSum = function(nums, target) {
var map = new Map();
for (var i = 0; i < nums.length; i++) {
var c = target - nums[i];
if (map.has(c)) {
return [map.get(c), i];
}
map.set(nums[i], i);
}
return [-1, -1];
};
var a = twoSum([2,7,11,15], 9);
console.log(a);
输出 [0,1]
1.最容易想到的是暴力遍历, 最多循环n * (n-1) 次。
2.用HashMap把数组元素作为key, 把数组的下标作为值。类似array_flip效果
3.在2的基础上优化,其实在创建HashMap的同时就可以开始2数之和凑target
假设结果是数组[a, b]即要找的2个数的下标, 1,2两种方法都是先遍历找到a,再找b
方法3是先找到b,再找前面的下标a,这时候a下标已经加入到HashMap中的value了。
javascript有自带的Map数据结构
js的map与java的Map接口区别
Java初始化HashMap需要指明key,value类型
Map<Integer, Integer> map = new HashMap<>();
js不需要指明key, value类型
var map = new Map();
关于HashMap实现: https://blog.csdn.net/fareast_mzh/article/details/82085749
对于整数Hash
可以使用函数:
public static int intHash(int key)
{
key += ~(key << 15);
key ^= (key >>> 10);
key += (key << 3);
key ^= (key >>> 6);
key += ~(key << 11);
key ^= (key >>> 16);
return key;
}
————————————————
版权声明:本文为CSDN博主「HQD因为有趣所以做题」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hqd_acm/article/details/5901955
用自己写的Map测试
(拆开文件Clazz.js module.exports = Clazz; 引入 var Clazz = import("./Clazz"))
合并放到leetcode上测试
function Node(e) {
this.element = e;
this.next = null;
}
function LinkedList() {
this.length = 0;
this.head = null;
}
LinkedList.prototype = {
append: function(element) {
var node = new Node(element), current;
if (this.head === null) {
this.head = node;
} else {
current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
}
this.length++;
},
insert: function(position, element) {
if (position <0 || position > this.length) {
return false;
}
var node = new Node(element),
current = this.head,
previous,
index = 0;
if (position === 0) {
node.next = current;
this.head = node;
} else {
while (index++ < position) {
previous = current;
current = current.next;
}
node.next = current;
previous.next = node;
}
this.length++;
return true;
},
removeAt: function(position) {
if (position <0 || position > this.length) {
return null;
}
var current = this.head,
previous,
index = 0;
if (position=== 0) {
this.head = current.next;
} else {
while (index++ < position) {
previous = current;
current = current.next;
}
previous.next = current.next;
}
this.length--;
return current.element;
},
remove: function(element) {
var index = this.indexOf(element);
return this.removeAt(index);
},
indexOf: function(element) {
var current = this.head,
index = -1;
while (current) {
if (element === current.element) {
return index;
}
index++;
current = current.next;
}
return -1;
},
isEmpty: function() {
return this.length === 0;
},
size: function() {
return this.length;
},
toString: function() {
var current = this.head,
string = '';
while (current) {
string += current.element + ", ";
current = current.next;
}
return string;
},
print: function() {
console.log(this.toString());
},
getHead: function() {
return this.head;
}
};
function KeyValuePair(key, value) {
this.key = key;
this.value = value;
}
KeyValuePair.prototype.toString = function() {
return '['+ this.key +'-'+ this.value +']';
};
function HashTable() {
this.table = [];
}
// 2 hash functions
var hash = {
loselose: function(/* string */ key) {
var hash = 0;
for (var i = 0; i < key.length; i++) {
hash += key.charCodeAt(i);
}
return hash % 37;
},
djb2: function(/* key */) {
var hash = 5381;
for (var i = 0; i < key.length; i++) {
hash = hash * 33 + key.charCodeAt(i);
}
return hash % 1013;
},
intHash: function(/* int */ key) {
key += ~(key << 15);
key ^= (key >>> 10);
key += (key >>> 6);
key ^= (key >>> 6);
key += ~(key << 11);
key ^= (key >>> 16);
return key;
}
};
HashTable.hashCode = hash.loselose;
HashTable.prototype = {
put: function(key, value) {
if (typeof key === "Number") {
HashTable.hashCode = hash.intHash;
}
var pos = HashTable.hashCode(key);
if (this.table[pos] === undefined) {
this.table[pos] = new LinkedList();
}
this.table[pos].append(new KeyValuePair(key, value));
},
// alias for put
set: function(key, value) {
return this.put(key, value);
},
get: function(key) {
var pos = HashTable.hashCode(key);
if (this.table[pos] !== undefined) {
var current = this.table[pos].getHead();
while (current.next) {
if (current.element.key === key) {
return current.element.value;
}
current = current.next;
}
if (current.element.key === key) {
return current.element.value;
}
}
return undefined;
},
has: function(key) {
var pos = HashTable.hashCode(key);
if (this.table[pos] === undefined) {
return false;
}
var current = this.table[pos].getHead();
while (current.next) {
if (current.element.key === key) {
return true;
}
current = current.next;
}
if (current.element.key === key) {
return true;
}
return false;
},
remove: function(key) {
var position = HashTable.hashCode(key);
if (this.table[position] !== undefined) {
var current = this.table[position].getHead();
while (current.next) {
if (current.element.key === key) {
this.table[position].remove(current.element);
if (this.table[position].isEmpty()) {
this.table[position] = undefined;
}
return true;
}
}
if (current.element.key === key) {
this.table[position].remove(current.element);
if (this.table[position].isEmpty()) {
this.table[position] = undefined;
}
return true;
}
}
return false;
},
print: function() {
for (var i = 0; i < this.table.length; ++i) {
if (this.table[i] !== undefined) {
console.log(i + ": " + this.table[i]);
}
}
}
};
var twoSum = function(nums, target) {
var map = new HashTable();
for (var i = 0; i < nums.length; i++) {
var c = target - nums[i];
if (map.has(c)) {
return [map.get(c), i];
}
map.set(nums[i], i);
}
return [-1, -1];
};
自己写的map比嵌套2层循环还慢1.66倍(耗时是2.66倍)。不知道怎么查看leetcode的测试用例。
用js内置的map大约比嵌套2层循环快1倍。
在服务器上用node只跑一个test case,user用时多0.007s, sys用时少0.006s
总体慢< 0.001s