通过SecretSum来训练循环能力

来源:互联网 发布:淘宝延迟发货怎么赔偿 编辑:程序博客网 时间:2024/05/16 05:23

Google Gam中有一道题目是SecretSum。题目要求如下:

Problem Statement

We can substitute each digit of a number with a unique letter from 'A' to 'Z'. This way we can write groups of numbers in a single representation. For example "ABA" can represent any of the following: 101, 151, 343, 767, 929. However, "ABA" cannot mean 555 because each letter must stand for a distinct digit. Furthermore, numbers cannot begin with 0 and thus 'A' cannot be replaced by 0.

Given two such representations num1 and num2 and the result of their summation return the total number of possible combinations of numbers for which the equation holds. If no combinations are possible then return 0.

Definition 

Class: SecretSum

Method: countPossible

Parameters: string, string, string

Returns: int Method signature:

int countPossible(string num1, string num2, string result)

Constraints

num1, num2, and result will each contain exactly 3 uppercase letters ('A' - 'Z').

Examples

0)

"AAA"

"BBB"

"CCC"

Returns: 32

1)

"ABB"

"DEE"

"TTT"

Returns: 112

2)

"ABC"

"ABA"

"ACC"

Returns: 0

Leading zeroes are not allowed.

3)

"AAA"

"CDD"

"BAA"

Returns: 32

4)

"TEF"

"FET"

"AAA"

Returns: 12

5)

"ABC"

"ABC"

"BCE"

Returns: 5

We can have the following 5 sums:

124 + 124 = 248

125 + 125 = 250

249 + 249 = 498

374 + 374 = 748

375 + 375 = 750

6)

"AAA"

"AAA"

"BBB"

Returns: 4

We can have the following 4 sums:

111 + 111 = 222

222 + 222 = 444

333 + 333 = 666

444 + 444 = 888

初拿到这个题目,感觉没什么好的思路。

再仔细想想,用比较笨的方法也不错。就是做循环,顺次查找,加数一从100到999,其中每次都要求加数二从100到999的子循环,在每次循环过程中,验证数据是否合法。

看来没其它好的思路,这种循环也不错阿。

关键是条件判断如何进行了。根据题意,result<1000,这是一个条件。

然后,过滤加数一的时候,产生一个字母到数字的映射,这个映射要作用到加数二和和数。加数二在这个映射上再加工产生一个映射,然后根据这个映射判断和数是否满足条件。

这两个条件都满足了,才可以pass一种组合。(至于'A'不允许为0,我们从100开始循环就行了,这个题意我是这样理解的)。

好,java写的如下:

public class SecretSum {
    public int countPossible(String num1, String num2, String result){  
        int count = 0;
        for(int i = 100; i < 1000; i++){
            for ( int j = 100; j < 1000; j ++){
                if(isSucceed(num1,num2,result,i,j)){
                    //System.out.print(count + ":[" + i + "," + j + "]/t");
                    // if(count %5 == 0)
                    //   System.out.println();
                    count ++;
                }
            }
        }
        return count;
    }
    //输入两个数,判断是否正确
    private boolean isSucceed(String num1, String num2, String result, int n1,int n2){
        //条件一:和数要<1000
        if(n1 + n2 > 1000)
            return false;
       
        //条件二:n1,n2要和num1,num2匹配,而且有附加条件
        Map outMap = new HashMap();//附加条件,表示当前确定了的数字字母对应关系       
       
        if(samePattern(num1,n1,outMap)
           && samePattern(num2,n2,outMap)
           && samePattern(result,n1+n2,outMap)){
            return true;
        }
        return false;
    }
    private boolean samePattern(String num, int n,Map outMap) {
        //首先,察看千位数num[0]是否已固定
        String hundred = num.substring(0,1);
        String ten = num.substring(1,2);
        String one = num.substring(2,3);
        //百位数
        int val = n/100;
        if(false == mergeVal(val,hundred,outMap))
            return false;
       
        //十位数
        val = n/10;
        val %= 10;
        if(false == mergeVal(val,ten,outMap))
            return false;
       
        //个位数
        val = n%10;
        if(false == mergeVal(val,one,outMap))
            return false;
       
        return true;
    }
    boolean mergeVal(int val,String num,Map outMap){
        if(outMap.containsKey(num)){
            Integer ih =(Integer)outMap.get(num);
            if(ih.intValue()!=(val))//如果不相符合
                return false;
        }
        else//没有,则加入
        {
            Integer iVal = new Integer(val);
            //保证无冲突
            if(!outMap.containsValue(iVal))
                outMap.put(num,iVal);
            else
                return false;
        }     
        return true;
    }
}

来几个测试:

import junit.framework.TestCase;

public class SecretSumTest extends TestCase {
    public void testAAABBBCCC(){
        SecretSum ss = new SecretSum();
        int count = ss.countPossible("AAA","BBB","CCC");
        assertEquals(32, count );
    }
    public void testABBDEETTT(){
        SecretSum ss = new SecretSum();
        int count = ss.countPossible("ABB","DEE","TTT");
        assertEquals(112, count );
    }
    public void testABCABA(){
        SecretSum ss = new SecretSum();
        int count = ss.countPossible("ABC","ABA","ACC");
        assertEquals(0, count );
    }
    public void testAAACDDBAA(){
        SecretSum ss = new SecretSum();
        int count = ss.countPossible("AAA","CDD","BAA");
        assertEquals(32, count );
    }  
    public void testTEFFETAAA(){
        SecretSum ss = new SecretSum();
        int count = ss.countPossible("TEF","FET","AAA");
        assertEquals(12, count );
    }   
    public void testABCABCBCE(){
        SecretSum ss = new SecretSum();
        int count = ss.countPossible("ABC","ABC","BCE");
        assertEquals(5, count );
    }  
}

均通过。

不过耗时较长,大约用了1个小时,主要是不想用这种思路,反复的找其他的巧的思路,这样做着实比较浪费时间。

原创粉丝点击