字符串切割的动态规划练习

2024-01-01

我一直在研究以下问题book http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf.

某种字符串处理语言提供了将字符串分成两部分的原始操作。由于此操作涉及复制原始字符串,因此无论剪切位置如何,长度为 n 的字符串都需要 n 个单位的时间。现在假设您想将一根绳子分成许多部分。中断的顺序会影响总运行时间。例如,如果要在位置 3 和 10 处剪切 20 个字符的字符串,则在位置 3 处进行第一次剪切的总成本为 20+17=37,而首先进行位置 10 的成本则为 20+ 10=30。

我需要一个动态编程算法,给定 m 次切割,找到将字符串切割成 m+1 块的最小成本。


在我看来,分而治之的方法似乎是解决此类问题的最佳方法。下面是该算法的 Java 实现:

Note:数组m应按升序排序(使用Arrays.sort(m);)

public int findMinCutCost(int[] m, int n) {
   int cost = n * m.length;
   for (int i=0; i<m.length; i++) {
      cost = Math.min(findMinCutCostImpl(m, n, i), cost);
   }
   return cost;
}

private int findMinCutCostImpl(int[] m, int n, int i) {
   if (m.length == 1) return n;
   int cl = 0, cr = 0;
   if (i > 0) {
      cl = Integer.MAX_VALUE;
      int[] ml = Arrays.copyOfRange(m, 0, i);
      int nl = m[i];
      for (int j=0; j<ml.length; j++) {
         cl = Math.min(findMinCutCostImpl(ml, nl, j), cl);
      }
   }
   if (i < m.length - 1) {
      cr = Integer.MAX_VALUE;
      int[] mr = Arrays.copyOfRange(m, i + 1, m.length);
      int nr = n - m[i];
      for (int j=0; j<mr.length; j++) {
         mr[j] = mr[j] - m[i];
      }
      for (int j=0; j<mr.length; j++) {
         cr = Math.min(findMinCutCostImpl(mr, nr, j), cr);
      }
   }
   return n + cl + cr;
}

例如 :

 int n = 20;
 int[] m = new int[] { 10, 3 };

 System.out.println(findMinCutCost(m, n));

会打印30

** Edit **

我已经实现了另外两种方法来回答问题中的问题。

1. 中值割近似

这种方法总是递归地切割最大的块。结果并不总是最好的解决方案,但提供了不可忽略的增益(根据我的测试,增益约为 +100000%),与最佳成本的最小切损差异可以忽略不计。

public int findMinCutCost2(int[] m, int n) {
   if (m.length == 0) return 0;
   if (m.length == 1) return n;
      float half = n/2f;
      int bestIndex = 0;
      for (int i=1; i<m.length; i++) {
         if (Math.abs(half - m[bestIndex]) > Math.abs(half - m[i])) {
            bestIndex = i;
         }
      }
      int cl = 0, cr = 0;
      if (bestIndex > 0) {
         int[] ml = Arrays.copyOfRange(m, 0, bestIndex);
         int nl = m[bestIndex];
         cl = findMinCutCost2(ml, nl);
      }
      if (bestIndex < m.length - 1) {
         int[] mr = Arrays.copyOfRange(m, bestIndex + 1, m.length);
         int nr = n - m[bestIndex];
         for (int j=0; j<mr.length; j++) {
         mr[j] = mr[j] - m[bestIndex];
      }
      cr = findMinCutCost2(mr, nr);
   }
   return n + cl + cr;
}

2. 恒定时间多次切割

代替计算成本最低,只需使用不同的索引和缓冲区。由于此方法在恒定时间内执行,因此它始终返回 n。另外,方法actually将字符串拆分为子字符串。

public int findMinCutCost3(int[] m, int n) {
   char[][] charArr = new char[m.length+1][];
   charArr[0] = new char[m[0]];
   for (int i=0, j=0, k=0; j<n; j++) {
      //charArr[i][k++] = string[j];   // string is the actual string to split
      if (i < m.length && j == m[i]) {
         if (++i >= m.length) {
            charArr[i] = new char[n - m[i-1]];
         } else {
            charArr[i] = new char[m[i] - m[i-1]];
         }
         k=0;
      }
   }
   return n;
}

