算法题--华为od机试考试(构成的正方形数量、TLV解码、简易内存池)

目录

构成的正方形数量

题目描述

输入描述

输出描述

示例1

输入

输出

示例2

输入

输出

注意

解析

答案

TLV解码

题目描述

输入描述

输出描述

示例1

输入

输出

解析

答案

简易内存池

题目描述

 注意

 输入描述

 输出描述

 示例1

 输入

 输出

 解析

答案


构成的正方形数量

考察数学、set集合

题目描述

输入N个互不相同的二维整数坐标,求这N个坐标可以构成的正方形数量。(内积为零的两个向量垂直)

输入描述

第一行输入N,N代表坐标数量,N为正整数。N<=100

之后的K行输入为坐标x y,以空格分隔,x、y为整数,-10<=x,y<=10

输出描述

输出可以构成正方形数量

示例1

输入

3

1 3

2 4

3 1

输出

0

示例2

输入

10

0 0

0 1

1 0

1 1

2 0

0 2

2 1

1 2

2 2

输出

6

注意

(1,0),(0,1),(1,2),(2,1)也可以构成正方形。

解析

确定2点,以这2点组成正方形的一条边,此时便可以确定正方形的另外两点的位置,有2种情况,需要判断另外2点是满足要求。

答案

function getSquareCount(str) {
    let coordinates = str.split('\n')
    let n = coordinates.shift()
    if (n <= 3) {
        return 0
    }
    let squareCount = 0;
    const set = new Set(coordinates);
    for (let i = 0; i < coordinates.length; i++) {
        let [x1, y1] = coordinates[i].split(" ").map((ele) => parseInt(ele));
        for (let j = i + 1; j < coordinates.length; j++) {
            let [x2, y2] = coordinates[j].split(" ").map((ele) => parseInt(ele));
            let x3 = x1 - (y1 - y2);
            let y3 = y1 + (x1 - x2);
            let x4 = x2 - (y1 - y2);
            let y4 = y2 + (x1 - x2);
            if (set.has(x3 + " " + y3) && set.has(x4 + " " + y4)) squareCount++;
            let x5 = x1 + (y1 - y2);
            let y5 = y1 - (x1 - x2);
            let x6 = x2 + (y1 - y2);
            let y6 = y2 - (x1 - x2);
            if (set.has(x5 + " " + y5) && set.has(x6 + " " + y6)) squareCount++;
        }
    }
    return squareCount / 4;
}
console.log(getSquareCount(`3
1 3
2 4
3 1`))
console.log(getSquareCount(`9
0 0
0 1
1 0
1 1
2 0
0 2
2 1
1 2
2 2
`))

TLV解码

考察字节序中小端序

题目描述

TLV编码是按[Tag Length Value]格式进行编码的,一段码流中的信元用Tag标识,Tag在码流中唯一不重复,Length表示信元Value的长度,Value表示信元的值。

码流以某信元的Tag开头,Tag固定占一个字节,Length固定占两个字节,字节序为小端序。现给定TLV格式编码的码流,以及需要解码的信元Tag,请输出该信元的Value。

输入码流的16进制字符中,不包括小写字母,且要求输出的16进制字符串中也不要包含小写字母;码流字符串的最大长度不超过50000个字节。

输入描述

输入的第一行为一个字符串,表示待解码信元的Tag;

输入的第二行为一个字符串,表示待解码的16进制码流,字节之间用空格分隔。

输出描述

输出一个字符串,表示待解码信元以16进制表示的Value。

示例1

输入

31

32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC

输出

32 33

解析

首先理解小端序,01 00 表示为从序号小的往大的排,正常的数字都是大端序,这里需要把位置交换为00 01即可。

答案

function getTagValue(str) {
    let [key, arr] = str.split('\n')
    arr = arr.split(' ')
    let i = 0
    let hash = {}
    while (i < arr.length) {
        let key = arr[i]
        let len = parseInt(arr[i + 2] + arr[i + 1], 16)
        let value = []
        for (let j = i + 3; j < i + 3 + len; j++) {
            value.push(arr[j])
        }
        i = i + 3 + len
        hash[key] = value
    }
    return hash[key].join(' ')
}
console.log(getTagValue(`31
32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC`))

简易内存池

 考察hash、数组增删改

