1、兩數之和
const twoSum = (nums, target) => {const obj = {}for (let m = 0; m < nums.length; m++) {const cur = nums[m]const diff = target - curif(obj.hasOwnProperty(diff)){ // 查詢對象中是否存在目標值-當前值鍵值對console.log([obj[diff], m]) // 存在則直接獲取差值key對應的值,即索引。m為當前索引break}else{obj[cur] = m // 存儲當前值和當前索引}}
}const twoSum = (nums, target) => {const obj = new Map()for (let m = 0; m < nums.length; m++) {const cur = nums[m]const diff = target - curif(obj.has(diff)){console.log([obj.get(diff), m])break}else{obj.set(cur, m)}}
}twoSum([1,2,3,4,5,6,76], 9) // [3, 4]
twoSum([3,3], 6) // [0, 1]
twoSum([1,2,3,4,5,6,3], 6) // [1, 3]
2、字母異位詞
var strs = ["eat", "tea", "tan", "ate", "nat", "bat"];
var obj = {};
var groupAnagrams = function () {strs.forEach((item) => {const st = item.split("").sort().join("");if (!obj[st]) obj[st] = new Set();obj[st].add(item);});var res = [];Object.values(obj).forEach((item) => {res.push([...item]);});console.log(res);
};
groupAnagrams();
// Output: [ [ 'eat', 'tea', 'ate' ], [ 'tan', 'nat' ], [ 'bat' ] ]
3、最長連續序列
var longestConsecutive = function(nums) {const numsNew = new Set(nums.sort((a,b) => a - b))const arr = []const numsNewList = [...numsNew]numsNewList.forEach((val, index) =>{const nextval = numsNewList[index + 1]const arrlen = arr.lengthconst arrLast = arr[arrlen - 1]if(arrLast){const arrLastlen = arrLast.lengthconst arrLastVal = arrLast[arrLastlen - 1]if(arrLastVal + 1 === val){arrLast.push(val)}else{arr.push([val])}}else{arr.push([val])}})const aaa = arr.sort((a, b) => b.length - a.length);return aaa[0].length
}
4、哈希表與鏈表
????????哈希表是無序的快速查找工具,鏈表是有序的動態序列容器
? ? 哈希表:
核心特性:
- 無序性
- 元素的存儲位置由哈希函數計算決定,與插入順序無關。
- 遍歷時元素的順序不可預測(取決于哈希桶的分布)。
- 快速訪問
- 通過鍵(Key)直接定位值(Value),時間復雜度接近?O(1)。
- 存儲結構
- 底層通常是數組 + 鏈表/紅黑樹(解決哈希沖突)。
- 典型應用
- 字典、緩存、快速查找場景(如數據庫索引)。
js中的對象是基于哈希表結構的,而哈希表的查找時間復雜度為O(1),訪問方式:直接通過鍵訪問(O(1))。所以很多人喜歡用對象來做映射,減少遍歷循環。
利用數組索引快速查找數據的特性,無序(由哈希函數決定),通過實現一個hash函數將key轉化為唯一的索引,對應數組中的一個位置。所以具有快速存取刪數據的特性
? ? ? 優點:
-
高效的查找:哈希表可以在常數時間復雜度內進行查找操作,即 O(1)。這使得它在需要快速查詢數據的場景中非常有用。
-
快速的插入和刪除:哈希表同樣可以在常數時間復雜度內執行插入和刪除操作,這使得它非常適合需要頻繁更新數據的場景。
-
空間利用率高:哈希表可以根據實際數據量動態調整大小,以盡可能減少內存的使用。
-
編碼簡單:哈希表的實現相對簡單,只需設計一個合適的哈希函數即可
? ? ? 缺點:?
-
沖突處理:當兩個不同的鍵被映射到同一個索引位置時,會發生沖突。解決沖突的方法有很多種,但不同的方法對性能的影響也不同。
-
哈希函數的選擇:選擇一個好的哈希函數對于避免沖突以及提高性能至關重要。如果選擇的哈希函數不好,可能會導致沖突增多或者性能下降。
-
不支持順序訪問:與數組或鏈表不同,哈希表中的元素沒有特定的順序。如果需要按照某種順序訪問元素,可能需要對哈希表進行額外的處理
class HashTable {size: numbertable: any[]constructor(size: number) {this.size = sizethis.table = Array.from({length: size}, () => [])}hash(key: string) {let h = 0for (let i = 0; i < key.length; i++) {h += key.charCodeAt(i)}return h % this.size}// 設置和更新set(key, value) {const index = this.hash(key)let bucket = this.table[index]const cur = bucket?.find(item => item.key === key)if (cur) {cur.value = value} else {bucket = []bucket.push({key, value})}}get(key: string) {const index = this.hash(key)const bucket = this.table[index]const cur = bucket?.find(item => item.key === key)return cur ? cur.value : null}delete(key: string) { const index = this.hash(key)const bucket = this.table[index]const findex = bucket?.findIndex(item => item.key === key)if (findex !== -1) {this.table.splice(findex, 1)return true} else {return false }}has(key) {return !!this.get(key)}}const hashtable = new HashTable(100)hashtable.set('name', 'zhangsan')hashtable.set('age', '20')
? ? 鏈表:
核心特性:
- 有序性(按插入順序)
- 元素通過節點指針顯式連接,遍歷順序始終是插入順序。
- 若需要排序,需額外維護(如有序鏈表)。
- 順序訪問
- 查找元素必須從頭節點開始遍歷,時間復雜度為?O(n)。
- 存儲結構
- 節點包含數據(Data)和指針(Next/Prev)。
- 典型應用
- 需要頻繁插入/刪除的場景(如LRU緩存淘汰算法)
鏈表格是一種線性數據結構,類似于數組,有序(按插入順序或顯式排序),? 訪問方式:順序遍歷(O(n))
。但不像數組的元素存儲在特定的存儲器位置或索引中,鏈表格的每個元素都是一個獨立的對象,其中包含一個指針或鏈接指向列表中的下一個對象。
每一個元素(通常 稱為節點)包含兩個項目:存儲的數據和到下一個節點的鏈接,這些數據可以是任何有效數據類型
? ? 優點:
? ? ? ? 可以很容易地從鏈表中刪除或添加節點,而無需重組整個數據結構。這是它相對于數組的一個優勢
-
動態內存分配:鏈表不需要在創建時就確定大小,它可以根據需要動態地增加或減少節點,這使得內存利用更加靈活。
-
插入和刪除效率高:在鏈表中添加或刪除節點時,只需要修改相關節點的指針,不必像數組那樣移動大量元素,這樣操作起來更快。
-
靈活性:鏈表可以輕松地實現各種復雜的數據結構,如雙向鏈表、循環鏈表等,為不同的算法實現提供了便利
? ? 缺點:
? ? ? ? 鏈表的搜索操作很慢,與數組不同,不允許隨機訪問數據元素,必須從第一個節點開始按順序訪問節點。由于需要儲存指針,相較于數組需要更多內存,
-
訪問效率低:鏈表不支持隨機訪問,訪問特定位置的節點需要從頭開始遍歷,這在數據量大時會影響效率1。
-
額外的內存開銷:每個鏈表節點都需要額外的存儲空間來存儲指針,這與數組相比是一種空間上的浪費
class Node{datanextconstrucotr(data) { this.data = data;this.next = null}}class linkedList{headsizeconstryctor() {this.head = nullthis.size = 0}append(data) { const node = new Node(data)if (!this.head) {this.head = node} else {const current = this.headwhile (current.next) {current = current.next}current.next = node}this.size++}// get(data){ // const head = this.head// while (head.next) {// if (head.data === data) {// return head.next// }// }// }delete (data){ if (!this.hear) returnif (this.head.data === data) {this.head = this.head.next} else {let current = this.headlet prev = nullwhile (current && current.data !== data) {current = current.nextprev = current}if (current) {prev.next = current.next}}this.size--}}