LeetCode-15

LeetCode-15

继续二刷代码随想录,以及随机的题目。

1477 找两个和为目标值且不重叠的子数组

时间:2022-02-28

这个题真的有点难度,而且一开始看走眼了,没看到互不重叠的子数组了,我以为是不能重复相同的子数组,我就说这也太难了8,所以这个解法就是滑动窗口,记录符合的长度和开始下标,然后按照长度进行排序,再判断两个有没有重叠,大概就这样子,速度有点慢的。

var minSumOfLengths = function (arr, target) {
    let sum = 0;
    // 存入数组[长度,开始下标]
    const memo = [];
    let j = 0;

    for (let i = 0; i < arr.length; i++) {
        sum += arr[i];
        while (sum >= target) {
            if (sum == target) memo.push([i - j + 1, j]);
            sum -= arr[j++];
        }
    }
    let min = Infinity;
    memo.sort((a, b) => a[0] - b[0]);
    console.log(memo);
    for (let i = 0; i < memo.length - 1; i++) {
        for (let j = i + 1; j < memo.length; j++) {
            // 两个互不重叠的
            if (memo[i][1] < memo[j][1] && memo[i][1] + memo[i][0] > memo[j][1]) continue;
            if (memo[j][1] < memo[i][1] && memo[j][1] + memo[j][0] > memo[i][1]) continue;

            min = Math.min(min, memo[i][0] + memo[j][0]);
            break;
        }
    }
    return min === Infinity ? -1 : min;
};

还有一种动态规划的写法,这个就比较的抽象了,非常的抽象,dp记录到编号i 满足target的最短子数组的长度,那么res就是dp[i-len]的最短子数组和加上当前len的长度,反正就说的通,但感觉又有点怪怪的。

var minSumOfLengths = function (arr, target) {
    const n = arr.length;
    // d[i]表示到编号i(不包含i)的情况下满足target目标的最短子数组的长度
    const dp = new Array(n + 1).fill(Infinity);
    let res = Infinity;
    let j = 0,
        sum = 0;
    for (let i = 1; i <= n; i++) {
        sum += arr[i - 1];
        while (sum > target) sum -= arr[j++];
        if (sum === target) {
            const len = i - j;
            dp[i] = Math.min(len, dp[i - 1]);
            res = Math.min(res, dp[j] + len);
        } else {
            dp[i] = dp[i - 1];
        }
    }
    return res === Infinity ? -1 : res;
};

1185 一周中的第几天

时间:2022-02-28

这种题目就很操蛋,怎么能算在简单题里面呢,再怎么说应该算在中等题吧,虽然这道题我直接copy的

var dayOfTheWeek = function (day, month, year) {
    const week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    const monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30];
    /* 输入年份之前的年份的天数贡献 */
    let days = 365 * (year - 1971) + Math.floor((year - 1969) / 4);
    /* 输入年份中,输入月份之前的月份的天数贡献 */
    for (let i = 0; i < month - 1; ++i) {
        days += monthDays[i];
    }
    if ((year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)) && month >= 3) {
        days += 1;
    }
    /* 输入月份中的天数贡献 */
    days += day;
    return week[(days + 3) % 7];
};

offer II 12 左右两边子数组的和相等

时间:2022-02-28

var pivotIndex = function (nums) {
    let sum = nums.reduce((a, b) => a + b, 0);
    let tmp = 0;
    for (let i = 0; i < nums.length; i++) {
        const left = sum - nums[i];
        if ((left & 1) == 0 && tmp == Math.floor(left / 2)) return i;
        tmp += nums[i];
    }
    return -1;
};

1128 等价多米诺骨牌对的数量

时间:2022-02-28

虽然这道题是简单题,但是我居然没有直接想到最优解,我太烂了。我还想两次循环呢,没想到因为这道题目因为限制了数字大小在1-9之间,这个真的绝好吧。

var numEquivDominoPairs = function (dominoes) {
    const arr = new Array(100).fill(0);
    let res = 0;
    for (const d of dominoes) {
        const val = d[0] < d[1] ? d[0] * 10 + d[1] : d[1] * 10 + d[0];
        res += arr[val];
        arr[val]++;
    }
    return res;
};

6 Z 字形变换

时间:2022-03-01

我tm直接模拟我tm,说简单也是蛮简单,说难也是有点难的,有点艹的

