日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

楔子 -- 青蛙跳臺階

一只青蛙一次可以跳上一級臺階,也可以跳上二級臺階,求該青蛙跳上一個n級的臺階總共需要多少種跳法。

分析: 當n=1的時候,①只需要跳一次即可;只有一種跳法,即f(1)=1;

當n=2的時候,①可以先跳一級再跳一級,②也可以直接跳倆級;共有倆種跳法,即f(2)=2;

當n=3的時候,①一階一階跳即可;
②他可以從一級臺階上跳倆階上來
③也可從二級臺階上跳一階上來;即共有f(3)=f(2)+f(1);

所以當有n階臺階時,且當n>2的時候,根據上面式子可推導出→ f(n)=f(n-1)+f(n-2)

再談前端算法,你這回明白了嗎?圖片

所以很直白的看出就是個 斐波那契數列 ,有一點不同的是,斐波那契數列從1,1,2,3,5,8,13…開始的,而我們這是以1,2,3,5,8,13…開始的,少了前面的1

什么是算法

解決一系列問題的具體步驟

算法是一組用于解決特定問題或執行特定任務的有限步驟序列。這些步驟按照確定的順序執行,以達到所需的結果。在計算機科學中,算法通常用于描述數據處理、自動化處理和數學運算的過程。算法可以用來解決各種問題,包括排序、搜索、路徑規劃等。

算法實例 :實現一個LRU緩存

LRU是Least Recently Used(最近最少使用)的縮寫。

在計算機科學中,LRU是一種頁面置換算法,通常用于操作系統的虛擬內存管理中。

該算法根據頁面(或者其他資源)的最近使用情況來進行置換,當需要置換時,選擇最近最少被使用的頁面進行替換。

這樣可以保證最常用的頁面保留在內存中,從而提高性能。

實例:vue keep-alive 緩存

LRU -- 最近使用

實現 LRUCache

緩存,有一個大小 const lru = new LRUCache(capacity)

提示

const lru = new LRUCache(2)
lru.put(1,1)
lru.put(2,2) // {1:1,2:2}
lru.get(1)

lru.put(3,3) // {1:1,3:3}
lru.get(2) // -1 (找不到)

lru.put(4,4)  // {4:4,3:3}

實現代碼

// 函數的 get 和 put 必須以 O(1)的時間復雜度運行 
// get,得是個hash(Map,Set),而不能是數組
// ES6 迭代器

const LRUCache = function(capacity){
 this.cacheQueue = new Map()
 this.capacity = capacity 
}

LRUCache.prototype.get = function(key){
  if(this.cacheQueue.has(key)){ // 如果找到了,這個key對應的value要提升新鮮度
    const result = this.cacheQueue.get(key)

    // 刪掉,然后再放進去,這樣,這個就能在cacheQueue的隊尾(隊尾為最新鮮地方)
    this.cacheQueue.delete(key) 
    this.cacheQueue.set(key,result) 
    return result

  }
  return -1 // 如果沒有找到key,則直接返回 -1 
}


LRUCache.prototype.put = function(key,value){
   if(this.cacheQueue.has(key)){ 
    // 如果找到了, 刪掉
     this.cacheQueue.delete(key)  
   }

   if(this.cacheQueue.size >= this.capacity){
      // 刪除map的第一個元素,即最長時間未使用的
      this.cacheQueue.set(key,value)  
      this.cacheQueue.delete(this.cacheQueue.keys().next().value)  
   } else {
      this.cacheQueue.set(key,value)  
   }
}

擴展:ES6 Map

ES6的Map是一種內置的數據結構,它存儲鍵值對并允許你通過鍵快速查找值。

Map對象類似于對象,但不同之處在于Map的鍵可以是任意數據類型,而對象的鍵只能是字符串或Symbol。

Map還保留了插入順序,這意味著當你遍歷一個Map對象時,它會按照插入順序返回鍵值對。

Map的創建和初始化:

要創建一個新的Map,你需要使用new Map()語法。

例如:

const myMap = new Map();

