算法

223 阅读4分钟

为面试作一些算法相关的准备~~

一、时间复杂度

通常使用最差的时间复杂度来衡量一个算法的好坏。

常数时间 O(1) 代表这个操作和数据量没关系,是一个固定时间的操作,比如说四则运算。

对于一个算法来说,可能会计算出如下操作次数 aN + 1N 代表数据量。那么该算法的时间复杂度就是 O(N)。因为我们在计算时间复杂度的时候,数据量通常是非常大的,这时候低阶项和常数项可以忽略不计。

当然可能会出现两个算法都是 O(N) 的时间复杂度,那么对比两个算法的好坏就要通过对比低阶项和常数项了。

十分钟搞定时间复杂度(算法的时间复杂度)

算法时间复杂度与空间复杂度分析

二、位运算

十进制和二进制之间的转换

位运算在算法中很有用,速度可以比四则运算快很多。

十进制33可以看成是32 + 1322^512^0。所以就是 100001.

那么二进制 100001同理,首位是 2^5 ,末位是2^0,相加得出 33

左移 <<

10 << 1
// 20

左移就是将二进制全部往左移动,10 在二进制中表示为 1010 ,左移一位后变成 10100 ,转换为十进制也就是 20,所以基本可以把左移看成以下公式a * (2 ^ b)

左移 <<

10 >> 1
// 5

算数右移就是将二进制全部往右移动并去除多余的右边,10 在二进制中表示为 1010 ,右移一位后变成 101 ,转换为十进制也就是 5,所以基本可以把右移看成以下公式int v = a / (2 ^ b)

  • 右移的一个用处就是在二分法的时候,计算中间值 13 >> 1 // -> 6

三、排序

两通用函数

function checkArray(arr) {
      if(!arr | arr.length <= 2) {
        return false
      }
      return true
    }

    // 交换数组中的两个值
    function swap(array, left, right) {
      let rightValue = array[right]
      array[right] = array[left]
      array[left] = rightValue
    }

1、冒泡排序

冒泡排序的原理如下,从第一个元素开始,把当前元素和下一个索引元素进行比较。如果当前元素大,那么就交换位置,重复操作直到比较到最后一个元素,那么此时最后一个元素就是该数组中最大的数。下一轮重复以上操作,但是此时最后一个元素已经是最大数了,所以不需要再比较最后一个元素,只需要比较到 length - 1 的位置。

    // 冒泡排序
    function sort_1 (arr) {
      // 外循环决定比较几轮次
      for(var i = arr.length-1; i > 0; i--) {
        // 内循环决定每一轮最少比较几次
        for(var j = 0; j < i; j ++) {
          if(arr[j] > arr[j+1]) {
            swap(arr, j, j+1);
          }
        }
      }
    }
    
    /**
    共有 5 元素,
    一共比4次。

    第一轮 比较 4次
    第二轮 3次
    第三轮 2次
    第四轮 1次
    最后一轮 0次
    **/

  • 冒泡就是,每次循环将该循环中的较大元素往后面放,小的往前面放。O(n*n)

2、插入排序

插入排序原理: 将数组分为两部分,前一部分是已经排好的序列,之后是未排序的序列,我们每次从未排序的序列中拿第一个,根前面已经排好的序列中从头进行比较,找到合适的位置,进行放置。我们最初假设第一次的时候,第一个是排好的。

    // 插入排序
    function sort_2(arr) {
      // 对除第一个元素之外的元素进行向前插入
      for(var i = 1 ; i < arr.length; i++){
        // 取到未排序的序列的第一个元素,往左侧进行插入。
        for(var j = 0; j < i ; j++) {
          if(arr[j] > arr[i]) {
            swap(arr, j, i);
          }
        }
      }
    }

3、选择排序

选择排序原理:每次从待排序的序列中找到最小的放在前面

// 每次从待排序的序列中找到最小的放在前面
    function sort_3(arr) {
      // 一共需要确定几次最小值 n-1次
      for(var i = 0 ; i < arr.length-1 ; i++) {
        // 从已经排好的之后开始,找到最小值,放入该序列的最开始,
        for(var j = i + 1; j < arr.length; j++) {
          if(arr[i] > arr[j]) {
            swap(arr, i, j);
          }
        }
      }
    }

    /**
    3 89 72  43 1

    3之后的序列中找到比3还小的,然后替换3的位置
    1 89 72 43 3

    89之后的序列中找比89还小的,然后替换89的位置
    1 3 72 43 89

    ...
    **/