热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP如何递归算法?

题目{代码...}回答如何把以下代码简化,因为$i~$iN是不确定的。如果有其他算法更好{代码...}2015-8-23一种算法,查看分布。(byCSDN某大牛){代码...}{代码...}
题目
有一个数组,由30个1~999键值组成,和为 12865,请写出计算此数组的 30 个值的方法
$arr[1]+$arr[2]+....+$arr[30]=12865
回答

如何把以下代码简化,因为 $i ~ $iN 是不确定的。如果有其他算法更好


function loopDeep($sum , $count, $min, $max)
{
    for ($i = $min; $i <$max; $i++) {
        for ($i2 = $min; $i2 <$max; $i2++) {
            for ($i3 = $min; $i3 <$max; $i3++) {
                for ($i4 = $min; $i4 <$max; $i4++) {
                    if ($i + $i2 + $i3 + $i4 == $sum) {
                        return [$i, $i2, $i3];
                    }
                }
            }
        }
    }
    
    return [];
}

2015-8-23 一种算法,查看分布。(by CSDN某大牛)


$r = foo(12865, 30);
echo array_sum($r), PHP_EOL; //验证总和
print_r(array_count_values($r)); //查看分布

function foo($num, $k, $min = 1, $max = 999)
{
    $res = array_fill(0, $k, 1);
    do {
        for ($i = 0; $i <$k; $i++) {
            $sum = array_sum($res);
            $t = rand(0, $max - $min);
            if ($res[$i] + $t > $max) $t = $max - $res[$i];
            if ($sum + $t > $num) $t = $num - $sum;
            $res[$i] += $t;
        }
    } while ($num > $sum);

    return $res;
}
12865
Array
(
    [222] => 2
    [589] => 1
    [127] => 1
    [538] => 1
    [268] => 1
    [444] => 1
    [922] => 1
    [537] => 1
    [211] => 1
    [17] => 1
    [848] => 1
    [800] => 1
    [893] => 1
    [274] => 1
    [499] => 1
    [45] => 1
    [660] => 1
    [686] => 1
    [968] => 1
    [491] => 1
    [355] => 1
    [849] => 1
    [857] => 1
    [322] => 1
    [217] => 1
    [1] => 4
)

回复内容:

题目
有一个数组,由30个1~999键值组成,和为 12865,请写出计算此数组的 30 个值的方法
$arr[1]+$arr[2]+....+$arr[30]=12865
回答

如何把以下代码简化,因为 $i ~ $iN 是不确定的。如果有其他算法更好


function loopDeep($sum , $count, $min, $max)
{
    for ($i = $min; $i <$max; $i++) {
        for ($i2 = $min; $i2 <$max; $i2++) {
            for ($i3 = $min; $i3 <$max; $i3++) {
                for ($i4 = $min; $i4 <$max; $i4++) {
                    if ($i + $i2 + $i3 + $i4 == $sum) {
                        return [$i, $i2, $i3];
                    }
                }
            }
        }
    }
    
    return [];
}

2015-8-23 一种算法,查看分布。(by CSDN某大牛)


$r = foo(12865, 30);
echo array_sum($r), PHP_EOL; //验证总和
print_r(array_count_values($r)); //查看分布

function foo($num, $k, $min = 1, $max = 999)
{
    $res = array_fill(0, $k, 1);
    do {
        for ($i = 0; $i <$k; $i++) {
            $sum = array_sum($res);
            $t = rand(0, $max - $min);
            if ($res[$i] + $t > $max) $t = $max - $res[$i];
            if ($sum + $t > $num) $t = $num - $sum;
            $res[$i] += $t;
        }
    } while ($num > $sum);

    return $res;
}
12865
Array
(
    [222] => 2
    [589] => 1
    [127] => 1
    [538] => 1
    [268] => 1
    [444] => 1
    [922] => 1
    [537] => 1
    [211] => 1
    [17] => 1
    [848] => 1
    [800] => 1
    [893] => 1
    [274] => 1
    [499] => 1
    [45] => 1
    [660] => 1
    [686] => 1
    [968] => 1
    [491] => 1
    [355] => 1
    [849] => 1
    [857] => 1
    [322] => 1
    [217] => 1
    [1] => 4
)

