前端算法與數(shù)據(jù)結(jié)構(gòu)自學(xué)總結(jié)(實(shí)戰(zhàn)篇)

2017年7月于長(zhǎng)城

一、如下是一個(gè)tree樹的實(shí)現(xiàn),寫出結(jié)果:

var s=[];
var arr=s;
    for(var i=0;i<3;i++){
    var pusher = {
        value: "item"+i
        },tmp;
     if(i!==2){
        tmp = []
        pusher.children = tmp
    }
    arr.push(pusher);
    arr = tmp;  // arr做了一個(gè)對(duì)象指針的移動(dòng),等于上一個(gè)children
}
console.log(s[0]);

// {
      value: "item0",
      children:[
           {
             value: "item1",
             children:[{
                 value: "item2"
             }]
            }
      ]
  }

二、查找如下有序數(shù)組中31出現(xiàn)的位置,最快的查找方法是什么,JavaScript怎么實(shí)現(xiàn)?

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

對(duì)于一個(gè)已經(jīng)排好序的數(shù)組,最快定位的方法是二分查找

function find (arr, item) {
    var low = 0;  //設(shè)定下標(biāo)
    var high = arr.length - 1; // 設(shè)定上標(biāo)
    while (high >= low) {
        var mid = Math.floor((low + high) / 2);   //二分查找的關(guān)鍵
        if (arr[mid] === item) {
            return mid;
        }else if (arr[mid] > item) {
             high = mid;
        } else if (arr[mid] < item){
            low = mid;
        } 
    }
    return  -1;
}

三、 用JavaScript實(shí)現(xiàn)數(shù)組的快速排序:

快速排序過程只需要三步:

  • 1、在數(shù)據(jù)集中,選擇一個(gè)元素作為“基準(zhǔn)”(pivot)。(基準(zhǔn)值可以任意選擇,但是選擇中間的值比較容易理解)
  • 2、所有小于"基準(zhǔn)"的元素,都移到"基準(zhǔn)"的左邊;所有大于"基準(zhǔn)"的元素,都移到"基準(zhǔn)"的右邊。
  • 3、對(duì)"基準(zhǔn)"左邊和右邊的兩個(gè)子集,不斷重復(fù)第一步和第二步,直到所有子集只剩下一個(gè)元素為止。
    使用js數(shù)組方法及遞歸
function quickSort(arr) {
   if(arr.length <= 1) return arr;
   var index = Math.floor(arr.length / 2);
   var key = arr.splice(index, 1)[0];
   var left = [],right = [];
   arr.forEach(function(v){
       v <= key ? left.push(v) : right.push(v);
   });
   return quickSort(left).concat([key], quickSort(right));
}

四、寫出單向鏈表和雙向鏈表的添加和刪除操作的實(shí)現(xiàn)過程。

單向鏈表的添加:

function insert(newElement, item){
    var newNode = new Node(newElement);  // 新建一個(gè)節(jié)點(diǎn)
    var current = this.find(item);   //找到item的位置(current在js中是引用,類似于C語(yǔ)言指針)
    newNode.next = current.next;  //將新節(jié)點(diǎn)的后繼指向item的后繼
    current.next = newNode;  // 修改item節(jié)點(diǎn)的后繼指向新節(jié)點(diǎn)
}

單向鏈表的刪除:

// 首先要找到刪除元素的上一個(gè)節(jié)點(diǎn)
function findPrevious (item) {
    var currentNode = this.head;
    while (!(currentNode.next === null) && (currentNode.element !== item)) {
    return currentNode;
    }
}

function remove (item) {
    var prevNode = this.findPrevious(item);
    var currentNode = this.find(item); // 查找到當(dāng)前要?jiǎng)h除的節(jié)點(diǎn)
    if (!(prevNode.next === null)) {
        prevNode.next = prevNode.next.next; //待刪除節(jié)點(diǎn)的前驅(qū)的后繼 指向 原本待刪除節(jié)點(diǎn)的后繼
        currentNode.next = null; // 釋放節(jié)點(diǎn),防止內(nèi)存泄漏
    }
}

雙向列表的添加:

// 插入節(jié)點(diǎn),注意插入的鏈指向
function insert(newElement, item){
    var newNode = new Node(newElement);  // 新建一個(gè)節(jié)點(diǎn)
    var current = this.find(item);   //找到item的位置
    newNode.next = current.next;  //將新節(jié)點(diǎn)的后繼指向item的后繼
        newNode.previous = current;
        current.next = newNode;
        if (newNode.next !== null) {
                newNode.next.previous = newNode; // 將item原本的位置的前驅(qū)指向新節(jié)點(diǎn)
        }
}

雙向鏈表的刪除:

