算法入门(JavaScript)

前言

虽然作为前端,目前接触到的数据结构和算法业务应用并不很多,但是要想有进一步的提升,学习这些是很有必要滴,所以,在这里记录下关于算法的一些扫盲问题,算是入门,也算是为了方便回顾和进步。

算法复杂度

算法复杂度分为时间复杂度空间复杂度

  • 时间复杂度:指执行算法所需要的计算工作量(时间)
  • 空间复杂度:指这个算法所需要的内在空间。

时间复杂度

时间复杂度用O(X)表示

  1. 常数时间:O(1),表示执行算法的时间与数据量大小无关
  2. 线性时间复杂度:O(N), N表示数据量。【对于一个算法来说,可能操作次数aN+1,该算法的时间复杂度则为O(N),可能两个算法都是O(N)的复杂度,此时要通过对比低阶项和常数项了】
  3. 对数时间复杂度:O(logN),由于计算机使用二进制的记数系统,对数常以2为底

位运算

位运算相对于四则运算(±*/)通常会快很多,所以这在算法运算中很有用
位运算就是直接对整数在内存中的二进制位进行操作,所以在学习位运算前,要知道二进制与十进制之间的转换过程

  • 十进制 33 可以看成是 32 + 1 ,并且 33 应该是六位二进制的(因为 33近似 32,而 32 是 2 的五次方,所以是六位),那么 十进制 33 就是100001 ,只要是 2 的次方,那么就是 1 否则都为 0
  • 那么二进制 100001 同理,首位是 2^5,末位是 2^0 ,相加得出 33

1. 左移 <<

/*
* 10 --> 二进制 1010
* 1010 --> 左移一位  10100
* 10100 --> 十进制 20
*/
10 << 1 

2. 右移>>

/*
* 10 --> 二进制 1010
* 1010 --> 右移一位  101
* 101 --> 十进制 5
*/
10 >> 1 

按位操作

1. 按位与&

每一个二进制位都为1,结果才为1

/*
* 8--> 二进制 1000
* 7--> 二进制 0111
* 1000 & 0111 -> 0000 -> 0
*/
8&7

2. 按位或|

其中一位为1,结果就是1

/*
* 8--> 二进制 1000
* 7--> 二进制 0111
* 1000 | 0111 -> 1111 -> 15
*/
8|7

4. 按位异或^

每一位都不同,结果才为1

/*
* 8--> 二进制 1000
* 7--> 二进制 0111
* 8^8 --> 1000 ^ 1000 --> 0000
* 8^7 --> 1000 ^ 0111--->1111
*/
8^7	// -> 15
8^8 // -> 0
一道leetCode算法题(序号136)

通过按位异或来解可以实现O(N)的时间复杂对,且空间复杂度也相对更低

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    var ans = 0;
    for(let num of nums){
		ans ^=num;  //这里借助相同数的^操作结果为0来实现
	}
	return ans;
};
singleNumber([4,1,2,1,2]); // 4
/*
* 过程解析:
* 1. num=4, 0^=4-->二进制 100
* 2. num=1, 4^=1-->二进制 100^001-->101
* 3. num=2, 二进制 101^= 010 --》 111
* 4. num=1, 二进制 111^= 001 ---> 110
* 5. num=2, 二进制 110^= 010 ---> 100 -->十进制 4
*/

排序算法

常见的排序算法有:冒泡排序,插入排序,选择排序,归并排序,快非(二分法)。。。

/*
* 思路:冒泡排序每次两两比较,将大的一位排向后边,每一轮都会将最大的排到最后
*/
function bubbleSort(arr){
   //因为冒泡排序算法是两两比较 所以外层比较次数应为数组长度-1
   for(var i = 0; i<arr.length - 1; i++){
   //  内循环的比较不必全部执行完  因为每一轮的内循环都会将最大的数排在最右
   //  所以后面的次数不用比较 所以内循环的次数是递减的 需要减去一个i
        for(var j = 0; j < arr.length -1 - i; j++){
            if(arr[j] > arr[j+1]){
                var t = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = t;
            }
           }
            console.log(arr)
       }
       return arr;
}

2. 插入排序

原理:第一个元素默认是已排序元素,取出下一个元素和当前元素比较,如果当前元素大就交换位置。那么此时第一个元素就是当前的最小数,所以下次取出操作从第三个元素开始,向前对比,重复之前的操作。
在这里插入图片描述

3. 选择排序

原理:遍历数组,设置最小值的索引为 0,如果取出的值比当前最小值小,就替换最小值索引,遍历完成后,将第一个元素和最小值索引上的值交换。如上操作后,第一个元素就是数组中的最小值,下次遍历就可以从索引 1 开始重复上述操作。
在这里插入图片描述

4. 快速排序

原理:随机选取一个数组中的值作为基准值,从左至右取值与基准值对比大小。比基准值小的放数组左边,大的放右边,对比完成后将基准值和第一个比基准值大的值交换位置。然后将数组以基准值的位置分为两部分,继续递归以上操作。

var arr = [3, 4, 2, 6, 5, 8, 9, 10, 16, 13]; // length = 10
function quickSort(arr) {
    if (arr.length <= 1) { return arr; }
    //     基准值
    var pivot = arr[Math.floor(arr.length / 2)];
    arr.splice(arr.indexOf(pivot), 1);
    var left = [];
    var right = [];
    for (var i = 0; i < arr.length; i++) {

        if (arr[i] < pivot) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }

    }
    return quickSort(left).concat([pivot], quickSort(right));

}

console.log(quickSort(arr));

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sophie_U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值