论坛首页 综合技术论坛

来来来,有兴趣的人便来战这算法题吧:

浏览 45082 次
该帖已经被评为精华帖
作者 正文
   发表时间: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;
		} 
	}
总不能让我写程序不加错误处理吧。好像没有犯规哦。呵呵,让我钻了空子。
0 请登录后投票
   发表时间: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固然也能实现分支,能想到这点值得表扬,但是,请测试确认无误之后再来。
0 请登录后投票
   发表时间: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还有很大差距
0 请登录后投票
   发表时间: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)吧
0 请登录后投票
   发表时间: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)。
0 请登录后投票
   发表时间:2007-03-21  
想起 好像02年 北大cs考研算法卷有一道题就是这个,很像。
0 请登录后投票
   发表时间:2007-03-21  
不管是A还是B都代表两个字母的唯一一种组合
假设有一个字符串
ABAA...A
长度为m,那么实际字符串长度为2m
假设n=2m,有下面的公式
见附件
  • 大小: 649 Bytes
0 请登录后投票
   发表时间:2007-03-21  
楼上,注意审题,误解题意了。
如果是这样问题简化许多。
0 请登录后投票
   发表时间:2007-03-22  
((a-b)&(0x80000000))==0?a:b;
溢出没考虑
0 请登录后投票
   发表时间: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还是不差的嘛。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics