js算法真题

179 阅读1分钟

合唱队

题目:给定人数,以及每个人身高,在不打乱队形的前提下,以最少出列人数组成合唱队(先升后降,最高不能为头尾)。

解题思路:动态规划法

let num = 8;
let heightArr = '186 186 150 200 160 130 197 200';
// 计算从0 - i元素做升序,最多可以有几个元素
function MaxList(arr) {
    const dp = [];
    for (let i = 0; i < arr.length; i++) {
        dp[i] = 1; // 默认一个元素组成队列
        for (let j = 0; j < i; j++) {
            if (arr[j] < arr[i]) {
                dp[i] = Math.max(dp[i], dp[j]+1); // arr[j] < arr[i] 意味着dp[i]至少比dp[j]大于1
            }
        }
    }
    return dp;
}

const arr = heightArr.split(' ');
let dp1 = MaxList(arr);
// 反转的方法计算降序
let dp2 = MaxList(arr.reverse()).reverse();
let max = 0;
// 遍历dp数组,求出每个位置上dp1和dp2的值,由于自身参与了两次计算,因此还需要再
// 减去1,减掉自身1次
for (let i = 0; i < dp1.length; i++){
    max = Math.max(max, dp1[i] + dp2[i]-1);
}
// 题目要求的输出是需要多少位同学出列,因此用总的同学人数减去符合的合唱队列的同学人数
// 得到的结果就是要出列的同学人数。
console.log(num - max);

字符串排序

给定字符串按照从小到大排序,不区分大小写,非字母保持原来的位置。

let testStr = 'A Famous Saying: Much Ado About Nothing (2012/8).'

function isLetter(str) {
    let reg = /[a-z]/gi;
    return reg.test(str);
}
let tokens = testStr.split(''); // 原字符串数组
let arr = testStr
    .match(/[a-z]+/gi)
    .join("")
    .split(""); // 清除非字母,得到纯字符串数组
arr.sort(function (a, b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    return a < b ? -1 : 0;
}); // 升序排序
tokens.forEach((item, index) => { // 把原数组中字母替换为排序后的字母
    if (isLetter(item)) {
        tokens[index] = arr[0];
        arr.shift();
    }
});
let result = tokens.join('') // 数组转为字符串
console.log(result); // A aaAAbc dFgghh: iimM nNn oooos Sttuuuy (2012/8).