小言_互联网的博客

华为机试 - 堆栈中的剩余数字

361人阅读  评论(0)

目录

题目描述

输入描述

输出描述

用例

题目解析

算法源码


题目描述

向一个空栈中依次存入正整数,假设入栈元素 n(1<=n<=2^31-1)按顺序依次为 nx…n4、 n3、n2、 n1, 每当元素入栈时,如果 n1=n2+…+ny(y 的范围[2,x], 1<=x<=1000),则 n1~ny 全部元素出栈,重新入栈新元素 m(m=2*n1)。

如:依次向栈存入 6、 1、 2、 3, 当存入 6、 1、 2 时,栈底至栈顶依次为[6、 1、 2];当存入 3时, 3=2+1, 3、 2、 1 全部出栈,重新入栈元素 6(6=2*3),此时栈中有元素 6;

因为 6=6,所以两个 6 全部出栈,存入 12,最终栈中只剩一个元素 12。

输入描述

使用单个空格隔开的正整数的字符串,如”5 6 7 8″, 左边的数字先入栈,输入的正整数个数为 x, 1<=x<=1000。

输出描述

最终栈中存留的元素值,元素值使用空格隔开,如”8 7 6 5″, 栈顶数字在左边。 6 1 2 3

用例

输入 5 10 20 50 85 1
输出 1 170
说明 5+10+20+50=85, 输入 85 时, 5、 10、 20、 50、 85 全部出栈,入栈 170,最终依次出栈的数字为 1 和 170。
输入 6 7 8 13 9
输出 9 13 8 7 6
说明
输入 1 2 5 7 9 1 2 2
输出 4 1 9 14 1
说明

题目解析

这题我们先求出,以每个输入元素为结尾子区间的和,存入dp数组中。如下图dp数组所示:

然后从第1个元素开始遍历(索引0开始),对比arr[i]和dp[i-1],此时

有三种可能:

  • arr[i] === dp[i-1]
  • arr[i] > dp[i-1]
  • arr[i] < dp[i-1]

其中dp[i-1]代表arr数组0~i-1索引元素值的总和。

如果arr[i] > dp[i-1],说明arr数组0~i-1的元素即使全算上,不够arr[i]打,即无法合并。

如果arr[i] === dp[i-1],arr[i]可以和前面0~i-1个数组元素合并。此时我们可以将arr[i]更改为dp[i]的值,即2 * dp[i-1] 或者 2 * arr[i],然后将arr数组的0~i-1索引删除,如下面例子所示

如果arr[i] < dp[i-1],则说明 arr数组 在 0~i-1 中存在子区间的和  可能 等于 arr[i]。

而这个子区间的右边界又必须为i-1,因此我们只能不断退出0~i-1的头部,第一次退出arr[0],然后算arr的1~i-1区间和是否等于arr[i],若不相等,则继续退出头部arr[1],然后算arr的2~i-1的区间和是否等于arr[i],若不相等,处理同上

 若相等,则我们需要将arr[i]的值替换为 2~i-1的区间和 * 2,然后删除arr数组的 2~i-1 子序列。

算法源码


  
  1. /* JavaScript Node ACM模式 控制台输入获取 */
  2. const readline = require( "readline");
  3. const rl = readline. createInterface({
  4. input: process. stdin,
  5. output: process. stdout,
  6. });
  7. rl. on( "line", (line) => {
  8. const arr = line. split( " "). map( Number);
  9. console. log( getRemain(arr));
  10. });
  11. function getRemain( arr) {
  12. const dp = [arr[ 0]];
  13. for ( let i = 1; i < arr. length; i++) {
  14. dp[i] = arr[i] + dp[i - 1];
  15. }
  16. for ( let i = 1; i < arr. length; i++) {
  17. if (arr[i] === dp[i - 1]) {
  18. arr[i] = dp[i];
  19. arr. splice( 0, i);
  20. dp. splice( 0, i);
  21. i = 0;
  22. continue;
  23. }
  24. if (arr[i] < dp[i - 1]) {
  25. let right = i - 1;
  26. let left = i - 1;
  27. while (left >= 1) {
  28. let subSum = dp[right] - dp[left - 1];
  29. if (subSum > arr[i]) break;
  30. if (subSum === arr[i]) {
  31. arr[i] *= 2;
  32. arr. splice(left, right - left + 1);
  33. dp. splice(left, right - left + 1);
  34. i = left;
  35. break;
  36. }
  37. left--;
  38. }
  39. }
  40. }
  41. return arr. reverse(). join( " ");
  42. }

转载:https://blog.csdn.net/qfc_128220/article/details/127711549
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场