问:
- 给定一个有序正数数组,其中每一项代表它在X轴上的坐标。现在有一个长度为L的绳子,请问它最多可以覆盖几个项
- 给定一个正数N,请用6和8这两种数拼出来,若能拼出来,返回最少用几个数,若不能则返回-1。例:N = 24,可以用4个6或者3个8。那么最少用3个数
- 有先手和后手两个动物吃草,每次只能按照4的次方来吃(1,4,16,64,...)。给一个草堆大小为N,在谁的回合把这个草吃完,谁就获胜。请返回获胜的动物
- 给一个字符串,包含R,G两种字符,可以把R,G互相转换,若要变成左侧都是G,右侧都是R,最少转换几个字符。例:GRGRGRR 转换结果为GGGGGRR,最少转换2个字符;例2:RRRRR,最少转换0个字符
解:
- 滑动窗口,判断窗口差值是否小于等于L,是的话就计算一次最大值,然后窗口右扩,否则窗口左收
function getMaxItem(arr, L) {
let left = 0
let right = 0
let max = 0
while (right < arr.length) {
if (left > right) right = left
if (l >= arr[right] - arr[left]) {
max = Math.max(max, right - left + 1)
right++
} else {
left++
}
}
return max
}
- 贪心策略,先尽可能多的要8,剩余的数用6来配,若配不出来,就依次减少8的数量。
function getMinNums(N) {
let eightNums = ~~(N / 8)
let sixNums = 0
while (eightNums >= 0) {
const need = N - eightNums * 8
// 超过24的值不必再讨论,因为24是6,8的最小公倍数,24的部分应该被8处理,而不是现在被6处理
if (need > 24) return -1
if (need % 6 === 0) {
sixNums = need / 6
return sixNums + eightNums
} else {
eightNums--
}
}
return -1
}
- 先手动物从1份开始吃,递归判断能否赢,不能就吃4份,16份,64份。。。若没有赢的情况,那就是后手赢
function getWinAnimal(N) {
function getRes(need) {
if (need === 0) {
return '后手'
}
for (let i = 0; 4 ** i <= need; i++) {
// 如果递归告诉我后手赢了,那就意味着先手赢了(因为此时我已经吃过一轮,变成了后手)
if (getRes(need - 4 ** i) === '后手') {
return '先手'
}
}
// 没有赢的情况,就是后手赢
return '后手'
}
return getRes(N)
}
// dp解
function getWinAnimal(N) {
const dp = ['后']
for (let i = 1; i <= N; i++) {
dp[i] = '后'
for (let j = 0; 4 ** j <= i; j++) {
if (dp[i - 4 ** j] === '后') {
dp[i] = '先'
}
}
}
return dp[N]
}
function getMinChangeChar(str) {
let minNum = Infinity
// 暴力解法中每次都要判断左右分别有多少个R和G
// 所以预处理,提前计算好每个位置的数据
const preLeftArr = []
const preRightArr = []
for (let i = 0;i<str.length;i++){
// 判断[0,i]范围内有多少个R
if (str[i] === 'R') {
preLeftArr[i] = (preLeftArr[i-1] ?? 0) + 1
} else {
preLeftArr[i] = preLeftArr[i-1] ?? 0
}
}
for (let i = str.length -1;i>=0;i--){
// 判断[i,N]范围内有多少个G
if (str[i] === 'G') {
preRightArr[i] = (preRightArr[i+1] ?? 0) + 1
} else {
preRightArr[i] = preRightArr[i+1] ?? 0
}
}
// left区域的分界线从-1开始,即全部都当做右区域
for (let i = -1; i <= str.length; i++) {
let tempNum = 0
// 全部都当做右区域
if (i === -1) {
tempNum = preRightArr[0]
continue
}
if (i === str.length) {
tempNum = preLeftArr[i-1]
continue
}
tempNum = preLeftArr[i] + (preRightArr[i+1] ?? 0);
minNum = Math.min(tempNum, minNum)
}
return minNum
}