js構(gòu)建二叉樹進(jìn)行數(shù)值數(shù)組的去重與優(yōu)化詳解
前言
本文主要介紹了關(guān)于js構(gòu)建二叉樹進(jìn)行數(shù)值數(shù)組的去重與優(yōu)化的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
常見兩層循環(huán)實(shí)現(xiàn)數(shù)組去重
let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2, 5, 7, 11, 11, 7, 6, 4, 5, 2, 2]
let newArr = []
for (let i = 0; i < arr.length; i++) {
let unique = true
for (let j = 0; j < newArr.length; j++) {
if (newArr[j] === arr[i]) {
unique = false
break
}
}
if (unique) {
newArr.push(arr[i])
}
}
console.log(newArr)
構(gòu)建二叉樹實(shí)現(xiàn)去重(僅適用于數(shù)值類型的數(shù)組)
將先前遍歷過的元素,構(gòu)建成二叉樹,樹中每個(gè)結(jié)點(diǎn)都滿足:左子結(jié)點(diǎn)的值 < 當(dāng)前結(jié)點(diǎn)的值 < 右子結(jié)點(diǎn)的值
這樣優(yōu)化了判斷元素是否之前出現(xiàn)過的過程
若元素比當(dāng)前結(jié)點(diǎn)大,只需要判斷元素是否在結(jié)點(diǎn)的右子樹中出現(xiàn)過即可
若元素比當(dāng)前結(jié)點(diǎn)小,只需要判斷元素是否在結(jié)點(diǎn)的左子樹中出現(xiàn)過即可
let arr = [0, 1, 2, 2, 5, 7, 11, 7, 6, 4,5, 2, 2]
class Node {
constructor(value) {
this.value = value
this.left = null
this.right = null
}
}
class BinaryTree {
constructor() {
this.root = null
this.arr = []
}
insert(value) {
let node = new Node(value)
if (!this.root) {
this.root = node
this.arr.push(value)
return this.arr
}
let current = this.root
while (true) {
if (value > current.value) {
if (current.right) {
current = current.right
} else {
current.right = node
this.arr.push(value)
break
}
}
if (value < current.value) {
if (current.left) {
current = current.left
} else {
current.left = node
this.arr.push(value)
break
}
}
if (value === current.value) {
break
}
}
return this.arr
}
}
let binaryTree = new BinaryTree()
for (let i = 0; i < arr.length; i++) {
binaryTree.insert(arr[i])
}
console.log(binaryTree.arr)
優(yōu)化思路一,記錄最大最小值
記錄已經(jīng)插入元素的最大最小值,若比最大元素大,或最小元素小,則直接插入
let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2, 5, 7, 11, 11, 7, 6, 4, 5, 2, 2]
class Node {
constructor(value) {
this.value = value
this.left = null
this.right = null
}
}
class BinaryTree {
constructor() {
this.root = null
this.arr = []
this.max = null
this.min = null
}
insert(value) {
let node = new Node(value)
if (!this.root) {
this.root = node
this.arr.push(value)
this.max = value
this.min = value
return this.arr
}
if (value > this.max) {
this.arr.push(value)
this.max = value
this.findMax().right = node
return this.arr
}
if (value < this.min) {
this.arr.push(value)
this.min = value
this.findMin().left = node
return this.arr
}
let current = this.root
while (true) {
if (value > current.value) {
if (current.right) {
current = current.right
} else {
current.right = node
this.arr.push(value)
break
}
}
if (value < current.value) {
if (current.left) {
current = current.left
} else {
current.left = node
this.arr.push(value)
break
}
}
if (value === current.value) {
break
}
}
return this.arr
}
findMax() {
let current = this.root
while (current.right) {
current = current.right
}
return current
}
findMin() {
let current = this.root
while (current.left) {
current = current.left
}
return current
}
}
let binaryTree = new BinaryTree()
for (let i = 0; i < arr.length; i++) {
binaryTree.insert(arr[i])
}
console.log(binaryTree.arr)
優(yōu)化思路二,構(gòu)建紅黑樹
構(gòu)建紅黑樹,平衡樹的高度
有關(guān)紅黑樹的部分,請見紅黑樹的插入
let arr = [11, 12, 13, 9, 8, 7, 0, 1, 2, 2, 5, 7, 11, 11, 7, 6, 4, 5, 2, 2]
console.log(Array.from(new Set(arr)))
class Node {
constructor(value) {
this.value = value
this.left = null
this.right = null
this.parent = null
this.color = 'red'
}
}
class RedBlackTree {
constructor() {
this.root = null
this.arr = []
}
insert(value) {
let node = new Node(value)
if (!this.root) {
node.color = 'black'
this.root = node
this.arr.push(value)
return this
}
let cur = this.root
let inserted = false
while (true) {
if (value > cur.value) {
if (cur.right) {
cur = cur.right
} else {
cur.right = node
this.arr.push(value)
node.parent = cur
inserted = true
break
}
}
if (value < cur.value) {
if (cur.left) {
cur = cur.left
} else {
cur.left = node
this.arr.push(value)
node.parent = cur
inserted = true
break
}
}
if (value === cur.value) {
break
}
}
// 調(diào)整樹的結(jié)構(gòu)
if(inserted){
this.fixTree(node)
}
return this
}
fixTree(node) {
if (!node.parent) {
node.color = 'black'
this.root = node
return
}
if (node.parent.color === 'black') {
return
}
let son = node
let father = node.parent
let grandFather = father.parent
let directionFtoG = father === grandFather.left ? 'left' : 'right'
let uncle = grandFather[directionFtoG === 'left' ? 'right' : 'left']
let directionStoF = son === father.left ? 'left' : 'right'
if (!uncle || uncle.color === 'black') {
if (directionFtoG === directionStoF) {
if (grandFather.parent) {
grandFather.parent[grandFather.parent.left === grandFather ? 'left' : 'right'] = father
father.parent = grandFather.parent
} else {
this.root = father
father.parent = null
}
father.color = 'black'
grandFather.color = 'red'
father[father.left === son ? 'right' : 'left'] && (father[father.left === son ? 'right' : 'left'].parent = grandFather)
grandFather[grandFather.left === father ? 'left' : 'right'] = father[father.left === son ? 'right' : 'left']
father[father.left === son ? 'right' : 'left'] = grandFather
grandFather.parent = father
return
} else {
grandFather[directionFtoG] = son
son.parent = grandFather
son[directionFtoG] && (son[directionFtoG].parent = father)
father[directionStoF] = son[directionFtoG]
father.parent = son
son[directionFtoG] = father
this.fixTree(father)
}
} else {
father.color = 'black'
uncle.color = 'black'
grandFather.color = 'red'
this.fixTree(grandFather)
}
}
}
let redBlackTree = new RedBlackTree()
for (let i = 0; i < arr.length; i++) {
redBlackTree.insert(arr[i])
}
console.log(redBlackTree.arr)
其他去重方法
通過 Set 對象去重
[...new Set(arr)]
通過 sort() + reduce() 方法去重
排序后比較相鄰元素是否相同,若不同則添加至返回的數(shù)組中
值得注意的是,排序的時(shí)候,默認(rèn) compare(2, '2') 返回 0;而 reduce() 時(shí),進(jìn)行全等比較
let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let newArr = []
arr.sort((a, b) => {
let res = a - b
if (res !== 0) {
return res
} else {
if (a === b) {
return 0
} else {
if (typeof a === 'number') {
return -1
} else {
return 1
}
}
}
}).reduce((pre, cur) => {
if (pre !== cur) {
newArr.push(cur)
return cur
}
return pre
}, null)
通過 includes() + map() 方法去重
let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2] let newArr = [] arr.map(a => !newArr.includes(a) && newArr.push(a))
通過 includes() + reduce() 方法去重
let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let newArr = arr.reduce((pre, cur) => {
!pre.includes(cur) && pre.push(cur)
return pre
}, [])
通過對象的鍵值對 + JSON 對象方法去重
let arr = [0, 1, 2, '2', 2, 5, 7, 11, 7, 5, 2, '2', 2]
let obj = {}
arr.map(a => {
if(!obj[JSON.stringify(a)]){
obj[JSON.stringify(a)] = 1
}
})
console.log(Object.keys(obj).map(a => JSON.parse(a)))
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
微信小程序自定義tabbar custom-tab-bar 6s出不來解決方案(cover-view不兼容)
這篇文章主要介紹了微信小程序自定義tabbar custom-tab-bar 6s出不來解決方案,cover-view不兼容問題,需要的朋友可以參考下2019-11-11
用Javascript輕松制作一套簡單的抽獎(jiǎng)系統(tǒng)
用Javascript輕松制作一套簡單的抽獎(jiǎng)系統(tǒng)...2006-12-12
寫出更好的JavaScript程序之undefined篇(中)
前一篇我介紹了幾種廣為使用的利用undefined這個(gè)概念值的辦法,這一篇我會(huì)介紹一些不太常見的辦法,其中還包括一個(gè)很巧妙的,我個(gè)人覺得很值得推廣的辦法。2009-11-11
uniapp在開發(fā)app時(shí)上傳文件時(shí)的問題記錄
在開發(fā)uniapp應(yīng)用時(shí),可能會(huì)遇到文件上傳功能在iOS和部分Android手機(jī)上不兼容的問題,經(jīng)過對比分析,發(fā)現(xiàn)問題可能出在文件的路徑上,通過使用uni.saveFile方法保存文件后,再上傳可以解決問題,這篇文章詳細(xì)介紹了解決方案,并引導(dǎo)讀者參考更多相關(guān)內(nèi)容2024-09-09
eslint+prettier統(tǒng)一代碼風(fēng)格的實(shí)現(xiàn)方法
這篇文章主要介紹了eslint+prettier 統(tǒng)一代碼風(fēng)格的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07

