[recent force buckle] color filling + number of islands + size of water area + open keyboard lock + word search + Curriculum

1.DFS (depth first search) and BFS (breadth first search) collection.

2. The main difference between the two is that the former maintains a stack data structure, so the recursive method can usually be used; The latter maintains the data structure of a queue, usually using the method of circular iteration.

3. At the same time, if the former is implemented by recursion, only the form of recursion and the conditions for ending recursion need to be considered. The computer maintains the stack itself, which is more convenient and easy to understand. The latter needs to write its own iteration to maintain the queue, which is relatively complex to start

4. If you are familiar with backtracking and recursion, DFS is easy to use, and there will be little explanation below

Color fill (simple)

  • Idea: DFS, pay attention to boundary conditions and special cases, and then search (fill color) in four directions up, down, left and right
var floodFill = function(image, sr, sc, newColor) {
    let begin = image[sr][sc]
    // Special attention
    if (begin === newColor) return image
    let srlen = image.length - 1, sclen = image[0].length - 1
    let dfs = (image, sr, sc, newColor) => {
    	// Focus on boundary conditions
        if (sr < 0 || sc < 0 || sr > srlen || sc > sclen) return
        if (image[sr][sc] === begin) {
            image[sr][sc] = newColor
        } else {
            return
        }
        dfs(image, sr - 1, sc, newColor) // lower
        dfs(image, sr + 1, sc, newColor) // upper
        dfs(image, sr, sc - 1, newColor) // Left
        dfs(image, sr, sc + 1, newColor) // right
    }
    dfs(image, sr, sc, newColor)
    return image
};

Number of islands (medium)

  • Idea: cycle through the grid array. As long as the current value is 1, add one to the count, and then perform DFS search in four directions up, down, left and right until it meets zero, and the place it passes each time should become zero to prevent repeated search from falling into an endless loop (such as searching from left to right, and from right to left, and so on)
var numIslands = function(grid) {
    if (!grid.length) return 0
    let nr = grid.length
    let nc = grid[0].length
    let sum = 0
    let dfs = (grid, r, c) => {
        if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] === '0') return
        grid[r][c] = '0' // The searched place is assigned to zero
        dfs(grid, r - 1, c) // lower
        dfs(grid, r + 1, c) // upper
        dfs(grid, r, c - 1) // Left
        dfs(grid, r, c + 1) // right
    }
    // Traversal array
    for (let i = 0; i < nr; i++) {
        for (let j = 0; j < nc; j++) {
            if (grid[i][j] === '1') {
                sum++
                dfs(grid, i, j)
            }
        }
    }
    return sum
};

Water area size (medium)

  • Idea: compared with the previous question, it has four more search directions - diagonal, but there is no essential difference. It can be done as long as you search several more directions
var pondSizes = function(land) {
    if (!land.length) return []
    let res = [], size = 0
    let nr = land.length
    let nc = land[0].length
    let dfs = (land, r, c) => {
        if (r < 0 || c < 0 || r >= nr || c >= nc || land[r][c] !== 0) return
        land[r][c] = -1
        size++
        // Search in eight directions
        dfs(land, r - 1, c)
        dfs(land, r - 1, c - 1)
        dfs(land, r - 1, c + 1)
        dfs(land, r, c - 1)
        dfs(land, r, c + 1)
        dfs(land, r + 1, c)
        dfs(land, r + 1, c - 1)
        dfs(land, r + 1, c + 1)
        return size
    }
    for (let i = 0; i < nr; i++) {
        for (let j = 0; j < nc; j++) {
            if (land[i][j] === 0) {
                size = 0
                dfs(land, i, j)
                if (size !== 0) res.push(size)
            }
        }
    }
    return res.sort()
};

Open keyboard lock (medium)

  • thinking
    • BFS. The code and ideas are complex. Look at the form of the topic, you can think of using a queue, because the operation is carried out in sequence, and the next rotation can only be carried out after one rotation. The difficulty of this problem is that it is easy to fall into a dead end - thinking about using code to write rotation operation and iteration together, and the two are carried out at the same time. If you think about it carefully, you will find that it is very hybrid, or almost impossible to achieve, because there are many situations after one rotation. So we need to turn the rotation operation into a function, and return the value to the array with various conditions. We can call the function in every iteration and traverse the result.
    • The rotation function and can directly see the code comments. Here we mainly talk about the idea of iteration. Maintain a queue, first store the initial state of 0000, then enter the total cycle (once for each total cycle, the number of steps plus one), then traverse and take out the states in the queue, and rotate each state. The results are stored in the array, and then the results in the rotating array are stored in the queue according to the sequence (at the same time, judge whether they meet the requirements, store them in the queue if they do not meet the requirements, and return the results if they meet the requirements), and then iterate over each result when entering the total cycle
