【满分】【华为OD机试真题2023C&D卷 JAVA&JS】攀登者2

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里

攀登者2

知识点数组

时间限制:1s 空间限制:32MB 限定语言:不限

题目描述:

攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的高度代表相对海拔高度。其中数组元素0代表地面。 例如[0,1,4,3,1,0,0,1,2,3,1,2,1,0], 代表如下图所示的地图,地图中有两个山脉位置分别为 1,2,3,4,5和8,9,10,11,12,13,最高峰高度分别为4,3。最高峰位置分别为3,10。 一个山脉可能有多座山峰(高度大于两边,或者在地图边界)。

               4  
             +---+ 
             |   | 
             |   | 3                       3 
             |   | 
             |   +---+                   ----- 
             |       |                   |   | 
           2 |       |                 2 |   |     2 
             |       |                   |   | 
         +---+       |               ----+   |   +---+ 
         |           |               |       |   |   | 
       1 |           | 1           1 |       | 1 |   | 1 
         |           |               |       |   |   | 
     +---+           +---+       +---+       +---+   +---+ 
     |                   |       |                       | 
   0 |                   | 0   0 |                       | 0 
     |                   |       |                       | 
 +---+                   +-------+                       +---+ 
 
   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14

2. 登山时会消耗登山者的体力(整数),上山时,消耗相邻高度差两倍的体力,下坡时消耗相邻高度差一倍的体力,平地不消耗体力,登山者体力消耗到零时会有生命危险。 例如,上图所示的山峰,从索引0,走到索引1,高度差为1,需要消耗2X1 = 2 的体力,从索引2高度2走到高度4索引3需要消耗2X2 = 4 的体力。如果是从索引3走到索引4则消耗1X1的体力。
3. 登山者体力上限为999。
4. 登山时的起点和终点可以是地图中任何高度为0的地面例如上图中的0,6,7,14 都可以作为登山的起点和终点
 攀登者想要评估一张地图内有多少座山峰可以进行攀登,且可以安全返回到地面,且无生命危险。
例如上图中的数组,有3个不同的山峰,登上位置在3的山可以从位置0或者位置6开始,从位置0登到山顶需要消耗体力1X2+1X2+2X2 = 8, 从山顶返回到地面0需要消耗体力 2X1 + 1X1 + 1X1 = 4 的体力,按照登山路线0->3->0需要消耗体力 12。攀登者至少需要12以上的体力(大于12)才能安全返回。

示例1

输入:

[0,1,4,3,1,0,0,1,2,3,1,2,1,0],13

输出:

3

说明:

登山者只能够登上位置10和12的山峰,7->10->7, 14->12>14

示例2

输入:

[1,4,3],999

输出:

0

说明:

没有合适的起点和终点

代码(JAVA): 

import java.util.HashSet;
import java.util.Set;

public class Main{

    public static void main(String[] args) {

        int[] hillMap = new int[]{0,1,4,3,1,0,0,1,2,3,1,2,1,0};

        System.out.println(count_climbable( hillMap, 13));

    }

    public static int count_climbable(int[] hill_map, int strength) {
        if (hill_map.length <= 1) {
            return 0;
        }
        int result = 0;
        //峰的位置集合
        Set<Integer> feng = new HashSet<>();
        for (int i = 0; i < hill_map.length; i++) {
            if (hill_map[i] != 0) {
                boolean flag = false;
                if (i == 0 && i + 1 < hill_map.length && hill_map[i + 1] < hill_map[i]) {
                    //第一个位置为峰
                    flag = true;
                }
                if (i == hill_map.length - 1 && i > 0 && hill_map[i] > hill_map[i - 1]) {
                    //最后一个为峰
                    flag = true;
                }
                if (i > 0 && i < hill_map.length - 1 && hill_map[i - 1] < hill_map[i] && hill_map[i] > hill_map[i + 1]) {
                    //中间位置为峰
                    flag = true;
                }
                if (flag) {
                    feng.add(i);
                }
            }
        }
        //从左侧地面上山
        int[][] left = new int[hill_map.length][2];
        int i = 0;
        //上山的高度
        int v1 = -1;
        //下山的高度
        int v2 = -1;
        while (i < hill_map.length) {
            if (hill_map[i] == 0) {
                v1 = 0;
                v2 = 0;
            } else if (v1 != -1) {
                if (hill_map[i] > hill_map[i - 1]) {
                    v1 += hill_map[i] - hill_map[i - 1];
                } else {
                    v2 += hill_map[i - 1] - hill_map[i];
                }
            }
            left[i][0] = v1;
            left[i][1] = v2;
            i++;
        }
        //从右侧地面上山
        int[][] right = new int[hill_map.length][2];
        i = hill_map.length - 1;
        //上山的高度
        v1 = -1;
        //下山的高度
        v2 = -1;
        while (i >= 0) {
            if (hill_map[i] == 0) {
                v1 = 0;
                v2 = 0;
            } else if (v1 != -1) {
                if (hill_map[i] > hill_map[i + 1]) {
                    v1 += hill_map[i] - hill_map[i + 1];
                } else {
                    v2 += hill_map[i + 1] - hill_map[i];
                }
            }
            right[i][0] = v1;
            right[i][1] = v2;
            i--;
        }

        for (int x : feng) {
            boolean flag = false;
            int cost1 = -1;
            int cost2 = -1;
            int cost3 = -1;
            int cost4 = -1;
            if (left[x][0] != -1) {
                //从左侧上山下山
                //上山的体力
                cost1 = left[x][0] * 2 + left[x][1];
                //下山的体力
                cost3 = left[x][1] * 2 + left[x][0];
                if (cost1 + cost3 < strength) {
                    //体力满足登上高峰
                    flag = true;
                }
            }
            if (right[x][0] != -1) {
                //从右侧上山下山
                //上山的体力
                cost2 = right[x][0] * 2 + right[x][1];
                //下山的体力
                cost4 = right[x][1] * 2 + right[x][0];
                if (cost2 + cost4 < strength) {
                    flag = true;
                }
            }
            if (cost1 != -1 && cost2 != -1) {
                if (Math.min(cost1, cost2) + Math.min(cost4, cost3)  < strength) {
                    //最小上山体力 + 最小下山体力
                    flag = true;
                }
            }
            if (flag) {
                result ++;
            }
        }
        return result;
    }

}

