算法题--华为od考试(日志排序、最长的顺子、求最多可以派出多少支团队)

目录

日志排序

题目描述

输入描述

输出描述

示例1

输入

输出

示例2

输入

输出

示例3

输入

输出

说明

解析

答案

最长的顺子

题目描述

输入描述

输出描述

示例1

输入

输出

示例2

输入

输出

说明

解析

答案

求最多可以派出多少支团队

题目描述

输入描述

输出描述

说明

解析

答案


日志排序

考察排序。

题目描述

运维工程师采集到某产品现网运行一天产生的日志N条,现需根据日志时间按时间先后顺序对日志进行排序。

日志时间格式为:

H:M:S.N

H表示小时(0-23),M表示分钟(0-59),S表示秒(0-59),N表示毫秒(0-999)

时间可能并没有补齐,也就是说:01:01:01.001,也可能表示为1:1:1.1,

输入描述

第一行输入一个整数N,表示日志条数,1<=N<=100000

接下来N行输入N个时间

输出描述

按时间升序排序之后的时间

如果有两个时间表示的时间相同,则保持输入顺序

示例1

输入

2

01:41:8.9

1:1:09.211

输出

1:1:09.211

01:41:8.9

示例2

输入

3

23:41:08.023

1:1:09.211

08:01:22.0

输出

1:1:09.211

08:01:22.0

23:41:08.023

示例3

输入

2

22:41:08.023

22:41:08.23

输出

22:41:08.023

22:41:08.23

说明

两个时间表示的时间相同,保持输入顺序

解析

需要比较每一位上的大小,从小到大排序,可以通过将冒号去掉,得到的相同位数的数字,不足个数的数需要补充0,最后拼接成一个数,进行比较大小。

由于每次都要判断位数补0比较麻烦,这里可以通过对不同位上的数乘以不同大小数后加起来达到相同的目的,保证以前位数的大小优先进行排序

答案

// 不需要以':'分隔后每个比较
// 注意相等的情况是不需要换位置的
function logSort(n, ...logs) {
    logs = logs.map(v => ({
        v,
        number: v.split(':').map((value, index) => {
            // 对不同位上的数乘以不同大小的数,分别是10^9,10^6,10^3,保证以前位数的大小优先排序
            return value * Math.pow(10, 3 * (3 - index))
        }).reduce((t, v) => t + v)
    }))
    logs.sort((a, b) => a.number - b.number)
    return logs.map(v => v.v)
}
console.log(logSort(2, '01:41:8.9', '1:1:09.211'))
console.log(logSort(3, '23:41:08.023', '1:1:09.211', '08:01:22.0'))
console.log(logSort(2, '22:41:08.023', '22:41:08.23'))

最长的顺子

考察hash算法和转化思想。

题目描述

斗地主Q起源于湖北十堰房县,据说是—位叫吴修全的年轻人根据当地流行的扑克玩法"跑得快"改编的,如今已风靡整个中国,并流行于 互联网上。

 牌型:单顺,又称顺子,最少5张牌,最多12张牌(3...A)不能有2,也不能有大小王,不计花色。 例如:3-4-5-6-7-8,7-8-9-10-J-Q,3-4-5-6-7-8-9-10-J-Q-K-A 可用的牌 3<4<5<6<7<8<9<10<j<Q<K<A<2<B(小王)<C(大王),每种牌除大小王外有四种花色 (共有13x4+2张牌)

输入: 1.手上有的牌 2.已经出过的牌(包括对手出的和自己出的牌)

输出: 对手可能构成的最长的顺子(如果有相同长度的顺子,输出牌面最大的那一个),如果无法构成顺子,则输出 NO-CHAIN。

输入描述

输入的第一行为当前手中的牌

输入的第二行为已经出过的牌

输出描述

最长的顺子

示例1

输入

3-3-3-3-4-4-5-5-6-7-8-9-10-J-Q-K-A

4-5-6-7-8-8-8

输出

9-10-J-Q-K-A

示例2

输入

3-3-3-3-8-8-8-8

K-K-K-K

输出

NO-CHAIN

说明

剩余的牌无法构成顺子

解析

方法一:算出用完了的牌之差是否大于等于5,大于5表示能取到顺子,获取能取到顺子的组合,然后对顺子的长度从大到小进行排序,取出长度最大的。

方法二:对'3-4-5-6-7-8-9-10-J-Q-K-A'字符串中用完的数字替换为x,再用x去分割,得到多个连续的字符串,对每个字符串进行判断是否满足要求(用-分割后判断数组长度是否大于4),最后在满足要求的字符串中筛选出最长的。