var convert = function (s, numRows) {
    const len = s.length;
    if (numRows == 1 || numRows >= len) return s;
    const t = numRows * 2 - 2;
    const res = [];
    // 每行开始
    for (let i = 0; i < numRows; i++) {
        // 每行的起始下标
        for (j = i; j < len; j += t) {
            res.push(s[j]);
            if (0 < i && i < numRows - 1) res.push(s[j + t - 2 * i]);
        }
    }
    return res.join('');
};

1848 到目标元素的最小距离

时间:2022-03-01

常规暴力

var getMinDistance = function (nums, target, start) {
    let res = Number.MAX_SAFE_INTEGER;
    for (let i = 0; i < nums.length; i++) if (nums[i] == target) res = Math.min(res,Math.abs(i - start));
    return res;
};

1685 有序数组中差绝对值之和

时间:2022-03-01

var getSumAbsoluteDifferences = function (nums) {
    const n = nums.length;
    let right = nums.reduce((a, b) => a + b, 0);
    const res = new Array(n).fill(0);
    let left = 0;
    for (let i = 0; i < n; i++) {
        right -= nums[i];
        res[i] += right - (n - i - 1) * nums[i];
        res[i] += i * nums[i] - left;
        left += nums[i];
    }
    return res;
};

648 单词替换

时间:2022-03-01

朴实无华的set集合

var replaceWords = function (dictionary, sentence) {
    const arr = sentence.split(' ');
    const set = new Set(dictionary);
    for (let i = 0; i < arr.length; i++) {
        for (let j = 1; j <= arr[i].length; j++) {
            if (set.has(arr[i].substring(0, j))) arr[i] = arr[i].substring(0, j);
        }
    }
    return arr.join(' ');
};

这里有个字典树,又好又快,好!。

class Trie {
    constructor() {
        this.dictionary = {};
    }

    insert(word) {
        let node = this.dictionary;

        for (const c of word) {
            if (!node[c]) node[c] = {};
            node = node[c];
        }
        node.isEnd = true;
        node.word = word;
    }

    search(word) {
        let node = this.dictionary;
        for (const c of word) {
            if (!node[c]) return word;
            else if (node[c]?.isEnd) return node[c].word;
            else node = node[c];
        }
        return word;
    }
}

const replaceWords = (dictionary, sentence) => {
    let trie = new Trie();
    for (const root of dictionary) trie.insert(root);
    return sentence
        .split(' ')
        .map((word) => trie.search(word))
        .join(' ');
};

还有个API调用法,这个startWith我还没用过呢,速度也还不错,整挺好的。

const replaceWords = (dictionary, sentence) => {
    const words = sentence.split(" ");
    const search = (word) => {
        for(const root of dictionary){
            if(word.startsWith(root)){
                word = root;
            }
        }
        return word;
    };
    return words.map(word => search(word)).join(" ");
};

415 字符串相加

时间:2022-03-02

为了下一道题题目做铺垫

var addStrings = function (num1, num2) {
    let n1 = num1.length - 1;
    let n2 = num2.length - 1;
    const arr = [];
    let add = 0;
    while (n1 >= 0 || n2 >= 0) {
        const x = n1 >= 0 ? num1[n1] - '0' : 0;
        const y = n2 >= 0 ? num2[n2] - '0' : 0;
        const res = x + y + add;
        arr.push(res % 10);
        add = Math.floor(res / 10);
        n1--;
        n2--;
    }
    if (add == 1) arr.push(1);
    return arr.reverse().join('');
};

43 字符串相乘

时间:2022-03-02

这道题就还行,算中等偏难一点点,问题不是很大。

var multiply = function (num1, num2) {
    if (num1 === '0' || num2 === '0') return '0';
    const m = num1.length;
    const n = num2.length;
    if (n < m) multiply(num2, num1);
    const arr = new Array(m + n).fill(0);
    let mul = 0;
    let x = 0,
        y = 0;
    for (let i = m - 1; i >= 0; i--) {
        mul = 0;
        y = num1[i] - '0';
        for (let j = n - 1; j >= 0; j--) {
            x = num2[j] - '0';
            const tmp = x * y + mul + arr[i + j + 1];
            arr[i + j + 1] = tmp % 10;
            mul = Math.floor(tmp / 10);
        }
        arr[i] = mul;
    }
    arr[0] = mul;
    if (arr[0] == 0) arr.shift();
    return arr.join('');
};

76 最小覆盖子串

时间:2022-03-02

困难题目,我只能说有、东西,滑动窗口,右边先找到能够满足的子串,左边再不断收窄看看能不能找到满足的子串,主要是这里判断会有点问题,他这里只判断数量,而不整个进行判断,节省了时间。