function remove (item) {
    var currentNode = this.find(item);
    if (!(currentNode === null)) {
        currentNode.previous.next = currentNode.next; // 刪除節(jié)點(diǎn)的前驅(qū)的后繼,指向刪除節(jié)點(diǎn)的后繼
        currentNode.next.previous = currentNode.previous; //刪除節(jié)點(diǎn)的后繼的前驅(qū),指向刪除節(jié)點(diǎn)的前驅(qū)
        currentNode.next = null; // 釋放節(jié)點(diǎn),防止內(nèi)存泄漏
        currentNode.previous = null;
    } else {
        currentNode.previous.next = null; // 尾節(jié)點(diǎn)的前驅(qū)的后繼指向null
        currentNode.previous = null; // 釋放尾節(jié)點(diǎn)
    }
}

五、用代碼實(shí)現(xiàn)二叉搜索樹,寫出相關(guān)方法查找最小值。

//定義節(jié)點(diǎn)
function Node(data, left, right) {
    this.data = data;
    this.left = left;
    this.right = right;
}

// 插入值
function insert (data) {
    var n = new Node(data, null, null); // 定義一個(gè)新節(jié)點(diǎn)
    if(this.root === null) {
        this.root = n;
    } else {
        var current = this.root;
        var parent;
        while (true) {
            parent = current;
            if (data < current.data) {
                current = current.left; // 比當(dāng)前值小就放左邊
                if (current === null) {
                    parent.left = n;
                    break;
                }
            } else {    // 比當(dāng)前值大就放右邊
                current = current.right;
                if(current === null){
                    parent.right = n;
                    break;
                }
            }
        }
    }
}

// 找最小值
function getSmallest (root) {
    // 一直往左子樹上去找,找到?jīng)]有左節(jié)點(diǎn)即找到了最小值
    var current = this.root || root;
    while (!(current.left === null)) {
        current = current.left;
    }
    return current;
}

六、編寫一個(gè)方法,求一個(gè)字符串的字節(jié)長(zhǎng)度:

(一個(gè)英文字符占1個(gè)字節(jié),一個(gè)中文字符占2個(gè)字節(jié))

function getBytes(str) {
        var len = str.length;
        var bytes = len;
        for (var i = 0; i< len; i++) {
                if (str.charCodeAt(i) >= 128) {     // 如果判斷是中文字符就+1
                        bytes++;
                }
        }
        return bytes;
}

七、找出一個(gè)正數(shù)數(shù)組的最大差值:

function getDifference(arr) {
        var minValue = arr[0];
        var maxDifference = 0;
        for (var i = 0; i < arr.length; i++) {
                var current = arr[i];
                minValue = Math.min(minValue, current);    // 用一個(gè)臨時(shí)變量存較小的值
                var difference = current - minValue;
                maxDifference = Math.max(maxDifferent, potential);
        }
        return maxDifference;
}

ES6擴(kuò)展運(yùn)算符

function getDifference(arr){
    var max = Math.max(...arr);  // 找出最大值
    var min = Math.min(...arr);   // 找出最小值
    return max - min;
}

數(shù)組sort排序

function getDifference(arr){
    var arr = arr.sort();
        var min = arr[0];
        var max = arr[arr.length-1];
        return maxDifference = max - min;
}

八、判斷一個(gè)單詞是否是回文:

(如mamam)

function isPalindrome(str) {
    var len = str.length;
    var start = Math.ceil(len / 2);
    while (start < len) {
        if(str[start] !== str[len - start - 1]) {
            return false;
        };
        start++;
    }
    return true;
}

九、數(shù)組去重:

function unique(arr) {
    var result = [];

    arr.forEach(function(v){
        if(result.indexOf(v) < 0) {
            result.push(v);
        }
    });
    return result;
}

十、計(jì)算字符串中出現(xiàn)次數(shù)最多的字母及次數(shù):

function findMaxDuplicate(str){
    if (str.length === 1) return str;
    
    var charObj = {};
    for(var i=0; i<str.length; i++){
        if(!charObj[str.charAt(i)]){
            charObj[str.charAt(i)] = 1;
        } else {
            charObj[str.charAt(i)] += 1;
        }
    }
    var maxChar = '',
    maxValue = 1;
    for(var k in charObj) {
        if (charObj[k] >= maxValue) {
            maxChar = k;    
            maxValue = charObj[k];
        }
    }
    return '出現(xiàn)次數(shù)最多的是:'+ maxChar +',一共'+charObj[maxChar]+'次'
}

十一、寫一個(gè)isPrime()函數(shù),當(dāng)其為質(zhì)數(shù)時(shí)返回為true,否則返回false。

(質(zhì)數(shù):大于1且只能被1和它本身整除的數(shù))

