查找数组中和的特定值的匹配对

问题描述

现有一列数组,找出数组中和为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)

可以看到,第三个算法对重复匹配项进行了过滤。如果不需要过滤,可以简单改进键值对,将值设为数字的出现次数,通过两个匹配项键值的乘积可以确定匹配次数。

待续……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值