一个计算数字的步数算法

这两天看了下某位大神的github,知道他对算法比较感兴趣,看了其中的一个计算数字的步数算法,感觉这个有点意思,所以就自己实现了一个

算法描述与实现原理

给出一个整型数字,统计出有多少种走法可以到达目标,比如一个数字4,可以有下面几种走法

    [ 1, 3 ]
        [ 4 ]
    [ 1, 1, 2 ]
        [ 2, 2 ]
    [ 1, 1, 1, 1 ]

其实通过上面的组合可以得出下面的结论

  • 先列出所有项是1的组合
  • 依次从左到右项为1的组合
  • 递归上面的集合,找出项里1的索引,然后计算左起2项的值,结果递归此操作
  • 排除1和2的情况

下面先提供三个工具函数

// 计算数组内的值
function calculate(arg){
    return eval(arg.join('+'));
}

// 输出数组的值
function print(arg){
    for(var i = 0; i < arg.length; i++){
        console.log(arg[i]);
    }
}

// 检查是否是正反的走法
function hasRepeat(src, dist){
    if (dist.length != 2) return false;
    for(var i = 0, len = src.length; i < len ; i++){
        if(dist.length == src[i].length){
            if(dist[0] == src[i][1]){
                return true;
            }
        }
    }
    return false;
}

下面贴出算法的实现

function countSteps(n){
    var counts = 0,i,j = 0;
    var result = [];
    var newresult = [];
    var source = [];
    var temparg = [];
    // 生成项全为1的数组
    for(i = 1; i <= n ; i++){
        source.push(1);
    }
    if(n > 2){
        for(j = 1; j < n - 1; j++){
            temparg.length = 0;
            if(j < n - 1){
                // 生成从左到右项为1递增的数组
                // 1.. 11.. 111..
                Array.prototype.push.apply(temparg, source.slice(0, j));
                temparg.push(calculate(source.slice(j,n)));
                result.push(temparg.slice(0));
                // 递归数组里的内容,直到项里没有1为止
                combine(temparg.slice(0));
            }
        }
    }
    // 组合包含1的数组项
    // 111->21->3
    function combine(arg){
        var linearg = [];
        for(var i = 0; i < arg.length; i++){
            if(arg[i] == 1){
                if(i ==0 || i == 1){
                    linearg.push(calculate(arg.slice(0,2)));
                    Array.prototype.push.apply(linearg, arg.slice(2, arg.length));
                    if(!hasRepeat(result, linearg)){
                        result.push(linearg);
                        combine(linearg.slice(0));
                    }
                    return;
                }
            }
        }
    }
    //为2的时候比1要多一项
    if(n == 2){
        result.push([2]);
    }
    // 添加全为1的情况
    result.push(source);
    // 输出所有步
    print(result);
    console.log('总共有:' + result.length + '种走法');
}

// 运行
countSteps(4);

// 输出下面内容
/*
    [ 1, 3 ]
    [ 4 ]
    [ 1, 1, 2 ]
    [ 2, 2 ]
    [ 1, 1, 1, 1 ]
    总共有:5种走
*/

总结

这个算法其实可以应用到某类游戏中去,当两个物体之前的距离一定的话,对所有的可能进行业务处理,当然也可以应用到别的地方,虽然大部分前端工程师对算法的实践比较少,不过它还是有存在的价值的,很多UI细节方面其实都运用了算法,以后有空还会贴更多关于算法相关的文章,欢迎大家多提些宝贵意见.

时间: 2024-11-01 20:57:54

一个计算数字的步数算法的相关文章

JavaScript实现的一个计算数字步数的算法分享_javascript技巧

这两天看了下某位大神的github,知道他对算法比较感兴趣,看了其中的一个计算数字的步数算法,感觉这个有点意思,所以就自己实现了一个. 算法描述与实现原理 给出一个整型数字,统计出有多少种走法可以到达目标,比如一个数字4,可以有下面几种走法 复制代码 代码如下:     [ 1, 3 ]         [ 4 ]     [ 1, 1, 2 ]         [ 2, 2 ]     [ 1, 1, 1, 1 ] 其实通过上面的组合可以得出下面的结论. 1.先列出所有项是1的组合 2.依次从

一个计算数字数组概览的算法2

