2023-07-04:给定一个数组A, 把它分成两个数组B和C

对于数组A每个i位置的数来说,

A[i] = B[i] + C[i]

也就是一个数字分成两份,然后各自进入B和C

要求B[i], C[i] >= 1

最终B数组要求从左到右不能降序

最终C数组要求从左到右不能升序

比如

A = { 5, 4, 5 }

可以分成

B = { 2, 2, 3 }

C = { 3, 2, 2 }

这是一种有效的划分

返回有多少种有效的划分方式

1 <= A的长度 <= 10^7

1 <= A[i] <= 10^7

最终结果可能很大,请返回对1000000007取余的结果。

国外算法面经帖子上的题。

答案2023-07-04:

大体步骤如下:

算法一:

1.定义一个递归函数 process1,接受一个数组 arr,一个索引 i,前一个增加值 preIncrease 和前一个减少值 preDecrease。

2.如果 i 等于数组的长度(即 i == arr.size()),返回 1。

3.将 ans 初始化为 0。

4.遍历 arr[i] 可能的增加值和减少值。

5.如果前一个增加值 preIncrease 小于等于当前增加值,并且前一个减少值 preDecrease 大于等于当前减少值,递归调用 process1,并将结果加到 ans 上。

6.返回 ans。

7.在 ways1 函数中,将 ans 初始化为 0。

8.遍历第一个元素 arr 的可能增加值和减少值。

9.对于每对可能的增加值和减少值,调用更新参数后的 process1,并将结果加到 ans 上。

10.返回 ans。

算法二:

1.定义一个函数 pascalTriangleModulus,使用给定的公式计算 Pascal's 三角形中元素的模值。

2.定义一个函数 power,使用模幂运算计算 x 的 n 次方。

3.在 ways2 函数中,将变量 n 设置为 arr 的大小,将变量 k 设置为 arr[0]-1。

4.从第二个元素开始遍历数组 arr,并根据前一个元素和当前元素之差来减小 k 的值(如果前一个元素大于当前元素)。

5.如果 k 小于等于 0,则返回 0,因为无法以有效方式对数组进行分割。

6.使用 pascalTriangleModulus 函数,参数为 k-1+n 和 n,计算结果。

7.返回结果。

总时间复杂度:

  • 算法一:process1 的时间复杂度为 $O(2^n)$ ,其中 n 是 arr 的大小。在 ways1 中,我们遍历第一个元素 arr 的每个可能的增加值和减少值,时间复杂度为 O(arr[0])。因此,总时间复杂度为 $O(arr[0] * 2^n)$。

  • 算法二:ways2 的时间复杂度为 O(n),其中 n 是 arr 的大小。pascalTriangleModulus 函数的时间复杂度为常数时间。

总空间复杂度:

  • 算法一:空间复杂度为 O(n),其中 n 是 arr 的大小,由于递归调用和函数栈的使用。

  • 算法二:空间复杂度为 O(1),因为没有使用额外的数据结构。

