2022-11-03:给定一个数组arr,和一个正数k
如果arr[i] == 0,表示i这里既可以是左括号也可以是右括号,
而且可以涂上1~k每一种颜色
如果arr[i] != 0,表示i这里已经确定是左括号,颜色就是arr[i]的值
那么arr整体就可以变成某个括号字符串,并且每个括号字符都带有颜色。
返回在括号字符串合法的前提下,有多少种不同的染色方案。
不管是排列、还是颜色,括号字符串任何一点不一样,就算不同的染色方案
最后的结果%10001,为了方便,我们不处理mod,就管核心思路。
2 <= arr长度 <= 5000
1 <= k <= 1000
0 <= arr[i] <= k。
2022.8.7笔试第三道。来自猿辅导。

答案2022-11-03:

递归或者动态规划。

代码用rust编写。代码如下:

use std::iter::repeat;

use rand::Rng;
fn main() {
let nn: i32 = 5;
let kk: i32 = 4;
let test_time: i32 = 1000;
println!("测试开始");
for _i in 0..test_time {
let n = (rand::thread_rng().gen_range(0, nn) + 1) << 1;
let k = rand::thread_rng().gen_range(0, kk) + 1;
let mut arr = random_array(n, k);
let ans1 = ways1(&mut arr, k);
let ans2 = ways2(&mut arr, k);
if ans1 != ans2 {
println!("arr = {:?},k = {}", arr, k);
println!("ans1 = {}", ans1);
println!("ans2 = {}", ans2);
println!("出错了!");
break;
}
}
println!("测试结束");
} // 暴力方法
// 为了验证
fn ways1(arr: &mut Vec<i32>, k: i32) -> i32 {
if arr.len() & 1 != 0 {
return 0;
}
return process1(arr, 0, k);
} fn process1(arr: &mut Vec<i32>, index: i32, k: i32) -> i32 {
if index == arr.len() as i32 {
let n = arr.len() as i32;
let mut stack: Vec<i32> = repeat(0).take(n as usize).collect();
let mut size = 0;
for i in 0..n {
if arr[i as usize] > 0 {
stack[size as usize] = arr[i as usize];
size += 1;
} else {
if size == 0 {
return 0;
}
size -= 1;
if stack[size as usize] != -arr[i as usize] {
return 0;
}
}
}
return if size == 0 { 1 } else { 0 };
} else if arr[index as usize] != 0 {
return process1(arr, index + 1, k);
} else {
let mut ans = 0;
for color in 1..=k {
arr[index as usize] = color;
ans += process1(arr, index + 1, k);
arr[index as usize] = -color;
ans += process1(arr, index + 1, k);
arr[index as usize] = 0;
}
return ans;
}
} fn ways2(arr: &mut Vec<i32>, k: i32) -> i32 {
let n = arr.len() as i32;
if n & 1 != 0 {
return 0;
}
let a = combines(arr);
let mut b = 0;
for num in arr.iter() {
if *num != 0 {
b += 1;
}
}
return if ((n - (b << 1)) >> 1) < 0 {
0
} else {
a * k.pow(((n - (b << 1)) >> 1) as u32)
};
} // 忽略染色这件事,求合法的括号结合数量
fn combines(arr: &mut Vec<i32>) -> i32 {
let n = arr.len() as i32;
let mut dp: Vec<Vec<i32>> = repeat(repeat(-1).take(n as usize).collect())
.take(n as usize)
.collect();
return f(arr, 0, 0, &mut dp);
} // arr[i....]范围上,去做决定
// j : arr[0..i-1]已经做完决定的部分,左括号比右括号,多几个
// 返回:
// arr[i....]范围上,去做决定,
// 已经做完决定的部分,左括号比右括号多j个
// 这样的情况下,最终合法的括号结合,多少个!
// process(arr, 0, 0)
fn process(arr: &mut Vec<i32>, i: i32, j: i32) -> i32 {
if i == arr.len() as i32 {
return if j == 0 { 1 } else { 0 };
}
if j < 0 {
return 0;
}
// 这个不写也行
// 锦上添花的剪枝条件
if arr.len() as i32 - i < j {
return 0;
}
// arr[i] != 0
if arr[i as usize] != 0 {
// (
return process(arr, i + 1, j + 1);
} else {
// arr[i] 0 ? ( )
let p1 = process(arr, i + 1, j + 1);
let p2 = process(arr, i + 1, j - 1);
return p1 + p2;
}
} // 在arr[i...]范围上做决定
// 之前在arr[0...i-1]上的决定,使得左括号比右括号多了j个
// 最终合法的括号结合是多少
fn f(arr: &mut Vec<i32>, i: i32, j: i32, dp: &mut Vec<Vec<i32>>) -> i32 {
let n = arr.len() as i32;
if i == n {
return if j == 0 { 1 } else { 0 };
}
if j < 0 {
return 0;
}
if n - i < j {
return 0;
}
// 如果缓存命中,直接返回答案
if dp[i as usize][j as usize] != -1 {
return dp[i as usize][j as usize];
}
let mut ans = 0;
if arr[i as usize] > 0 {
ans = f(arr, i + 1, j + 1, dp);
} else {
ans = f(arr, i + 1, j + 1, dp) + f(arr, i + 1, j - 1, dp);
}
dp[i as usize][j as usize] = ans;
return ans;
} // 生成长度随机的数组
// 值在0~K之间,但是50%的概率值是0,50%的概率值是1~k中的一个
fn random_array(n: i32, k: i32) -> Vec<i32> {
let mut ans = vec![];
for _ in 0..n {
ans.push(if rand::thread_rng().gen_range(0, 2) == 0 {
0
} else {
rand::thread_rng().gen_range(0, k) + 1
})
}
return ans;
}

