问题描述
现有一列数组,找出数组中和为10的匹配对。
例如,
输入:[-10,1,5,3,20,9,9,10,2]
输出:(-10,20);(1,9)
算法
JavaScript实现
内外层两次循环
使用两层嵌套循环,外层从index为0处开始移动,每到一个新index则在内层循环中将该值与后续的数列依次对比。
function match(arr, total) {
var i = 0,
j = 0,
len = arr.length,
result = [];
while (i < len - 1) {
j = i + 1;
while (j < len) {
if (+arr[i] + +arr[j] == total) {
result.push([arr[i], arr[j]]);
}
j++;
}
i++;
}
return result;
}
function print(arr) {
var str = '',
TOTAL = 10,
temp = [];
if (Object.prototype.toString.call(arr) != '[object Array]' || arr.length == 0) {
console.log('Please enter a valid Array');
return result
};
arr = match(arr, TOTAL);
while (arr[0]) {
temp = arr.shift();
str += '(' + temp.join(',') + ');';
}
console.log(str.substring(0, str.length - 1));
}
print([-10, 1, 5, 3, 20, 9, 9, 10, 2]);//(-10,20);(1,9);(1,9)
向内收缩
首先对数组进行排序,之后,对排序后的数组从index为0处开始比对,第一次比对后形成新的边界,作为第二次比对的边界。
其中,排序算法可以使用快排或堆排序等,此处为了方便实现,使用JavaScript数组内置的sort方法。
function squeezeMatch(arr, total) {
arr = arr.sort(function(a, b) {
return a - b;
});//升序
var i = 0,
j = 0,
lastIndex = arr.length,
result = [];
while (i < lastIndex) {
j = i + 1;
while (j < lastIndex) {
if (+arr[i] + +arr[j] == total) {
result.push([arr[i], arr[j]]);
} else if (+arr[i] + +arr[j] > total) {
lastIndex = j - 1;//更新尾部阈值
break;
}
j++;
}
i++;
}
return result
}
function print(arr) {
var str = '',
TOTAL = 10,
temp = [];
if (Object.prototype.toString.call(arr) != '[object Array]' || arr.length == 0) {
console.log('Please enter a valid Array');
return result
};
arr = squeezeMatch(arr, TOTAL);
while (arr[0]) {
temp = arr.shift();
str += '(' + temp.join(',') + ');';
}
console.log(str.substring(0, str.length - 1));
}
print([-10, 1, 5, 3, 20, 9, 9, 10, 2]);//(-10,20);(1,9);(1,9)
索引方法
利用JavaScript中的字符串键值,可以减少比对次数。
但需要先循环建立字典。
function generate(arr) {
var obj = {},
i = 0,
len = arr.length;
while (i < len) {
obj[arr[i]] = obj[arr[i]] ? +obj[arr[i]] + 1 : 1; //索引
i++;
}
return obj;
}
function indexMatch(arr) {
var obj = generate(arr),
str = '',
TOTAL = 10,
result = [];
for (key in obj) {
if (obj[TOTAL - key]) { //根据索引判断是否有对应的数存在
if (2 * key == TOTAL && obj[key] < 2) { //二分之一需要出现两次
continue; //例如TOTAL为10,5需要出现两次
}
result.push([key, 10 - key]);
delete obj[key]; //删除已经判断过key值,防止重复计算
delete obj[10 - key];
}
}
return result;
}
function print(arr) {
if (Object.prototype.toString.call(arr) != '[object Array]' || arr.length == 0) {
console.log('Please enter a valid Array');
return result
};
arr = indexMatch(arr);
var str = '',
temp = [];
while (arr[0]) {
temp = arr.shift();
str += '(' + temp.join(',') + ');';
}
console.log(str.substring(0, str.length - 1));
}
print([-10, 1, 5, 3, 20, 9, 9, 10, 2]);//(1,9);(20,-10)
可以看到,第三个算法对重复匹配项进行了过滤。如果不需要过滤,可以简单改进键值对,将值设为数字的出现次数,通过两个匹配项键值的乘积可以确定匹配次数。
待续……