【算法】力扣菜鸟

12 篇文章 0 订阅

二维数组在计算机中也是以连续空间存放,并记录第一行数组的索引位置,即 A[0][0] 的内存地址。

1.两个内部已排序数组,如arr1=[1,3,4,6,7],arr2=[3,4,6,8,9],将两个数组合并为一个新的排序数组。

思路:依次对比两个数组头部的数字,哪个小就放入新数组中,当其中一个已经空了,就把另一个剩余部分全追加到新数组后面。

$arr1=[1,3,4,5,9];
$arr2=[2,4,6,7,9];

function myMerge($arr1,$arr2){
	 $i=0;$j=0;
	 $int = array();
	 while($i<count($arr1) && $j<count($arr2)){
	  $int[] = $arr1[$i]<$arr2[$j]?$arr1[$i++]:$arr2[$j++];
	 }
	 while($i<count($arr1)){
	  $int[] = $arr1[$i++];
	 }
	 while($j<count($arr2)){
	  $int[] = $arr2[$j++];
	 }

	return $int;
}


$a = myMerge($arr1,$arr2);
var_dump($a);

2.

思路:先算出数组值总和$sums,当判断中心点是否为0时,left_sum=0,右边就是$sums-$nums[0],

之后判断中心点是否为1,left_sum = left_sum+$nums[0],右边等于$sums-left_sum-$nums[1]

$nums = [1, 7, 3, 6, 5, 6];
function getCenter($nums){
	$sums = array_sum($nums);
	$left_sum = 0;
	if($sums == $nums[0]){//总和等于$nums[0],那么剩下的元素和是0,此时0就是对称点
		return 0;
	}
	for($i=1;$i<count($nums);$i++){
		$left_sum += $nums[$i-1];
		$right_sum = $sums - $left_sum - $nums[$i];
		if($left_sum == $right_sum){//左边之和=右边之和
			return $i;
		}
	}
	return -1;
}
echo getCenter($nums);

3.

思路:

这题一开始是顺序对比,比nums[0]大就放它后面,小于等于它就放它前面

 function searchInsert($nums, $target) {
   for($i=0;$i<count($nums);$i++){
		if($target <= $nums[$i]){
			return $i;
		}
	}
	return count($nums);
 }

换一种思路,逆序对比,比最后一个数大就放它后面,如果遍历后不大于任意数,就直接拍首位

function searchInsert($nums, $target) {
   for($i=count($nums)-1;$i>= 0 ;$i--){
      if($nums[$i] < $target){
         return $i+1;
      }
   }
   return 0;
}

总体思路都是差不多的,看自己哪个边界值比较好理解就用哪个吧。

4.

思路:以为的水平,写不出不占用额外空间的写法,所以这是非常传统的赋值到新的数组,找到他们对应关系来旋转的:

function rotate(&$matrix) {
	$count = count($matrix);
	$count_i = count($matrix[0]);//因为所有一维数组长度相等
	$arr = [];
	for($i=0;$i<$count;$i++) {
		for($j=0;$j<$count_i;$j++) {
			$arr[$i][$j] = $matrix[$count - $j - 1][$i];
		}
	}
	//$matrix = $arr; leetcode是要求最后给出$matrix的值所以才需要赋值一下
	return $arr;
}

5.

思路:

1.找到0所在的行的集合$zero_a、列的集合$zero_b,这些都是要清零的。

2.遍历,当前行在$zero_a或者列在$zero_b,清零

为什么第一次找的时候不直接清零:怕污染原数组

(并不是特别高明的方法)

function setZeroes(&$matrix) {
	
	$zero_a = $zero_b = [];
	for($i=0;$i<count($matrix);$i++){
		for($j=0;$j<count($matrix[$i]);$j++){
			if($matrix[$i][$j] == 0){
				if(! in_array($i,$zero_a)){
					$zero_a[] = $i;//记录要清零的行
				}
				if(! in_array($j,$zero_b)){
					$zero_b[] = $j;//记录要清零的列
				}
				
			}
		}
	}

	for($i=0;$i<count($matrix);$i++){
		for($j=0;$j<count($matrix[$i]);$j++){
			if(in_array($i,$zero_a) || in_array($j,$zero_b)){ //当前行或列匹配到清零行或列
				$matrix[$i][$j] = 0;
			}
		}
	}

	return $matrix;
}

6.快速排序

思路:先默认第一个是中间值,比它小的放它左边,比它大的放它右边,分别排序后,组合在一起。

function quick_sort($a){

$count = count($a);
if($count <= 1){
	return $a;
}

$left = $right = [];
$mid = $a[0];

for($i=1;$i<$count ;$i++){
	if($mid < $a[$i]){//升序<  降序> 其他不用改
		$right[] = $a[$i];
	}else{
		$left[] = $a[$i];
	}
}
$left = quick_sort($left);
$right = quick_sort($right);
return array_merge($left,array($mid),$right);

}

