力扣 146. LRU 缓存
https://leetcode-cn.com/problems/lru-cache/
第一种方法 把键值对存放在一个数组中,每次查找喝存放需遍历数组
get:
- 通过键名在数组中查找
- 如不存在,返回-1
- 如存在,把元素放到数组首位,同时返回键值
put:
- 通过键名在数组中查找
- 如存在,删除查找到的数组元素
- 如不存在,判断当前数组容量是否大于等于限定容量,如大于等于则删除数组最后一个元素
- 最后统一都在数组首位添加输入的数组元素
但get和put的平均时间复杂度在O(n)
interface Cache {
key:number
value:number
}
class LRUCache {
capacity:number
cache:Cache[]
constructor(capacity:number){
this.capacity=capacity
this.cache=[]
}
get(key:number){
let index = this.cache.findIndex((item)=>{
return item.key=== key
})
if (index===-1)
return index
let result:Cache=this.cache[index]
this.cache.splice(index,1)
this.cache.unshift({key:result.key,value:result.value})
return result.value
}
put(key:number,value:number){
let index = this.cache.findIndex((item)=>{
return item.key=== key
})
if (index!==-1)
{
this.cache.splice(index,1)
}
else if(this.cache.length>=this.capacity)
{
this.cache.pop()
}
this.cache.unshift({key,value})
}
第二种方法使用map
class LRUCache {
capacity: number
cache: Map<number,number>
constructor(capacity: number) {
this.capacity = capacity
this.cache = new Map()
}
get(key: number): number {
//不存在
if (!this.cache.has(key))
return -1
//存在就把值提前
let value = this.cache.get(key)
this.cache.delete(key)
this.cache.set(key, value)
return value
}
put(key: number, value: number): void {
//存在就删除当前键值对(最后插入)
if (this.cache.has(key)) {
this.cache.delete(key)
}
//判断map对象容器是否大于等于限定容器大小,大于等于则删除首位键值对
else if (this.cache.size >= this.capacity) {
this.cache.delete(this.cache.keys().next().value)
}
//插入键值对
this.cache.set(key, value)
}
}
二叉树广度深度
kmp算法
KMP (Knuth-Morris-Pratt) 字符串查找算法可在一个字符串 S 内查找一个词 P 的出现位置。 一个词在不匹配时本身就包含足够的信息来确定下一个匹配可能的开始位置,此算法利用这一特性以避免重新检查先前匹配的字符。
function kmp(str1:string,str2:string):number
{
let next =new Array(str2.length)
next[0]=0
//构造next数组 判断每一位元素及左侧字符串首末最大公共子串的长度
for(let i:number=1,j:number=0;i<str2.length;i++)
{
//不匹配左移
while(j>0&&str2[i]!==str2[j]){
j=next[j-1]
}
//匹配j++ 右移
if(str2[i]===str2[j]) ++j
next[i]=j
}
console.log(next)
for(let i:number=0,j:number=0;i<str1.length;i++)
{
//不匹配 左移
while(j>0&&str1[i]!==str2[j]){
j=next[j-1]
}
//匹配 右移
if(str1[i]===str2[j]) j++
if(j===str2.length-1) return i-j+1
}
return -1
console.log(next)
}
console.log(kmp('asdasdasdsadqqq','sad'))
参考
https://www.cnblogs.com/honey-cat/p/15259629.html
判断回文字符串
第一种方法
//i递增到字符串长度一般下取整
function ishuiwen(str:string):boolean{
for(let i=0,j=str.length-1;i<Math.floor(str.length/2);i++,j--)
{
if(str[i]!==str[j])
return false
}
return true
}
console.log(ishuiwen('abbbbab'))
第二种方法
function ishuiwen(str:string):string{
return str.split("").reverse().join("")
}
console.log(ishuiwen('abbbbab'))
正则表达式,千分位分隔符
function thousand(num) {
return (num+"").replace(/\d(?=(\d{3})+$)/g, "$&,")
}
console.log(thousand(123456789));
正则表达式思维导图:
参考
https://www.cnblogs.com/lnlvinso/p/10467941.html
斐波那契数列
递归1,但这里当n=5时 fibonacci(5)=fibonacci(4)+fibonacci(3) fibonacci(4)=fibonacci(3)+fibonacci(2) fibonacci(4)重复
function fibonacci(n:number):number{
if(n===1||n===2)
{
return 1
}
return fibonacci(n-1)+fibonacci(n-2)
}
console.log(fibonacci(6))
递归2
增加参数来消除重复
function fibonacci(n:number,v1:number=1,v2:number=1):number{
if (n==0)
return 0
if(n===1)
return v1
if(n===2)
return v2
return fibonacci(n-1,v2,v2+v1)
}
console.log(fibonacci(6))
1.使用for循环
function fibonacci(n:number):number{
let sum:number=0
let num1=1;
let num2=1;
//前两位已给出
for(let i=3;i<=n;i++)
{
let temple= num2
num2=num2+num1
num1=temple
}
return num2
}
console.log(fibonacci(6))
2.for 循环 使用结构赋值
function fibonacci(n:number):number{
let sum:number=0
let num1=1;
let num2=1;
for(let i=3;i<=n;i++)
{
[num1,num2]=[num2,num2+num1]
}
return num2
}
console.log(fibonacci(6))
参考
https://www.cnblogs.com/superlizhao/p/11603158.html
数组去重
function removeDuplication1(arr:number[]):number[]{
let newArr=[]
for(let i=0;i<arr.length;i++)
{
if(!newArr.includes(arr[i]))
newArr.push(arr[i])
}
return newArr
}
function removeDuplication2(arr:number[]):number[]{
for(let i=0;i<arr.length;i++)
{
let num1=arr[i]
for(let j=i+1;j<arr.length;j++)
{
if(num1===arr[j])
{
arr.splice(j,1)
//由于前面删除了数组中的一个元素,从而j需要减一
j--
}
}
}
return arr
}
//使用对象
function removeDuplication3(arr:number[]):number[]{
let obj={}
for(let i=0;i<arr.length;i++)
{
let item =arr[i]
if(obj[item])
{
arr[i]=arr[arr.length-1]
arr.pop()
continue
}
obj[item]=item
}
return arr
}
//使用set对象
function removeDuplication4(arr:number[]):number[]{
let newArr=new Set(arr)
return [...arr]
}
//
let arr=[1,2,3,1,1,2,3,4,5,5,2,3,1]
console.log(removeDuplication1(arr))
console.log(removeDuplication2(arr))
console.log(removeDuplication3(arr))
console.log(removeDuplication4(arr))
获取字符串中第一个只出现一次的值
使用map对象
let str= 'asdasdasdasdl'
function firstShow(str){
let hashMap =new Map()
for (let i = 0 ;i< str.length ;i++){
if(!hashMap.has(str[i])) hashMap.set(str[i],1)
else hashMap.set(str[i],hashMap.get(str[i])+1)
}
let result =null
hashMap.forEach((value,key)=>{
if(hashMap.get(key) === 1) {
result = key
}
})
return result
}
console.log(firstShow(str))
使用普通对象
var str = 'eerrtreefffp'
function fun(str){
var arr=[],arr1=[],obj={}
arr=str.split('')
for(var i=0;i<arr.length;i++){
!obj[arr[i]] ? obj[arr[i]]=1 : obj[arr[i]]++
}
for(var i in obj){
if(obj[i]==1){
arr1.push(i)
}
}
console.log(arr1[0])
}
fun(str)
排序算法汇总
冒泡算法排序
//冒泡排序从大到小
function bubbleSort(arr:number[]):number[]{
for(let i:number=0;i<arr.length;i++)
{
for(let j:number=0;j<<arr.length-i;j++)
{
if(arr[j+1]>arr[j])
{
let temple:number=arr[j]
arr[j]=arr[j+1]
arr[j+1]=temple
}
}
}
return arr
}
let arr:number[]=[5,1,2,3,4,5,6,1,21,3,4]
console.log(bubbleSort(arr))
选择排序
//选择排序从大到小
function selectSort(arr:number[]):number[]{
for(let i:number=0;i<arr.length;i++)
{
let maxIndex=i
for(let j:number=i+1;j<arr.length;j++)
{
if(arr[j]>arr[maxIndex])
{
maxIndex=j
}
}
let temple=arr[i]
arr[i]=arr[maxIndex]
arr[maxIndex]=temple
}
return arr
}
let arr:number[]=[2131,213,123,4,12,3,12,3,12,33,12]
console.log(selectSort(arr))
快速排序
由小到大
/*
快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。
然后递归调用,在两边都实行快速排序。
*/
// 左右各一列,左边放小的,右面放大的;不停的划分的过程
function quickSort(arr:number[]):number[]{
if(arr.length<=1)
return arr
let middle=Math.floor(arr.length/2)
let left:number[]= []
let right:number[] = []
//删除中间值,splice返回删除的数组
let middleData=arr.splice(middle,1)[0]
for(let i:number=0;i<arr.length;i++)
{
if(arr[i]<middleData)
{
left.push(arr[i])
}
else{
right.push(arr[i])
}
}
return quickSort(left).concat([middleData],quickSort(right))
}
let arr:number[]=[124,123,123,4,132,123,12,3,123,123,4,23,1,54]
console.log(quickSort(arr))
插入排序
//插入排序从小到大
function insertSort(arr:number[]):number[]{
//默认第一个为排好序的
for(let i:number=1;i<arr.length;i++)
{
// 如果后面的小于前面的直接把后面的插到前边正确的位置
if(arr[i]<arr[i-1])
{
let el =arr[i]
arr[i]=arr[i-1]
let j:number=i-1;
//从右向左寻找比它小的数,找的途中把比它大的数往右移一位
while(j>=0&&arr[j]>el)
{
arr[j]=arr[j-1]
j--;
}
arr[j+1]=el
}
}
return arr
}
let arr:number[] =[1,23,3,4,12,3,1,3,2,3,123]
console.log(insertSort(arr))
从小到大
//插入排序由大到小
let insertSort=function(arr:number[]){
//默认第一个元素为有序
for (let i=1;i<arr.length;i++)
{
//从右到左寻找该元素位置
let cur =arr[i]
let j:number = i
//当前值与左边元素值进行对比,如左边元素小于当前值往后进一位,直到找到比它大的值
while(j>=1&&arr[j-1]<cur)
{
arr[j]=arr[j-1]
j--
}
arr[j]=cur
}
return arr
}
let arr:number[]=[1,123,123,3,123,123,123,4,3,4,5,234,23,4]
console.log(insertSort(arr))
希尔排序
从小到大
// 希尔排序---升级的插入排序 从小到大
function shellSort(arr:number[]):number[]{
//划分成几组
for(let gap = Math.floor(arr.length/2);gap>0;gap=Math.floor(gap/2))
{
//每组进行插入排序
for(let i:number=gap;i<arr.length;i++)
{
let cur:number=arr[i]
let j:number=i;
while(cur<arr[j-gap]&&j-gap>=0)
{
arr[j]=arr[j-gap]
j-=gap
}
arr[j]=cur
}
}
return arr
}
let arr:number[] =[1,23,3,4,12,3,1,3,2,3,123]
console.log(shellSort(arr))
从大到小
//希尔排序
function shellSort(arr:number[]){
for(let gap=Math.floor(arr.length/2);gap>0;gap=Math.floor(gap/2))
{
for(let i:number=gap;i<arr.length;i++)
{
let cur:number =arr[i]
let j:number=i
while(cur>arr[j-gap]&&j-gap>=0)
{
arr[j]=arr[j-gap]
j-=gap
}
arr[j]=cur
}
}
return arr
}
let arr:number[]=[1,123,123,3,123,123,123,4,3,4,5,234,23,4]
console.log(shellSort(arr))
归并排序
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
平均复杂度O(nlogn)
function mergeSort(arr:number[]){
if(arr.length<2)
return arr
//分
let middle = Math.floor(arr.length/2)
let left=arr.slice(0,middle)
let right=arr.slice(middle)
return merge(mergeSort(left), mergeSort(right))
}
//治
function merge(left,right){
let result=[]
console.log(right)
while(left.length>0&&right.length>0)
{
if(left[0]>=right[0])
{
result.push(right.shift())
}
else{
result.push(left.shift())
}
}
while(left.length)
{
result.push(left.shift())
}
while(right.length)
{
result.push(right.shift())
}
console.log(result)
return result
}
let arr:number[]=[1,123,123,3,123,123,123,4,3,4,5,234,23,4]
console.log(mergeSort(arr))
从大到小
//归并排序 从大到小
function mergeSort(arr:number[]){
if(arr.length<=1)
return arr
let middle=Math.floor(arr.length/2)
let left:number[] =arr.slice(0,middle)
let right:number[] =arr.slice(middle)
return merge(mergeSort(left),mergeSort(right))
}
//治
function merge(left:number[],right:number[]){
let result:number[]=[]
while(left.length>0&&right.length)
{
if(left[0]>right[0])
result.push(left.shift())
else
result.push(right.shift())
}
// while(left.length>0)
// {
// result.push(left.shift())
// }
// while(right.length)
// {
// result.push(right.shift())
// }
if(left.length>0)
return result.concat(left)
else if(right.length>0)
return result.concat(right)
return result
}
let arr:number[]=[1,123,123,3,123,123,123,4,3,4,5,234,23,4]
console.log(mergeSort(arr))