前端工程师算法(一)

算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指定,算法代表着用系统的方法描述解决问题的策略机制。这个解释来源于百度,对于入门来说这个解释等于白说了,你的一脸懵逼我懂,大神略过。

  • 说人话
  • 算法
  • 你需要了解的算法是什么?

开始了解算法就应该对程序有一些认识和理解了,其实我们所有的程序可以理解为算法加数据结构。撇开数据结构不谈,我们日常写的代码如if-else、for(...)等就是算法。在数学里加减乘除是算法,方程公式,几何公式,乃至高数也都是算法,而我们的if-else、for(...)就相当于数学中的加减乘除这种级别的算法,当然在程序里也有加减乘除,同样也是算法。

但是我们日常所表达的算法和算法通常的说法有一些区别,我们日常表达的算法基本上都是特指一些特殊的算法,这些特殊的算法就相当于数学中的高数级别(不是指难度)。这些算法的特殊性并非其难度,而是具备通用性、高效(空间和时间)、解决特定问题的程序。

前端常用算法之数组查重算法

在前端编程中查重是比较常见的应用,以数组查重为例,通常的思路是通过嵌套循环,让每个值与其他每个值进行逐个对比。思路有了,我们就来实现以下:

var arr = [8,4,79,38,2,67,4,19,8,13,47,68,37,13,48,2];
var cont = 0;//记录比较次数
for(var i = 0; i < arr.length; i++){
    for(var j = 0; j < arr.length; j++){
        if(arr[i] == arr[j] && i != j){//‘i != j‘-->排除与自己比较
            console.log(arr[i]);
        }
        cont ++;//累计
    }
}
console.log(cont);//256

这个查重算法可以说基本就实现了,因为解决了特定问题:找到重复的元素。但是这个算法并不是我们真正需要的算法,因为这样对比出现了很多重复,浪费很多计算资源和时间,所以这个算法需要改进。

改进的目的就是消除重复对比,从数组的有序性我们可以知道,每一次内部循环不需要从头开始对比,因为前面已经对比过了,所以改进代码如下:

for(var i = 0; i < arr.length; i++){
    for(var j = i + 1; j < arr.length ; j++){//i+1表示自身和自身之前的元素都不需要比较了
        if(arr[i] == arr[j]){
            console.log(arr[i]);
        }
        cont ++;//累计
    }
}
console.log(cont);//120

这样改进后的查重效率可以从对比次数看到,减少了一半多,也就说明了改进后的查重算法效率提高了一倍多。在算法中,不存在对错的概念,而是在保证实现功能的最优方案是什么。这些最优方案就是我们需要的算法,这些算法可以提高用户的体验,减少硬件资源的消耗。

用这样的思路我们来实现以下数组去重算法:(这段代码折叠,大家可以先尝试自己写)

function unique(arr){
    var obj = {};
    var result = [];
    for(var i in arr){
        if(!obj[arr[i]]){
            obj[arr[i]] = true;
            result.push(arr[i]);
        }
    }
    return result;
}

数组去重

算法入门之经典的排序算法详解

  • 冒泡排序
  • 选择排序

这里暂时介绍两种排序算法,就这两种排序算法介绍一些关于排序的应用场景解析,在前面的查重和去重算法中我们主要考虑到了效率。接着我们用这两个排序算法来将算法的解决特定问题引述出来,这两个算法并不能全面说明什么是特定的问题,它们仅仅只能告诉我们不同的算法存在其优点和缺点,适应的场景也就会随之发生变化,而这些场景往往来自不同的业务和功能的需求,需求来源不同,但可以根据其不同特性归类从而选择不同的算法,这就是算法的通用性。

1.冒泡排序(升序):

for(var j = 0; j < arr.length - 1; j++){
    for(var i = 0; i < arr.length - j - 1; i++){
        if(arr[i] > arr[i + 1]){
            var temp = arr[i];
            arr[i] = arr[i + 1];
            arr[i + 1] = temp;
        }
    }
}

