2025-01-18:施咒的最大总伤害。用go语言,一个魔法师掌握了多种不同的咒语,每个咒语对应一个伤害值,这些伤害值存储在数组 power 中,其中可能会有多个咒语具有相同的伤害值。 使用某个特定伤
2025-01-18:施咒的最大总伤害。用go语言,一个魔法师掌握了多种不同的咒语,每个咒语对应一个伤害值,这些伤害值存储在数组 power 中,其中可能会有多个咒语具有相同的伤害值。
使用某个特定伤害值为 power[i] 的咒语后,魔法师不能再使用伤害值为 power[i] - 2、power[i] - 1、power[i] + 1 或 power[i] + 2 的任何咒语。此外,每个咒语只能被施放一次。
请你计算并返回魔法师能够实现的最大伤害值总和。
1 <= power.length <= 100000。
1 <= power[i] <= 1000000000。
输入:power = [7,1,6,6]。
输出:13。
解释:
可以使用咒语 1,2,3,伤害值分别为 1,6,6,总伤害值为 13 。
答案2025-01-18:
题目来自leetcode3186。
大体步骤如下:
1.在 main
函数中,定义了输入的 power 数组,然后调用 maximumTotalDamage
函数,并打印最终结果。
2.在 maximumTotalDamage
函数中,首先使用一个 map 统计每种攻击力出现的次数,并将不同的攻击力存储到一个切片中,并进行排序。
3.使用动态规划的方法计算最大伤害值总和。创建一个数组 dp 用于存储计算过程中的最大伤害值总和,然后遍历排序后的攻击力数组。
4.对于每个攻击力,根据规则选择是否使用当前攻击力,并更新最大伤害值总和。
5.最终返回 dp[n+2],即最大伤害值总和。
总的时间复杂度:
统计每种攻击力的出现次数时间复杂度为 O(n)。
将不同的攻击力进行排序的时间复杂度为 O(nlogn)。
最大伤害值总和的动态规划过程时间复杂度为 O(n)。
所以总的时间复杂度为 O(n + nlogn)。
总的额外空间复杂度:
除了 power 数组外,在统计每种攻击力的出现次数、排序和动态规划过程中额外使用的空间为 O(n)。
所以总的额外空间复杂度为 O(n)。
综上,总的时间复杂度为 O(nlogn),总的额外空间复杂度为 O(n)。
Go完整代码如下:
package main
import (
"fmt"
"sort"
)
func maximumTotalDamage(power []int) int64 {
// 统计每种攻击力的出现次数
cnt := make(map[int]int)
for _, p := range power {
cnt[p]++
}
// 将不同的攻击力存储到一个切片并排序
powers := make([]int, 0, len(cnt))
for p := range cnt {
powers = append(powers, p)
}
sort.Ints(powers)
n := len(powers)
// dp数组多开几个空间防止下标越界
dp := make([]int64, n+3)
for i := 0; i < n; i++ {
x := powers[i]
// 继承不选当前值的情况
dp[i+3] = dp[i+2]
// 选择当前值x,并处理不同的跳过情况
if _, ok1 := cnt[x-2]; ok1 && cnt[x-1] > 0 {
dp[i+3] = max(dp[i+3], dp[i]+int64(x)*int64(cnt[x]))
} else if ok1 || cnt[x-1] > 0 {
dp[i+3] = max(dp[i+3], dp[i+1]+int64(x)*int64(cnt[x]))
} else {
dp[i+3] += int64(x) * int64(cnt[x])
}
}
return dp[n+2]
}
func main() {
power := []int{7, 1, 6, 6}
result := maximumTotalDamage(power)
fmt.Println(result)
}
Rust完整代码如下:
use std::collections::HashMap;
fn maximum_total_damage(power: Vec<i32>) -> i64 {
// 统计每种攻击力的出现次数
let mut cnt = HashMap::new();
for &p in &power {
*cnt.entry(p).or_insert(0) += 1;
}
// 将不同的攻击力存储到一个 Vec 中并排序
let mut powers: Vec<i32> = cnt.keys().cloned().collect();
powers.sort();
let n = powers.len();
// dp数组多开几个空间防止下标越界
let mut dp = vec![0; n + 3];
for i in 0..n {
let x = powers[i];
// 继承不选当前值的情况
dp[i + 3] = dp[i + 2];
// 选择当前值 x,并处理不同的跳过情况
if cnt.contains_key(&(x - 2)) && cnt.contains_key(&(x - 1)) {
dp[i + 3] = dp[i + 3].max(dp[i] + x as i64 * cnt[&x] as i64);
} else if cnt.contains_key(&(x - 2)) || cnt.contains_key(&(x - 1)) {
dp[i + 3] = dp[i + 3].max(dp[i + 1] + x as i64 * cnt[&x] as i64);
} else {
dp[i + 3] += x as i64 * cnt[&x] as i64;
}
}
dp[n + 2]
}
fn main() {
let power = vec![7, 1, 6, 6];
let result = maximum_total_damage(power);
println!("{}", result);
}
C完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#define MAX_POWERS 1000 // 假设最大的咒语伤害值不会超过1000
// 比较函数用于 qsort
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
// 计算最大总伤害
long long maximumTotalDamage(int *power, int size) {
int cnt[MAX_POWERS] = {0}; // 统计每种攻击力的出现次数
for (int i = 0; i < size; i++) {
cnt[power[i]]++;
}
int powers[MAX_POWERS];
int n = 0;
// 将不同的攻击力存储到数组并排序
for (int i = 0; i < MAX_POWERS; i++) {
if (cnt[i] > 0) {
powers[n++] = i;
}
}
// 排序
qsort(powers, n, sizeof(int), compare);
long long dp[n + 3]; // dp数组
for (int i = 0; i < n + 3; i++) {
dp[i] = 0; // 初始化
}
for (int i = 0; i < n; i++) {
int x = powers[i];
// 继承不选当前值的情况
dp[i + 3] = dp[i + 2];
// 选择当前值x,并处理不同的跳过情况
if (cnt[x - 2] > 0 && cnt[x - 1] > 0) {
dp[i + 3] = dp[i + 3] > dp[i] + (long long)x * cnt[x] ? dp[i + 3] : (dp[i] + (long long)x * cnt[x]);
} else if (cnt[x - 2] > 0 || cnt[x - 1] > 0) {
dp[i + 3] = dp[i + 3] > dp[i + 1] + (long long)x * cnt[x] ? dp[i + 3] : (dp[i + 1] + (long long)x * cnt[x]);
} else {
dp[i + 3] += (long long)x * cnt[x];
}
}
return dp[n + 2];
}
int main() {
int power[] = {7, 1, 6, 6}; // 示例输入
int size = sizeof(power) / sizeof(power[0]);
long long result = maximumTotalDamage(power, size);
printf("%lld\n", result); // 输出结果
return 0;
}
C++完整代码如下:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
long long maximumTotalDamage(vector<int>& power) {
// 统计每种攻击力的出现次数
unordered_map<int, int> cnt;
for (const auto& p : power) {
cnt[p]++;
}
// 将不同的攻击力存储到一个向量中并排序
vector<int> powers;
for (const auto& p : cnt) {
powers.push_back(p.first);
}
sort(powers.begin(), powers.end());
int n = powers.size();
// dp 数组多开几个空间防止下标越界
vector<long long> dp(n + 3, 0);
for (int i = 0; i < n; i++) {
int x = powers[i];
// 继承不选当前值的情况
dp[i + 3] = dp[i + 2];
// 选择当前值 x,并处理不同的跳过情况
if (cnt.count(x - 2) && cnt[x - 1] > 0) {
dp[i + 3] = max(dp[i + 3], dp[i] + static_cast<long long>(x) * cnt[x]);
} else if (cnt.count(x - 2) || cnt[x - 1] > 0) {
dp[i + 3] = max(dp[i + 3], dp[i + 1] + static_cast<long long>(x) * cnt[x]);
} else {
dp[i + 3] += static_cast<long long>(x) * cnt[x];
}
}
return dp[n + 2];
}
int main() {
vector<int> power = {7, 1, 6, 6}; // 示例输入
long long result = maximumTotalDamage(power);
cout << result << endl; // 输出结果
return 0;
}
Python完整代码如下:
# -*-coding:utf-8-*-
from collections import Counter
def maximum_total_damage(power):
# 统计每种攻击力的出现次数
cnt = Counter(power)
# 获取不同的攻击力并排序
powers = sorted(cnt.keys())
n = len(powers)
# dp数组多开几个空间防止下标越界
dp = [0] * (n + 3)
for i in range(n):
x = powers[i]
# 不选当前值的情况
dp[i + 3] = dp[i + 2]
# 选择当前值 x,并处理不同的跳过情况
if (x - 2) in cnt and (x - 1) in cnt:
dp[i + 3] = max(dp[i + 3], dp[i] + x * cnt[x])
elif (x - 2) in cnt or (x - 1) in cnt:
dp[i + 3] = max(dp[i + 3], dp[i + 1] + x * cnt[x])
else:
dp[i + 3] += x * cnt[x]
return dp[n + 2]
# 示例测试
if __name__ == "__main__":
power = [7, 1, 6, 6]
result = maximum_total_damage(power)
print(result) # 输出结果
Javascript完整代码如下:
function maximumTotalDamage(power) {
// 统计每种攻击力的出现次数
const cnt = {};
for (const p of power) {
cnt[p] = (cnt[p] || 0) + 1; // 计数
}
// 将不同的攻击力存储到一个数组并排序
const powers = Object.keys(cnt).map(Number);
powers.sort((a, b) => a - b);
const n = powers.length;
// dp数组多开几个空间防止下标越界
const dp = new Array(n + 3).fill(0);
for (let i = 0; i < n; i++) {
const x = powers[i];
// 继承不选当前值的情况
dp[i + 3] = dp[i + 2];
// 选择当前值x,并处理不同的跳过情况
if ((x - 2) in cnt && (x - 1) in cnt) {
dp[i + 3] = Math.max(dp[i + 3], dp[i] + x * cnt[x]);
} else if ((x - 2) in cnt || (x - 1) in cnt) {
dp[i + 3] = Math.max(dp[i + 3], dp[i + 1] + x * cnt[x]);
} else {
dp[i + 3] += x * cnt[x];
}
}
return dp[n + 2];
}
// 示例测试
const power = [7, 1, 6, 6];
const result = maximumTotalDamage(power);
console.log(result); // 输出结果
2025-01-18:施咒的最大总伤害。用go语言,一个魔法师掌握了多种不同的咒语,每个咒语对应一个伤害值,这些伤害值存储在数组 power 中,其中可能会有多个咒语具有相同的伤害值。 使用某个特定伤的更多相关文章
- 请给Array本地对象增加一个原型方法,它用于删除数组条目中重复的条目(可能有多个),返回值是一个包含被删除的重复条目的新数组。
这是牛客网上的一道题~ 题意:遇到重复元素就删除(留下第一个不重复的即可). 解题思路:双循环一遍数组,arr[i] == arr[j] 成立时,删除 arr[j],并将 arr[j] 直接push到 ...
- JS删除数组条目中重复的条目
[腾讯2015春招web前端开发练习卷] 请给Array本地对象增加一个原型方法,它用于删除数组条目中重复的条目(可能有多个),返回值是一个包含被删除的重复条目的新数组. Array.prototyp ...
- 19 01 18 dango 模型
定义属性 Django根据属性的类型确定以下信息: 当前选择的数据库支持字段的类型 渲染管理表单时使用的默认html控件 在管理站点最低限度的验证 django会为表创建自动增长的主键列,每个模型只能 ...
- [Effective JavaScript 笔记]第36条:只将实例状态存储在实例对象中
理解原型对象与其实例之间是一对多的关系,对于实现正确的对象行为很重要.常见的错误是不小心将每个实例的数据存储到了其原型中. 示例 一个实现了树型数据结构的类可能将子节点存储在数组中. 实例状态在原型中 ...
- 一个想法(续五):IT联盟创业计划:现阶段进度公示、疑问解答及进行中的计划
前言: 首先今天是元宵节,先祝大伙元宵节快,单纯的快乐! 然后看看开展中的计划: IT联盟创业计划众筹发起:一个想法(续三):一份IT技术联盟创业计划书,开启众筹创业征程 IT联盟创业计划众筹进度:一 ...
- JavaScript中对象数组 根据某个属性值 然后push到新的数组
原文链接 https://segmentfault.com/q/1010000010075035 将下列对象数组中,工资大于1w的员工,增加到对象数组 WanSalary中 var BaiduUser ...
- 将字符串存储到注册表中,长度一定是 strlen(text) + 1
参考:https://docs.microsoft.com/en-us/windows/desktop/sysinfo/registry-value-types 将字符串存储到注册表中,长度参数一定要 ...
- 利用POI工具读取word文档并将数据存储到sqlserver数据库中
今天实现了利用POI工具读取word文档,并将数据存储到sql数据库中,代码如下: package word; import java.io.File; import java.io.FileInpu ...
- [ES6系列-03]ES6中关于参数相关特性详解(参数默认值与参数解构赋值与剩余参数)
[原创] 码路工人 大家好,这里是码路工人有力量,我是码路工人,你们是力量. 今天总结一下 ES6 中跟参数相关的内容. 欢迎补充斧正.留言交流. 让我们互相学习一起进步. 1. ES6 参数默认值( ...
- Js数组对象的属性值升序排序,并指定数组中的某个对象移动到数组的最前面
需求整理: 本篇文章主要实现的是将一个数组的中对象的属性值通过升序的方式排序,然后能够让程序可以指定对应的数组对象移动到程序的最前面. 数组如下所示: var arrayData= [{name: & ...
随机推荐
- FPGA时序约束基础
一.时序约束的目的 由于实际信号在FPGA内部期间传输时,由于触发器等逻辑期间并非理想期间,因此不可避免地存在传输延时,这种延迟在高速工作频率.高逻辑级数时会造成后级触发器地建立时间和保持时间不满足, ...
- vagrant 环境安装(前置篇)
ubuntu可以直接 apt 源查找 sudo apt search vagrant 直接就 sudo apt-get install vagrant 如果版本不是 2.2.6 可以去 https:/ ...
- Spring源码学习 ------ IoC——AOP
一直想抽空把Spring源码拿来读读,但真正去做这件事的时候发现不简单,Spring发展这么多年,它的规模已不是一个一般的开源框架所能比的,它的主要架构和流程不是非常清晰,很难抓到要害,但有一点可以肯 ...
- Python打包工具之pyinstaller
前言: 近期使用PySimpleGUI开发了一款开发者工具X-助手工具,意打造成平常开发助手,无论是图片还是网址的处理等等都需要这一个工具即可,无需在网上找各个网站去找解决方案, 对于GUI的打包工具 ...
- 版本管理客户端工具SourceTree
[使用] 1.设置SSH客户端 工具 > 选项 设置OpenSSH, SSH 密钥这一栏自然会去选择当前用户下的 .ssh 目录下的 id_rsa 这个私钥:
- Kafka可视化工具之Kafka Tool
官网: https://www.kafkatool.com/download.html Kafka Tool是一个用于管理和使用Apache Kafka集群的GUI应用程序. Kafka Tool提供 ...
- 2023 CCPC 深圳
2023 CCPC 深圳 D. Bot Brothers 有一棵 \(n\) 个点的树,\(m\) 个叶子,编号为 \(1∼m\).两人在树上博弈,均从根出发,轮流行动,每次走向一个当前所在节点的子节 ...
- ecognition server注意事项
1.4002端口是节点管理界面,默认密码admin. 2.8184端口是任务管理界面. 3.节点在线状态下,查看提交的影像矢量路径是否正确. 4.看服务器读取各个文件是否有误. 5.用develope ...
- chrome浏览器设置允许跨域
前情 在访问测试搭建的测试环境的时候,发现接口因为跨域全部失败了,服务端又不想设置允许跨域,又急于使用,于是想到是不是可以使用跨域浏览器 放开chrome的跨域设置步骤 复制一个chrome快捷图标, ...
- Java线程 interrupt 方法使用异常
背景 需要在异步任务中中断任务的执行,故选择通过调用 interrupt 方法对线程设置中断信号. 在比较耗时的业务代码增加判断 Thread.currentThread().isInterrupte ...