字符的最短距离

130 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目描述

给你一个字符串 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]
解释:字符 'e' 出现在下标 35611 处(下标从 0 开始计数)。
距下标 0 最近的 'e' 出现在下标 3 ,所以距离为 abs(0 - 3) = 3 。
距下标 1 最近的 'e' 出现在下标 3 ,所以距离为 abs(1 - 3) = 2 。
对于下标 4 ,出现在下标 3 和下标 5 处的 'e' 都离它最近,但距离是一样的 abs(4 - 3) == abs(4 - 5) = 1 。
距下标 8 最近的 'e' 出现在下标 6 ,所以距离为 abs(8 - 6) = 2

示例 2:

输入:s = "aaab", c = "b"
输出:[3,2,1,0]

提示:

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

二、思路分析

分析一下题意,我们可以知道题目要求的是我们计算字符串s中每一个字符距离最近字符c的距离。我们可以先找出字符串s中的所有c字符的位置,然后在比较一下字符串中每一个字符和c字符位置,找出最近的距离。比较距离这一块我们可以进行一些优化,每次比较我们只需要比较字符c的距离数组中的前两项,如果第一项的距离已经远于第二项的距离,我们就将第一项移除出数组,这样每次进行比较我们都可以直接得出结果,不需要遍历完整个数组来寻找最小值。

  • 找出所有字符c的位置集合
let cInd = [];
for(let i = 0; i < s.length; i++){
    if(s[i] === c) cInd.push(i);
}
  • 判断是否该移除第一项
if(Math.abs(cInd[0] - i) > Math.abs((cInd[1] || Infinity) - i)){
    cInd.shift();
}
  • 计算当前字符与c字符的最近距离
res[i] = Math.abs(cInd[0] - i);

完整AC代码如下。

三、AC代码

/**
 * @param {string} s
 * @param {character} c
 * @return {number[]}
 */
var shortestToChar = function(s, c) {
    let cInd = [];
    for(let i = 0; i < s.length; i++){
        if(s[i] === c) cInd.push(i);
    }
    let res = new Array(s.length).fill(0);
    for(let i = 0; i < s.length; i++){
        if(Math.abs(cInd[0] - i) > Math.abs((cInd[1] || Infinity) - i)){
            cInd.shift();
        }
        res[i] = Math.abs(cInd[0] - i);
    }
    return res;
};