Note:最后一个方法可以很容易地修改为接受String str论证而不是n并设置n = str.length(),并返回一个String[]数组来自charArr[][].

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串切割的动态规划练习 的相关文章

  • 计算 Adamic-Adar 的快速算法

    我正在研究图形分析 我想计算一个 N N 相似度矩阵 其中包含每两个顶点之间的 Adamic Adar 相似度 为了概述 Adamic Adar 让我从以下介绍开始 给定邻接矩阵A无向图的G CN是两个顶点的所有公共邻居的集合x y 两个顶
  • 地图应用的聚类算法

    我正在研究地图上的聚类点 纬度 经度 对于快速且可扩展的合适算法有什么建议吗 更具体地说 我有一系列纬度 经度坐标和一个地图视口 我正在尝试将靠近的点聚集在一起以消除混乱 我已经有了解决问题的方法 see here http bouldr
  • 所有可能的骑士在普罗梅拉的棋盘上移动

    是否有可能用马从初始位置 I J 绕过大小为 N N 的棋盘 并且只访问每个方格一次 define A True A I J false active proctype method bit I 4 bit J 3 bit K 1 bit
  • 将整数列表划分为总和相等的 K 个子列表

    类似的问题还有1 https stackoverflow com questions 27322804 partition of a set into k disjoint subsets with equal sum and 2 http
  • 给定一个点向量(可能无序),找到多边形(不是凸包)

    我目前有一个点向量 vector
  • 为什么《破解编码面试》这个例子的时间复杂度是O(k c^k)?

    该问题来自 破解编码面试 第 6 版 问题 V1 11 以下代码打印长度为 k 的所有字符串 其中字符 是按排序顺序排列的 它通过生成所有长度的字符串来做到这一点 k 然后检查每个是否已排序 什么是运行时间 package QVI 11 P
  • 当平方和为N时,如何找到四个变量的所有可能值?

    A 2 B 2 C 2 D 2 N给定一个整数N 打印出整数值的所有可能组合ABCD求解方程 我猜我们可以比暴力做得更好 天真的暴力会是这样的 n 3200724 lim sqrt n 1 for a 0 a lt lim a for b
  • 处理流星中的长服务器端计算

    我正在使用 jimp https www npmjs com package jimp https www npmjs com package jimp 在meteor JS中生成图像服务器端 换句话说 我正在使用递归算法 计算 图像的像素
  • 一种良好且简单的随机性测量方法

    获取一长整数序列 例如 100 000 个 并返回序列随机性的测量值的最佳算法是什么 该函数应返回单个结果 如果序列并非完全随机 则返回 0 如果完全随机 则返回 1 如果序列有点随机 它可以给出介于两者之间的东西 例如0 95 可能是一个
  • 从原点开始在离散 2D 网格上迭代向外螺旋的算法

    例如 这是预期螺旋的形状 以及迭代的每个步骤 y 16 15 14 13 12 17 4 3 2 11 18 5 0 1 10 x 19 6 7 8 9 20 21 22 23 24 其中线条是 x 轴和 y 轴 以下是算法每次迭代 返回
  • 线段树java实现[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 你知道 二进制 的良好实现吗线段树 http en wikipedia org wiki Segmen
  • 简单的排名算法

    我需要创建一个民意调查 按照项目的好坏顺序创建一个排名列表 我打算向每个用户展示两个项目 让他们选择一个他们认为更好的项目 然后多次重复这个过程 它有点类似于您在社交网络电影 我应该如何根据收到的答案对项目进行排名 看着那 这ELO国际象棋
  • 在任意时间范围内找到最佳日/月/年间隔的算法?

    如果您有时间表 请说 March 19 2009 July 15 2011 是否有一种算法可以将该时间范围分解为 March 19 2009 March 31 2009 complete days April 1 2009 December
  • 当给定块大小时反转单链表

    有一个单连接链表 并给出了块大小 例如 如果我的链表是1 gt 2 gt 3 gt 4 gt 5 gt 6 gt 7 gt 8 NULL我的块大小是4然后反转第一个4元素 然后是第二个 4 个元素 问题的输出应该是4 gt 3 gt 2 g
  • 坐标算法 - 绕中心旋转

    通过查看这张图片 我想您会很好地理解我的问题 图片已删除 网址不再有效 现在返回广告 所以基本上我想要一个函数 它接受一个对象作为参数 并根据我之前添加的对象数量为该对象提供正确的坐标 假设我将所有这些对象添加到一个数组中 objectAr
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 如何计算 3D Morton 数(交织 3 个整数的位)

    我正在寻找一种快速计算 3D Morton 数的方法 这个网站 http www graphics stanford edu seander bithacks html InterleaveBMN有一个基于幻数的技巧来处理 2D Morto
  • 贝尔曼福特算法可以有任意的边顺序吗?

    我刚刚开始学习新算法 但当我阅读 极客为极客而写的贝尔曼福特算法 时 我陷入了困境 http www geeksforgeeks org dynamic programming set 23 bellman ford algorithm h
  • 在树结构的 Big-O 表示法中:为什么有些来源引用 O(logN),有些来源引用 O(h)?

    在研究遍历二叉搜索树的任何算法的复杂性时 我看到两种不同的方式来表达同一件事 版本 1 最坏情况下的遍历算法对树的每个高度进行一次比较 因此复杂度是O h 版本 2 最坏情况下的遍历算法对树的每个高度进行一次比较 因此复杂度是O logN
  • 测试 python Counter 是否包含在另一个 Counter 中

    如何测试是否是pythonCounter https docs python org 2 library collections html collections Counter is 包含在另一个中使用以下定义 柜台a包含在计数器中b当且

随机推荐