js中的分治算法和归并算法

189 阅读2分钟

一、分治算法

1、分治算法:

就是把一个复杂的问题分解两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到最后子问题可以简单的直接解决,原问题的解即子问题的解的合并

2、适用情况

2.1、当该问题缩小到一定规模的时候,比如,该数组只有两个元素,这个时候,这个问题就很好解决。

2.2、该问题可以分解为若干规模较小的相同问题。

2.3、分解的问题的答案可以合并为该问题的解。

3、实现分治算法

function fn(arr, from, to) {
            if (to - from == 1) {
                return { "max": Math.max(arr[from], arr[to]), "min": Math.min(arr[from], arr[to]) }
            } else if (to - from == 0) {
                return { "max": arr[from], "min": arr[to] }
            } else {
                let middle = parseInt(from + (to - from) / 2);
                let result1 = fn(arr, from, middle);
                let result2 = fn(arr, middle + 1, to);
                let result = {};
                if (result1["max"] > result2["max"]) {
                    result["max"] = result1["max"];
                } else {
                    result["max"] = result2["max"];
                }
                if (result1["min"] > result2["min"]) {
                    result["min"] = result2["min"];
                } else {
                    result["min"] = result1["min"];
                }
                return result;
            }
        }
        let arr = [34, 5, 6, 7111, 7, 8, 889, 9];
        console.log(fn(arr, 0, arr.length - 1));

核心思想是把数组分解到只有一个元素或者两个元素的时候,直接比大小返回,然后递归处理并返回结果。

二、归并算法

归并算法:

将待排序的元素分为大小大致相同的集合, 分别对两个子集合进行排序, 最终排序号的子集合合并为有序集合。运用分治法。

归并排序的步骤:

1、将给定的列表分为两半(如果列表中的元素数为奇数,则使其大致相等)。

2、以相同的方式继续划分子数组,直到只剩下单个元素数组。

3、从单个元素数组开始,合并子数组,以便对每个合并的子数组进行排序。

4、重复第 3 步单元,直到最后得到一个排好序的数组。

function merge(left, right) {
    var tmp = [];
    while (left.length && right.length) {
    if (left[0] < right[0])
        tmp.push(left.shift());//将第一个元素删除并返回,即存放到tmp空数组中
    else
        tmp.push(right.shift());
}
//    console.log(tmp)
    return sum=tmp.concat(left, right);//比较完毕后合并,然后进行下一次归并判断
//    console.log(tmp)
}

function mergeSort(arr) {
    if (arr.length === 1)
        return arr;

    var mid = Math.floor(arr.length / 2);//数组长度减半
    var left = arr.slice(0, mid);//左半边新数组
    var right = arr.slice(mid);//右半边新数组
    return merge(mergeSort(left),mergeSort(right));//将左右继续对半分,直到arr.length/2=1.这样就完成了将所有数组拆分的工作
}
//    var arr = [49, 38, 65, 97, 76, 13, 27, 49,21];
//    mergeSort(arr);
//    console.log(sum)