有道难题之eaglet的算法

 
有道难题之eaglet的算法

刚才在园子里看到 周利华关于 "有道难题"的两道题的算法,eaglet 做了一下,第一题比周利华的算法快10倍左右,第二天快100倍左右。由于eaglet不符合参赛条件,所以就在博客园和大家交流交流吧。

原帖链接  

 

 

第一道算法题(250分)

      话 说你在走路上班时,经过一片种植萝卜的农田。这块田地的形状是一个矩形的网格。field的第i个元素的第j个字符,表示田地的第i 行第j列的格子里包含的萝卜的数目。我们定义一个格子的特殊程度为它周围所有格子的萝卜个数的和; 它周围的格子包含它上下左右以及对角相邻的格子,最多有8个,在田地的边界上的格子会少一些。如果一个格子周围没有别的格子,则它的特殊程度为0。
请返回田地中特殊程度在A和B之间的所有格子的数目(包含A,B)。
Definition
      Class:  NumberField
Method:  countSpecialNumbers
Parameters:  string[], int, int
Returns:  int
Method signature:  int countSpecialNumbers(string[] field, int A, int B)
(be sure your method is public)

      
 
Constraints
-  field 包含1个到50个元素,含1和50。
-  field的每个元素包含1个到50个字符,含1和50。
-  field的每个元素包含相同的字符数。
-  field的每个元素的字符均为’0’到’9’之一。
-  A的范围会在0到100之间,含0和100。
-  B 的范围会在A到100之间,含A和100。
Examples
0)  
      {"111",
 "111",
 "111"}
4
8

Returns: 5
在这块田地里面,位于角落的格子的特殊程度是3,位于中间的格子的特殊程度是8,其他4个格子的特殊程度为5。


1)  
      {"111",
 "141",
 "111"}
4
8

Returns: 9
现在所有的9个格子都满足要求。


2)  
      {"2309",
 "0239",
 "2314"}
5
7

Returns: 3

 

3)  
      {"924",
 "231",
 "390",
 "910",
 "121"}
31
36

Returns: 0

 

4)  
      {"5"}
3
8

Returns: 0

 

5)  
      {"1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890",
 "1234567890"}
3
18

Returns: 26

下面是eaglet 的算法。

 

     class  T1
    
{
        
///   <summary>
        
///  获取第i,j格的特殊程度
        
///   </summary>
        
///   <param name="field"></param>
        
///   <param name="i"></param>
        
///   <param name="j"></param>
        
///   <returns></returns>
        
///   <author> eaglet </author>

         static   private   int  GetSpecialNumbers( string [] field,  int  width,  int  i,  int  j)
        
{
            
int  y  =  i  -   1   >=   0   ?  i  -   1 0 ;
            
int  sum  =   0 ;

            
while  (y  <=  i  +   1   &&  y  <  field.Length)
            
{
                
int  x  =  j  -   1   >=   0   ?  j  -   1  :  0 ;

                
while  (x  <=  j  +   1   &&  x  <  width)
                
{
                    
if  (x  !=  j  ||  y  !=  i)
                    
{
                        sum 
+=  field[y][x]  -   ' 0 ' ;
                    }


                    x
++ ;
                }


                y
++ ;
            }


            
return  sum;
        }


        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="field"></param>
        
///   <param name="A"></param>
        
///   <param name="B"></param>
        
///   <returns></returns>
        
///   <author> eaglet </author>

         static   public   int  countSpecialNumbers( string [] field,  int  A,  int  B)
        
{
            
// Check paramaters
             if  (field  ==   null )
            
{
                
return   0 ;
            }


            
if  (field.Length  ==   0 )
            
{
                
return   0 ;
            }


            
int  width  =  field[ 0 ].Length;

            
if  (width  ==   0 )
            
{
                
return   0 ;
            }


            
if  (A  >  B)
            
{
                
throw   new  ArgumentException( " A > B " );
            }


            
// Begin calculate
             int  count  =   0 ;

            
for  ( int  i  =   0 ; i  <  field.Length; i ++ )
            
{
                
for  ( int  j  =   0 ; j  <  field[i].Length; j ++ )
                
{
                    
int  number  =  GetSpecialNumbers(field, width, i, j);

                    
if  (number  >=  A  &&  number  <=  B)
                    
{
                        count
++ ;
                    }

                }

            }


            
return  count;
        }

    }

 

 测试代码

