力扣 821. 字符的最短距离

227 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 15 天,点击查看活动详情

题目链接

821. 字符的最短距离 - 力扣(LeetCode)

题目描述

给你一个字符串 s 和一个字符 c ,且 c 是 s 中出现过的字符。

返回一个整数数组 answer ,其中 answer.length == s.length 且 answer[i] 是 s 中从下标 i 到离它 最近 的字符 c 的 距离 。

两个下标 i 和 j 之间的 距离 为 abs(i - j) ,其中 abs 是绝对值函数。

测试用例

用例1:

输入: s = "loveleetcode", c = "e"
输出: [3,2,1,0,1,0,0,1,2,2,1,0]

限制

  • 1 <= s.length <= 10^4
  • s[i] 和 c 均为小写英文字母
  • 题目数据保证 c 在 s 中至少出现一次

题目分析

题目给出了一个字符串 str,以及 str 中出现过的字符 c,需要我们求字符串中每个字符距离 c 的最短下标。需注意,c 出现的次数是不确定的,即 次数 >=1

首先,我们求出 cstr 中的全部下标位置,使用一个数组 arr 记录下来,此时,arr 中的数据是递增的。

对于 str 中的某个字符 n 的下标 i 有如下几种情况判断处理:

  • i <= arr[0],或者 i >= arr[arr.length - 1] 的时候,直接相减取绝对值即可
  • arr[j] < i < arr[j + 1] 的时候,将 i 分别与 arr[j], arr[j + 1] 相减,取其中一个最小值即可

代码实现

完整的代码实现如下

var shortestToChar = function (s, c) {
    let arr = [];
    for (let i = 0; i < s.length; i++) {
        if (s.charAt(i) == c) {
            arr.push(i);
        }
    }
    let nums = [];
    arr.push(Number.MAX_SAFE_INTEGER);
    for (let i = 0, j = 0; i < s.length; i++) {
        if (j == 0) {
            nums.push(Math.abs(i - arr[j]))
        } else {
            nums.push(Math.min(Math.abs(i - arr[j]), Math.abs(i - arr[j - 1])))
        }
        if (i >= arr[j]) j++;
    }
    return nums;
};

image.png

优化

在字符 c 重复出现的次数超过 2 次的时候,两个坐标之间的数据,呈现一个 倒V;将这两个下标命名为 left, right,套用一个循环体,left++, right-- 的时候,对应的值 val++,直到 left > right 的时候,跳出循环体

var shortestToChar = function (s, c) {
    let arr = [];
    for (let i = 0; i < s.length; i++) {
        if (s.charAt(i) == c) {
            arr.push(i);
        }
    }
    let nums = new Array(s.length).fill(0);
    for (let j = 0; j < arr.length - 1; j++) {
        setDiff(nums, arr[j], arr[j + 1]);
    }
    for (let i = 0; i <= arr[0]; i++) {
        nums[arr[0] - i] = i;
    }
    for (let i = arr[arr.length - 1], k = 0; i < s.length; i++, k++) {
        nums[i] = k;
    }
    function setDiff(arr, left, right) {
        let val = 0;
        for (; left <= right; left++, right--, val++) {
            arr[left] = val;
            arr[right] = val;
        }
    }
    return nums;
};

image.png