c++完整代码如下:

  1. #include <iostream>
  2. #include <vector>
  3. #define MOD 1000000007
  4. using namespace std;
  5. int process1(vector<int>& arr, int i, int preIncrease, int preDecrease);
  6. int ways1(vector<int>& arr) {
  7. int ans = 0;
  8. for (int increase = 1, decrease = arr[0] - 1; increase < arr[0]; increase++, decrease--) {
  9. ans += process1(arr, 1, increase, decrease);
  10. }
  11. return ans;
  12. }
  13. int process1(vector<int>& arr, int i, int preIncrease, int preDecrease) {
  14. if (i == arr.size()) {
  15. return 1;
  16. }
  17. int ans = 0;
  18. for (int increase = 1, decrease = arr[i] - 1; increase < arr[i]; increase++, decrease--) {
  19. if (preIncrease <= increase && preDecrease >= decrease) {
  20. ans += process1(arr, i + 1, increase, decrease);
  21. }
  22. }
  23. return ans;
  24. }
  25. long long power(long long x, int n);
  26. int pascalTriangleModulus(int n, int r) {
  27. long long up = 1;
  28. long long inv1 = 1;
  29. long long inv2 = 1;
  30. for (int i = 1; i <= n; i++) {
  31. up = (up * i) % MOD;
  32. if (i == r) {
  33. inv1 = power(up, MOD - 2);
  34. }
  35. if (i == n - r) {
  36. inv2 = power(up, MOD - 2);
  37. }
  38. }
  39. return (((up * inv1) % MOD) * inv2) % MOD;
  40. }
  41. long long power(long long x, int n) {
  42. long long ans = 1;
  43. while (n > 0) {
  44. if ((n & 1) == 1) {
  45. ans = (ans * x) % MOD;
  46. }
  47. x = (x * x) % MOD;
  48. n >>= 1;
  49. }
  50. return ans;
  51. }
  52. int ways2(vector<int>& arr) {
  53. int n = arr.size();
  54. int k = arr[0] - 1;
  55. for (int i = 1; i < n && k > 0; i++) {
  56. if (arr[i - 1] > arr[i]) {
  57. k -= arr[i - 1] - arr[i];
  58. }
  59. }
  60. if (k <= 0) {
  61. return 0;
  62. }
  63. return pascalTriangleModulus(k - 1 + n, n);
  64. }
  65. vector<int> randomArray(int n, int v) {
  66. vector<int> arr(n);
  67. for (int i = 0; i < n; i++) {
  68. arr[i] = rand() % v + 1;
  69. }
  70. return arr;
  71. }
  72. int main() {
  73. cout << "打印部分杨辉三角形" << endl;
  74. for (int n = 0; n <= 10; n++) {
  75. for (int r = 0; r <= n; r++) {
  76. cout << pascalTriangleModulus(n, r) << " ";
  77. }
  78. cout << endl;
  79. }
  80. int N = 10;
  81. int V = 20;
  82. int testTimes = 20000;
  83. cout << "功能测试开始" << endl;
  84. for (int i = 0; i < testTimes; i++) {
  85. int n = rand() % N + 1;
  86. vector<int> arr = randomArray(n, V);
  87. int ans1 = ways1(arr);
  88. int ans2 = ways2(arr);
  89. if (ans1 != ans2) {
  90. cout << "出错了!" << endl;
  91. }
  92. }
  93. cout << "功能测试结束" << endl;
  94. cout << "性能测试开始" << endl;
  95. int n = 10000000;
  96. int v = 10000000;
  97. cout << "随机生成的数据测试 : " << endl;
  98. cout << "数组长度 : " << n << endl;
  99. cout << "数值范围 : [" << 1 << "," << v << "]" << endl;
  100. vector<int> arr(n);
  101. for (int i = 0; i < n; i++) {
  102. arr[i] = rand() % v + 1;
  103. }
  104. clock_t start, end;
  105. start = clock();
  106. ways2(arr);
  107. end = clock();
  108. cout << "运行时间 : " << (end - start) << " 毫秒" << endl;
  109. cout << "运行最慢的数据测试 : " << endl;
  110. cout << "数组长度 : " << n << endl;
  111. cout << "数值都是 : " << v << endl;
  112. cout << "这种情况其实是复杂度最高的情况" << endl;
  113. for (int i = 0; i < n; i++) {
  114. arr[i] = v;
  115. }
  116. start = clock();
  117. ways2(arr);
  118. end = clock();
  119. cout << "运行时间 : " << (end - start) << " 毫秒" << endl;
  120. cout << "性能测试结束" << endl;
  121. return 0;
  122. }