首先我们就这这个升序的冒泡排序算法做一个图解,来理解冒泡排序的逻辑及其原理:

假设有数组:var arr = [5,3,7,2,8,6,1,9,4];

当外层循环第一次时:j == 0, i == 0。

通过一次外层循环,图解内部完全循环,可以看到冒泡循环就是通过两个相邻元素两两比较,升序就是将大值交换到后面的逻辑,每一次外层循环都可以获得对应循环终点的最大值。既然是两两比较,那么最一个单独的元素就不需要在循环比较了,所以外层循环也可以减去一次。

2.选择排序(升序):

for(var j = 0; j <  arr.length - 1; j ++){
    var max = 0;
    for(var i = 0; i < arr.length - j - 1; i++){
        if (arr[i + 1] > arr[max]) {
            max = i + 1;
        }
    }
    var temp = arr[arr.length - j -1];
    arr[arr.length - j - 1] = arr[max];
    arr[max] = temp;
}

选择排序的逻辑就是外层负责交换,内层负责找到对应一次外层循环终点内的最大值的索引,然后在一次外层循环结束时,将最大值与该次循环终点的元素进行交换位置。下面提供选择排序的图解:

假设有数组:var arr = [5,3,7,2,8,6,1,9,4];

  • 第一轮外层循环

    i  [i+1]>[max]  max

    0 3>5 =>false   0

    1 7>5 =>true    2

    2 2>7 =>false  2

    3 8>7 =>true    4

    4 6>8 =>false  4

    5 1>8 =>false  4

    6 9>8 =>true    7

    7 4>9 =>false   7

    max=7;终点=8;

  • 第二轮外层循环

    i  [i+1]>[max]  max

    0 3>5 =>false   0

    1  7>5 =>true    2

    2 2>7 =>false  2

    3 8>7 =>true    4

    4 6>8 =>false   4

    5 1>8 =>false   4

    6 4>8 =>false   4

    max=4;终点=7;

  • 第三轮外层循环

    i  [i+1]>[max]  max

    0 3>5 =>false   0

    1  7>5 =>true    2

    2 2>7 =>false  2

    3 4>7 =>false    2

    4 6>7 =>false   2

    5 1>7 =>false   2

    max=2;终点=6;

  • 第四轮外层循环

    i  [i+1]>[max]  max

    0 3>5 =>false   0

    1  1>5 =>false   0

    2  2>5 =>false  0

    3   4>5 =>false   0

    4   6>5 =>true    5

    max=5;终点=5;

  • 第五轮外层循环

    i  [i+1]>[max]  max

    0 3>5 =>false   0

    1 1>5 =>false   0

    2 2>5 =>false   0

    3 4>5 =>false    0

    max=0;终点=4;

  • 第六轮外层循环

    i  [i+1]>[max]  max

    0 3>4 =>false   0

    1  1>4 =>false   0

    2 2>4 =>false   0

    max=0;终点=3;

  • 第七轮外层循环

    i  [i+1]>[max]  max

    0  3>2 =>true   1

    1  1>3 =>false   1

    max=1;终点=2;

  • 第八轮外层循环

    i  [i+1]>[max]  max

    0 1>2 =>false   0

    max=0;终点=1;

通过上图将选择排序的处理逻辑可视化展示后,可以看到交换次数明显少于冒泡排序,但是借助了一个最大值索引变量来完成,这个变量会在每次外层循环时被创建,从这个角度来说对于空间的需求比冒泡排序要大。从效率的角度来讲选择排序的空间效率是肯定弱于冒泡排序,但是时间效率会如何呢?这个问题需要考虑更多的因素才能得到结果,由于这篇博客是基于入门级别的角度来阐述,所以暂时不探讨太深入的问题。

