算法学习记录(四十)

155 阅读1分钟

问:

  1. 给定一个整数数组,长度为n。数组的每个元素都在1~ n的范围内。对于1~ n范围内的整数,其中有些重复有些没有。请找到没出现过的整数。
  2. 假设有一个主播初始人气值start,目标人气值target。某观众可以给主播人气施加影响的操作有:①点赞,花费a元,人气+2;②送礼,花费b元,人气*2;③私聊,花费c元,人气-2。start和end均为偶数。请问最少花费多少刚好达成target。

解: 1.

function getMaxSubsequence(arr) {
    // 对于i位置上来说,需要的是i+1这个数。
    // 所以遍历到i的时候,如果当前值不正确,就将这个数弹出去找它应该去的位置。
    // 如果那个位置上的数也不正确,就取代之,并弹出不正确数。
    // 如果那个位置上的数正确。就放弃本轮操作。
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] !== i + 1) {
            let temp = arr[i]
            arr[i] = null
            while (temp) {
                // temp对应位置上的值不正确
                if (arr[temp - 1] !== temp) {
                    const cur = arr[temp - 1]
                    arr[temp - 1] = temp
                    temp = cur
                } else {
                    break
                }
            }
        }
    }
    const res = []
    arr.forEach((item,idx) => {
        if (!item) res.push(idx+1)
    })
    return res
}
// 暴力递归
function getMinSpend(start, end, a, b, c) {
    // 一般解: 只点赞达到目标人气的花费,也就是说在递归过程中,超过这个花费的路线没有必要考虑
    const commonMoney = ((end - start) / 2) * a
    // 人气超过两倍也是没有必要的
    const maxHot = end * 2
    function getRes(curHot, curMoney) {
        // 由于这个递归函数base case无法停止递归
        // 所以需要根据业务自己规定base case。
        if (curHot === end) {
            return curMoney
        }
        // 热度超过目标值两倍后,或者降到初始人气以下直接认定为无效解
        if (curHot > maxHot || curHot < start) {
            return Infinity
        }
        // 花费超过一般解后,直接认定为无效解
        if (curMoney > commonMoney) {
            return Infinity
        }
        return Math.min(getRes(curHot + 2, curMoney + a),
            getRes(curHot * 2, curMoney + b),
            getRes(curHot - 2, curMoney + c))
    }
    return getRes(start, 0)
}
// dp表想不出来