Code

 

 测试结果 //重复执行10000次

eaglet 的算法
5
9
3
0
0
26
用时1439毫秒 //0.1439毫秒每次
周利华 的算法
5
9
3
0
0
26
用时18205毫秒
西狐.Net 的算法
5
9
3
0
0
26
用时31902毫秒

 

      
 
Constraints
-  n取值范围为1到1,000,000,000(含)
Examples
0)  
      1

Returns: 0


1)  
      1729

Returns: 1
1729=1^3+12^3
1729=9^3+10^3


2)  
      475574

Returns: 27

 

 eaglet 的代码

 

     class  T2
    
{
        
static  List < int >  _CubeCache  =   new  List < int > ();
        
static  Dictionary < int int >  _CubeCountDict  =   new  Dictionary < int int > ();

        
///   <summary>
        
///  
        
///   </summary>
        
///   <param name="n"></param>
        
///   <returns></returns>
        
///   <author> eaglet </author>

         static   public   int  count( int  n)
        
{
            
if  (n  <   0 )
            
{
                
return   0 ;
            }


            _CubeCountDict.Clear();

            
// b <= n 的 3 次方根
             int  max_b  =  ( int )Math.Pow(( double )n, 1f  /   3 );

            
// 构造整数三次方计算缓存
             for  ( int  i  =  _CubeCache.Count; i  <=  max_b; i ++ )
            
{
                _CubeCache.Add(i 
*  i  *  i);
            }


            
            
int  count  =   0 ;
            
int  a  =   1 // 正整数
             int  b  =  a;
            
int  sumCube;
            sumCube 
=  _CubeCache[a]  +  _CubeCache[b];

            
do
            
{
                
// 计算 a^3+b^3
                 while  (sumCube  <=  n)
                
{
                    
int  hit;

                    
// 看hash表中有没有已经存在的记录
                     if  (_CubeCountDict.TryGetValue(sumCube,  out  hit))
                    
{
                        
// 存在,且只击中了1次,则计数加1
                         if  (hit  ==   1 )
                        
{
                            count
++ ;
                        }


                        
// 击中超过1次,计数减1
                        
// 存在三组或以上组合相等的情况时走到这个分支
                         if  (hit  ==   2 )
                        
{
                            count
-- ;
                        }


                        
// 击中数加一
                        _CubeCountDict[sumCube] ++ ;
                    }

                    
else
                    
{
                        _CubeCountDict.Add(sumCube, 
1 );
                    }


                    b
++ ;

                    
if  (b  >  max_b)
                    
{
                        
break ;
                    }


                    sumCube 
=  _CubeCache[a]  +  _CubeCache[b];
                }


                a
++ ;
                b 
=  a;

                
if  (b  >  max_b)
                
{
                    
break ;
                }


                sumCube 
=  _CubeCache[a]  +  _CubeCache[b];
            }

            
while  (sumCube  <=  n);
 
            
return  count;
        }

    }

 

 测试代码

Code

 

 测试结果 //重复执行1000次

eaglet 的算法
0
1
27
用时262毫秒 //0.262毫秒每次
周利华 的算法
0
1
27
用时21770毫秒

备 注: 由于是算法题,eaglet 对一些参数的检查没有做的很完整,另外没有做线程安全设计,这些已经超出了算法考察的范围,希望大家把讨论的重点放在算法上,eaglet 水平有限,相信园子里像老赵这样的高手应该大把大把的,eaglet热切希望能看到比这个跑的更快的算法出现。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值