通过两个排序算法我们可以了解到解决同一个问题有多种方案,但是不同方案会有不同的优势和劣势,怎么在实际问题中应用这两个算法,需要对它们的优势和劣势进行深入的分析,这不在入门的范围内,后期会有博客更新算法知识点的深入理解部分。这篇博客旨在介绍算法是什么?我们如何对具体问题进行分析及编写算法,所以上面的两个排序算法还并不是我们能拿来解决具体问题的工具,我们还需要对其进一步逻辑分析和封装,修改成可以在需要是随时使用的函数。

  • 排序算法需要做的核心工作是什么?
  • 排序算法都有什么共同的特点?

这两个问题其实是一个问题,排序算法的核心工作就是【比较+交换】,这也是排序算法的共同特点,所以根据这个核心工作原理,上面两个排序算法可以封装成以下具体方法:

//比较
function compare(a,b){
    if (a > b) {
        return true;
    }else{
        return false;
    }
}
//交换
function exchange(arr,m,n){
    var temp = arr[m];
    arr[m] = arr[n];
    arr[n] = temp;
}
//封装冒泡排序
function bubbleSort(arr){
    for(var j = 0; j < arr.length - 1; j++){
        for(var i = 0; i < arr.length - j - 1 ; i++){
            if(compare(arr[i] , arr[i + 1])){
                exchange(arr,i,i+1)
            }
        }
    }
}
//封装选择排序
function selectionSort(arr){
    for(var j = 0; j <  arr.length - 1; j ++){
        var max = 0;
        for(var i = 0; i < arr.length - j - 1; i++){
            if(compare(arr[i +1] , arr[max])){
                max = i + 1;
            }
        }
        exchange(arr,arr.length - j -1,max);
    }
}

了解到这里,我们应该可以大概的理解算法的定义了:算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指定,算法代表着用系统的方法描述解决问题的策略机制。对于同一个问题我们又会有不同的策略机制,就拿排序算法来说,我们分析的就有两种了,但是并不止这两种,常见的排序算法还有快速排序、直接插入排序、希尔排序、堆排序、归并排序、基数排序。不同的排序算法有不同的应用场景,有时间再来更新深入分析算法的内容了,今天是大年初四,在这里祝福大家猪年好运,身体健康,猪定幸福!

想深入了解算法的话可以先参考这两个博客:

排序算法的稳定性

算法的复杂度

原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/10355397.html

时间: 2024-11-06 20:09:24

前端工程师算法(一)的相关文章

web前端工程师必备技能汇总

web前端知识结构图. 图片的形式具有诸多的不便.缺失源图的我们,无法为此图贡献些什么,随着时间的迁移,或许有些技术点会发生改变,所以有了这个github项目.我们可以通过协作的方式来共同维护这个项目.Git的历史记录也可以见证前端行业的一些变迁. 尽管会变成文字的方式来维护这些内容,但是我承诺写一个小工具帮大家生成更好玩的图形(基于DataV项目). 前端开发知识结构 前端工程师 SVG/Canvas/VML SVG: D3/Raphaël/Snap.svg/DataV Canvas: Cre

前端工程师需要掌握以及具备的/////////////转

