问:
-
规定字符串只由'0','1'组成,若某一个字符串中,每个'0'的左边是都是'1',这种字符串就算达标。给定一个正数N,返回所有长度为N的字符串中,达标字符串的数量
-
有一个木棍数组arr,数组长度为n,第i根木棍长度为i+1。譬如arr=[1,2,3],含义为有三根棍子长度分别为1,2,3。请问最少去掉多少个木棍,可以使得任意三根木棍都不能组成三角形
-
给定一个背包容量为w和一个零食数组arr。数组中每一项的值代表零食的体积,请问有多少种放置方法可以使得零食总体积不超过背包容量
-
给定一个JobArr,其中每一项是一个岗位节点对象,岗位节点的信息是hard和money。分别代表岗位的难度和报酬(岗位是无限的,多个人可以选同一个岗位)。 再给定一个peopleArr,其中每一项代表一个人的能力值。当能力大于等于岗位难度时,则可以胜任这个工作,请返回所有人能拿到的最高报酬。
interface JobArr { hard: string, money: number } type peopleArr = number[]
解: 1.
function getAllNums(N) {
// 1个或者2个都只有一种放法
if (N === 1 || N === 2) return 1
// 对于每个0来说,都有一个1在左边
// 那么可以得到一个结论,N个长度,第0位一定是1。所以F(N)相当于求F(N-1),F(n-1)有两种放置方法,
// 第0位放0或者放1。
// 放1就是该情况下的F(N-1),如果放0,则后续是F(N-2)
// 假设N = 8,有7位数自由选择。
// 1 1|0 ? ? ? ? ? ?
// 当第1位等于1的时候,后续自由选择
// 当第1位等于0的时候,后一位固定只能选1.所以是再加上F(6)的情况
return getAllNums(N - 1) + getAllNums(N - 2)
}
function getMinNum(arr) {
const N = arr.length
// 形成斐波那契数即可
// 假设是17根棍子。斐波那契数是前两项之和。刚好满足第三边不大于两边和的最小情况。
// [1,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17]
// 斐波那契数
let fb = 0
// 斐波那契数的个数
let fbNums = 0
let one = 1
let two = 1
// 生成斐波那契数
while (fb + res[res.length - 1] <= N) {
fb = one + two
one = two
two = fb
fbNums++
}
return N - fbNums
}
function getAllSumDp(arr, w) {
const dp = []
for (let i = 0; i <= arr.length; i++) {
dp[i] = []
}
for (let i = arr.length; i >= 0; i--) {
for (let j = 0; j <= w; j++) {
if (i === arr.length) {
dp[i][j] = 1
continue
}
dp[i][j] = dp[i + 1][j] + (dp[i + 1][j + arr[i]] ?? 0)
}
}
let sum = 0
for (let i = 0; i < dp[0].length;i++) {
sum += dp[0][i]
}
return sum
}
- 岗位按难度升序,同难度按酬劳降序,只保留同难度的第一个元素。然后再剔除掉难度增加酬劳不加的元素。最后结果就是难度升序并且酬劳也升序的job数组。每一个人只需要倒序遍历job数组,能力够了直接拿,否则就看下一项。
function getAllMax(jobArr, peopleArr) {
// 给岗位按两种条件排序
jobArr.sort((a, b) => {
return a.hard - b.hard || b.money - a.money
})
// 只拿同hard的情况下第一个数据(即同难度下报酬最高的)
const hardSet = new Set()
jobArr = jobArr.filter((item, idx, arr) => {
if (!hardSet.has(item.hard)) {
hardSet.add(item.hard)
return true
}
return false
})
// 难度较低岗位的薪酬
let preMoney = 0
// 剔除掉难度增加,报酬不加的
jobArr = jobArr.filter((item) => {
if (item.money > preMoney) {
preMoney = item.money
return true
}
return false
})
const res = []
// 给各位选手按能力排序
peopleArr.sort((a,b) => a - b)
// 从哪个工作开始看
let idx = jobArr.length - 1
// 首先倒序遍历。能力强的选手先看工作。看工作也是倒序看。也就是先看薪酬高的工作,满足要求直接拿下
// 然后轮到下一个选手,直接从上一个选手看到的位置开始看,因为这个选手不可能比上一个选手能力强,所以无须再看一遍工作
// 这样可以从暴力遍历的O(n*m)优化至O(n+m)
for (let i = peopleArr.length - 1; i >= 0; i--) {
for (let j = idx; j >= 0; j--) {
// 如果当前选手能力大于等于工作的难度,直接拿下
if (peopleArr[i] >= jobArr[j].hard) {
res.unshift(jobArr[j].money)
// idx重新赋值
idx = j
break
}
// 当走到最后一个工作,表明他拿不到工作了,结果数组加个0薪酬
if (j === 0) {
res.unshift(0)
}
}
}
return res
}