• "有道难题"之ealget的算法


    有道难题之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 - 10;
                
    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<intint> _CubeCountDict = new Dictionary<intint>();

            
    /// <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热切希望能看到比这个跑的更快的算法出现。

  • 相关阅读:
    django 一对多操作
    django 单表常用操作
    element-ui
    vue与后台交互之post用法
    pip换国内源
    TCP/UDP的理解
    进程/线程/协程的理解
    《手牵手带你走进python世界》系列四
    《手牵手带你走进python世界》系列五
    《手牵手带你走进python世界》系列三
  • 原文地址:https://www.cnblogs.com/eaglet/p/1493801.html
Copyright © 2020-2023  润新知