日常刷题0x8之未出新手村

118 阅读2分钟

如果不小心网友来到了这里请网友自动飘走,浪费你们时间表示歉意。该系列博客的目的是:想作为自律工具和朋友一起每天刷几道题作为打卡督促的功能,没有什么可参考学习的东西,也不是刷博客量充大佬的目的

题号:139
//bfs超时
var wordBreak = function (s, wordDict) {
    let path = []
    let helper = (subStr) => {
        for (let i = 0; i < wordDict.length; i++) {
            let word = wordDict[i]
            if (subStr.startsWith(word)) {
                path.push(word)
                if (helper(subStr.slice(word.length))) {
                    return true
                }
                path.pop()
            }
        }
        if (path.join("") == s) {
            return true
        }
        return false
    }
    return helper(s)
};

//动态规划
var wordBreak = function (s, wordDict) {
    //s中到第i个元素的串长是否符合题意
    //状态table初始化多一个看需要如果不加1那么就需要在下面额外判断临界条件
    let dptable = new Array(s.length + 1).fill(false)
    dptable[0] = true
    for (let i = 1; i <= s.length; i++) {
        for (let j = 0; j < wordDict.length; j++) {
            const word = wordDict[j]
            const stri = s.slice(0, i)
            //到i的字串是否有以word结尾的情况如果是,要判断除了这个单词之后
            //的串是否符合题意,二者都符合题意那么可以判定到第i个字符的串此时
            //符合题意
            if (stri.endsWith(word) && dptable[i - word.length]) {
                dptable[i] = true
                break
            }
        }
    }
    return dptable.pop()
};
题号:347
//桶排序
var topKFrequent = function (nums, k) {
    let map = new Map()
    //遍历记录数字出现频率
    nums.forEach((item) => {
        if (map.has(item)) {
            let count = map.get(item)
            count++
            map.set(item, count)
        } else {
            map.set(item, 1)
        }
    });
    //动态桶,下标为数字出现频率
    //下标不一定连续比如下标1,3,5,6有值
    //2,4,7等为undefined
    let buckets = []
    map.forEach((value, key) => {
        //value为出现频率
        let arr = buckets[value]
        if (arr == undefined) {
            arr = []
            buckets[value] = arr
        }
        if (!arr.includes(key)) {
            arr.push(key)
        }
    });
    //倒叙遍历桶
    let result = []
    for (let i = buckets.length - 1; i > 0; i--) {
        const arr = buckets[i];
        if (arr != undefined) {
            //把对应下标里的元素(如果有的话全部加入结果数组)
            result.push(...arr)
            k -= arr.length
        }
        if (k == 0) {
            break
        }
    }
    return result
};
//由于js没有原生支持的堆排序内置库
//自己实现大顶堆
var topKFrequent = function (nums, k) {
    let map = new Map()
    //统计数字出现频率
    nums.forEach((item) => {
        if (map.has(item)) {
            let count = map.get(item)
            count++
            map.set(item, count)
        } else {
            map.set(item, 1)
        }
    });
    let newArr = []
    map.forEach((value, key) => {
        let obj = {}
        obj.key = key
        obj.value = value
        newArr.push(obj)
    });
    let buildheap = (n, end) => {
        //从最后一个非叶子节点开始
        //最后一个非叶子节点下标为nums.length/2 -1
        let length = end + 1
        for (let i = Math.floor(length / 2) - 1; i >= 0; i--) {
            //节点i的左孩子右孩子在数组中下标位置
            const left = i * 2 + 1, right = i * 2 + 2
            //right有可能没有,只有左的情况,要判断
            if (right > (length - 1)) {
                //此时没有右孩子
                if (n[i].value < n[left].value) {
                    //交换
                    let tmp = n[i]
                    n[i] = n[left]
                    n[left] = tmp
                }
            } else {
                //此时左右孩子都有
                let max = left
                if (n[left].value < n[right].value) {
                    max = right
                }
                if (n[i].value < n[max].value) {
                    //交换
                    let tmp = n[i]
                    n[i] = n[max]
                    n[max] = tmp
                }
            }
        }
    }
    let end = newArr.length - 1
    let result = []
    while (k != 0) {
        buildheap(newArr, end)
        result.push(newArr[0].key)
        //把顶交换到尾去
        let tmp = newArr[0]
        newArr[0] = newArr[end]
        newArr[end] = tmp
        k--
        end--
    }
    return result
};