代码(JS):

let hillMap = [0, 1, 4, 3, 1, 0, 0, 1, 2, 3, 1, 2, 1, 0];

function count_climbable(hill_map, strength) {
    if (hill_map.length <= 1) {
        return 0;
    }
    let result = 0;
    //峰的位置集合
    let feng = new Set();
    for (let i = 0; i < hill_map.length; i++) {
        if (hill_map[i] !== 0) {
            let flag = false;
            if (i === 0 && i + 1 < hill_map.length && hill_map[i + 1] < hill_map[i]) {
                //第一个位置为峰
                flag = true;
            }
            if (i === hill_map.length - 1 && i > 0 && hill_map[i] > hill_map[i - 1]) {
                //最后一个为峰
                flag = true;
            }
            if (i > 0 && i < hill_map.length - 1 && hill_map[i - 1] < hill_map[i] && hill_map[i] > hill_map[i + 1]) {
                //中间位置为峰
                flag = true;
            }
            if (flag) {
                feng.add(i);
            }
        }
    }
    //从左侧地面上山
    let left = new Array(hill_map.length).fill(0).map(() => new Array(2).fill(0));
    let i = 0;
    //上山的高度
    let v1 = -1;
    //下山的高度
    let v2 = -1;
    while (i < hill_map.length) {
        if (hill_map[i] === 0) {
            v1 = 0;
            v2 = 0;
        } else if (v1 !== -1) {
            if (hill_map[i] > hill_map[i - 1]) {
                v1 += hill_map[i] - hill_map[i - 1];
            } else {
                v2 += hill_map[i - 1] - hill_map[i];
            }
        }
        left[i][0] = v1;
        left[i][1] = v2;
        i++;
    }
    //从右侧地面上山
    let right = new Array(hill_map.length).fill(0).map(() => new Array(2).fill(0));
    i = hill_map.length - 1;
    //上山的高度
    v1 = -1;
    //下山的高度
    v2 = -1;
    while (i >= 0) {
        if (hill_map[i] === 0) {
            v1 = 0;
            v2 = 0;
        } else if (v1 !== -1) {
            if (hill_map[i] > hill_map[i + 1]) {
                v1 += hill_map[i] - hill_map[i + 1];
            } else {
                v2 += hill_map[i + 1] - hill_map[i];
            }
        }
        right[i][0] = v1;
        right[i][1] = v2;
        i--;
    }

    for (let x of feng) {
        let flag = false;
        let cost1 = -1;
        let cost2 = -1;
        let cost3 = -1;
        let cost4 = -1;
        if (left[x][0] !== -1) {
            //从左侧上山下山
            //上山的体力
            cost1 = left[x][0] * 2 + left[x][1];
            //下山的体力
            cost3 = left[x][1] * 2 + left[x][0];
            if (cost1 + cost3 < strength) {
                //体力满足登上高峰
                flag = true;
            }
        }
        if (right[x][0] !== -1) {
            //从右侧上山下山
            //上山的体力
            cost2 = right[x][0] * 2 + right[x][1];
            //下山的体力
            cost4 = right[x][1] * 2 + right[x][0];
            if (cost2 + cost4 < strength) {
                flag = true;
            }
        }
        if (cost1 !== -1 && cost2 !== -1) {
            if (Math.min(cost1, cost2) + Math.min(cost4, cost3) < strength) {
                //最小上山体力 + 最小下山体力
                flag = true;
            }
        }
        if (flag) {
            result++;
        }
    }
    return result;
}

console.log(count_climbable(hillMap, 13));
  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值