矩阵中的最长递增路径【php版】

47 篇文章 1 订阅

在这里插入图片描述

使用记忆化深度优先搜索

<?php
class Solution {
	private $dir = [
			[0,1],
			[0,-1],
			[1,0],
			[-1,0],
		];
	// 用于记录已经搜索过的点的最大路径值
	private $path = [];
	private $rCnt;
	private $cCnt;
	/**
	 * @param Integer[][] $matrix
	 * @return Integer
	 */
	function longestIncreasingPath($matrix) {
		$this->rCnt = count($matrix);
		if ($this->rCnt == 0) {
			return 0;
		}

		$this->cCnt = count($matrix[0]);
		if ($this->cCnt == 0) {
			return 0;
		}

		$this->path = array_fill(0, $this->rCnt*$this->cCnt, 0);
		$ans = 1;
		foreach ($matrix as $rIdx => $rowData) {
			foreach ($rowData as $cIdx => $cellData) {
				$pathLen = $this->findLongestPath($matrix, $rIdx, $cIdx);
				$ans = max($ans, $pathLen);
			}
		}
		return $ans;
	}

	function findLongestPath(&$matrix, $rIdx, $cIdx) {
		$idx = $rIdx * $this->cCnt + $cIdx;
		if ($this->path[$idx] != 0) {
			return $this->path[$idx];
		}
		$tmpMax = 0;
		foreach ($this->dir as $dir) {
			$newR = $rIdx+$dir[0];
			$newC = $cIdx+$dir[1];
			if ($newR>=0 && $newR<$this->rCnt && $newC>=0 && $newC<$this->cCnt
			  && $matrix[$newR][$newC] > $matrix[$rIdx][$cIdx]) {
				$curLen = $this->findLongestPath($matrix, $newR, $newC);
				$tmpMax = max($curLen, $tmpMax);
			}
		}

		$this->path[$idx] = $tmpMax + 1;
		return $tmpMax + 1;
	}
}

结果
在这里插入图片描述

新增一种解法:动态规划+拓扑排序

class Solution {
	private $dir = [
			[0,1],
			[0,-1],
			[1,0],
			[-1,0],
		];
    /**
     * @param Integer[][] $matrix
     * @return Integer
     */
    function longestIncreasingPath($matrix) {
		$rCnt = count($matrix);
		if ($rCnt == 0) {
			return 0;
		}

		$cCnt = count($matrix[0]);
		if ($cCnt == 0) {
			return 0;
		}

		$outDegrees = [];
		foreach ($matrix as $rIdx => $rowData) {
			foreach ($rowData as $cIdx => $cellData) {
				$idx = $rIdx*$cCnt+$cIdx;
				$outDegrees[$idx] = 0;
				foreach ($this->dir as $dir) {
					$newR = $rIdx+$dir[0];
					$newC = $cIdx+$dir[1];
					if ($newR>=0 && $newR<$rCnt && $newC>=0 && $newC<$cCnt
						&& $matrix[$newR][$newC] > $matrix[$rIdx][$cIdx]) {
						$outDegrees[$idx]++;
					}
				}
			}
		}

		$queue = new SplQueue();
		foreach ($outDegrees as $k => $degree) {
			if ($degree == 0) {
				$queue->enqueue($k);
			}
		}

		$ans = 0;
		while(!$queue->isEmpty()) {
			$ans++;
			$size = $queue->count();
			while ($size-- > 0) {
				$idx = $queue->dequeue();
				$rIdx = intdiv($idx, $cCnt);
				$cIdx = $idx % $cCnt;
				foreach ($this->dir as $dir) {
					$newR = $rIdx+$dir[0];
					$newC = $cIdx+$dir[1];
					if ($newR>=0 && $newR<$rCnt && $newC>=0 && $newC<$cCnt
						&& $matrix[$newR][$newC] < $matrix[$rIdx][$cIdx]) {
						$newIdx = $newR*$cCnt+$newC;
						if (--$outDegrees[$newIdx]==0) {
							$queue->enqueue($newIdx);
						}
					}
				}
			}
		}
		return $ans;
    }
}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值