algorithm

72 阅读5分钟
统计每个元素出现的次数
//reduce实现
const arr = [1,2,3,4,5,1];
const arrReduce = arr.reduce((pre,cur)=>{
    pre[cur] = (pre[cur] || 0)+1;
    return pre;
},{})
console.log(arrReduce)
{1: 2, 2: 1, 3: 1, 4: 1, 5: 1}

// for循环实现
const arr = [1,2,3,4,5,1];
const count = {};
for (const char of arr){
    count[char] = (count[char] || 0) + 1;
}
console.log(count)
{1: 2, 2: 1, 3: 1, 4: 1, 5: 1}

// Map统计
const arr = [1,2,3,4,5,1];
const map = new Map()
arr.forEach(item=>{
    map.set(item,(map.get(item) || 0 ) + 1)
})
console.log(map)
Map(5) {1 => 2, 2 => 1, 3 => 1, 4 => 1, 5 => 1}
console.log(map.entries())
MapIterator {1 => 2, 2 => 1, 3 => 1, 4 => 1, 5 => 1}
console.log(Array.from(map.entries()))
[[1,2],[2,1],[3,1],[4,1],[5,1]]
查找最大值
//reduce实现
const arr = [1,2,3,4,5,1];
const arrReduce = arr.reduce((pre,cur)=>{
    return pre>cur?pre:cur
},0)
console.log(arrReduce)
5
//Math方法实现
const arr = [1,2,3,4,5,1];
const arrMax = Math.max.apply(null,arr)  //最大值
const arrMin = Math.min.apply(null,arr)  //最小值
console.log(arrMax,arrMin)
5 1
求对象中某个键值和
const reduceObj = [
  {name:'zs',age:10},
  {name:'ls',age:20},
  {name:'we',age:22},
];
const arrReduce = reduceObj.reduce((pre,cur)=>{
    return pre+cur.age
},0)
console.log(arrReduce)
52
数组拍平(转一维数组)
// reduce写法
const arr = [1,2,[3,[4,5]]];
const arrReduce = function(arr){
    return arr.reduce((pre,cur)=>{
        return pre.concat(Array.isArray(cur)?arrReduce(cur):cur)
    },[])
}
console.log(arrReduce(arr))
[1, 2, 3, 4, 5]
//flat写法
const arr = [1,2,[3,[4,5]]];
const arrFlat = arr.flat(Infinity)
console.log(arrFlat)
去重
//reduce 实现
const arr = [1,2,1,2];
const arrReduce = arr.reduce((pre,cur)=>{
    if(!pre.includes(cur)){
        return pre.concat(cur)
    }else{
        return pre
    }
},[])
console.log(arrReduce)
[1, 2]

//set函数实现
const arr = [1,2,1,2];
console.log(Array.from(new Set(arr)))
[1, 2]

// filter实现

const array = [1, 2, 3, 2, 1];
const uniqueArray = array.filter((item, index) => array.indexOf(item) === index);
console.log(uniqueArray); 

const data = [
  {id:1, name:2},
  {id:1, name:2},
  {id:3, name:2},
  {id:4, name:2}
];

const arrReduce = data.reduce((pre,cur)=>{
    if(!pre.some(item=>item.id === cur.id)){
        return pre.concat(cur)
    }else{
        return pre
    }
},[])
console.log(arrReduce)
[
    {
        "id": 1,
        "name": 2
    },
    {
        "id": 3,
        "name": 2
    },
    {
        "id": 4,
        "name": 2
    }
]
防抖
function debounce(fn,delay){
    let timer = null;
    return function(){
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(this)
        },delay)
    }
}
   document.getElementById('debounce').addEventListener('keyup', debounce(function () {
        console.log('input事件被触发' + Date.now())
    }, 10000))
节流
function throttle(fn,delay){
    let timeLast = 0;
    return function(){
        let timeNow = Date.now();
        if(timeNow-timeLast>delay){
            fn.apply(this);
            timeLast = timeNow
        }
    }
}

   document.onscroll = throttle(function () {
        console.log('scroll事件被触发了' + Date.now())
    }, 2000)

reduce 递归实现树=》数组
let tree = [
    { 
        id: 1, 
        name: 'Root', 
        children: [
            { 
                id: 2, 
                name: 'Child1', 
                children: [] 
            },
            { 
                id: 3, 
                name: 'Child2', 
                children: [
                    { 
                        id: 4, 
                        name: 'Grandchild1', 
                        children: [] 
                    }
                ]
            }
        ]
    }
];
function flatTreeWithReduce(nodes,parentId){
    return nodes.reduce((acc,node)=>{
        const {children,...rest} = node;
        acc.push({...rest,parentId});
        return acc.concat(flatTreeWithReduce(children,node.id))
    },[])
}
console.log(flatTreeWithReduce(tree))
[
    {
        "id": 1,
        "name": "Root"
    },
    {
        "id": 2,
        "name": "Child1",
        "parentId": 1
    },
    {
        "id": 3,
        "name": "Child2",
        "parentId": 1
    },
    {
        "id": 4,
        "name": "Grandchild1",
        "parentId": 3
    }
]
非递归方法实现树=》数组
let tree = [
    { 
        id: 1, 
        name: 'Root', 
        children: [
            { 
                id: 2, 
                name: 'Child1', 
                children: [] 
            },
            { 
                id: 3, 
                name: 'Child2', 
                children: [
                    { 
                        id: 4, 
                        name: 'Grandchild1', 
                        children: [] 
                    }
                ]
            }
        ]
    }
];
const flatTree = (tree) =>{
    let result = [];
    let quene = [];
    if(tree.length>0){
        quene = [...tree]
    }
    while(quene && quene.length>0){
        let node = quene.shift()
        result.push(node)
        if(node.children && node.children.length>0){
            quene.push(...node.children)
        }
    }
    return result
}
console.log(flatTree(tree))
[
    {
        "id": 1,
        "name": "Root",
        "children": [
            {
                "id": 2,
                "name": "Child1",
                "children": []
            },
            {
                "id": 3,
                "name": "Child2",
                "children": [
                    {
                        "id": 4,
                        "name": "Grandchild1",
                        "children": []
                    }
                ]
            }
        ]
    },
    {
        "id": 2,
        "name": "Child1",
        "children": []
    },
    {
        "id": 3,
        "name": "Child2",
        "children": [
            {
                "id": 4,
                "name": "Grandchild1",
                "children": []
            }
        ]
    },
    {
        "id": 4,
        "name": "Grandchild1",
        "children": []
    }
]

