个人力扣刷题答案,使用js解题
GitHub - ispaomoya/suanfa: 力扣js算法草稿
持续更新哈
目录
一、栈
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>栈</title>
</head>
<body>
<script>
//封装栈类
function Stack() {
//栈的属性
this.items = []
//栈的相关操作
//1进栈
Stack.prototype.push = function (el) {
this.items.push(el)
}
//2出栈
Stack.prototype.pop = function (){
return this.items.pop()
}
//3查看栈顶
Stack.prototype.peek = function (){
return this.items[this.items.length - 1]
}
//4是否空栈
Stack.prototype.isEmpty = function (){
return this.items.length === 0
}
//5获取栈元素的个数
Stack.prototype.size = function (){
return this.items.length
}
//6正序
Stack.prototype.order = function (){
return this.items.join('')
}
//7倒序
Stack.prototype.reverseOrder = function (){
return this.items.reverse().join('')
}
}
//栈的使用
let s = new Stack()
s.push(1)
s.push(2)
s.push(3)
console.log(s.order());
//十进制转二进制
function dec2bin(num){
//1定义一个对象
let s = new Stack()
//
while(num > 0){
s.push(num % 2)
num = Math.floor(num / 2)
}
return s.reverseOrder()
}
console.log(dec2bin(10));
</script>
</body>
</html>
二、队列
2.1 基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组队列</title>
</head>
<body>
<script>
function Queue(){
this.items = []
//1入队
Queue.prototype.enQueue = function (el){
this.items.push(el)
}
//2 出队
Queue.prototype.deQueue = function (){
return this.items.shift()
}
//3 查看第一个元素
Queue.prototype.front = function(){
return this.items[0]
}
// 4查看是否为空
Queue.prototype.isEmpty = function (){
return this.items.length === 0
}
// 5查看个数
Queue.prototype.size = function (){
return this.items.length
}
//6正序
Queue.prototype.order = function (){
return this.items.join('')
}
}
// 实例
let q = new Queue()
q.enQueue('a')
q.enQueue('b')
q.enQueue('c')
q.enQueue('d')
console.log(q.order());
</script>
</body>
</html>
2.2 优先队列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function PriorityQueue(){
function QueueElement(element,priority){
this.element = element
this.priority = priority
}
this.items = []
PriorityQueue.prototype.enqueue = function (element,priority){
// 1创建对象
let queueElement = new QueueElement(element,priority)
// 2判断队列是否为空
if(this.items.length === 0){
this.items.push(queueElement)
}else {
let added = false
let n = this.items.length
for (let i = 0; i < n; i++) {
if(queueElement.priority < this.items[i].priority){
this.items.splice(i,0,queueElement)
added = true
break
}
//插入到最后
if(!added){
this.items.push(queueElement)
}
}
}
}
//2 出队
PriorityQueue.prototype.deQueue = function (){
return this.items.shift()
}
//3 查看第一个元素
PriorityQueue.prototype.front = function(){
return this.items[0]
}
// 4查看是否为空
PriorityQueue.prototype.isEmpty = function (){
return this.items.length === 0
}
// 5查看个数
PriorityQueue.prototype.size = function (){
return this.items.length
}
//6正序
PriorityQueue.prototype.order = function (){
let str = ''
for (let i = 0; i < this.items.length-1; i++) {
str = str+this.items[i].element+'_'+this.items[i].priority+ ' '
}
console.log('我想看一下',this.items);
return str
}
}
//测试代码
let pq = new PriorityQueue()
pq.enqueue('abc',111)
pq.enqueue('cba',200)
pq.enqueue('nba',50)
pq.enqueue('bb',66)
console.log(pq.order());//nba_50 bb_66 abc_111 cba_200
</script>
</body>
</html>
三、链表
3.1 单向链表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function LinkedList(){
function Node(data){
this.data = data
this.next = null
}
//属性
this.head = null
this.length = 0
//一、追加方法
LinkedList.prototype.append = function (data) {
//1如果是第一个节点
let newNode = new Node(data)
if(this.length === 0){
this.head = newNode
}else {
let current = this.head
while(current.next) {
current = current.next
}
current.next = newNode
}
//2添加后长度加一
this.length += 1
}
// 二、tostring方法
LinkedList.prototype.toString = function (){
// 1定义变量
let current = this.head
let listString = ''
// 2循环一个个节点
while(current){
listString += current.data + ' '
current = current.next
}
return listString
}
// 三、insert方法
LinkedList.prototype.insert = function (position,data){
// 1对position进行越界判断
if(position < 0 || position > this.length ) return false
// 2创建对象
let newNode = new Node(data)
// 3判断插入的位置是否第一个
if(position === 0){
newNode.next = this.head
this.head = newNode
}else {
let i = 0
let current = this.head
let previous = null
while(i++ < position){
previous = current
current = current.next
}
newNode.next = current//这个是插入的元素,连接下一个节点
previous.next = newNode//这个是插入的元素上一个,连接当前要插入的元素
}
// 4长度加一
this.length += 1
return true
}
// 四、get方法
LinkedList.prototype.get = function (position) {
//1越界判断
if(position < 0 || position >= this.length) return null
// 2获取对应的元素
let current = this.head
let i = 0
while(i++ < position){
current = current.next
}
return current.data
}
// 五、indexOf方法
LinkedList.prototype.indexOf = function (data){
// 1定义变量
let current = this.head
let i = 0
//2 查找
while(current){
if(current.data === data){
return i
}
current = current.next
i += 1
}
// 3找到最后没有直接返回-1
return -1
}
// 六、update方法
LinkedList.prototype.update = function (position,data){
//1越界判断
if(position < 0 || position >= this.length)return false
// 2定义变量
let current = this.head
let i = 0
//3 查找
while(i++ < position){
current = current.next
}
// 4更新
current.data = data
return true
}
// 七、removeAt方法,从链表中删除特定一项
LinkedList.prototype.removeAt = function (position){
// 1越界判断
if(position < 0 || position >= this.length)return false
let current = this.head
// 2当是第0个节点
if(position === 0){
this.head = this.head.next
}else {
let i = 0
let previous = null
while(i++ < position) {
previous = current
current = current.next
}
previous.next = current.next
}
//3长度-1
this.length -= 1
return true
}
// 八、remove方法,从链表中移除一项,根据数据
LinkedList.prototype.remove = function (data){
const i = this.indexOf(data)
return this.removeAt(i)
}
}
//测试代码
let list = new LinkedList()
list.append('abc')
list.append('cba')
list.append('nba')
// console.log(list.toString());
list.insert(0,'aaa')
list.insert(3,'bbb')
list.insert(5,'ccc')
// console.log(list.toString());
// console.log(list.get(0));
// console.log(list.get(3));
// console.log(list.get(5));
// console.log(list.toString());
// console.log(list.indexOf('abc'));
// console.log(list.indexOf('ccc'));
// console.log(list.indexOf('1231'));
// console.log(list.toString());
// console.log(list.update(0,123));
// console.log(list.update(4,123));
// console.log(list.toString());
// console.log(list.removeAt(1))
// console.log(list.toString());
// console.log(list.remove('ccc'));
// console.log(list.toString());
</script>
</body>
</html>
3.2 双向链表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 双向链表 -->
<script>
function DoublyLinkedList(){
// 内部类
function Node(data){
this.data = data
this.prev = null//指向前一个指针
this.next = null//指向后一个指针
}
// 属性
this.head = null
this.tail = null
this.length = 0
// 1append方法
DoublyLinkedList.prototype.append = function (data){
// 1.1创建节点
let newNode = new Node(data)
// 1.2判断是否添加第一个节点
if(this.length === 0){
this.head = newNode
this.tail = newNode
}else {
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}
// 1.3长度加1
this.length += 1
}
// 2前向遍历,后向遍历
DoublyLinkedList.prototype.first_back = function(v){
if(v === 'back'){
let current = this.head
let res = ''
while(current){
res += current.data
current = current.next
}
console.log(res);
}else {
let current = this.tail
let res = ''
while(current){
res += current.data
current = current.prev
}
console.log(res);
}
}
// 3根据位置插入
DoublyLinkedList.prototype.insert = function (position, data){
// 3.1越界判断
if(position < 0 || position > this.length)return false
// 3.2创建新节点
let newNode = new Node(data)
// 3.3判断原来列表是否为空
if(this.length === 0 ){
this.head = newNode
this.tail = newNode
}else {
// 3.31假如插入的位置是0
if(position === 0){
this.head.prev = newNode
newNode.next = this.head
this.head = newNode
// 假如插入的最后一个位置
}else if(position === this.length){
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}else {
let current = this.head
let i = 0
while(i++ < position){
current = current.next
}
newNode.next = current
newNode.prev = current.prev
current.prev.next = newNode
current.prev = newNode
}
}
// 4长度加一
this.length += 1
return true
}
// 4get方法
DoublyLinkedList.prototype.get = function (position){
// 4.1越界判断
if(position < 0 || position > this.length)return null
// 4.2获取元素
let current = this.head
let i = 0
while(i++ < position){
current = current.next
}
console.log('查找到的值--------',current.data);
return current.data
}
}
// 测试代码
let list = new DoublyLinkedList()
list.append('aaa')
list.append('ccc')
list.append('zzz')
// list.first_back('back')//从前往后
// list.first_back()//从后往前
// list.insert(3,'000')
// list.first_back('back')//从前往后
// list.get(0)
</script>
</body>
</html>
四、哈希表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>哈希表</title>
</head>
<body>
<script>
// 这个是哈希表
function HashTable() {
// 属性
this.storage = []
this.count = 0//记录当前已存放的个数
this.limit = 7//总长度
// 方法
// 这个是哈希函数
HashTable.prototype.hashFunc = function (str, size) {
// 1定义hashCode变量
let hashCode = 0
// 2计算值
// Unicode码
for (let i = 0; i < str.length; i++) {
hashCode = 37 * hashCode + str.charCodeAt(i)
}
// 3取余
let index = hashCode % size
return index
}
// 插入/修改
HashTable.prototype.put = function (key, value) {
// 1根据key获取对应的index
let index = this.hashFunc(key, this.limit)
// 2根据index获取对应的bucket
let bucket = this.storage[index]
// 3判断bucket是否为空,如果为空创建一下
if (bucket == null) {
this.storage[index] = []
}
// 4判断是否修改数据
for (let i = 0; i < bucket.length; i++) {
let tuple = bucket[i]
if (tuple[0] === key) {
tuple[1] = value
return
}
}
// 5如果不是修改,直接添加
bucket.push([key, value])
this.count += 1
// 6扩容
if (this.count > this.limit * 0.75) {
let newPrime = this.getPrime(this.limit * 2)
this.resize(newPrime)
}
}
// 查找
HashTable.prototype.get = function (key) {
// 1根据key获取index
let index = this.hashFunc(key, this.limit)
// 2根据index获取对应的bucket
let bucket = this.storage[index]
// 3判断是否为空,是的话直接返回
if (bucket == null) return null
// 4有bucket的话,线性查找
for (let i = 0; i < bucket.length; i++) {
let tuple = bucket[i]
if (tuple[0] === key) {
return tuple[1]
}
}
// 5如果没有找到
return null
}
// 删除
HashTable.prototype.remove = function (key) {
// 1根据key获取index
let index = this.hashFunc(key, this.limit)
// 2根据index获取对应的bucket
let bucket = this.storage[index]
// 3判断是否为空,是的话直接返回
if (bucket == null) return null
// 4有bucket的话,线性查找,并且删除
for (let i = 0; i < bucket.length; i++) {
let tuple = bucket[i]
if (tuple[0] === key) {
bucket.splice(i, 1)
this.count--
// 缩小容量,最小容量为7
if (this.limit > 7 && this.count < this.limit * 0.25) {
let newPrime = this.getPrime(Math.floor(this.limit / 2))
this.resize(newPrime)
}
return tuple[1]
}
}
// 5如果没有找到
return null
}
//哈希表是否为空
HashTable.prototype.isEmpty = function () {
return this.count === 0
}
//获取元素个税,所有
HashTable.prototype.size = function () {
return this.count
}
// 扩容
HashTable.prototype.resize = function (newLimit) {
// 1保存旧数组的内容
let oldStroage = this.storage
// 2重置所有属性
this.storage = []
this.count = 0
this.limit = newLimit
// 3循环oldStroage所有的bucket
for (let i = 0; i < oldStroage.length; i++) {
// 3.1取出桶
let bucket = oldStroage[i]
// 3.2判断桶是否为空,为空直接下一次循环
if (bucket == null) continue
// 3.3bucket中有数据取出数据,重新插入
for (let j = 0; j < bucket.length; j++) {
let tuple = bucket[j]
this.put(tuple[0], tuple[1])
}
}
}
// 判断是不是质数
HashTable.prototype.isPrime = function (num) {
// 1获取num的平方根
let temp = parseInt(Math.sqrt(num))
for (let i = 2; i <= temp; i++) {
if (num % 2 === 0) {
return false
}
}
return true
}
// 获取质数的方法
HashTable.prototype.getPrime = function (num) {
while (!this.isPrime(num)) {
num++
}
return num
}
}
// 测试代码
let ht = new HashTable()
ht.put('aaa', '111')
ht.put('bbb', '222')
ht.put('ccc', '333')
</script>
</body>
</html>
五、合集
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>集合</title>
</head>
<body>
<script>
function Set() {
// 属性
this.items = {}
// 方法
Set.prototype.add = function (value) {
// 如果已有属性,就退出
if (this.has(value)) return false
this.items[value] = value
return true
}
// has方法,是否有这个属性
Set.prototype.has = function (value) {
return this.items.hasOwnProperty(value)
}
// remove
Set.prototype.remove = function (value) {
// 1是否包含
if (!this.has(value)) return false
// 2如果有,就删除
delete this.items[value]
return true
}
// clear方法
Set.prototype.clear = function () {
this.items = {}
}
// size方法
Set.prototype.size = function () {
return Object.keys(this.items).length
}
// 属性数组
Set.prototype.values = function () {
return Object.keys(this.items)
}
// 并集
Set.prototype.union = function (otherSet) {
let unionSet = new Set()
let values = this.values()
// 把当前的加进去
for (let i = 0; i < values.length; i++) {
unionSet.add(values[i])
}
// 把传进来的加进去
values = otherSet.values()
for (let i = 0; i < values.length; i++) {
unionSet.add(otherSet[i])
}
return unionSet
}
// 交集
Set.prototype.intersection = function (otherSet) {
let intersection = new Set()
let values = this.values()
for (let i = 0; i < values.length; i++) {
if (otherSet.has(values[i])) {
intersection.add(values[i])
}
}
return intersection
}
// 差集
Set.prototype.difference = function (otherSet) {
let differenceSet = new Set()
let values = this.values()
for (let i = 0; i < values.length; i++) {
if (!otherSet.has(values[i])) {
differenceSet.add(values[i])
}
}
}
// 子集
Set.prototype.subset = function (otherSet) {
let values = this.values()
for (let i = 0; i < values.length; i++) {
if (!otherSet.has(values[i])) return false
}
return true
}
}
// 测试代码
// 交集
let set_1 = new Set()
set_1.add('aaa')
set_1.add('bbb')
set_1.add('ccc')
let set_2 = new Set()
set_2.add('bbb')
// console.log(set_1.intersection(set_2));
// 子集
console.log(set_2.subset(set_1));
</script>
</body>
</html>
六、二叉树
6.1 二叉搜索树
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>二叉搜索树</title>
</head>
<body>
<script>
function BinarySerachTree() {
function Node(key) {
this.key = key
this.left = null
this.right = null
}
// 属性
this.root = null
// 一、插入
BinarySerachTree.prototype.insert = function (key) {
// 1根据key创建节点
let newNode = new Node(key)
// 2判断跟节点是否有值
if (this.root == null) {
this.root = newNode
} else {
this.insertNode(this.root, newNode)
}
}
// 递归调用
BinarySerachTree.prototype.insertNode = function (node, newNode) {
if (newNode.key < node.key) {
// 左叶子
if (node.left == null) {
node.left = newNode
} else {
this.insertNode(node.left, newNode)
}
} else {
// 右叶子
if (node.right == null) {
node.right = newNode
} else {
this.insertNode(node.right, newNode)
}
}
}
// 二、先序遍历
BinarySerachTree.prototype.preOrderTraversal = function (handler) {
this.preOrderTraversalNode(this.root, handler)
}
BinarySerachTree.prototype.preOrderTraversalNode = function (node, handler) {
if (node != null) {
// 1处理经过的节点
handler(node.key)
// 2处理经过的左节点
this.preOrderTraversalNode(node.left, handler)
// 3处理经过的右节点
this.preOrderTraversalNode(node.right, handler)
}
}
// 三,中序遍历
BinarySerachTree.prototype.midOrderTraversal = function (handler) {
this.midOrderTraversalNode(this.root, handler)
}
BinarySerachTree.prototype.midOrderTraversalNode = function (node, handler) {
if (node != null) {
// 1处理左
this.midOrderTraversalNode(node.left, handler)
// 2处理节点
handler(node.key)
// 3处理右
this.midOrderTraversalNode(node.right, handler)
}
}
// 四、后序遍历
BinarySerachTree.prototype.postOrderTraversal = function (handler) {
this.postOrderTraversalNode(this.root, handler)
}
BinarySerachTree.prototype.postOrderTraversalNode = function (node, handler) {
if (node != null) {
// 1处理左
this.postOrderTraversalNode(node.left, handler)
// 2处理右
this.postOrderTraversalNode(node.right, handler)
// 3处理节点
handler(node.key)
}
}
}
// 测试代码
const bst = new BinarySerachTree()
bst.insert(2)
bst.insert(1)
bst.insert(3)
// 先序,根左右
let left = ''
bst.preOrderTraversal(function (key) {
left += key + ' '
})
console.log('先序,根左右', left);
// 中序,左根右
let center = ''
bst.midOrderTraversal(function (key) {
center += key + ' '
})
console.log('中序,左根右', center);
// 后序,左右根
let right = ''
bst.midOrderTraversal(function (key) {
right += key + ' '
})
console.log('后序,左右根', right);
</script>
</body>
</html>
待续呀...