LeetCode #003# Longest Substring Without Repeating Characters(js描述)

问题描述:https://leetcode.com/problems/longest-substring-without-repeating-characters/

思路1:分治策略

按照算法导论上的分治算法框架强行写的。

class CommonUtil {
    static lightCopy(obj) {
        let result = {}
        Object.assign(result, obj);
        return result;
    }
}

// O(???), Runtime: 7792 ms, faster than 1.00% ...
var lengthOfLongestSubstring = function(s) {
    if (s == "") return 0;

    let buildMaps = (symbol, p, q, r) => {
        let map = [],
            length = 0;
        let current = () => q - length;
        if (symbol == "right") {
            current = () => q - 1 + length;
        }

        let init = () => { // 创建一个空对象,免去繁琐的初始化过程
            map[length++] = {};
        };

        let isSafe = () => { // 越界or字符重复返回false
            let out = symbol == "right" ? current() >= r : current() < p;
            let repeat = map[length - 1][s[current()]];
            return !out && !repeat;
        };

        let createMap = () => { // 复制map>>添加元素>>为下次调用做准备
            map[length] = CommonUtil.lightCopy(map[length - 1]);
            map[length][s[current()]] = true;
            length++;
        };

        init();
        while (isSafe()) {
            createMap();
        }
        return map;
    };

    let combineMaps = (leftMaps, rightMaps, max) => {
        let compatible = (map1, map2) => {
            if (map1.length < map2.length) {
                let temp = map1;
                map1 = map2;
                map2 = temp;
            }
            let keys = Object.keys(map2);
            return !keys.some(x => map1[x]);
        };

        let getPairs = (totalReduce) => {
            let reducePairs = [];
            for (let k = 0; k <= totalReduce; ++k) {
                reducePairs.push({
                    i: k,
                    j: totalReduce - k,
                });
            }
            return reducePairs;
        };

        const leftLen = leftMaps.length - 1,
            rightLen = rightMaps.length - 1,
            baseLen = leftLen + rightLen;

        let sum = 0;
        let totalReduce = 0;
        while ((sum = baseLen - totalReduce) > max) {
            // 只检测比子问题解的值更大的情形,由大往小找,一旦找到立刻停止搜索
            let reducePairs = getPairs(totalReduce);
            for (let k = 0; k != reducePairs.length; ++k) {
                let i = leftLen - reducePairs[k].i;
                let j = rightLen - reducePairs[k].j;
                if (i > 0 && j > 0 && compatible(leftMaps[i], rightMaps[j])) {
                    return sum;
                }
            }
            totalReduce++;
        }
        return max;
    };

    let findMaxCrossingSubstring = (p, q, r, subMaxLength) => {
        if (s[q - 1] == s[q]) { // 不可连接
            return subMaxLength;
        } else {
            let leftMaps = buildMaps("left", p, q, r);
            let rightMaps = buildMaps("right", p, q, r);
            return combineMaps(leftMaps, rightMaps, subMaxLength);
        }
    };

    let findMax = (start, end) => {
        if (start + 1 < end) {
            let mid = Math.floor((start + end) / 2); // Divide
            let maxLeft = findMax(start, mid); // Conquer
            let maxRight = findMax(mid, end); // Conquer
            const subMaxLength = Math.max(maxLeft, maxRight); // Combine
            return findMaxCrossingSubstring(start, mid, end, subMaxLength); // Combine
        } else {
            return 1; // basecase
        }
    };

    return findMax(0, s.length);
};
View Code

思路2:Brute Force - O(n^3)

let satisfyCondition = (i, j, s) => {
    let map = {};
    for (let k = i; k <= j; ++k) {
        if (map[s[k]]) return false;
        map[s[k]] = true;
    }
    return true;
};

var lengthOfLongestSubstring2 = function(s) {
    if (s == "") return 0;
    let max = 1,
        length, i, j;
    for (i = 0; i != s.length; ++i) {
        for (j = i + 1; j != s.length; ++j) {
            length = j - i + 1;
            if (length > max) {
                if (satisfyCondition(i, j, s)) {
                    max = length;
                } else {
                    break;
                }
            }
        }
    }
    return max;
};

思路3

var lengthOfLongestSubstring = function(s) {
    if (s.length < 2) return s.length;
    let max = 0, lastBegin = 0, code, characterIndex = new Array(255), fresh;
    for (let i = 0; i !== s.length; ++i) {
        code = s.charCodeAt(i);
        if (characterIndex[code] >= lastBegin) {
            lastBegin = characterIndex[code] + 1;
        }
        fresh = i - lastBegin + 1;
        if (fresh > max) {
            max = fresh;
        }
        characterIndex[code] = i;
    }
    return max;
};
原文地址:https://www.cnblogs.com/xkxf/p/10230703.html