21xrx.com
2024-12-22 19:19:42 Sunday
登录
文章检索 我的文章 写文章
三数之和 - PHP
2019-05-25 17:54:21 深夜i     --     --
php 算法 编程

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

分析:本题算法比较简单,主要考点是算法的时间复杂度

思路1:三次遍历,选取所有的[a,b,c]组合判断是否满足条件,时间复杂度为O(n^3).这种思路显然在时间上就过不了.

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer[][]
     */
    function threeSum($nums) {
        sort($nums);
        $length=3;
        $arr=array();
        if(count($nums)==$length&&array_sum($nums)===0){
            array_push($arr,$nums);
        }
        for($i=0;$i<count($nums)-$length-1;$i++){//循环整个数组(不包括最后两个元素)
            for($j=$i+1;$j<count($nums)-1;$j++){
                for($k=$j+1;$k<count($nums);$k++){
                    $subArr=array();
                    array_push($subArr,$nums[$i]);
                    array_push($subArr,$nums[$j]);
                    array_push($subArr,$nums[$k]);
                    if(array_sum($subArr)===0){
                        array_push($arr,$subArr);
                    }
                }
            }
        }
        return $arr;
    }

结果:

思路2: 以0为分界点,将数组分成大于0和小于0以及0三部分.这样可能出现的解答为[a,b,c],[a,0,b],[0,0,0]三大类,数组长度变短后遍历时所需时间也会变少,时间复杂度小于O(n^3)(具体是多少我也不会推导。。)

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer[][]
     */
    function threeSum($nums) {
        sort($nums);//排序
        $length=3;
        $arr=array();
        $negatives=array();
        $zeros=array();
        $positives=array();
        for($i=0;$nums[$i]<0;$i++){//取出负数
            array_push($negatives,$nums[$i]);
        }
        for($i=0;$i<count($nums)&&$nums[$i]<1;$i++){//取出零
            if($nums[$i]===0){
                array_push($zeros,$nums[$i]);
            }
        }
        for($i=(count($nums)-1);$nums[$i]>0;$i--){//取出正数
            array_push($positives,$nums[$i]);
        }
        for($i=0;$i<count($negatives);$i++){//遍历负数
            if($i<count($negatives)-1){
                for($j=$i+1;$j<count($negatives);$j++){
                    if(in_array(0-($negatives[$i]+$negatives[$j]),$positives)){//[a,b,c]模式
                        array_push($arr,array($negatives[$i],$negatives[$j],0-($negatives[$i]+$negatives[$j])));
                    }
                }
            }
            if(in_array(0-$negatives[$i],$positives)&&count($zeros)>0){//[a,0,b]模式
                array_push($arr,array($negatives[$i],0,0-$negatives[$i]));
            }

        }

        for($i=0;$i<count($positives)-1;$i++){//遍历正数
            for($j=$i+1;$j<count($positives);$j++){
                if(in_array(0-($positives[$i]+$positives[$j]),$negatives)){//[a,b,c]模式
                    array_push($arr,array($positives[$i],$positives[$j],0-($positives[$i]+$positives[$j])));
                }
            }
        }
        if(count($zeros)>=3){//[0,0,0]模式
            array_push($arr,array(0,0,0));
        }
        //去重复
        $temp=array();
        foreach ($arr as $v){
            $v=join(',',$v); //降维,也可以用implode,将一维数组转换为用逗号连接的字符串
            $temp[]=$v;
        }
        $temp=array_unique($temp); //去掉重复的字符串,也就是重复的一维数组
        foreach ($temp as $k => $v){
            $temp[$k]=explode(',',$v); //再将拆开的数组重新组装
        }

        return $temp;
    }
    
}

结果:

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复