go完整代码如下:

  1. package main
  2. import (
  3. "fmt"
  4. "math/big"
  5. "math/rand"
  6. "time"
  7. )
  8. func ways1(arr []int) int {
  9. ans := 0
  10. for increase, decrease := 1, arr[0]-1; increase < arr[0]; increase, decrease = increase+1, decrease-1 {
  11. ans += process1(arr, 1, increase, decrease)
  12. }
  13. return ans
  14. }
  15. func process1(arr []int, i, preIncrease, preDecrease int) int {
  16. if i == len(arr) {
  17. return 1
  18. }
  19. ans := 0
  20. for increase, decrease := 1, arr[i]-1; increase < arr[i]; increase, decrease = increase+1, decrease-1 {
  21. if preIncrease <= increase && preDecrease >= decrease {
  22. ans += process1(arr, i+1, increase, decrease)
  23. }
  24. }
  25. return ans
  26. }
  27. func ways2(arr []int) int {
  28. n := len(arr)
  29. k := arr[0] - 1
  30. for i := 1; i < n && k > 0; i++ {
  31. if arr[i-1] > arr[i] {
  32. k -= arr[i-1] - arr[i]
  33. }
  34. }
  35. if k <= 0 {
  36. return 0
  37. }
  38. return pascalTriangleModulus(k-1+n, n)
  39. }
  40. func pascalTriangleModulus(n, r int) int {
  41. mod := big.NewInt(1000000007)
  42. up := big.NewInt(1)
  43. inv1 := big.NewInt(1)
  44. inv2 := big.NewInt(1)
  45. for i := 1; i <= n; i++ {
  46. up.Mul(up, big.NewInt(int64(i)))
  47. if i == r {
  48. inv1.Exp(up, big.NewInt(int64(mod.Int64()-2)), mod)
  49. }
  50. if i == n-r {
  51. inv2.Exp(up, big.NewInt(int64(mod.Int64()-2)), mod)
  52. }
  53. }
  54. inv1.Mod(inv1, mod)
  55. inv2.Mod(inv2, mod)
  56. ans := new(big.Int)
  57. ans.Mul(up, inv1)
  58. ans.Mod(ans, mod)
  59. ans.Mul(ans, inv2)
  60. ans.Mod(ans, mod)
  61. return int(ans.Int64())
  62. }
  63. func power(x int64, n, mod int64) int64 {
  64. ans := int64(1)
  65. for n > 0 {
  66. if n&1 == 1 {
  67. ans = (ans * x) % mod
  68. }
  69. x = (x * x) % mod
  70. n >>= 1
  71. }
  72. return ans
  73. }
  74. func randomArray(n, v int) []int {
  75. arr := make([]int, n)
  76. rand.Seed(time.Now().UnixNano())
  77. for i := 0; i < n; i++ {
  78. arr[i] = rand.Intn(v) + 1
  79. }
  80. return arr
  81. }
  82. func main() {
  83. fmt.Println("打印部分杨辉三角形")
  84. for n := 0; n <= 10; n++ {
  85. for r := 0; r <= n; r++ {
  86. fmt.Print(pascalTriangleModulus(n, r), " ")
  87. }
  88. fmt.Println()
  89. }
  90. N := 10
  91. V := 20
  92. testTimes := 20000
  93. fmt.Println("功能测试开始")
  94. for i := 0; i < testTimes; i++ {
  95. n := rand.Intn(N) + 1
  96. arr := randomArray(n, V)
  97. ans1 := ways1(arr)
  98. ans2 := ways2(arr)
  99. if ans1 != ans2 {
  100. fmt.Println("出错了!")
  101. }
  102. }
  103. fmt.Println("功能测试结束")
  104. fmt.Println("性能测试开始")
  105. n := 10000000
  106. v := 10000000
  107. fmt.Println("随机生成的数据测试 : ")
  108. fmt.Println("数组长度 : ", n)
  109. fmt.Println("数值范围 : [", 1, ",", v, "]")
  110. arr := randomArray(n, v)
  111. start := time.Now()
  112. ways2(arr)
  113. end := time.Now()
  114. fmt.Println("运行时间 : ", end.Sub(start).Milliseconds(), " 毫秒")
  115. n -= 5
  116. v -= 5
  117. fmt.Println("运行最慢的数据测试 : ")
  118. fmt.Println("数组长度 : ", n)
  119. fmt.Println("数值都是 : ", v)
  120. fmt.Println("这种情况其实是复杂度最高的情况")
  121. for i := 0; i < n; i++ {
  122. arr[i] = v
  123. }
  124. start = time.Now()
  125. ways2(arr)
  126. end = time.Now()
  127. fmt.Println("运行时间 : ", end.Sub(start).Milliseconds(), " 毫秒")
  128. fmt.Println("性能测试结束")
  129. }

