Problem

Given a sequence of words, check whether it forms a valid word square.

A sequence of words forms a valid word square if the k_th row and column read the exact same string, where 0 ≤ k < max(numRows, numColumns).

Note:

Examples

Example 1:

$$ \begin{bmatrix} \color{red} a & \color{red} b & \color{red} c & \color{red} d \\ \color{red} b & \color{green} n & \color{green} r & \color{green} t \\ \color{red} c & \color{green} r & \color{blue} m & \color{blue} y \\ \color{red} d & \color{green} t & \color{blue} y & \color{violet} e \end{bmatrix} $$

Input: words = ["abcd","bnrt","crmy","dtye"]
Output: true
Explanation:
The 1st row and 1st column both read "abcd".
The 2nd row and 2nd column both read "bnrt".
The 3rd row and 3rd column both read "crmy".
The 4th row and 4th column both read "dtye".
Therefore, it is a valid word square.

Example 2:

$$ \begin{bmatrix} a & b & c & d \\ b & n & r & t \\ c & r & m \\ d & t \end{bmatrix} $$

Input: words = ["abcd","bnrt","crm","dt"]
Output: true
Explanation:
The 1st row and 1st column both read "abcd".
The 2nd row and 2nd column both read "bnrt".
The 3rd row and 3rd column both read "crm".
The 4th row and 4th column both read "dt".
Therefore, it is a valid word square.

Example 3:

$$ \begin{bmatrix} b & a & \color{blue} l & l \\ a & r & \color{blue} e & a \\ \color{red} r & \color{red} e & \color{red} a & \color{red} d \\ l & a & \color{blue} d & y \end{bmatrix} $$

Input: words = ["ball","area","read","lady"]
Output: false
Explanation:
The 3rd row reads "read" while the 3rd column reads "lead".
Therefore, it is NOT a valid word square.

Constraints

  • 1 <= words.length <= 500
  • 1 <= words[i].length <= 500
  • words[i] consists of only lowercase English letters.

Solution

Method 1 - Iterative

Code

C++

class Solution {
public:
    bool validWordSquare(vector<string>& words) {
        int m = words.size();
        for (int i = 0; i < m; ++i) {
            int n = words[i].size();
            for (int j = 0; j < n; ++j) {
                if (j >= m || i >= words[j].size() || words[i][j] != words[j][i]) {
                    return false;
                }
            }
        }
        return true;
    }
};

Go

func validWordSquare(words []string) bool {
	m := len(words)
	for i, w := range words {
		for j := range w {
			if j >= m || i >= len(words[j]) || w[j] != words[j][i] {
				return false
			}
		}
	}
	return true
}

Java

class Solution {
    public boolean validWordSquare(List<String> words) {
        int m = words.size();
        for (int i = 0; i < m; ++i) {
            int n = words.get(i).length();
            for (int j = 0; j < n; ++j) {
                if (j >= m || i >= words.get(j).length()) {
                    return false;
                }
                if (words.get(i).charAt(j) != words.get(j).charAt(i)) {
                    return false;
                }
            }
        }
        return true;
    }
}

Python3

class Solution:
    def validWordSquare(self, words: List[str]) -> bool:
        m = len(words)
        n = max(len(w) for w in words)
        if m != n:
            return False
        for j in range(n):
            if words[j] != "".join(w[j] for w in words if j < len(w)):
                return False
        return True
class Solution:
    def validWordSquare(self, words: List[str]) -> bool:
        m = len(words)
        for i, w in enumerate(words):
            for j, c in enumerate(w):
                if j >= m or i >= len(words[j]) or c != words[j][i]:
                    return False
        return True

TypeScript

function validWordSquare(words: string[]): boolean {
    const m = words.length;
    for (let i = 0; i < m; ++i) {
        const n = words[i].length;
        for (let j = 0; j < n; ++j) {
            if (j >= m || i >= words[j].length || words[i][j] !== words[j][i]) {
                return false;
            }
        }
    }
    return true;
}

Complexity

  • Time: O(m*n) where m is number of words, and n is average length of words.
  • Space: O(1)