var openLock = function(deadends, target) {
    if (target === '0000') return 0
    if (deadends.includes('0000')) return -1
    // The result of enumeration rotation is a string, which requires additional processing
    const go = (x) => { // Forward rotation
        return x === '9' ? '0' : (parseInt(x) + 1) + ''
    }
    const back = (x) => { // reversal
        return x === '0' ? '9' : (parseInt(x) - 1) + ''
    }
    const get = (status) => {
        const res = []
        const arr = Array.from(status)
        // Only four digits
        for (let i = 0; i < 4; i++) {
            const num = arr[i] // Save current traversal number
            arr[i] = go(num)
            res.push(arr.join('')) // Deposit forward transfer result
            arr[i] = back(num)
            res.push(arr.join('')) // Save reversal result
            arr[i] = num // Restore current traversal number
        }
        return res // Returns all results of one rotation
    }
    // BFS
    let step = 0
    let dead = new Set(deadends)
    const queue = []
    queue.push('0000')
    let seed = new Set()
    seed.add('0000')
    while (queue.length) {
        step++
        const len = queue.length
        for (let i = 0; i < len; i++) {
        	// Take out multiple results after the last rotation in sequence
            let status = queue.shift()
            // Traverse the various cases of rotation once
            for (let next of get(status)) {
            	// Judge whether it meets the requirements, store it in the queue if it does not meet the requirements, and return the results if it meets the requirements
                if (!seed.has(next) && !dead.has(next)) {
                    if (next === target) {
                        return step
                    } else {
                        queue.push(next)
                        seed.add(next)
                    }
                }
            }
        }
    }
    return -1
};

Word search (medium)

  • Idea: DFS, the efficiency after submission is extremely low and outrageous. Traverse each element of the array, and then search up, down, left and right. General, not much explanation
var exist = function(board, word) {
    let len = word.length
    let nr = board.length
    let nc = board[0].length
    let isTrue = false
    let dfs = (board, r, c, sub) => {
        if (r < 0|| c < 0 || r >= nr || c >= nc || sub.length > len || board[r][c] === '1') return
        sub += board[r][c]
        if (sub === word) isTrue = true
        let str = board[r][c]
        board[r][c] = '1'
        dfs(board, r - 1, c, sub)
        dfs(board, r + 1, c, sub)
        dfs(board, r, c - 1, sub)
        dfs(board, r, c + 1, sub)
        board[r][c] = str
    }
    for (let i = 0; i < nr; i++) {
        for (let j = 0; j < nc; j++) {
            if (board[i][j] === word[0]) {
                dfs(board, i, j, '')
            }
        }
    }
    return isTrue
};

Curriculum (medium)

  • Idea: BFS, the efficiency after submission is extremely low and outrageous. This problem involves topological sorting. If you understand topological sorting, you will understand it very well
var canFinish = function(numCourses, prerequisites) {
    let pic = new Array(numCourses)
    let len = prerequisites.length
    let queue = [], sum = 0

    for (let i = 0; i < numCourses; i++) {
        pic[i] = []
    }
	// Store the corresponding relationship of course order to form a topology
    for (let i = 0; i < len; i++) {
        let [back, pre] = prerequisites[i]
        pic[back].push(pre)
    }
	
	// First, the nodes with zero penetration are stored in the queue
    for (let i = 0; i < numCourses; i++) {
        if (pic[i].length === 0) queue.push(i)
    }
	
	// Check whether there is a ring in the topology. If there is no ring, it returns true
    while (queue.length) {
        let mid = queue.shift()
        for (let i = 0; i < numCourses; i++) {
            let cur = pic[i]
            let index = cur.indexOf(mid)
            if (index === -1) continue
            cur.splice(index, 1)
            if (cur.length === 0) queue.push(i)
        }
        sum++
    }

    return sum === numCourses
};

If you think it's helpful to you, give it a compliment~

Anyway, posting doesn't make money. Make friends~

If you need to reprint, please indicate the source foolBirdd

Tags: data structure leetcode

Posted on Sat, 23 Oct 2021 05:20:05 -0400 by jkewlo