7.二分查找(注意是要对已排序数组才能用)

思路:先找到中间位置的数据,要查找的比它小,就去它左边找,比它大,就去它右边找。

function selectone($arr,$find,$left=0,$right=0){
	if($right == 0){
		$right = count($arr);
	}
	if($right < $left || $find>$arr[count($arr)-1] || $find < $arr[0]){
		return 0;
	}
	
	if($right - $left<=1){
		if($find==$arr[$right] || $find==$arr[$left]){
			return 1;
		}else{
			return 0;
		}
	}
	$mid=round(($left+$right)/2);
	
	if($find > $arr[$mid]){
		
		return selectone($arr,$find,$mid++,$right);
	}elseif($find == $arr[$mid]){
		
		return $mid;
	}else{
		return selectone($arr,$find,$left,$mid--);
	}
}

8.冒泡排序

function selectone($arr){
	
	for($i=0;$i<count($arr)-1;$i++){
		for($j=0;$j<count($arr)-1-$i;$j++){
			if($arr[$j] > $arr[$j+1] ){
				$temp = $arr[$j];
				$arr[$j] = $arr[$j+1];
				$arr[$j+1] = $temp;
			}
		}
		
	}
	return $arr;
}

 9.选择排序

function selectone($arr){
	
	for($i=0;$i<count($arr)-1;$i++){
		$min_index = $i;
		for($j=$i;$j<count($arr)-1;$j++){
			if($arr[$j+1] < $arr[$min_index] ){
				$min_index = $j+1;
				
			}
		}
		$temp = $arr[$i];
		$arr[$i] = $arr[$min_index];
		$arr[$min_index] = $temp;
			
	}
	return $arr;
}

10.

思路:这题需要位运算,

a ^ a  = 0  任何一个数字和自己按位异或结果是0

a ^  0  = a   任何一个数字和0按位异或结果是自己

(按位异或:按位取或后,再依次求反)

function singleNumber($nums) {

	$single = 0;
	foreach ($nums as $k => $v) {
		 $single=  $single ^ $v;
	}
	return $single;
}

$nums = [4,1,2,1,2,4,6];
echo singleNumber($nums);

11.

思路:无论是否有地址,那地址肯定不能是主表了

select P.FirstName, P.LastName, a.City, a.State
from Person P
left join  Address as a 
on a.PersonId = p.PersonId

12.

思路:重复值 having

select Email from Person group by Email having count(Email) >1

13.

思路:递归

function fib($n) {
  if($n<=1){
     return $n;
  }else{
     return $this->fib($n-1)+$this->fib($n-2);
  }
}

14.

思路:(效率不高)先遍历字符串,将所有出现过的字符串放入$map,所有$map中出现过的字符串放入$same,遍历原数组,返回不在$same的第一个。

function firstUniqChar($s) {
	$arr = str_split($s);
	$map = $same = [];
	for($i=0;$i<count($arr);$i++){
		if(! in_array($arr[$i], $map)){
			$map[] = $arr[$i];
		}else{
			$same[]=$arr[$i];
		}
	}
	for($i=0;$i<count($arr);$i++){
		if(! in_array($arr[$i], $same)){
			return $i;
		}
	}
	return -1;
}

$s="always";
echo firstUniqChar($s);

另一种思路:(效率好一点点)先遍历,统一各个值出现的次数,再遍历,第一个使用一次的就是。(注意不要想着第一次遍历时存在的就设为1,再次出现就删除,这样出现三次的就会被当作一次了)

function firstUniqChar($s) {
	$arr = str_split($s);
	$map = [];
	foreach ($arr as $k => $v) {
		if(! isset($map[$v])){
			$map[$v] = 1;
		}else{
			$map[$v] ++;
		}
	}
	
	for($i=0;$i<count($arr);$i++){
		if($map[$arr[$i]] == 1){
			return $i;
		}
	}
	return -1;
}

15.

思路:糖果种类可以遍历数组,记录在$map数组中,之后对比$map和糖果总数的一半,返回较小值。

function distributeCandies($candyType) {
	$map = [];
	foreach ($candyType as $k => $v) {
		if(! in_array($v, $map)){
			$map[] = $v;
		}
	}
	return min(count($map),count($candyType)/2);
}

$candies = [1,1,2,2,2,2];
echo distributeCandies($candies);

16.

思路:id=1的员工ManagerID=3,意思是id=3的员工是他的经理。

我用的联表查询

select ee.Name as Employee from Employee as e join Employee as ee
on e.Id = ee.ManagerId
where ee.Salary > e.Salary

17.

18.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值