答案

// 方法一
// 需要处理到不参与顺子的牌2,B,C
function longSequence(myCard, useCard) {
    let obj = {}
    let noUse = []
    let hash = {
        3: 3,
        4: 4,
        5: 5,
        6: 6,
        7: 7,
        8: 8,
        9: 9,
        10: 10,
        'J': 11,
        'Q': 12,
        'K': 13,
        'A': 14,
        11: 'J',
        12: 'Q',
        13: 'K',
        14: 'A',
    }
    // 获取哪些牌用完了
    let tmp = [...myCard.split('-'), ...useCard.split('-')].forEach(v => {
        v = hash[v]
        if (!v) {
            return
        }
        if (obj[v]) {
            obj[v]++
            if (obj[v] === 4) {
                noUse.push(v)
            }
        } else {
            obj[v] = 1
        }
    })
    // 用完了的牌从小到大排序
    noUse.sort((a, b) => a - b)
    // 获取哪些可以组成顺子
    let sequences = []
    for (let i = -1, j = i + 1; i < noUse.length; i++, j++) {
        // start表示用完了,所以这里要写3-1 = 2 
        let start = i === -1 ? 2 : noUse[i] 
        // end表示用完了,所以这里要写14+1 = 15
        let end = j === noUse.length ? 15 : noUse[j]
        if (end - start > 5) {
            sequences.push([start + 1, end - 1])
        }
    }
    if (!sequences.length) {
        return 'NO-CHAIN'
    }
    // 上面是按从小到大的顺序取的顺子,所以这里只用对长度进行小到大排序取最后一个
    let res = sequences.sort((a, b) => (a[1] - a[0]) - (b[1] - b[0])).pop()
    tmp = []
    for (let i = res[0]; i <= res[1]; i++) {
        tmp.push(hash[i])
    }
    return tmp.join('-')
}
// 方法二
function longSequence(myCard, useCard) {
    let str = '3-4-5-6-7-8-9-10-J-Q-K-A'
    let obj = {}
    let noUse = []
    // 获取哪些牌用完了
    let tmp = [...myCard.split('-'), ...useCard.split('-')].forEach(v => {
        if (obj[v]) {
            obj[v]++
            if (obj[v] === 4) {
                noUse.push(v)
            }
        } else {
            obj[v] = 1
        }
    })
    // 用完了的牌替换为x
    noUse.forEach(v=>{
        str=str.replace(v,'x')
    })
    let res = []
    str.split('x').forEach(v=>{
        // 去除-和空串,获取数字
        let arr = v.split('-').filter(value=>value)
        // 获取哪些字符串可以组成顺子
        if(arr.length>4){
            res.push(arr)
        }
    })
    if (!res.length) {
        return 'NO-CHAIN'
    }
    // 先按相同大小,大的顺子在前排序
    res.sort((a,b)=>(b[0]-a[0]))
    // 再按长的顺子在前排序
    res.sort((a,b)=>b.length-a.length)
    return res[0].join('-')
}
console.log(longSequence('3-3-3-3-4-4-5-5-6-7-8-9-10-J-Q-K-A', '4-5-6-7-8-8-8'))
console.log(longSequence('3-3-3-3-8-8-8-8', 'K-K-K-K'))

求最多可以派出多少支团队

考察双指针

题目描述

用数组代表每个人的能力,一个比赛活动要求参赛团队的最低能力值为N,每个团队可以由1人或2人组成,且1个人只能参加1个团队,请计算出最多可以派出多少支符合要求的团队?

输入描述

5

3 1 5 7 9

8

第一行数组代表总人数,范围[1,500000]

第二行数组代表每个人的能力,每个元素的取值范围[1,500000],数组的大小范围[1,500000] 第三行数值为团队要求的最低能力值,范围[1,500000]

输出描述

最多可以派出的团队数量

说明

3,5组成一队,1,7组成一队,9自己一个队,故输出3

解析

首先将可以单独成一对的拿出来,再对队伍进行从小到大的排序,然后采用双指针遍历从两端开始遍历取出可以组合成一队的。

答案

// 求最多可以派出多少支团队
function maxGroup(num, groups, min) {
    let sum = groups.filter(v => v >= min).length
    groups = groups.filter(v => v < min).sort((a, b) => a - b)
    let i = 0, j = groups.length - 1
    while (i < j) {
        if (groups[j] + groups[i] >= min) {
            sum++
            j--
            i++
        } else {
            i++
        }
    }
    return sum
}
console.log(maxGroup(5, [3, 1, 5, 7, 9], 8))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值