在先前的博文中提到了如何自己写一个算法来实现该功能.虽然算法很简单,但毕竟需要自己实现.如果用objc的话,其Foundation中自带了NSIndexSet和NSMutableIndexSet类,可以很方便的为我们解决这个问题: NSMutableIndexSet *set = [NSMutableIndexSet indexSet]; NSArray *ary = @[@0,@1,@2,@3,@5,@7,@8,@9,@27]; for(NSNumber *n in ary){ [set ad

一个计算数字数组概览的算法

已知数组 a = [0,1,2,3,5,7,8,9] 要求输入其"概览" [0..3,5,7..9] 用ruby实现如下: def sum_ary(ary) tmp = [] start_v,end_v=-1,-1 is_start = false idx = 0 count = ary.count ary.each_with_index do |v,i| if(i+1<count) sub = ary[i+1] - v if(sub == 1) if(is_start) nex

算法 全排列 动态规划-有一个由数字1,2,3,4,5,6,7,8,9组成的数字串(长度不超过200),问如何将M个加号插入这个串中

问题描述 有一个由数字1,2,3,4,5,6,7,8,9组成的数字串(长度不超过200),问如何将M个加号插入这个串中 所得的算术表达式的值最小,加号不能加在数字串的最前面或最末尾,也不应有两个或两个以上的加号相邻 解决方案 什么语言啊?没分给吗? 解决方案二: 什么语言啊?没分给吗? 解决方案三: VB.NET假定你的字符串变量名是TXTDIM TXT1DIM NEWTXT AS STRINGDIM A AS INT32FOR A=1 TO LEN(TXT)IF A=LEN(TXT) THEN

量子计算核心突破!Shor算法实现或使密码成摆设

文章来源:新智元微信公众号 互联网时代绝大多数的加密,都由RSA算法完成.过去我们认为RSA不可破解,但随着量子计算的发展,RSA的安全性正受到挑战.今天刊发在<科学>杂志的最新论文,量子计算机有史以来第一次以可扩展的方式,用Shor算法完成对数字15的质因数分解.IBM 物理科学高级主管Mark Ritter表示,将Shor算法实现出来这件事,能够与经典计算中的'Hello,World' 相提并论. 互联网时代,密码和网络安全是通信的基础,无论是微信聊天,还是淘宝交易,都需要密码技术保障个人

关于统计数字问题的算法_C 语言

一本书的页码从自然数1开始顺序编码直到自然数n.书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0.例如第6页用6表示而不是06或006.数字统计问题要求对给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,3,.....9. 这个题目有个最容易想到的n*log10(n)的算法.这是自己写的复杂度为O(n*log10(n))的代码: void statNumber(int n) { int i, t; int count[10] = {0}; for(i = 1; i <=

下个2的幂-一个简单而优雅的算法优化介绍

在并行计算和图形图像等处理中,经常会遇到一类叫做"下个2的幂"的问题,简单说来就是给定一个数,需要找到满足如下条件的一个数: 1. 最靠近这个数 2. 大于或等于这个数 3. 是2的N次方 简单函数描述就是int nextPowerOfTwo(int num); 首先想到的一般算法可能是: int nextPowerOfTwo(int num) { int npot = 1; while( npot < num ) npot <<= 1; return npot; }

求一个(c#)派工的算法

问题描述 问题描叙:此软件为一服装公司车间工人的计件工资管理系统,公司主要是团体职业装定制业务,也就是说业务员拿定单后然后给客户做工服.一个定单包括多个品种,如(毛料高档春秋西服上衣(MGCX/S),化纤高档夏装裤子(HGXX/K)).车间制造是采用流水线制造的方式,分上衣组,裤子组等,每个组的人员是相对固定的,也就是说每个人做哪些工序是固定的,每个人做的工序的工价规定,那么我要实现的功能包括:(1)计算每个工人每个月的工资,其中要知道每一个工人每一天干了多少活?(2)要记录每个工人每一天做了哪

asp.net下计算数字1至10的总和_实用技巧

复制代码 代码如下: protected void Page_Load(object sender, EventArgs e) { Response.Write(string.Format("数字1~10总和等于{0}.", Sum(1, 10).ToString())); } private int Sum(int min, int max) { int s = 0; for (int i = min; i <= max; i++) { s += i; } return s;