2020-10-02 BFS 二分查詢

來個西柚發表於2020-10-02

BFS

用「佇列」這種資料結構,每次將一個節點周圍的所有節點加入佇列。

框架

// 計算從起點 start 到終點 target 的最近距離
int BFS(Node start, Node target) {
    Queue<Node> q; // 核心資料結構 佇列
    Set<Node> visited; // 避免走回頭路 維護一個visited集合

    q.offer(start); // 將起點加入佇列
    visited.add(start);
    int step = 0; // 記錄擴散的步數

    while (q not empty) {
        int sz = q.size();
        /* 將當前佇列中的所有節點向四周擴散 */
        for (int i = 0; i < sz; i++) {
            Node cur = q.poll();
            /* 劃重點:這裡判斷是否到達終點 */
            if (cur is target)
                return step;
            /* 將 cur 的相鄰節點加入佇列 */
            for (Node x : cur.adj())
                if (x not in visited) {
                    q.offer(x);
                    visited.add(x);
                }
        }
        /* 劃重點:更新步數在這裡 */
        step++;
    }
}

111. 二叉樹的最小深度

var minDepth = function(root) {
    if(!root) return 0;
    let queue = [root];
    let depth = 1;
    while(queue.length) {
        let sz = queue.length;
        for(let i=0; i<sz; i++) {
            let cur = queue.shift();
            if(!cur.left && !cur.right) {
                return depth;
            }
            if(cur.left) queue.push(cur.left);
            if(cur.right) queue.push(cur.right);
        }
        depth++;
    }
};

752. 開啟轉盤鎖

var openLock = function(deadends, target) {
    let queue = ['0000'];
    let deads = new Set(deadends);
    let visited = new Set();
    let step = 0;
    while(queue.length) {
        let sz = queue.length;
        for(let i=0; i<sz; i++) {
            let cur = queue.shift();
            if(deads.has(cur)) continue;
            if(cur == target) return step;
            for(let j=0; j<4; j++) {
                let u = up(cur, j);
                let d = down(cur, j);
                if(!visited.has(u)) {
                    queue.push(u);
                    visited.add(u);
                }
                if(!visited.has(d)) {
                    queue.push(d);
                    visited.add(d)
                }
            }
            
        }
        step ++;
    }
    return -1;
    function up(str, index) {
        let tmp = parseInt(str[index]);
        tmp = tmp == 9 ? 0 : tmp+1
        return str.slice(0,index) + tmp + str.slice(index+1);
    }
    function down(str, index) {
        let tmp = parseInt(str[index]);
        tmp = tmp == 0 ? 9 : tmp-1
        return str.slice(0,index) + tmp + str.slice(index+1);
    }
};

二分查詢

框架

int binarySearch(int[] nums, int target) {
    int left = 0, right = ...;

    while(...) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            ...
        } else if (nums[mid] < target) {
            left = ...
        } else if (nums[mid] > target) {
            right = ...
        }
    }
    return ...;
}

704. 二分查詢

var search = function(nums, target) {
    let left = 0;
    let right = nums.length-1;
    while(left <= right) {
        let mid = left + Math.floor((right-left)/2);
        if(nums[mid] === target) {
            return mid;
        } else if(nums[mid] > target) {
            right = mid-1;
        } else {
            left = mid+1;
        }
    }
    return -1;
};

34. 在排序陣列中查詢元素的第一個和最後一個位置

var searchRange = function(nums, target) {
    let low = findLow(nums, target);
    let high = findHigh(nums, target);
    return [low, high];

    function findLow(nums, target) {
        let left = 0;
        let right = nums.length-1;
        let res;
        while(left <= right) {
            let mid = left + Math.floor((right-left)/2);
            if(nums[mid] == target) {
                right = mid-1;
            } else if(nums[mid] > target) {
                right = mid-1;
            } else {
                left = mid+1;
            }
        }
        if(left >= nums.length || nums[left] !== target) {
            return -1;
        }
        return left;
    }
    function findHigh(nums, target) {
        let left = 0;
        let right = nums.length-1;
        let res;
        while(left <= right) {
            let mid = left + Math.floor((right-left)/2);
            if(nums[mid] == target) {
                left = mid+1;
            } else if(nums[mid] > target) {
                right = mid-1;
            } else {
                left = mid+1;
            }
        }
        if(right<0 || nums[right] !== target) {
            return -1;
        }
        return right;
    } 
};

相關文章