function isPrime(number) {
    if (typeof number !== 'number' || !Number.isInteger(number)) {
        return false;
    } 
    if (number < 2) {
        return false;
    } else if (number === 2) {
        return true;
    } else if (number % 2 === 0) {
        return false;
    }
    var squareRoot = Math.sqrt(number); // 求平方根
    for(var i = 3; i <= squareRoot; i += 2) {
        if (number % i === 0) {
            return false;
        }
    }
    return true;
}

十二、對(duì)下列字符串進(jìn)行排序,按照字符串中的數(shù)字排序:

"hell2o wor5ld Compa1y T4est 3abc"
1.首先對(duì)給定字符串根據(jù)空格進(jìn)行分割,畢竟數(shù)組比字符串更容易操作。
2.接著制定排序規(guī)則,哪個(gè)單詞中包含的數(shù)字更大,排名就靠后。
3.然后,用數(shù)組的sort方法,傳入排序規(guī)則匿名函數(shù),進(jìn)行定制排序。
4.最后,將sort后的數(shù)組進(jìn)行聚合,返回字符串。

function FindNumber(str){  
    for(var i=0;i<str.length;i++){  
        var chr = str.charAt(i);  
        if(!isNaN(chr)){  
            return parseInt(chr);  
        }  
    }  
}  
  
function Order(words){  
    return words.split(" ").sort(function(a,b){  
        return findNumber(a) - findNumber(b); 
    }).join(" ");  
}  

十三、寫一個(gè)flat函數(shù)將如下一個(gè)多層嵌套數(shù)組輸出成字符串。

輸入:['a', ['b', 'c'], 1, 2, ['d', 'e'], 'f', 3, 4]
輸出:a, b, c, 1, 2, d, e, f, 3, 4

方法一:遞歸方法

var arr = ['a', ['b', 'c', ['d']], 1, 2, ['e', 'f'], 'g', 3, 4];
function flat (arr) {
      var result = [];
      var each = function (arr) {
            arr.forEach(item => {
                  if (item instanceof Array) {
                       each(item);
                   } else {
                       result.push(item);
                   }
            });
       }
       each(arr);
       return result.join(',');
}

flat(arr);

方法二:toString格式轉(zhuǎn)換

var arr = ['a', ['b', 'c', ['d']], 1, 2, ['e', 'f'], 'g', 3, 4];

Array.prototype.toString = function () {
    return this.join(',');  // 這里this就是arr數(shù)組
}

var flat = function (arr) {
    return arr + '';
}

flat(arr);

十四、將1234567 變成 1,234,567,即千分位標(biāo)注

// 方法一:
function exchange(num) {
     num = String(num); // 轉(zhuǎn)成字符串
    if (num.length <= 3) {
        return num;
    }

    num = num.replace(/\d{1,3}(?=(\d{3})+$)/g, (v) => {
        return v + ',';
    });
    return num;
}

exchange(1234567)  // 1,234,567

// 方法二
function format(num){  
   num = String(num); // 數(shù)字轉(zhuǎn)字符串  
  var str=""; // 字符串累加  
  for(var i = num.length - 1, j=1; i>=0; i--, j++){  
      if(j%3 == 0 && i !== 0){ // 每隔三位加逗號(hào),過濾正好在第一個(gè)數(shù)字的情況  
          str+=num[i]+","; // 加千分位逗號(hào)  
          continue;  
      }  
      str+=num[i]; // 倒著累加數(shù)字
  }  
  return str.split('').reverse().join(""); // 字符串=>數(shù)組=>反轉(zhuǎn)=>字符串 
}

十五 、有100格臺(tái)階,可以跨1步可以跨2步,一共有多少種走法:

(本質(zhì)是斐波那契數(shù)列)

function step(){
    this.n1 = 1;
    this.n2 = 2;
    this.total = 100;
    this.getFunction = getFunction;
}

var Stairs = new step();

function getFunction(){
    for(i=2; i<this.total;i++){
        res = this.n1 + this.n2;
        this.n1 = this.n2;
        this.n2 = res;
    }
    return res;
}

var totalStairs = Stairs.getFunction();
console.log(totalStairs);

// 方法二:
function fib(n) {
  let array = new Array(n + 1).fill(null)
  array[0] = 0
  array[1] = 1
  for (let i = 2; i <= n; i++) {
    array[i] = array[i - 1] + array[i - 2]
  }
  return array[n]
}

十六、多維數(shù)組問題
1、多維數(shù)組轉(zhuǎn)一維數(shù)組:

let arr = ['a', ['b', 'c'], 1, 2, ['d', 'e'], 'f', 3, 4]
arr.concat.apply([], arr)  // ["a", "b", "c", 1, 2, "d", "e", "f", 3, 4]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容