添加鍵值對:

你可以使用Map對象的set()方法添加鍵值對。

例如:

myMap.set('key1', 'value1');
myMap.set('key2', 'value2');

獲取鍵值對:

你可以使用Map對象的get()方法獲取鍵對應的值。

例如:

const value1 = myMap.get('key1'); // 返回 'value1'
const value2 = myMap.get('key2'); // 返回 'value2'

檢查Map中是否存在某個鍵:

你可以使用Map對象的has()方法檢查Map中是否存在某個鍵。

例如:

const hasKey1 = myMap.has('key1'); // 返回 true
const hasKey3 = myMap.has('key3'); // 返回 false

刪除鍵值對:

你可以使用Map對象的delete()方法刪除鍵值對。

例如:

myMap.delete('key1');

遍歷Map:

你可以使用Map對象的keys()、values()或entries()方法遍歷Map中的鍵或值。

例如:

for (const key of myMap.keys()) {
  console.log(key); // 輸出鍵名
}
for (const value of myMap.values()) {
  console.log(value); // 輸出值
}
for (const [key, value] of myMap.entries()) {
  console.log(key, value); // 輸出鍵名和值
}

myMap.forEach((value, key) => {
  console.log(key + ' = ' + value);
});

獲取Map的大小:

myMap.size; // 返回Map的大小

更多詳細內容,請微信搜索“前端愛好者“, 戳我 查看 。

算法實例 :求環狀鏈表

leecode的地址:https://leetcode.cn/problems/linked-list-cycle/

鏈表:常見 -- react源碼

再談前端算法,你這回明白了嗎?圖片

思路:快慢指針,兩個(起點相同位置)指針,n步驟以后指針相遇

再談前端算法,你這回明白了嗎?圖片

實現代碼

head.next 指向下一個值

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    let fast = slow = head
    while(fast && fast.next){
        fast = fast.next.next
        slow = slow.next
        if(fast === slow){
            return true
        }  
    }
    return false
};

擴展:鏈表

鏈表是一種數據結構,其中的元素以節點的形式按順序排列。

每個節點都包含數據和指向下一個節點的引用。

相比數組,鏈表在插入和刪除元素時更靈活,因為它們不需要連續的存儲空間。

舉例來說,一個簡單的鏈表可以被定義如下:

Node 1: 23 -> Node 2
Node 2: 47 -> Node 3
Node 3: 95 -> null

在這個例子中,鏈表中的每個節點包含一個值和指向下一個節點的引用。

第一個節點包含值23,同時指向第二個節點,依此類推。最后一個節點指向null,表示鏈表的結束。

通過使用鏈表,我們可以輕松地插入或刪除節點,而無需移動其他節點。

這使得鏈表在某些場景下比數組更為適用。

鏈表是一種物理存儲結構上 非連續、非順序 的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。

鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。

每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。

鏈表有很多種不同的類型,包括單向鏈表、雙向鏈表以及循環鏈表。

鏈表可以在多種編程語言中實現,例如C、C++和JAVA等。

算法實例 :二又樹的前序、中序、后序遍歷

再談前端算法,你這回明白了嗎?圖片

前序遍歷 - 根左右

先走根節點,然后左,然后右

再談前端算法,你這回明白了嗎?圖片

中序遍歷 - 左根右

先走左節點,然后根節點,然后右節點

再談前端算法,你這回明白了嗎?圖片

后序遍歷 - 左右根

先走左節點,然后右節點,然后再根節點

再談前端算法,你這回明白了嗎?圖片

舉例

再談前端算法,你這回明白了嗎?圖片

前/先序遍歷: GDAFEMHZ 中序遍歷: ADEFGHMZ 后序遍歷: AEFDHZMG

再談前端算法,你這回明白了嗎?圖片

前序遍歷: A-B-D-F-G-H-I-E-C 中序遍歷: F-D-H-G-I-B-E-A-C 后序遍歷: F-H-I-G-D-E-B-C-A

實現代碼