var minWindow = function (s, t) {
    const map = new Map();
    for (let i = 0; i < t.length; i++) map.set(t[i], (map.get(t[i]) || 0) + 1);
    let i = 0,
        j = 0;
    let window = {};
    let num = 0,
        res = '',
        length = Number.MAX_SAFE_INTEGER;
    while (j < s.length) {
        let ch = s[j];
        if (map.has(ch)) {
            window[ch] = (window[ch] || 0) + 1;
            if (map.get(ch) == window[ch]) num++;
        }
        while (num == map.size) {
            let c = s[i];
            if (map.has(c)) {
                if (length > j - i + 1) {
                    res = s.substring(i, j + 1);
                    length = j - i + 1;
                }
                window[c]--;
                if (window[c] < map.get(c)) num--;
            }
            i++;
        }
        j++;
    }
    return res;
};

258 各位相加

时间:2022-03-03

简单题简单写,但是还有个O(1)的数学方法,玩不来。

var addDigits = function (num) {
    while (num >= 10) {
        let sum = 0;
        while (num > 0) {
            sum += num % 10;
            num = Math.floor(num / 10);
        }
        num = sum;
    }
    return num;
};

576 出界的路径数

时间:2022-03-03

动态规划,也可以不降维,因为看似降维了,但其实是没有的,反而还增加了垃圾回收的次数,所以不建议。

var findPaths = function (m, n, maxMove, startRow, startColumn) {
    // dp 表示移动到当前坐标的所有路径数量和
    const dp = new Array(maxMove + 1).fill(0).map(() => new Array(m).fill(0).map(() => new Array(n).fill(0)));
    let res = 0;
    const dirs = [
        [-1, 0],
        [1, 0],
        [0, -1],
        [0, 1]
    ];
    dp[0][startRow][startColumn] = 1;
    const mod = 10 ** 9 + 7;
    for (let i = 1; i <= maxMove; i++) {
        for (let j = 0; j < m; j++) {
            for (let k = 0; k < n; k++) {
                for (let dir of dirs) {
                    const x = dir[0] + j;
                    const y = dir[1] + k;
                    if (x >= 0 && x < m && y >= 0 && y < n) {
                        dp[i][j][k] += dp[i - 1][x][y];
                        dp[i][j][k] %= mod;
                    } else {
                        res += dp[i - 1][j][k];
                        res %= mod;
                    }
                }
            }
        }
    }
    return res;
};

2140 解决智力问题

时间:2022-03-03

动态规划,不过要从右到左这样子规划,所以有点绕

var mostPoints = function (questions) {
    // dp为当前获得最多的分数
    const n = questions.length;
    const dp = new Array(n + 1).fill(0);

    for (let i = n - 1; i >= 0; i--) {
        if (i + questions[i][1] < n) {
            dp[i] = Math.max(dp[i + 1], dp[i + questions[i][1] + 1] + questions[i][0]);
        } else {
            dp[i] = Math.max(dp[i + 1], questions[i][0]);
        }
    }
    return dp[0];
};

2104 子数组范围和

时间:2022-03-04

太废物了,我连O(n2)的方法都写不出来,确实有点拉胯了,这个真的是有点真的是了。

var subArrayRanges = function (nums) {
    let res = 0;
    for (let i = 0; i < nums.length; i++) {
        let minVal = Number.MAX_VALUE,
            maxVal = -Number.MAX_VALUE;
        for (let j = i; j < nums.length; j++) {
            minVal = Math.min(minVal, nums[j]);
            maxVal = Math.max(maxVal, nums[j]);
            res += maxVal - minVal;
        }
    }
    return res;
};

1856 子数组最小乘积的最大值

时间:2022-03-04

佛了,这尼玛什么神仙解法,两个单调栈+前缀和。前缀和就是从[0,i-1]的和,然后下个就是[0,i-1]+nums[i]的和,相当于递增的和,这个倒是很好理解。

单调栈就是那个样子,这个题就是求出左边和右边都比这个数字小的位置,然后左开右开(left,right),这个子数组,这个数字就是最小的,然后右边的前缀和减去左边的前缀和,就是子数组的和了。

思路倒是还挺开阔的,但是代码能力太差了,实属有点难了。