下面的内容(摘自https://gist.github.com/ourai/6411507)是一名优秀的前端工程师需要掌握以及具备的—— 开发技术 程序 标准规范 ECMAScript HTTP 知识储备 作用域/闭包 数据结构 算法 编程范式 函数式 面向对象 基于原型 面向方面 设计模式 软件架构 MVC MVVM 安全 XSS CSRF 富互联网应用程序 编程语言 JavaScript ActionScript CoffeScript 页面 标准规范 W3C 知识储备 网页设计 排版 响应

整个互联网行业都缺前端工程师?

本文来自 100offer 团队原创,部分内容译自:Why can’t we find Front End developers? 前端工程师的缺乏问题几乎蔓延到整个互联网行业,从刚起步的创业公司,到上市公司乃至巨头,这个问题都存在着.没错,优秀的前端工程师简直比大熊猫还稀少. 每天,100offer 的 HR 群都有人在吐槽招不到靠谱的前端工程师.实话说对这些需求,100offer 也无能为力:在供不应求的前端招聘市场上,优秀的前端工程师才是有话语权的那一方. 在国外,前端工程师一样是需求旺盛

前端工程师说明(仅以自勉)

现在,一位合格的前端工程师,必须对视觉设计有兴趣. 很显然,要处理大量的Web应用程序需求,技术任务就要进行分类,以便于多人同时处理网站请求.事实上,现在已经不可能一个人快速地解决所有的技术细节了. 1.前端的误解 大多人都认为前端开发是一个[相对于其他模块来说更简单的领域],在他们心中的前端工程师是这样工作的的: 1.把Photoshop文件.图片或者线框放进一个网页: 2.偶尔设计Photoshop文件.图片或者线框: 3.用JS编程,为网页制作动画.过渡效果: 4.用HTML和CSS编程,

前端常见算法JS实现

算法是程序的灵魂,一个优秀的前端工程师对算法也是要有所了解的. 排序算法 1. 冒泡排序 //冒泡排序 function bubbleSort(arr){ var i = j = 0; for(i=1;i<arr.length;i++){ for(j=0;j<=arr.length-i;j++){ var temp = 0; if(arr[j]>arr[j+1]){ temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } 2.

淘宝前端工程师:国内WEB前端开发十日谈

转自:http://www.jianshu.com/p/8cf2df3fdbf2 一直想写这篇“十日谈”,聊聊我对Web前端开发的体会,顺便解答下周围不少人的困惑和迷惘.我不打算聊太多技术,我想,通过技术的历练,得到的反思应当更重要. 我一直认为自己是“初级”前端开发工程师,一方面我入道尚浅,只有短短几年,另一方面我自知对技术的钻研并不深入,可能是由于环境的原因,当然最重要的是,我幸运的参与到互联网崛起的浪潮之巅.时势造就了一批技能薄弱但备受追捧的“弄潮者”,这在很大程度上影响我们对“技术本质”

为什么前端工程师很难找?(知乎上一个读后蛮有感慨的回答)

知乎用户 IBM CRL,前端田园犬 89 人赞同 因为看到朴灵大神出现在这个帖子所以来写这个答案,首先感谢朴灵大神您写的关于nodejs的书和推荐过的javascript的书,图灵社区的奉献让我受益匪浅.让我这个曾经的菜鸟对js有了重新认识,路漫漫其修远兮,吾将上下而求索. 先说下自己早年的经历吧,最早的时候跟很多现在看到的各种廉价前端程序员一样(如果那算程序员的话),就是写写HTML,CSS,用ps切切图,jquery的API都会调用,会把网上各种插件搬来用.因为我ps用的还可以,又熟悉各类

web前端工程师知识学习路线

想要成为一名优秀的web前端工程师(http://www.maiziedu.com/course/web/)需要具备哪些技能?因为web前端开发涵盖了许多领域的技术,那么需要掌握的技能有哪些呢?下面就一起来看看web前端工程师必备技能知识. 1.界面和用户体验 注意,浏览器的实现标准是不一致的,请确保你的网站能够兼容所有主流的浏览器.最少需要测试的有 Gecko 引擎(Firefox),WebKit引擎(Safari以及一些手机浏览器),Chrome,你所要支持的 IE 浏览器,以及 Opera

前端工程师必备技能汇总

首先,看一张前端知识结构图:  (原文: ithomer) 图片的形式具有诸多的不便.缺失源图的我们,无法为此图贡献些什么,随着时间的迁移,或许有些技术点会发生改变,所以有了这个GitHub项目.我们可以通过协作的方式来共同维护这个项目.Git的历史记录也可以见证前端行业的一些变迁. 尽管会变成文字的方式来维护这些内容,但是我承诺写一个小工具帮大家生成更好玩的图形(基于DataV项目). 前端开发知识结构 前端工程师 浏览器 IE6/7/8/9/10/11 (Trident) Firefox (