const treeRoot = {
  val: 1,
  left: {
    val: 2,
    left: {
      val: 4,
    },
    right: {
      val: 5,
    }
  },
  right: {
    val: 3,
    left: {
      val: 6,
    },
    right: {
      val: 7,
    }
  }
}

// 前序
const preOrder = function(node){
  if(node){
    // 如果有根節點
    console.log(node.val)
    preOrder(node.left)
    preOrder(node.right)
  }
}

preOrder(treeRoot)

// 中序
const inOrder = function(node){
  if(node){
    // 如果有根節點
    inOrder(node.left)
    console.log(node.val)
    inOrder(node.right)
  }
}

inOrder(treeRoot)

// 后序
const nextOrder = function(node){
  if(node){
    // 如果有根節點
    nextOrder(node.left)
    nextOrder(node.right)
    console.log(node.val)
  }
}

nextOrder(treeRoot)

(二叉樹)層序遍歷

leetcode地址:https://leetcode.cn/problems/binary-tree-level-order-traversal/

再談前端算法,你這回明白了嗎?圖片

輸入:root = [3,9,20,null,null,15,7] 輸出:[[3],[9,20],[15,7]]

/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
  if(!root) return []
  let queue = [root]
  let result = []

  // 開始遍歷
  while(queue.length){
    let temQueue = []
    let temResult = []
    let len = queue.length
    for(let i = 0; i < len; i++){
      let node = queue.shift()
      temResult.push(node.val)
      node.left && temQueue.push(node.left)
      node.right && temQueue.push(node.right)
    }
    // 循環完畢
    result.push(temResult)
    temResult = []
    queue = temQueue
  }
  return result
};

(二叉樹)的層級

leetcode地址:https://leetcode.cn/problems/maximum-depth-of-binary-tree/

直接return 上面層序的lengh

/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var maxDepth = function(root) {
  if(!root) return []
  let queue = [root]
  let result = []

  // 開始遍歷
  while(queue.length){
    let temQueue = []
    let temResult = []
    let len = queue.length
    for(let i = 0; i < len; i++){
      let node = queue.shift()
      temResult.push(node.val)
      node.left && temQueue.push(node.left)
      node.right && temQueue.push(node.right)
    }
    // 循環完畢
    result.push(temResult)
    temResult = []
    queue = temQueue
  }
  return result.length
};

使用DP方法

let maxDepth = function(root){
  if(!root) return 0 // 如果沒有根節點,則直接返回0
  // 找左右叉的最大值
  return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1
}

類數組轉數組有多少種方法

const arrayLike = document.querySelectorAll('div')

再談前端算法,你這回明白了嗎?圖片

擴展運算符

[...arrayLike]

prototype

Array.prototype.slice.call(arrayLike) 
Array.prototype.concat.Apply([],arrayLike)

Array.from

Array.from(arrayLike)

Array.apply

Array.apply(null,arrayLike)

擴展:數組常用哪些方法?

數組常用方法很多,主要包括以下幾個:

  1. 1. find():返回數組中符合測試函數條件的第一個元素值。
const numbers = [10, 20, 30, 40];
const result = numbers.find(num => num > 25);
// 結果為30
  1. 2. findIndex():返回數組中符合測試函數條件的第一個元素索引。
const numbers = [10, 20, 30, 40];
const index = numbers.findIndex(num => num > 25);
// 結果為2(即元素30對應的索引)
  1. 3. forEach():對數組的每個元素執行提供的函數。
const numbers = [1, 2, 3];
numbers.forEach(num => console.log(num * 2));
// 輸出2, 4, 6
  1. 4. map():對數組的每個元素執行提供的函數,并返回結果組成的新數組。
 
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
// 結果為[2, 4, 6]
  1. 5. filter():使用給定函數測試所有元素,并返回由所有通過測試的元素組成的新數組。
const numbers = [10, 15, 20, 25, 30];
const greaterThan20 = numbers.filter(num => num > 20);
// 結果為[25, 30]

這些方法在處理數組時非常有用,并且能夠簡化一些常見的操作。

分享到:
標簽:算法
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定