【算法】双指针合集

12 篇文章 0 订阅

1.合并排序数组

对撞指针

非常经典的解法

//合并排序数组
function arrayAdd($arra,$arrb){
	$counta = count($arra) - 1;
	$countb = count($arrb) - 1;
	$arr = [];
	$a = $b = 0;
    //两个数组都没循环完
	while($a<=$counta && $b<=$countb){
		if($arra[$a] <= $arrb[$b]){
			$arr[] = $arra[$a];
			$a++;
		}else{
			$arr[] = $arrb[$b];
			$b++;
		}
	}
	//当数组b循环完但a还有剩余
	while($a<=$counta){
		$arr[] = $arra[$a];
		$a++;
	}
	//或者数组a循环完但b还有剩余
	while($b<=$countb){
		$arr[] = $arrb[$b];
		$b++;
	}
	return $arr;
}

$arra = [4,5];
$arrb=[1,2,3,6,7,8];
$a = arrayAdd($arra,$arrb);
var_dump($a);

2.剑指orrer21题:调整数组顺序使奇数位于偶数前面

https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/

额外空间法

把奇数放到数组a,偶数放到数组b,再合并,思路简单,虽然费了一点点内存...

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer[]
     */
function exchange($nums) {
	$count = count($nums);
	$i=0;
	$a = $b = [];
	while($i<$count){
		if($nums[$i]%2==1){
			$a[]=$nums[$i];
		}else{
			$b[]=$nums[$i];
		}
		$i++;
	}
	return array_merge($a,$b);
}
}

其实时间复杂度O(n)很好了,但是开辟了新的数组内存空间,空间也是O(n)级别的

对撞指针

左指针向右寻找双数,右指针向左寻找单数,找到时交换两个数,直到两个指针相遇时结束。

function exchange($nums){
	$left = 0;
	$right = count($nums)-1;
	while($right>$left){
		if($nums[$left] %2 == 1){
			$left++;
		}
		elseif($nums[$right] %2 == 0){
			$right--;
		}
		elseif($nums[$left] %2 == 0 && $nums[$right] %2 == 1){
			$temp = $nums[$left];
			$nums[$left] = $nums[$right];
			$nums[$right] = $temp;
		}
	}
	return $nums;
}

内存优化了一点点,时间复杂度没变o(n),但是空间复杂度o(1),因为只用了常量级的几个变量,不随数组增大而改变。 

快慢指针

本人最不擅长的解法,很多时候都想不到...

快指针用来遍历数组,去寻找单数以把它往前换,慢指针用来标记当前可以换的位置。

function exchange($nums){
	$slow = 0;
	for($fast=0;$fast<count($nums);$fast++){
		if($nums[$fast] %2 == 1){
			$temp = $nums[$fast];
			$nums[$fast] = $nums[$slow];
			$nums[$slow] = $temp;
			$slow++;
		}
	}
	return $nums;
}

 时间复杂度o(n),空间复杂度o(1),理解的话会发现这是三种里最简洁的方法。

再次强调,官方执行结果只做参考,且多次执行结果并不相同,算法好坏还需要结合时间、空间复杂度和实际业务中数据来评判。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值