0%

1042. 不邻接植花

n 个花园,按从 1n 标记。另有数组 paths ,其中 paths[i] = [xi, yi] 描述了花园 xi 到花园 yi 的双向路径。在每个花园中,你打算种下四种花之一。

另外,所有花园 最多3 条路径可以进入或离开.

你需要为每个花园选择一种花,使得通过路径相连的任何两个花园中的花的种类互不相同。

以数组形式返回 任一 可行的方案作为答案 answer,其中 answer[i] 为在第 (i+1) 个花园中种植的花的种类。花的种类用 1、2、3、4 表示。保证存在答案。

示例 1:

输入:n = 3, paths = [[1,2],[2,3],[3,1]]
输出:[1,2,3]
解释:
花园 1 和 2 花的种类不同。
花园 2 和 3 花的种类不同。
花园 3 和 1 花的种类不同。
因此,[1,2,3] 是一个满足题意的答案。其他满足题意的答案有 [1,2,4]、[1,4,2] 和 [3,2,1]

题解

/**
 * @param {number} n 花园的数量
 * @param {number[][]} paths 花园之间的路径列表
 * @return {number[]} 返回一个长度为 n 的数组,代表每个花园所涂的颜色
 */
var gardenNoAdj = function(n, paths) {
    // 构造邻接表,用 nei[i] 存储与第 i 个花园相邻的花园编号
    let nei = new Array(n).fill(null).map(() => []);
    for (let path of paths) {
        nei[path[0] - 1].push(path[1] - 1);
        nei[path[1] - 1].push(path[0] - 1);
    }
    // 初始化结果数组 res,用 res[i] 存储第 i 个花园所涂的颜色
    let res = new Array(n).fill(0);
    // 遍历每个花园,对其进行着色
    for (let i = 0; i < n; ++i) &#123;
        let usedColor = new Array(5).fill(false); // 初始化 usedColor,用于记录相邻花园已经使用的颜色
        // 遍历第 i 个花园的相邻花园,统计已经使用的颜色
        for (let vertex of nei[i]) &#123;
            usedColor[res[vertex]] = true;
        &#125;
        // 找到第一个未使用的颜色
        for (let j = 1; j <= 4; ++j) &#123;
            if (!usedColor[j]) &#123;
                res[i] = j;
                break;
            &#125;
        &#125;
    &#125;
    return res;
&#125;;

复杂度分析

时间复杂度:O(n+m),其中 n 表示花园的数目,m 表示 paths 的数目。由于题目中每个花园的邻接节点数目不超过 3 个,因此每个节点的边不超过 3 条,所以遍历所有的节点与所有的边需要的总的时间不超过 O(m+n)。

空间复杂度:O(n+m),其中 n 表示花园的数目,m 表示 paths 的数目。需要存储每个节点的邻接节点,总共需要的空间为 O(n+m)。

1023. 驼峰式匹配

如果我们可以将小写字母插入模式串 pattern 得到待查询项 query,那么待查询项与给定模式串匹配。(我们可以在任何位置插入每个字符,也可以插入 0 个字符。)

给定待查询列表 queries,和模式串 pattern,返回由布尔值组成的答案列表 answer。只有在待查项 queries[i] 与模式串 pattern 匹配时, answer[i] 才为 true,否则为 false

示例 1:

输入:queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FB"
输出:[true,false,true,true,false]
示例:
"FooBar" 可以这样生成:"F" + "oo" + "B" + "ar"。
"FootBall" 可以这样生成:"F" + "oot" + "B" + "all".

题解

/**
 * @param &#123;string[]&#125; queries
 * @param &#123;string&#125; pattern
 * @return &#123;boolean[]&#125;
 */
var camelMatch = function(queries, pattern) &#123;
    let res = [];
    if (!queries || queries.length === 0) &#123;
        return res;
    &#125;
    for (let i = 0; i < queries.length; ++i) &#123;
        res.push(match(queries[i], pattern));
    &#125;
    return res;
&#125;;

function match(str, pattern) &#123;
    let j = 0;
    for (let i = 0; i < str.length; ++i) &#123;
        if (j < pattern.length && str[i] === pattern[j]) &#123;
            ++j;
        &#125;
        // 若str出现在pattern中不存在的大写字母,则直接返回false
        else if (str[i] >= 'A' && str[i] <= 'Z') &#123;
            return false;
        &#125;
    &#125;
    return j === pattern.length;
&#125;

2404. 出现最频繁的偶数元素

给你一个整数数组 nums ,返回出现最频繁的偶数元素。

如果存在多个满足条件的元素,只需要返回 最小 的一个。如果不存在这样的元素,返回 -1

示例 1:

输入:nums = [0,1,2,2,4,4,1]
输出:2
解释:
数组中的偶数元素为 0、2 和 4 ,在这些元素中,2 和 4 出现次数最多。
返回最小的那个,即返回 2 。

题解

function mostFrequentEven(nums) &#123;
  const cnt = new Map(); // 创建一个Map对象
  for (const x of nums) &#123; // 遍历数组中的每个数
    if (x % 2 === 0) &#123; // 判断该数是否为偶数
      cnt.set(x, (cnt.get(x) || 0) + 1); // 将偶数x和对应的出现次数加入Map中
    &#125;
  &#125;
  let ans = -1; // 初始化结果为-1
  let mx = 0; // 初始化最大出现次数为0
  for (const [x, v] of cnt.entries()) &#123; // 遍历Map中的所有键值对
    if (mx < v || (mx === v && ans > x)) &#123; // 如果当前偶数出现的次数更多,或者两个偶数的出现次数相等,但是x更小,则更新ans和mx
      ans = x;
      mx = v;
    &#125;
  &#125;
  return ans; // 返回出现次数最多的偶数
&#125;

1147. 段式回文

你会得到一个字符串 text 。你应该把它分成 k 个子字符串 (subtext1, subtext2,…, subtextk) ,要求满足:

  • subtexti非空 字符串
  • 所有子字符串的连接等于 text ( 即subtext1 + subtext2 + ... + subtextk == text )
  • 对于所有 i 的有效值( 即 1 <= i <= k ) ,subtexti == subtextk - i + 1 均成立

返回k可能最大值。

示例 1:

输入:text = "ghiabcdefhelloadamhelloabcdefghi"
输出:7
解释:我们可以把字符串拆分成 "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)"。

示例 2:

输入:text = "merchant"
输出:1
解释:我们可以把字符串拆分成 "(merchant)"。

题解:双指针+贪心

/**
 * @param &#123;string&#125; text
 * @return &#123;number&#125;
 */
var longestDecomposition = function(text) &#123;
    let n = text.length;
    let i = 0, j = n - 1, ans = 0;
    let s1 = '', s2 = '';
    while(1) &#123;
        if (i >= j)&#123;
            break;
        &#125;
        s1 += text[i];
        s2 = text[j] + s2;
        if (s1 === s2) &#123;
            ans++;
            s1 = '';
            s2 = '';
            if (i + 1 === j) &#123;
                return 2 * ans;
            &#125;
        &#125;
        i++;
        j--;
    &#125;
    // 如果无法找到重复子序列,直接返回最小分解数乘以2再加1,表示字符串不能再分解了
    return ans * 2 + 1;
&#125;;

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
/**
 * @param &#123;number[]&#125; nums
 * @return &#123;number[][]&#125;
 */
var permute = function(nums) &#123;
    const result = [];
    const n = nums.length;
    const used = new Array(n).fill(false); // 记录每个元素是否已被使用过
    const path = [];

    function dfs() &#123;
        if (path.length === n) &#123; // 如果路径中的元素个数等于 n,表示已经找到一组解
            result.push([...path]); // 将路径中的元素加入结果数组
            return;
        &#125;
        for (let i = 0; i < n; i++) &#123;
            if (!used[i]) &#123; // 如果元素未被使用过
                path.push(nums[i]); // 将其加入路径
                used[i] = true; // 标记元素已被使用
                dfs(); // 继续搜索下一个元素
                used[i] = false; // 恢复现场
                path.pop(); // 回溯
            &#125;
        &#125;
    &#125;

    dfs();
    return result;
&#125;;

递归真难啊

矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法

示例 1:

img

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

示例 2:

img

输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
/**
 * @param &#123;number[][]&#125; matrix
 * @return &#123;void&#125; Do not return anything, modify matrix in-place instead.
 */
var setZeroes = function(matrix) &#123;
    let row = [], column = [];
    let rowLen = matrix.length;
    let columnLen = matrix[0].length;
    for (let i = 0; i < rowLen; ++i) &#123;
        for (let j = 0; i < columnLen; ++j) &#123;
            if (matrix[i][j] === 0)&#123;
                row.push(i);
                column.push(j);
            &#125;
        &#125;
    &#125;
    for (let i = 0; i < row.length; ++i) &#123;
        matrix[row[i]] = 0;
        for (let j = 0; j < rowLen; ++j)&#123;
            matrix[j][column[i]] = 0;
        &#125;
    &#125;
    return matrix;
&#125;;

单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。https://blog.csdn.net/qq_37264323/article/details/114366943

递归

https://leetcode.cn/problems/merge-two-sorted-lists/

img

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) {
            return l2;
        }
        else if (l2 == nullptr) {
            return l1;
        } 
        else if (l1->val < l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }
        else {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
}

Hi there! Wish you have a good day!