var maxSumMinProduct = function (nums) {
    const len = nums.length;

    // 前缀和
    const sum = new Array(len + 1).fill(0);
    for (let i = 1; i <= len; i++) {
        sum[i] = sum[i - 1] + nums[i - 1];
    }
    console.log(sum);
    // 使用单调栈求解出左侧第个严格小于该数的元素位置,和右侧第一个严格小于该数的元素的位置
    let stack = [];
    const right = new Array(len).fill(len);
    for (let i = 0; i < len; i++) {
        while (stack.length && nums[stack[stack.length - 1]] > nums[i]) {
            right[stack[stack.length - 1]] = i;
            stack.pop();
        }
        stack.push(i);
    }
    stack = [];
    const left = new Array(len).fill(-1);
    for (let j = len - 1; j >= 0; j--) {
        while (stack.length && nums[stack[stack.length - 1]] > nums[j]) {
            left[stack[stack.length - 1]] = j;
            stack.pop();
        }
        stack.push(j);
    }
    // 根据前缀和和left, right数组进行枚举求解
    let max = BigInt(0);
    for (let k = 0; k < len; k++) {
        const total = BigInt(sum[right[k]] - sum[left[k] + 1]) * BigInt(nums[k]);
        if (max < total) {
            max = total;
        }
    }
    return max % BigInt(1000000007);
};

2108 找出数组中的第一个回文字符串

时间:2022-03-04

var firstPalindrome = function (words) {
    for (let i of words) {
        if (isPalindrome(i)) return i;
    }
    return ""
};
function isPalindrome(word) {
    let i = 0,
        j = word.length - 1;
    while (i < j) {
        if (word[i++] != word[j--]) return false;
    }
    return true;
}

521 最长特殊序列 I

时间:2022-03-05

略草,我以为我没看出来,结果我已经看出来了。

var findLUSlength = function (a, b) {
    return a !== b ? Math.max(a.length, b.length) : -1;
};

1780 判断一个数字是否可以表示成三的幂的和

时间:2022-03-05

这个题目也略草,虽然我没想到,转换成三进制。

var checkPowersOfThree = function (n) {
    while (n > 0) {
        if (n % 3 == 2) return false;
        n = Math.floor(n / 3);
    }
    return true;
};

1503 所有蚂蚁掉下来前的最后一刻

时间:2022-03-05

又是脑筋急转弯,怎么回事,随机一题都是一样的?

var getLastMoment = function (n, left, right) {
    return Math.max(Math.max(...left),n-Math.min(...right));
};

1436 旅行终点站

时间:2022-03-05

过于简单

var destCity = function (paths) {
    const map = new Map();
    for (let p of paths) {
        map.set(p[0], (map.get(p[0]) || 0) + 2);
        map.set(p[1], (map.get(p[1]) || 0) + 1);
    }
    for (let m of map) {
        if (m[1] == 1) return m[0];
    }
};

1287 有序数组中出现次数超过25%的元素

时间:2022-03-05

var findSpecialInteger = function (arr) {
    const n = Math.floor(arr.length / 4);
    let cnt = 1;
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] == arr[i - 1]) {
            cnt++;
            if (cnt > n) return arr[i];
        } else cnt = 1;
    }
    return arr[0]
};

1401 圆和矩形是否有重叠

时间:2022-03-05

这个题目看起来蛮简单的,但是实现起来还是蛮复杂的,我不一定能够做出来。

var checkOverlap = function (radius, xCenter, yCenter, x1, y1, x2, y2) {
    // 在矩形中间
    if (xCenter >= x1 && xCenter <= x2 && yCenter <= y2 && yCenter >= y1) return true;
    // 在上下左右
    if (xCenter >= x1 && xCenter <= x2 && yCenter > y2) return yCenter - y2 <= radius;
    if (xCenter >= x1 && xCenter <= x2 && yCenter < y1) return y1 - yCenter <= radius;
    if (yCenter <= y2 && yCenter >= y1 && xCenter < x1) return  x1- xCenter <= radius;
    if (yCenter <= y2 && yCenter >= y1 && xCenter > x2) return xCenter - x2 <= radius;
    // 在四个角落
    const x0 = Math.floor((x1 + x2) / 2),
        y0 = Math.floor((y1 + y2) / 2);
    const p = [Math.abs(xCenter - x0), Math.abs(yCenter - y0)];
    const q = [x2 - x0, y2 - y0];
    const u = [p[0] - q[0], p[1] - q[1]];
    return u[0] ** 2 + u[1] ** 2 <= radius ** 2;
};

6016 Excel 表中某个范围内的单元格

