小米OJ:找到第N个数字(i、ii)PHP实现

简单介绍一下我解这两道题的思路和误区,最后附上正确代码!

(一)先看下题目(懒得打了)

小米OJ:找到第N个数字(i、ii)PHP实现_第1张图片

这题的规律挺好找的,第一行(a1)有一个,第二行(a2)有两个,~~~,第n行(an)有n个,于是,前n行(Sn)有(n*n+n)/2个。假如$line(即要查找的那个整数)在第n+1行,则可以用$line-Sn来表示该数在这一行(an+1)的位置。下面我们来找一下每一行(an)的规律,取一个长一点的行 a33=123456789876543212345678987654321,我们可以很容易的看出这段数字可以被分成若干个”2345678987654321“拼接起来的,那么我们就可以用($line-Sn)%16来代表目标数字在字符串中的位置,上面就是这一题的思路。下面是我的第一种方法(本地环境):

//方法1   运行超时
($n*$n+$n)/2&&$res<=($n*$n+3*$n+2)/2){
		$b=$res-($n*$n+$n)/2;
		break; 
	}
}
$c=$b%16;
var_dump($a,$b,$c,$a[$c]);

代码超级简单,但是当$line长度大于15时,代码执行开始变得缓慢,长度大于17时,已经开始超时,不符合小米OJ的要求。

唔,回头重读题目,突然发现他的运行空间有点大———10M。回头再看我们的代码,发现我们获取Sn的循环的次数特别多,于是,我们可以用空间来换取时间:

//方法2   运行成功
3){
    for($n=2;;$n++){
		$s[$n]=$n+$s[$n-1];
		$s[$n+1]=$n+1+$s[$n];
		if($line>$s[$n]&&$line<=$s[$n+1]){
			$b=$line-$s[$n];
			break; 
		}
	}
	$c=$b%16;
}
    // 返回处理后的结果
    // return $ans;
echo $a[$c];	

代码复杂了一点,实际上是因为多了一个if判断,本地运行时有可能会报”致命错误“,其实仔细看后面可以发现是因为本地默认的空间不够,这个可以设置,传到线上就能正常执行。下面粘上正确代码:

function solution($line) {
    // 在此处理单行数据
    $a=["2","1","2","3","4","5","6","7","8","9","8","7","6","5","4","3"];
    $b=1;
    $s[1]=1;
    $s[2]=3;
    if($line<=3){
        if($line==3){
            $c=2;
        }else{
            $c=1;
        }      
    }elseif($line>3){
        for($n=2;;$n++){
		    $s[$n]=$n+$s[$n-1];
		    $s[$n+1]=$n+1+$s[$n];
		    if($line>$s[$n]&&$line<=$s[$n+1]){
		    	$b=$line-$s[$n];
		    	break; 
		    }
	    }
	    $c=$b%16;
    }

    // 返回处理后的结果
    // return $ans;
    return $a[$c];
}

(二)老规矩,先看题目

小米OJ:找到第N个数字(i、ii)PHP实现_第2张图片

这一题相对而言难了很多,因为an的规律没那么好找了,不过,如果仔细一点的话还是能找到的:我们发现,当n>9时,数字开始变成了两位,公差变成了2,当n>99时,数字变成了三位,公差变成了3,~~~,这样我们可以在循环时将n的长度获取到,来作为公差,于是,$w=strlen($n),an=w*n-((10^w-10)/9-w+1),看上去有点复杂,但运用高中的知识可以很轻松的算出来。还是找到$line在an中的位置,将an用1,2,~~~,99,100,~~~拼接起来,变成字符串,然后获取数字,(快下班了不多说了^~^),直接粘代码:

//找到第N个数字ii
function solution($line) {
    
    $an = 0;
    for($n=1;$n<=$line;$n++){
        $w=strlen($n);
        $bn = $w*$n-((pow(10,$w)-10)/9-$w+1);
        $an+=$bn;
		$an_1=$an-$bn;
        if($an>=$line&&$an_1<$line){
            $x = $line-$an_1;
            $y = '';
            for($i=1;$i<=$x+2;$i++){
                $y .=$i;
                $len = strlen($y);
				if($len>$x){
                    $res = substr($y,$x-1,1);
					return $res;						
                }
            }            
        }
    }
}

 

如有错误,欢迎各位大佬指正!

 

你可能感兴趣的:(php)