2023-07-04:给定一个数组A, 把它分成两个数组B和C 对于数组A每个i位置的数来说, A[i] = B[i] + C[i] 也就是一个数字分成两份,然后各自进入B和C 要求B[i], C[i的更多相关文章

  1. 我追一个处女座的女孩快两个月了,我之前聊得很好,她说过有空call我去看电影,过了一个月她就不理我了,我喜欢她, 我是程序员,百度发不了那么多字。

    她刚刚进公司的时候,公司组织去打球,我叫她一起去她也去了,我和她聊了很多,聊得很自然,很开心,如我是哪个学习毕业的 我出来工作多久了等,她也聊了 她自己好多,她现在在读大学,只有周日上一天课那种. 我 ...

  2. 作业帮:给定一个整数数组,找出其中两个数相加等于目标值(去重set)

    题目描述 给定一个整数数组,找出其中两个数相加等于目标值 输入 [1,3,5,7,9,11] 10 输出 1,9 3,7 代码: import java.util.HashMap; import ja ...

  3. 剑指offer40:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

    1 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 2 思路和方法 (1)异或:除了有两个数字只出现了一次,其他数字都出现了两次.异或运算中,任 ...

  4. C语言:判断t所指字符串中的字母是否由连续递增字母组成。-判断一个输入的任何整数n,是否等于某个连续正整数序列之和。-将一副扑克牌编号为1到54,以某种方式洗牌,这种方式是将这副牌分成两半,然后将他们交叉,并始终保持编号1的牌在最上方。

    //判断t所指字符串中的字母是否由连续递增字母组成. #include <stdio.h> #include <string.h> void NONO(); int fun( ...

  5. 在主方法中定义一个大小为50的一维整型数组,数组i名为x,数组中存放着{1,3,5,…,99}输出这个数组中的所有元素,每输出十个换一行

    package hanqi; import java.util.Scanner; public class Test7 { public static void main(String[] args) ...

  6. 用js编程输出100以内所有的质数和个数(提示:一个大于1的自然数,除了1和它本身外,不能被其他自然数整除的数都是质数)

    <script type="text/javascript"> for(var i = 3; i <= 100; i ++) {//控制2-100所有的数i fo ...

  7. spring-data-mongodb一个系统xml文件里面配置两个数据源

    spring-data-mongodb一个系统xml文件里面配置两个数据源 参考文档如下: http://www.iteye.com/problems/92789 http://stackoverfl ...

  8. 17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。 (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和。) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

    17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行.请采用循环控制语句来实现. (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和.) 1 1 1 1 ...

  9. 类似智能购票的demo--进入页面后默认焦点在第一个输入框,输入内容、回车、right时焦点自动跳到下一个,当跳到select时,下拉选项自动弹出,并且可以按上下键选择,选择完成后再跳到下一个。

    要实现的效果:进入页面后默认焦点在第一个输入框,输入内容.回车.right时焦点自动跳到下一个,当跳到select时,下拉选项自动弹出,并且可以按上下键选择,选择完成后再跳到下一个. PS:自己模拟的 ...

  10. 一个diff工具,用于判断两个目录下所有的改动(比较新旧版本文件夹)

    需求: 编写一个diff工具,用于判断两个目录下所有的改动 详细介绍: 有A和B两个目录,目录所在位置及层级均不确定 需要以B为基准找出两个目录中所有有改动的文件(文件或内容增加.修改.删除),将有改 ...

随机推荐

  1. Arrays.asList() 示例

    1 package Test.others; 2 3 import java.util.Arrays; 4 import java.util.Collections; 5 import java.ut ...

  2. SpringCloud导入spring boot项目当作子模块微服务IDEA不识别子module问题

    1.在父工程下面引入module. <modules> <module>study-design-mode</module> </modules> 2. ...

  3. python数据可视化神库:Matplotlib快速入门

    Matplotlib易于使用,是Python中了不起的可视化库.它建立在NumPy数组的基础上,旨在与更广泛的SciPy堆栈一起工作,并由几个图组成:线图.条形图.散点图.直方图等. 快速入门 imp ...

  4. Vue+echarts实现中国地图射线效果

    效果图如上 前提是安装Echarts并引入 并且配置中国地图json文件这些都在同账号另一篇博客上有说明,查看请自行移步 下展示代码 <template> <div class=&q ...

  5. C# 系统菜单弹出框方向

    右键菜单,tootip等弹出时,弹出的位置经常在左侧,使用体验不好. 弹出方向有左对齐和右对齐 SystemParameters.MenuDropAlignment 当右对齐时,值为false 可以在 ...

  6. etcd:增加30%的写入性能

    etcd:增加30%的写入性能 本文最终的解决方式很简单,就是将现有卷升级为支持更高IOPS的卷,但解决问题的过程值得推荐. 译自:etcd: getting 30% more write/s 我们的 ...

  7. 2022-11-24:小团在地图上放了3个定位装置,想依赖他们进行定位! 地图是一个n*n的棋盘, 有3个定位装置(x1,y1),(x2,y2),(x3,y3),每个值均在[1,n]内。 小团在(a,

    2022-11-24:小团在地图上放了3个定位装置,想依赖他们进行定位! 地图是一个n*n的棋盘, 有3个定位装置(x1,y1),(x2,y2),(x3,y3),每个值均在[1,n]内. 小团在(a, ...

  8. 2022-06-25:给定一个正数n, 表示有0~n-1号任务, 给定一个长度为n的数组time,time[i]表示i号任务做完的时间, 给定一个二维数组matrix, matrix[j] = {a,

    2022-06-25:给定一个正数n, 表示有0~n-1号任务, 给定一个长度为n的数组time,time[i]表示i号任务做完的时间, 给定一个二维数组matrix, matrix[j] = {a, ...

  9. 2021-12-16:给定两个数a和b, 第1轮,把1选择给a或者b, 第2轮,把2选择给a或者b, ... 第i轮,把i选择给a或者b。 想让a和b的值一样大,请问至少需要多少轮? 来自字节跳动。

    2021-12-16:给定两个数a和b, 第1轮,把1选择给a或者b, 第2轮,把2选择给a或者b, - 第i轮,把i选择给a或者b. 想让a和b的值一样大,请问至少需要多少轮? 来自字节跳动. 答案 ...

  10. 函数strncpy和memcpy的区别

    1定义 1.1 memcpy void *memcpy(void *destin, void *source, unsigned n); 参数 *destin ---- 需要粘贴的新数据(地址) *s ...