算法之概括与分治系列小算法

算法一:候选消除算法 (实现语言javascript)

javascript

将数据存储在一个数组中 let array = [2,2,1,9,9,9,9,9]java

描述:在遍历过程当中,利用多数元素的特性,采用抵消的方式,例如数据为 3 1 2 3 5 3 3 3 3 ,将3和1去掉后数组为2 3 5 3 3 3 3,多数元素仍然是3,不发生任何影响算法

利用这样特色咱们能够写出算法,采用递归的方式,代码以下数组

function candidate(array,k,n) {
  var c = array[k]
  var count = 1
  let i
  for(i = k + 1; i < n && count > 0; i++) {
    if(array[i] === c) {
      count ++
    } else {
      count --
    }
  }
  if(i === n) {
    // 验证是否超过数组长度的一半
    if (isArrLen2(array,c)) {
      return c
    } else {
      return null
    }
  } else {
    return candidate(array,i,n)
  }
}
function isArrLen2(array,c) {
  let count = 0
  for(let j = 0; j < array.length; j++) {
    if(array[j] === c) {
      count ++
    }
  }
  if(count > array.length / 2) {
    return true
  } else {
    return false
  }
}
复制代码

实现思路: 将数组(array)开始坐标值(k)以及数组长度(n)传入到函数中,用变量c来保存当前要遍历查找的值,用变量count来计算数量,接下来采用for循环来遍历数组,若是数组中有变量值等于c,count加1,不然count-1,这个过程就至关于在一个一个的抵消掉,退出循环后判断判断i是否等于n,若是等于说明数组遍历完成,则查找出来的这个值必定会是最优解,那么只需判断该值出现的次数是否大于数组长度的一半(方法:isArrLen2(array,c)),若是是,返回该值,不然返回null,当循环后i不等于n,则说明数组没有遍历完,那么利用递归,继续遍历数组直到遍历结束.该算法只须要遍历两遍数组,一遍是利用不相等的值抵消掉查找最优解,第二遍是遍历该数组查看最优节是否是多数元素。事件复杂的为2n,用到了算法的概括,查找问题中的一些小规律bash

算法二:归并排序

函数

将数据存储在一个数组中 var arr = [3,5,7,1,4,56,12,78,25,0,9,8,42,37]测试

描述:把长度为n的输入序列分红两个长度为n/2的子序列,而后对这两个子序列分别采用归并排序,最后将两个排序好的子序列合并成一个最终的排序序列ui

采用了递归,算法代码以下:(语言javascript)spa

function mergeSort(arr) {
  let len = arr.length
  if (len < 2) {
    return arr
  }
  let mid = Math.floor(len / 2)
  let left = arr.slice(0,mid)
  let right = arr.slice(mid)
  return merge(mergeSort(left),mergeSort(right))
}

function merge(left,right) {
  let result = []
  while(left.length > 0 && right.length > 0) {
    if (left[0] <= right[0]) {
      result.push(left.shift())
    } else {
      result.push(right.shift())
    }
  }
  while (left.length) {
    result.push(left.shift())
  }
  while (right.length) {
    result.push(right.shift())
  }
  return result
}
复制代码

将数组传入函数mergeSort(arr),将数组切割为两部分,若是数组长度大于2的话,那么继续切割,直到数组中只有两个元素,就不切割开始排序,排序过程当中分别对左右两边进行排序。定义一个结果集result,采用while循环,若是left.length和right.length的长度(也就是切割后的左右两边数组长度不为空,那就继续排序),排序采用进栈退栈的方式,比较左右两边数组值得大小,将左右两边数组较小的值从数组中退栈,而后将该值压栈,push到result结果集中,比较完成后,数组中会剩下最大的那个值,而后判断左右两边数组长度是否为0,若有还有值,若是有,则压栈进入到result结果集中,最后一层一层递归数组,最终result集中为排好序的数组。code

算法三:基数排序

测试数据:var array = [1,25,7,89,11,135,8964,23,77,1967,54,8932893,25631,22563,7412]

描述:利用数值的位数进行排序,右个位到十位再到百位...

算法代码实现以下:(语言javascript)

var k = 7   // 最大位数
// 基数排序
function redixSort(array,k) {
  var flag = []
  var index = 0
  for(let i = 0; i < k; i++) {
    for(let j = 0; j <= 9; j++) {
      for(let m = 0; m < array.length; m++) {
        if(Math.floor((array[m] / Math.pow(10,i) % 10)) === j) {
          flag.push(array[m])
        }
      }
    }
    array = flag
    flag = []
  }
  return array
}
console.log(redixSort(array,k))
复制代码

这里k值位最大位数,由于测试数据最大位数为7,我就写死了k=7,固然也能够写一个方法去求,我这里为了方便就没写了。

思路:采用了三重循环,第一从为遍历位数(这里为7),第二重循环为0-9遍历位的值,第三重循环为遍历数组。

for(let j = 0; j <= 9; j++) {
      for(let m = 0; m < array.length; m++) {
        if(Math.floor((array[m] / Math.pow(10,i) % 10)) === j) {
          flag.push(array[m])
        }
      }
    }
复制代码

该式子位求对应位上的数值 Math.floor((array[m] / Math.pow(10,i) % 10)) 二重循环,外循环遍历0-9,也就是位上的值,内循环遍历数组,外循环遍历时,将数组中相应位的大小按0-9排序,而且压栈进入到flag数组中,即第一遍循环将数组中位数为0的值压栈进入flag,第二遍为1,第三遍为2...,

而后在外面遍历没一个位,第一次个位,第二次十位,第三次百位...直至遍历位数结束 遍历每一位后,须要将排好序的数组flag的值赋予给原数组array,并将数组flag至为空

遍历数组次数为10*7(位数)*array.length ,若是数据小的话不建议用基数排序,若是数据庞大的话,那么基数排序就颇有用了

有错之处欢迎指出,若是您以为写得还凑合的话那就帮我点个赞啦~ 但愿能够帮到您哈~

相关文章
相关标签/搜索