Java&C++题解与拓展——leetcode821.字符的最短距离【么的新知识】

每日一题做题记录,参考官方和三叶的题解

题目要求

image.png

思路一:两次遍历

算是个直接模拟的思路,从左到右遍历获得到左边最近目标字符的距离,从右到左遍历得到右边最近目标字符距离,有点像双指针的感觉。

两种语言的初始指针指向不太一样。

Java

  • 初始化结果数组为 n + 1 n+1 n+1(大于最远距离),用于在从右向左遍历(第二圈)时找到更小值,因为第一圈遍历时,第一个目标字符前元素的结果为默认值;
  • 遍历时将指针指在 − 1 -1 1位置,找到第一个目标字符后开始更新后面元素的距离。
class Solution {
    public int[] shortestToChar(String s, char c) {
        int n = s.length();
        int[] res = new int[n];
        Arrays.fill(res, n + 1);
        // 从左到右,到左边c的距离
        for(int i = 0, j = -1; i < n; i++) {
            if(s.charAt(i) == c)
                j = i;
            if(j != -1)
                res[i] = i - j;
        }
        // 从右到左,到右边c的距离
        for(int i = n - 1, j = -1; i > -1; i--) {
            if(s.charAt(i) == c)
                j = i;
            if(j != -1)
                res[i] = Math.min(res[i], j - i);
        }
        return res;
    }
}
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

C++

  • 无需初始化数组,在第一圈遍历时可更新所有元素;
  • 从左向右遍历时,指针指向 − n -n n,以此更新第一个目标字符前的元素,结果将大于最大距离 n − 1 n-1 n1
  • 从右向左遍历时,指针指向 2 n 2n 2n,以此更新一个目标字符前元素,但计算结果都不会取到,因为其结果将一定大于当前结果数组内所存值。
class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
        int n = s.size();
        vector<int> res(n);
        // 从左到右,到左边c的距离
        for(int i = 0, j = -n; i < n; i++) {
            if(s[i] == c)
                j = i;
            res[i] = i - j;
        }
        // 从右到左,到右边c的距离
        for(int i = n - 1, j = 2 * n; i > -1; i--) {
            if(s[i] == c)
                j = i;
            res[i] = min(res[i], j - i);
        }
        return res;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

思路二:BFS

  • 需要一个队列容器用来存下一个待处理节点,一个结果数组存距离,将所有距离初始化为 − 1 -1 1
  • 找出所有目标字符,将其相应距离置 0 0 0,并将相应下标入队;
  • 依次处理队列内节点:
    • 分别更新其左、右节点(即前一个和后一个,下标减一和加一);
    • 若未更新过(距离为初始值 − 1 -1 1),则当前节点在其最短距离路径上,更新结果为当前节点距离 + 1 +1 +1
    • 若更新过,则之前有距离更近的节点。

Java

class Solution {
    public int[] shortestToChar(String s, char c) {
        int n = s.length();
        int[] res = new int[n];
        Arrays.fill(res, -1);
        Deque<Integer> que = new ArrayDeque<>();
        // 初始化目标字符距离为0
        for(int i = 0; i < n; i++) {
            if(s.charAt(i) == c) {
                que.addLast(i);
                res[i] = 0;
            }
        }
        // 更新左右两个节点距离
        int[] lr = {-1, 1};
        while(!que.isEmpty()) {
            int cur = que.pollFirst();
            for(int t : lr) {
                int tmp = t + cur;
                if(tmp > -1 && tmp < n && res[tmp] == -1) {
                    res[tmp] = res[cur] + 1;
                    que.addLast(tmp);
                }
            }
        }
        return res;
    }
}
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n),队列大小

C++

class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
        int n = s.size();
        vector<int> res(n, -1);
        queue<int> que;
        // 初始化目标字符距离为0
        for(int i = 0; i < n; i++) {
            if(s[i] == c) {
                que.emplace(i);
                res[i] = 0;
            }
        }
        // 更新左右两个节点距离
        int lr[2] = {-1, 1};
        while(!que.empty()) {
            int cur = que.front();
            que.pop();
            for(int t : lr) {
                int tmp = t + cur;
                if(tmp > -1 && tmp < n && res[tmp] == -1) {
                    res[tmp] = res[cur] + 1;
                    que.emplace(tmp);
                }
            }
        }
        return res;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n),队列大小

总结

是个快乐简单题,能稍微动动脑子的模拟题。

用BFS是真的完全没想到,虽然需要额外空间复杂度,但是思路很巧妙,受教了。


欢迎指正与讨论!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值