Description
Given a 2D array of characters grid of size m x n, you need to find if there exists any cycle consisting of the same value in grid.
A cycle is a path of length 4 or more in the grid that starts and ends at the same cell. From a given cell, you can move to one of the cells adjacent to it - in one of the four directions (up, down, left, or right), if it has the same value of the current cell.
Also, you cannot move to the cell that you visited in your last move. For example, the cycle (1, 1) -> (1, 2) -> (1, 1) is invalid because from (1, 2) we visited (1, 1) which was the last visited cell.
Return true if any cycle of the same value exists in grid, otherwise, return false.
Example 1:

Input: grid = [["a","a","a","a"],["a","b","b","a"],["a","b","b","a"],["a","a","a","a"]] Output: true Explanation: There are two valid cycles shown in different colors in the image below:![]()
Example 2:

Input: grid = [["c","c","c","a"],["c","d","c","c"],["c","c","e","c"],["f","c","c","c"]] Output: true Explanation: There is only one valid cycle highlighted in the image below:![]()
Example 3:

Input: grid = [["a","b","b"],["b","z","b"],["b","b","a"]] Output: false
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 500gridconsists only of lowercase English letters.
Solutions
This code detects if a grid contains a cycle — a path of adjacent cells with the same character that loops back on itself. It uses depth-first search (DFS) to explore connected cells: it maintains a seen array to track visited cells, and the dfs function recursively explores all four directions (up, down, left, right) from each position, but skips the cell it just came from (using px and py to track the parent) to avoid false positives. If it encounters a cell that's already seen, it found a cycle and returns true; if it revisits any cell through a different path without going backwards, that confirms a cycle exists. The outer loop starts DFS from each unvisited cell in the grid, returning true if any path finds a cycle, otherwise false.
/**
* @param {character[][]} grid
* @return {boolean}
*/
var containsCycle = function(grid) {
const m = grid.length;
const n = grid[0].length;
const seen = Array.from({ length: m }, () => Array(n).fill(false));
const dfs = (x, y, px, py) => {
if (seen[x][y]) return true;
seen[x][y] = true;
let res = false;
if (x + 1 < m && x + 1 !== px && grid[x + 1][y] === grid[x][y]) res |= dfs(x + 1, y, x, y);
if (!res && y + 1 < n && y + 1 !== py && grid[x][y + 1] === grid[x][y]) res |= dfs(x, y + 1, x, y);
if (!res && x > 0 && x - 1 !== px && grid[x - 1][y] === grid[x][y]) res |= dfs(x - 1, y, x, y);
if (!res && y > 0 && y - 1 !== py && grid[x][y - 1] === grid[x][y]) res |= dfs(x, y - 1, x, y);
return res;
};
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (!seen[i][j] && dfs(i, j, -1, -1)) {
return true;
}
}
}
return false;
};