执行结果如下:


左神java代码

2022-11-03:给定一个数组arr,和一个正数k 如果arr[i] == 0,表示i这里既可以是左括号也可以是右括号, 而且可以涂上1~k每一种颜色 如果arr[i] != 0,表示i这里已经确的更多相关文章

  1. 七、如何在Java中高效检查一个数组是否含有一个值

    如何检查一个数组(非排序的)是否包含特定的值.这是个非常有用或经常被在Java中使用.这是个在Stack Overflow中高得票的问题.在已经高得票的答案中,有许多不同的处理方法,但是时间的复杂度非 ...

  2. js判断一个数组是否包含一个指定的值

    今天看了一下  有好几种方法  总结一下 1:array.indexOf   此方法判断数组中是否存在某个值,如果存在返回数组元素的下标,否则返回-1 let arr = ['something', ...

  3. [转]php判断一个数组是另一个数组的子集

    FROM : http://blog.csdn.net/lcion/article/details/8985220 今天完成一个算法的过程中,有几个需求模块,其中就有判断$a数组是否是$b数组的子集, ...

  4. php判断一个数组是另一个数组的子集

    需求最少的时间复杂度判断$a数组是否是$b数组的子集 // 快速的判断$a数组是否是$b数组的子集$a = array(135,138);$b = array(135,138,137); 实现方法 这 ...

  5. MATLAB一个数组中另一个数组的值

    c = setdiff(a,b) 删掉素组a中数组b的元素 如:

  6. includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

    注意:对象数组不能使用includes方法来检测. JavaScript Demo: Array.includes() var array1 = [1, 2, 3]; console.log(arra ...

  7. php让一个数组按照另外一个数组的键名进行排序

    $a = [ 'id', 'name', 'identityId', 'phone', 'email', 'schoolId' ]; $b = [ 'id' => '唯一标识', 'identi ...

  8. 判断一个数组是否包含一个指定的值 includes-ES6

    var array1 = [1, 2, 3]; console.log(array1.includes(2));  // trueconsole.log(array1.includes(2, 5)); ...

  9. Java 将两个有序数组合成为一个有序数组

    基本思路 1.如果其中一个数组的元素均大于另一个数组的元素,则可以直接组合,不用拆分. 即:其中一个数组的第一个元素大于或者小于另一个数组的最后一个元素 2.若不满足1中的情况,则表明数组需要拆分,拆 ...

  10. java二分法来求一个数组中一个值的key

    package TestArray; import java.util.Arrays; /** * 二分法查找 */ public class Test { public static void ma ...

随机推荐

  1. ubuntu添加了id_rsa.pub*authorized_keys依然不能免密登录?

    cd .ssh chmod 600 authorized_keys 还是不行,看日志 tail -f /var/log/auth.log bad ownership or modes for dire ...

  2. C++ sort排序

    sort(begin, end, cmp),其中begin为指向待sort()的数组的第一个元素的指针,end为指向待sort()的数组的最后一个元素的下一个位置的指针,cmp参数为排序准则,如果没有 ...

  3. 不同时间格式转换问题_python2

    def unix_to_cst(data): """2019-03-17 11:00:00 --> Sun, 17 Mar 2019 11:00:00 GMT+08 ...

  4. 接入HMS Core应用内支付服务过程中一些常见问题总结

    华为HMS Core应用内支付服务(In-App Purchases,IAP)为应用提供便捷的应用内支付体验和简便的接入流程.该服务支持客户端和服务端两种开发形式,具体可以参考官方文档. 往期文章:常 ...

  5. Centos 6 部署PPTP服务

    前言:PPTP使用一个TCP连接对隧道进行维护,使用通用路由封装(GRE)技术把数据封装成PPP数据桢通过隧道传送.可以对封装PPP桢中的负载数据进行加密或压缩. 注意:PPTP协议已经被IOS系统所 ...

  6. C++内存重叠

    内存重叠是指在内存中存在两个或多个区域,它们的地址范围有交叉部分.在 C++ 中,内存重叠可能会导致程序出现不可预期的行为,因此我们需要了解它的原因和如何避免. 内存重叠的原因 内存重叠的主要原因是指 ...

  7. vuex记录状态

    // actions import { queryProductDetailsById } from '../service' /* * 异步 */ export const addAndGetPro ...

  8. GKCTF X DASCTF应急挑战杯-Maple_root-Writeup

    GKCTF X DASCTF应急挑战杯-Maple_root-Writeup 参赛队员: b4tteRy, x0r, f1oat 最终成绩:2285 最终排名:27 总结 经过最近几次类线下的演练,感 ...

  9. ICMP隐蔽隧道攻击分析与检测(三)

    • ICMP隧道攻击工具特征分析 一.原理 由于ICMP报文自身可以携带数据,而且ICMP报文是由系统内核处理的,不占用任何端口,因此具有很高的隐蔽性. 通过改变操作系统默认填充的Data,替换成自己 ...

  10. 二进制安装Kubernetes(k8s) v1.24.1 IPv4/IPv6双栈 --- Ubuntu版

    二进制安装Kubernetes(k8s) v1.24.1 IPv4/IPv6双栈 --- Ubuntu版本 Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes二进制安 ...