超大数相加
// 使用 BigInt
function bigIntAdd(a, b) {
    const result = BigInt(a) + BigInt(b);
    return result.toString(); // 转为字符串返回
}

// 示例
const num1 = "123456789123456789123456789123456789";
const num2 = "987654321987654321987654321987654321";
console.log(bigIntAdd(num1, num2)); 
1111111111111111111111111111111111110

// 字符串逐位相加
function largeNumberAdd(a, b) {
    let carry = 0;
    let result = [];

    // 确保 a 和 b 长度相同,不够则在前面补 0
    a = a.padStart(Math.max(a.length, b.length), '0');
    b = b.padStart(Math.max(a.length, b.length), '0');

    // 从最后一位开始逐位相加
    for (let i = a.length - 1; i >= 0; i--) {
        const sum = parseInt(a[i], 10) + parseInt(b[i], 10) + carry;
        carry = Math.floor(sum / 10); // 计算进位
        result.unshift(sum % 10);    // 取当前结果的个位
    }

    // 若最后还有进位,则加到结果的最前面
    if (carry > 0) {
        result.unshift(carry);
    }

    return result.join(''); // 返回最终结果
}

// 示例
const num1 = "123456789123456789123456789123456789";
const num2 = "987654321987654321987654321987654321";
console.log(largeNumberAdd(num1, num2)); 

1111111111111111111111111111111111110

数组交并差补集
var nums1 = [1, 2, 2, 1, 3]
var nums2 = [2, 2, 4]
// es6 交集
var a = nums1.filter(item => {
    return nums2.includes(item)
})
console.log(a)
[2,2]
// es6 并集
const union = [...new Set([...nums1,...nums2])]
console.log(union)
[1,2,3,4]
// es6 差集
const difference = nums1.filter(item=>!nums2.includes(item))
console.log(difference)
[1,1,3]
const difference = nums2.filter(item=>!nums1.includes(item))
console.log(difference)
[4]
// es6 补集 相对于定义的全集来说

闭包应用

一、 实现「一个」函数,输入一个“字符串”prefix,生成一个递增的 key,以「prefix」+ _ + 数字返回, // 注意容错和边界情况,不要用全局变量 // 1. getUniqueId('my') => my_0 // 2. getUniqueId('my') => my_1 // 3. getUniqueId('my') => my_2 // 4. getUniqueId('he') => he_0 // 5. getUniqueId('he') => he_1 // 6. getUniqueId('you') => you_0 // 7. getUniqueId('my') => my_3

function createUniqueIdGenerator() {
  // 使用一个对象来存储每个 prefix 的计数器
  const counters = {};

  // 返回一个函数,每次调用生成一个唯一 ID
  return function getUniqueId(prefix) {
    if (typeof prefix !== 'string' || prefix.trim() === '') {
      throw new Error('Prefix must be a non-empty string');
    }

    // 如果该 prefix 还没有使用过,初始化计数器为 0
    if (!(prefix in counters)) {
      counters[prefix] = 0;
    }

    // 获取当前计数器值作为 id,随后递增计数器
    const id = counters[prefix];
    counters[prefix] += 1;

    // 返回根据规则拼接的结果
    return `${prefix}_${id}`;
  };
}

// 使用示例
const getUniqueId = createUniqueIdGenerator();
console.log(getUniqueId('my')); // 输出: my_0
console.log(getUniqueId('my')); // 输出: my_1
console.log(getUniqueId('my')); // 输出: my_2
console.log(getUniqueId('he')); // 输出: he_0
console.log(getUniqueId('he')); // 输出: he_1
console.log(getUniqueId('you')); // 输出: you_0
console.log(getUniqueId('my')); // 输出: my_3

一个数组,出现最多的元素是哪个,以及出现次数是多少
function findMostFrequentElements(arr) {
  const frequencyMap = {};

  // 统计每个元素的出现次数
  for (let element of arr) {
    frequencyMap[element] = (frequencyMap[element] || 0) + 1;
  }

  // 找到最大出现次数
  const maxCount = Math.max(...Object.values(frequencyMap));

  // 找出所有出现次数为最大值的元素
  const mostFrequentElements = [];
  for (let element in frequencyMap) {
    if (frequencyMap[element] === maxCount) {
      mostFrequentElements.push(Number(element));
    }
  }

  // 返回结果
  return { elements: mostFrequentElements, count: maxCount };
}

// 示例:
const arr = [1, 2, 3, 4, 1, 2, 2, 3, 3, 3, 4, 4];
const result = findMostFrequentElements(arr);
console.log(`出现次数最多的元素是: ${result.elements}, 次数是: ${result.count}`);