锁定老帖子 主题:来来来,有兴趣的人便来战这算法题吧:
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-09-08
public static int max(int num1,int num2);{ try{ int tmp=num1-num2; byte[] array= new byte[tmp]; return num1; } catch(Exception ex);{ return num2; } }总不能让我写程序不加错误处理吧。好像没有犯规哦。呵呵,让我钻了空子。 |
|
返回顶楼 | |
发表时间:2005-09-09
mooniscrazy 写道 public static int max(int num1,int num2);{ try{ int tmp=num1-num2; byte[] array= new byte[tmp]; return num1; } catch(Exception ex);{ return num2; } }总不能让我写程序不加错误处理吧。好像没有犯规哦。呵呵,让我钻了空子。 try...catch固然也能实现分支,能想到这点值得表扬,但是,请测试确认无误之后再来。 |
|
返回顶楼 | |
发表时间:2007-03-20
/** * */ package study.puzzle.sample1; import java.util.*; import junit.framework.TestCase; /** * DOCUMENT ME! * * @author Godlikeme 2007-3-20 */ public class Algorithm1Test extends TestCase { public void testCompute() throws Exception { // assertEquals(,Algorithm.compute("")); assertEquals(1, Algorithm.compute("A")); assertEquals(1, Algorithm.compute("B")); assertEquals(1, Algorithm.compute("AA")); assertEquals(2, Algorithm.compute("AB")); assertEquals(2, Algorithm.compute("BA")); assertEquals(1, Algorithm.compute("BB")); assertEquals(1, Algorithm.compute("AAA")); assertEquals(3, Algorithm.compute("AAB")); assertEquals(5, Algorithm.compute("ABA")); assertEquals(3, Algorithm.compute("ABB")); assertEquals(3, Algorithm.compute("BAA")); assertEquals(5, Algorithm.compute("BAB")); assertEquals(3, Algorithm.compute("BBA")); assertEquals(1, Algorithm.compute("BBB")); assertEquals(1, Algorithm.compute("AAAA")); assertEquals(4, Algorithm.compute("AAAB")); assertEquals(9, Algorithm.compute("AABA")); assertEquals(6, Algorithm.compute("AABB")); assertEquals(9, Algorithm.compute("ABAA")); assertEquals(16, Algorithm.compute("ABAB")); assertEquals(11, Algorithm.compute("ABBA")); assertEquals(4, Algorithm.compute("ABBB")); assertEquals(1, Algorithm.compute("AAAA")); assertEquals(1, Algorithm.compute("BBBB")); assertEquals(1, Algorithm.compute("BBBBBBBBBBBBBBBBB")); assertEquals(1, Algorithm.compute("AAAAAAAAAAAAAAAAAAA")); assertEquals(40932737,Algorithm.compute("AAAAABBAABBAAAAA")); }} /** * * 假设有这样一种字符串,它们的长度不大于 26 ,而且若一个这样的字符串其长度为 m ,则这个字符串必定由 a, b, c ... z 中的前 m * 个字母构成,同时我们保证每个字母出现且仅出现一次。比方说某个字符串长度为 5 ,那么它一定是由 a, b, c, d, e 这 5 * 个字母构成,不会多一个也不会少一个。嗯嗯,这样一来,一旦长度确定,这个字符串中有哪些字母也就确定了,唯一的区别就是这些字母的前后顺序而已。 * 现在我们用一个由大写字母 A 和 B 构成的序列来描述这类字符串里各个字母的前后顺序: 如果字母 b 在字母 a 的后面,那么序列的第一个字母就是 A * (After),否则序列的第一个字母就是 B (Before); 如果字母 c 在字母 b 的后面,那么序列的第二个字母就是 A ,否则就是 B; * 如果字母 d 在字母 c 的后面,那么 …… 不用多说了吧?直到这个字符串的结束。 这规则甚是简单,不过有个问题就是同一个 AB * 序列,可能有多个字符串都与之相符,比方说序列“ABA”,就有“acdb”、“cadb”等等好几种可能性。说的专业一点,这一个序列实际上对应了一个字符串集合。 * 那么现在问题来了:给你一个这样的 * AB 序列,问你究竟有多少个不同的字符串能够与之相符?或者说这个序列对应的字符串集合有多大? * 注意,只要求个数,不要求枚举所有的字符串。 * */ abstract class Algorithm { public static int compute(String sequenceStr) { return Algorithm.calcPossible(sequenceStr, 0, 0); } /** * * a bit like binary tree. * @param sequenceStr * @param left * @param right * @return */ private static int calcPossible(String sequenceStr, int left, int right) { if (sequenceStr.length() == 1) { if (sequenceStr.equalsIgnoreCase("A")) return right + 1; else if (sequenceStr.equalsIgnoreCase("B")) return left + 1; } if (sequenceStr.substring(0, 1).equalsIgnoreCase("A")) { int result = 0; for (int i = 0; i <= right; i++) { result += calcPossible(sequenceStr.substring(1), left + i + 1, right - i); } return result; } else if (sequenceStr.substring(0, 1).equalsIgnoreCase("B")) { int result = 0; for (int i = 0; i <= left; i++) { result += calcPossible(sequenceStr.substring(1), left - i, right + i + 1); } return result; } else { throw new IllegalArgumentException(); } } } 距离n^3还有很大差距 |
|
返回顶楼 | |
发表时间:2007-03-21
abstract class Algorithm { public static int compute(String sequenceStr) { matrix=new int[sequenceStr.length()][sequenceStr.length()]; return Algorithm.calcPossible(sequenceStr, 0, 0); } static int[][] matrix;// a memory matrix for fast calc; private static int calcPossible(String sequenceStr, int left, int right) { if (sequenceStr.length() == 1) { if (sequenceStr.equalsIgnoreCase("A")) return right + 1; else if (sequenceStr.equalsIgnoreCase("B")) return left + 1; } if (sequenceStr.substring(0, 1).equalsIgnoreCase("A")) { if(matrix[left][right]!=0) return matrix[left][right]; int result = 0; for (int i = 0; i <= right; i++) { result += calcPossible(sequenceStr.substring(1), left + i + 1, right - i); } matrix[left][right]=result; return result; } else if (sequenceStr.substring(0, 1).equalsIgnoreCase("B")) { if(matrix[right][left]!=0) return matrix[right][left]; int result = 0; for (int i = 0; i <= left; i++) { result += calcPossible(sequenceStr.substring(1), left - i, right + i + 1); } matrix[right][left]=result; return result; } else { throw new IllegalArgumentException(); } } } 有待验证。。。接近O(n^3)吧 |
|
返回顶楼 | |
发表时间:2007-03-21
abstract class Algorithm1 { public static BigDecimal compute(String sequenceStr) { matrix = new BigDecimal[sequenceStr.length()][sequenceStr.length()]; return Algorithm1.calcPossible(sequenceStr, 0, 0); } static BigDecimal[][] matrix;// a memory matrix for fast calc; private static BigDecimal calcPossible(String sequenceStr, int left, int right) { if (sequenceStr.length() == 1) { if (sequenceStr.equalsIgnoreCase("A")) return new BigDecimal(right + 1); else if (sequenceStr.equalsIgnoreCase("B")) return new BigDecimal(left + 1); } if (sequenceStr.substring(0, 1).equalsIgnoreCase("A")) { if (matrix[left][right] != null) return matrix[left][right]; BigDecimal result = new BigDecimal(0); for (int i = 0; i <= right; i++) { result=result.add(calcPossible(sequenceStr.substring(1), left + i + 1, right - i)); } matrix[left][right] = result; return result; } else if (sequenceStr.substring(0, 1).equalsIgnoreCase("B")) { if (matrix[right][left] != null) return matrix[right][left]; BigDecimal result = new BigDecimal(0); for (int i = 0; i <= left; i++) { result=result.add(calcPossible(sequenceStr.substring(1), left - i, right + i + 1)); } matrix[right][left] = result; return result; } else { throw new IllegalArgumentException(); } } } assertEquals( "77961101052771906279054003892476957478231542072323497761785202067698072199176691641558426633749048526359312876540673943650496621566256840081699153379703191232351264431848226789053430627229534974255679805774570964054601540378538438843097861227735459941778654699563308336374269767832682962176221580822415371619054678180592255250557108283479859134366715129117248030015013252495410340365746159653594812237689092688329502816565884197840680643248615557790386065427220993356310034524724459592233757880705810389624854250116398499956155395244214595828664435566808211796623188", Algorithm1 .compute( "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "AAAAAABBBBBBBBAAAAAAAAABBBBBBBBAAAAAAAAABBBBBB" + "").toString()); 最后版本,不到400字串 7秒。后来发现是楼主算法的一个变种,也是O(n^2)。 |
|
返回顶楼 | |
发表时间:2007-03-21
想起 好像02年 北大cs考研算法卷有一道题就是这个,很像。
|
|
返回顶楼 | |
发表时间:2007-03-21
不管是A还是B都代表两个字母的唯一一种组合
假设有一个字符串 ABAA...A 长度为m,那么实际字符串长度为2m 假设n=2m,有下面的公式 见附件 |
|
返回顶楼 | |
发表时间:2007-03-21
楼上,注意审题,误解题意了。
如果是这样问题简化许多。 |
|
返回顶楼 | |
发表时间:2007-03-22
((a-b)&(0x80000000))==0?a:b;
溢出没考虑 |
|
返回顶楼 | |
发表时间:2007-03-22
Elminster 写道 最后总结一下吧:
实际上这个问题的算法直接做是 O(n^3) 的,做些优化之后可以到 O(n^2)。这里的关键是只考虑可能性而不要去想具体如何插入:请在脑子里面建一张三角形的表,每一行对应于 AB 字符串中的一个字符,每一行中第 i 个元素代表了到目前为止最后一个字母放在第 i 个位置的可能性个数。比方说: A: 0 1 B: 1 1 0 A: 0 1 2 2 这里第一行 A ,当前最后一个字母是 b ,b 放在第 0 个位置的可能性个数是 0 ,放在第 1 个位置的可能性个数是 1 ;第二行 B ,当前最后一个字母是 c ,放在第 0、1 两个位置的可能性个数都是 1 ,放在最后一个位置的可能性是 0 …… 依此类推。很容易可以看出,如果当前行的次序是 A ,那么放在第 i 个位置的可能性就是上一行从 0 到 i-1 位置的可能性个数之和,否则就是从 i 到最后一个位置的可能性个数之和。逐步向下做,直到用完输入的 AB 字符串即可,最后的总数就是对上述表格最后一行求个和。这里每一行中各个列的可能性是没有重叠的,因为最后一个字母的位置各不相同。 复杂度么,这个表格一共有 O(n^2) 项,每一格构造最多花 O(n) ,所以总复杂度自然是 O(n^3) ,稍做优化可以把计算每一格的开销降到 O(1) ,复杂度可以降到 O(n^2) 。这里给个参考实现 —— C++ 写的,不熟悉的朋友只能说见谅了,好在还算简单,没用什么特殊的东西: 向老榆树致敬! 咱算法菜,充当一把coder,把算法写成ruby def count(input) probs = Array.new(input.length+1) probs[0] = 1 for i in 0...input.length if input[i]==?A save, probs[0] = probs[0], 0 for j in 1..i+1 save, probs[j] = probs[j], probs[j-1]+save end else probs[i+1] = 0 i.downto(0) do |j| probs[j] += probs[j+1] end end end probs.inject(0){|sum,i|sum+i} end class CountTest < RUNIT::TestCase def testCount assert_equals(11, count('ABBA')) assert_equals(16, count('ABAB')) assert_equals(4, count('ABBB')) assert_equals(9, count('AABA')) end end 似乎不需要vector之类的动态内存分配。只需要一个预先分配的数组存放当前行的概率就够了。 楼上的n=369基本上在0.02秒之内。看来ruby还是不差的嘛。 |
|
返回顶楼 | |