题目描述

 请实现一个简易内存池,根据请求命令完成内存分配和释放。内存池支持两种操作命令,REQUEST和RELEASE,其格式为:REQUEST=请求的内存大小 表示请求分配指定大小内存,如果分配成功,返回分配到的内存首地址;如果内存不足,或指定的大小为0,则输出error。RELEASE=释放的内存首地址表示释放掉之前分配的内存,释放成功无需输出,如果释放不存在的首地址则输出error。

 注意

 1.内存池总大小为100字节。

 2.内存池地址分配必须连续内存,并优先从低地址分配。

 3.内存释放后可被再次分配,已释放的内存在空闲时不能被二次释放。

 4.不会释放已申请的内存块的中间地址。

 5.释放操作只是针对首地址所对应的单个内存块进行操作,不会影响其它内存块。

 输入描述

 首行为整数N,表示操作命令的个数,取值范围:0<N<=100。

 接下来的N行,每行将给出一个操作命令,操作命令和参数之间用'='分割。

 输出描述

 见题面输出要求

 示例1

 输入

 2

 REQUEST = 10

 REQUEST = 20

 输出

 0

 10

 解析

 将内存池中每一块可用内存用数组表示,需要按顺序排列,每次申请内存从小往大搜索每个数组中内存大小是否满足,使用的内存通过对象用key:value形式记录,key为起始内存地址。

 每次释放内存的时候需要判断多种情况,释放的内存在不同的位置,是否需要和前后的内存合成一个更大。

答案

class EasyStorage {
    constructor() {
        this.canUse = [[0, 100]]
        this.used = {}
    }
    request(n) {
        if (n === 0) {
            return 'error'
        }
        let isEqual = false
        let index = this.canUse.findIndex(v => {
            // 搜索每个数组中内存大小是否满足
            if (v[1] - v[0] >= n) {
                if (v[1]- v[0] === n) {
                    isEqual = true
                }
                return true
            }
            return false
        })
        if (index === -1) {
            return 'error'
        }
        let [start, end] = this.canUse[index]
        if (isEqual) {
            this.used[start] = this.canUse[index]
            this.canUse.splice(index, 1)
        } else {
            this.used[start] = [start, start+n]
            this.canUse.splice(index, 1, [start+n, end])
        }
        return start
    }
    release(n) {
        if(this.used[n]){
            let tmp = this.used[n]
            delete this.used[n]
            if(this.canUse.length===0){
                this.canUse.push(tmp)
                return
            }
            let index = this.canUse.findIndex(v=>{
                if(v[1]<= tmp[0]){
                    return true
                }
                return false
            })
            
            if(index === -1){
                //从头部插入释放内存
                if(this.canUse[0][0]===tmp[1]){
                    this.canUse[0][0]=tmp[0]
                }else{
                    this.canUse.unshift(tmp)
                }
                return
            }
            if(this.canUse.length>index+1&&this.canUse[index][1]===tmp[0]&&this.canUse[index+1][0]===tmp[1]){
                // 插入中间位置,释放的内存跟上下的合成一个
                this.canUse.splice(index,1)
                this.canUse[index][0]=tmp[0]
            }else if(this.canUse.length>index+1&&this.canUse[index][1]===tmp[0]&&this.canUse[index+1][0]!==tmp[1]){
                // 插入中间位置,释放的内存只跟上的合成一个
                this.canUse[index][1]=tmp[1]
            }else if(this.canUse.length>index+1&&this.canUse[index][1]!==tmp[0]&&this.canUse[index+1][0]===tmp[1]){
                // 插入中间位置,释放的内存只跟下的合成一个
                this.canUse[index+1][0]=tmp[0]
            }else if(this.canUse.length===index+1&&this.canUse[index][1]===tmp[0]){
                // 从末尾插入释放的内存跟上一个合成一个
                this.canUse[index][1]=tmp[1]
            }else if(this.canUse.length===index+1&&this.canUse[index][1]!==tmp[0]){
                // 从末尾插入释放的内存,不合成
                this.canUse.push(tmp)
            }
        }else{
            return 'error'
        }
    }
}

function storageOperate(str){
    let s = new EasyStorage()
    let operates = str.split('\n')
    let n = operates.shift()
    for(let i=0;i<n;i++){
        let tmp = operates[i]
        let n = Number(tmp.split(' ').pop())
        if(tmp.includes('REQUEST')){ 
            console.log(s.request(n))
        }else{
            console.log(s.release(n))
        }
    }
}
storageOperate(`2
REQUEST = 10
REQUEST = 20`)

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值