算法题纪录(2)

1、给出一组数列:1,2,6,15,31,56…, 求第n个数。

1.1 解题思路

类似斐波那契数列,可以用双指针移动来解题。

1.2 参考代码

// 1,2,6,15,31,56.. 求 第 n 个 数
function getNthNumber(n) {
  let res = 1;
  let n1 = 0;
  let n2 = 1;

  for (let i = 1; i <= n; i++) {
    res = n2 + Math.pow(i - 1, 2)
    n1 = n2;
    n2 = res;
  }

  return res
}

console.log(getNthNumber(1));
console.log(getNthNumber(2));
console.log(getNthNumber(3));
console.log(getNthNumber(4));
console.log(getNthNumber(5));
console.log(getNthNumber(6));
console.log(getNthNumber(7));

2.小明去赌钱,每次都押现有钱的一半,假设他参与了 2n 场,赢了 n 场,输了 n 场,问最终小明是赢了还是输了?

2.1 解题思路

我们可以用代码来模拟小明的赌钱策略,并计算最终是赚还是亏。关键点是赢的情况下钱加倍,输的情况下减半。在 2𝑛场中,赢了 𝑛 场,输了 𝑛 场,最终的结果只与赢输的顺序无关。

2.2 参考代码

function calculateOutcome(initialMoney, n) {
    let money = initialMoney;

    // 模拟 n 场赢,n 场输
    for (let i = 0; i < n; i++) {
        money *= 2; // 赢了钱加倍
    }
    for (let i = 0; i < n; i++) {
        money /= 2; // 输了钱减半
    }

    // 返回最终的钱和赚亏状态
    return {
        finalMoney: money,
        result: money > initialMoney ? '赚了' : (money < initialMoney ? '亏了' : '持平')
    };
}

// 测试
const initialMoney = 100; // 初始资金
const n = 3; // 假设赌了 6 场,赢了 3 场,输了 3 场
const outcome = calculateOutcome(initialMoney, n);

console.log(`初始资金: ${initialMoney}`);
console.log(`最终资金: ${outcome.finalMoney}`);
console.log(`结果: ${outcome.result}`);

运行结果
无论赢输顺序如何,小明最终资金与初始资金相同,结果为持平。

答案
小明最终不赚也不亏,因为每次押一半的策略使得资金在赢输数量相同的情况下保持恒定。

3.小明花零花钱, 第一天花所有钱的一半多1块,第二天花前一天的钱的一半多一块,依次类推,第n天后小明刚好剩 1块,问小明有多少零花钱?

3.1 解题思路

我们可以用逆推法解决这个问题:

  • 从第 𝑛 天向第 1 天逆推小明的零花钱。
  • 每天剩下的钱可以反推计算出前一天的钱。

3.2 参考代码

function calculateInitialMoney(days) {
    let money = 1; // 第 n 天剩余的钱是 1 块
    for (let i = days; i > 0; i--) {
        money = (money + 1) * 2; // 根据公式逆推前一天的钱
    }
    return money;
}

// 测试
const days = 5; // 假设小明花了 5 天
const initialMoney = calculateInitialMoney(days);
console.log(`小明刚开始有零花钱: ${initialMoney}`);

3.3示例运行

假设 𝑛=5:

  • 第 5 天剩下的钱:1 块
  • 第 4 天的钱:(1+1)×2=4
  • 第 3 天的钱:(4+1)×2=10
  • 第 2 天的钱:(10+1)×2=22
  • 第 1 天的钱:(22+1)×2=46

输出:小明刚开始有 46 块零花钱。

### 华为算法题:分积木问题的详细解法及思路 #### 问题概述 在华为OD机试中,“分积木”问题是考察数据组合、匹配以及优化的经典题目之一。该类问题通常涉及给定一系列不同长度的积木,目标是在满足特定条件下构建尽可能多的层次结构。 #### 输入输出说明 对于此类问题的具体形式化定义如下: - **输入**:一组整数表示各个积木的长度,这些数值之间由单个空格隔开; -1`表明无法完成任务[^3]。 #### 关键约束条件分析 为了有效解决这个问题,需注意几个重要的限制因素: - 所有使用的积木宽度和高度均一致而仅有长度存在差异; - 构建过程中每一层仅允许放置一块单独的砖头或是若干块连续排列并紧密相连的小型砖头构成的整体; - 同一水平面内的总跨度应当保持恒定不变; - 至少需要形成两层以上的建筑体才视为有效的解答方案[^4]。 #### 解决策略探讨 针对上述特性设计了一套较为通用性的处理框架来应对这类挑战: ##### 特殊情况快速响应机制 首先考虑极端情形下的即时判定规则: - 当只有一根柱子的时候显然只能竖立起单一层面; - 若恰好拥有两件物品,则依据它们尺寸是否吻合决定能否建立双层构造——完全相同的规格意味着可行,否则不行。 ##### 动态规划核心理念阐述 面对更复杂的情况即三者以上的情形下采用动态规划方法论进行探索。具体操作流程包括但不限于以下几个方面: - 对原始序列执行降序排序以便后续计算过程更加直观高效; - 设定变量用于记录当前最优解对应的累积厚度值域区间端点位置; - 运用双重循环枚举可能的一级单位扩展量直至触及边界为止,在此期间不断更新全局最佳纪录状态直到遍历结束为止。 ```python def max_levels(blocks): blocks.sort(reverse=True) if not blocks or sum(blocks[:2]) == 0: return -1 n = len(blocks) # Special cases handling if n == 1: return 1 elif n == 2 and blocks[0] != blocks[1]: return 1 elif n >= 2 and all(x==blocks[0] for x in blocks[:2]): return min(2, n) dp = [[False]*(sum(blocks)+1) for _ in range(n+1)] count = [0]*(sum(blocks)+1) target_range_start = blocks[0] target_range_end = blocks[0]+blocks[1] result = float('inf') for length in range(target_range_start,target_range_end+1): dp[0][length]=True for i in range(1,n+1): current_block=blocks[i-1] for j in reversed(range(current_block,length+1)): if dp[i-1][j-current_block]: dp[i][j]|=dp[i-1][current_block] if j>=target_range_start<=target_range_end: count[j]+=count[j-current_block]+1 temp_result=min([c for c,l in zip(count,range(len(dp[-1])))if l>=target_range_start and l<=target_range_end],default=float('inf')) result=min(result,temp_result) return int(-1) if math.isinf(result) else int(result//2) print(max_levels([int(i.strip())for i in "3 6 6 3".split()])) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值