时间:2022-03-06

尝试打一下周赛,虽然没有正式参加,但也算一种尝试了。

这道简单题简单,不过也浪费了我一些时间

var cellsInRange = function (s) {
    const res = [];
    let xStart = s[0].charCodeAt() - 65;
    let xEnd = s[3].charCodeAt() - 65;
    let yStart = Number.parseInt(s[1]);
    let yEnd = Number.parseInt(s[4]);
    for (let i = xStart; i <= xEnd; i++) {
        for (let j = yStart; j <= yEnd; j++) {
            res.push(String.fromCharCode(i + 65) + j.toString());
        }
    }
    return res;
};

6017 向数组中追加 K 个整数

时间:2022-03-06

这道题JS过不去,BigInt都不行,有点拉胯

var minimalKSum = function (nums, k) {
    nums.sort((a, b) => a - b);
    nums.unshift(0);
    let res = 0;
    for (let i = 1; i < nums.length; i++) {
        const cnt = nums[i] - nums[i - 1] - 1;
        if (cnt <= 0) continue;
        const min = Math.min(cnt, k);
        res += Math.floor((min * (nums[i] + 1 + nums[i - 1] - 1)) / 2);
        k -= min;
        if (k == 0) return res;
    }
    let j = nums[nums.length - 1] + 1;
    res = BigInt(res) + BigInt(Math.floor((k * (j + j + k - 1)) / 2));
    return res;
};

6018 根据描述创建二叉树

时间:2022-03-06

这道题搞不来,我知道要用哈希表和map表,但是,唉,就是没有搞出来,有点拉了兄弟。

var createBinaryTree = function (descriptions) {
    const map = new Map();
    const set = new Set();
    for (let des of descriptions) {
        let parent;
        if (map.has(des[0])) parent = map.get(des[0]);
        else {
            parent = new TreeNode(des[0]);
            map.set(des[0], parent);
        }
        let child;
        if (map.has(des[1])) child = map.get(des[1]);
        else {
            child = new TreeNode(des[1]);
            map.set(des[1], child);
        }
        set.add(des[1]);
        if (des[2] == 1) parent.left = child;
        else parent.right = child;
    }
    for (let m of map) {
        if (!set.has(m[1].val)) {
            return m[1];
        }
    }
    return null;
};

6019 替换数组中的非互质数

时间:2022-03-06

这道题配不上困难,虽然我还是没有一开始做对,还是看了一下题解,但这道题就是用栈弄一下就行了,算不上多难。

var replaceNonCoprimes = function (nums) {
    let st = [nums[0]];
    for (let i = 1; i < nums.length; i++) {
        st.push(nums[i]);
        while (st.length > 1) {
            const res = gcd(st[st.length - 1], st[st.length - 2]);
            if (res !== 1) {
                st.push(Math.floor((st.pop() * st.pop()) / res));
            } else break;
        }
    }
    return st;
};
function gcd(a, b) {
    if (b == 0) return a;
    else return gcd(b, a % b);
}

1402 做菜顺序

时间:2022-03-07

相当的难,虽然看起来很简单,但是想法却很难。首先从大到小排序,然后计算它的前缀和,再将前缀和累加,如果前缀和小于0,那么就break,因为再加进去肯定是会使值变小。

var maxSatisfaction = function (satisfaction) {
    satisfaction.sort((a, b) => b - a);
    let res = 0;
    let presum = 0;
    for (let i of satisfaction) {
        if (presum + i >= 0) {
            presum += i;
            res += presum;
        } else break;
    }
    return res;
};

504 七进制数

时间:2022-03-07

和两年前的错误一模一样,就是没有考虑0,真有我的。

var convertToBase7 = function (num) {
    if (num == 0) return '0';
    const arr = [];
    let flag = 1;
    if (num < 0) {
        num = -num;
        flag = -1;
    }

    while (num > 0) {
        arr.push(num % 7);
        num = Math.floor(num / 7);
    }
    if (flag < 0) arr.push('-');
    return arr.reverse().join('');
};

1409 查询带键的排列

时间:2022-03-07

就嗯模拟就行了。

var processQueries = function (queries, m) {
    const arr = new Array(m).fill(0).map((value, index) => (value = index + 1));
    const res = [];
    for (let q of queries) {
        const index = arr.indexOf(q);
        for (let i = index - 1; i >= 0; i--) {
            arr[i + 1] = arr[i];
        }
        arr[0] = q;
        res.push(index);
    }
    return res;
};
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