正准备睡觉,瞬间有了思路。。。
先来个js版本的---我是前端(:

function forFn($i,$max,$sum,$sum_end,$loop_num,$loop_index,$indexArr){
    if($loop_index==$loop_num){
        if($sum==$sum_end){
console.log('///$sum:'+$sum+'/$sum_end:'+$sum_end+'/$indexArr:'+$indexArr+'/$loop_index:'+$loop_index);
        }
        return false;
    }else{
        for(var $ii=$i;$ii<=$max;$ii++){
            $indexArr[$loop_index]=$ii;
            if($indexArr[$loop_index]>($max-$loop_num+1+$loop_index)){
                break;
            }
            $sum=eval($indexArr.join("+"));
console.log('$sum:'+$sum+'/$sum_end:'+$sum_end+'/$loop_index:'+$loop_index+'/$ii:'+$ii+'/$indexArr:'+$indexArr);
            forFn($ii+1,$max,$sum,$sum_end,$loop_num,$loop_index+1,$indexArr);
        }
    }
};
function addFn($min,$max,$sum,$sum_end,$loop_num,$loop_index,$indexArr){
    for(var $i=$min;$i<=$max-$loop_num+1;$i++){
        var $loop_index=0;
        $indexArr[$loop_index]=$i;
        forFn($i+1,$max,$sum,$sum_end,$loop_num,$loop_index+1,$indexArr)
    }
}

addFn(0,999,0,12865,30,0,[])

php:


function forFn($i,$max,$sum,$sum_end,$loop_num,$loop_index,$indexArr){
    if($loop_index==$loop_num){
        if($sum==$sum_end){
echo('///$sum:'.$sum.'/$sum_end:'.$sum_end.'/$indexArr:'.$indexArr);
print_r($indexArr);
        };
        return false;
    }else{
        for($ii=$i;$ii<$max;$ii++){
            $indexArr[$loop_index]=$ii;
            if($indexArr[$loop_index]>($max-$loop_num+1+$loop_index)){
                break;
            }
            $sum=array_sum($indexArr);
            forFn($ii+1,$max,$sum,$sum_end,$loop_num,$loop_index+1,$indexArr);
        }
    }
};
function addFn($min,$max,$sum,$sum_end,$loop_num,$loop_index,$indexArr){
    for($i=$min;$i<($max-$loop_num+1);$i++){
        $loop_index=0;
        $indexArr[$loop_index]=$i;
        forFn($i+1,$max,$sum,$sum_end,$loop_num,$loop_index+1,$indexArr)
    }
}

addFn(0,999,0,12865,30,0,[])

刚刚用node跑了一下,没跑完(复杂度太大),也不知道对不对,谁跑完结果告诉我一下(:
可以睡觉去了。。。

用测试数据0,1,2,3跑了一下
[0,1,2,3]取3个数字,和为6;

addFn(0,3,0,6,3,0,[])

dp方案

dp, 只用一维数组节省内存, 但是题目复杂度太大... 不玩了.

public Set> compute(int N, int SUM, int MAX_KEY) {
    Set>[] pre = null;
    Set>[] cur = new Set[SUM + 1];
    
    // one elem
    for (int i = 0; i <= MAX_KEY; i++) {
        cur[i] = new HashSet<>();
        cur[i].add(Collections.singletonList(i));
    }
    
    for (int i = 2; i <= N; i++) {
        pre = cur;
        cur = new Set[SUM + 1];
        for (int j = 0; j <= SUM; j++)
            for (int k = 0; k <= MAX_KEY; k++)
                if (j - k >= 0 && pre[j - k] != null) {
                    if (cur[j] == null)
                        cur[j] = new HashSet<>();
                    for (List l: pre[j - k]) {
                        List tmp = new ArrayList<>(l);
                        tmp.add(k);
                        Collections.sort(tmp);
                        cur[j].add(tmp);
                    }
                }
    }
    return cur[SUM];
}

@Test
public void test(){
    compute(30, 12865, 999);
}

dp方案2

二维数组, 太费内存

private Set>[][] dp = null;
private Set> res = null;

public Set> compute(int N, int SUM, int MAX_KEY) {
    dp = new Set[N + 1][SUM + 1];
    for (int i = 0; i <= MAX_KEY; i++) {
        dp[1][i] = new HashSet<>();
        dp[1][i].add(Collections.singletonList(i));
    }
    for (int i = 2; i <= N; i++)
        for (int j = 0; j <= SUM; j++)
            for (int k = 0; k <= MAX_KEY; k++)
                if (j - k >= 0 && dp[i - 1][j - k] != null) {
                    if (dp[i][j] == null)
                        dp[i][j] = new HashSet<>();
                    for (List l: dp[i - 1][j - k]) {
                        List tmp = new ArrayList<>(l);
                        tmp.add(k);
                        dp[i][j].add(tmp);
                    }
                }
    return dp[N][SUM];
}

递归方案

Java代码. 用了一些优化提高效率, 但复杂度还是太高. 权当参考吧.

private Set failedSet = null;
private Set> res = null;

public Set> compute() {
    failedSet = new HashSet<>();
    res = new HashSet<>();
    computeInt(30, 12865, 999, new int[30]);
    return res;
}

private boolean computeInt(int count, int sum, int max, int[] arr) {
    if (count == 0 || sum <0) {
        if (sum == 0){
            List tmp = Arrays.stream(arr).sorted().boxed()
                                      .collect(Collectors.toList());
            res.add(tmp);
        }
        return sum == 0;
    }
    long key = (long)count * Integer.MAX_VALUE + sum;
    if (failedSet.contains(key))
        return false;
    boolean found = false;
    for (int i = 0; i <= max; i++) {
        arr[count - 1] = i;
        if (computeInt(count - 1, sum - i, Math.min(max, i), arr))
            found = true;
    }
    if (!found)
        failedSet.add(key);
    return found;
}

题目意思比较含糊,没说要所有结果还是只要一组还是搜索特定结果;
只要一组,数字可以重复的话,29个1加一个12836就可以了;
只要一组数字,数字要求不重复,随机生成29个,sum超过12865和重复数字的回退,最后一个用12865减掉前面29个值;
如果搜索给定的数组的话,直接DFS吧;
如果是求出所有可能结果,那就BFS吧。

推荐阅读
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了《中秋夜作》的翻译及原文赏析,以及诗人当代钱钟书的背景和特点。通过对诗歌的解读,揭示了其中蕴含的情感和意境。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文描述了作者第一次参加比赛的经历和感受。作者是小学六年级时参加比赛的唯一选手,感到有些紧张。在比赛期间,作者与学长学姐一起用餐,在比赛题目中遇到了一些困难,但最终成功解决。作者还尝试了一款游戏,在回程的路上感到晕车。最终,作者以110分的成绩取得了省一会的资格,并坚定了继续学习的决心。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 关羽败走麦城时路过马超封地 马超为何没有出手救人
    对当年关羽败走麦城,恰好路过马超的封地,为啥马超不救他?很感兴趣的小伙伴们,趣历史小编带来详细的文章供大家参考。说到英雄好汉,便要提到一本名著了,没错,那就是《三国演义》。书中虽 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
author-avatar
乌龟考拉互受
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有