leetcode-pp / 91alg-7-daily-check

6 stars 0 forks source link

【Day 2 】2022-04-02 - 821. 字符的最短距离 #3

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

821. 字符的最短距离

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/shortest-distance-to-a-character

前置知识

示例 1:

输入: S = "loveleetcode", C = 'e' 输出: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0] 说明:

sallyrubyjade commented 2 years ago

思路

遍历字符串,对每一个字符元素,使用左右指针思想,分别向左和向右寻找最近的字符c,使用Math.min()进行对比,找到最短距离,把值放进数组中,再对下一个字符元素进行相同操作,直到遍历结束。

代码

/**
 * @param {string} s
 * @param {character} c
 * @return {number[]}
 */
var shortestToChar = function(s, c) {
    let ans = [];
    for(let i = 0; i < s.length; i++) {
        if(s[i] === c) {
            ans.push(0);
            continue;
        }

        let left = i;
        let right = i;
        let shortest = Number.MAX_VALUE;

        while(left >= 0) {
            if(s[left] === c) {
                shortest = Math.min(shortest, i - left);
                break;
            }
            left--;
        }

        while(right <= s.length - 1) {
            if (s[right] === c) {
                shortest = Math.min(shortest, right - i);
                break;
            }
            right++;
        }
        ans.push(shortest);
    }
    return ans;
};

复杂度分析

miss1 commented 2 years ago

思路

两遍循环,先从左到右遍历s, 找到值左边第一个c的距离。再从右到左遍历,找到值右边第一个c的距离。取两个值中的最小值。

代码

var shortestToChar = function(s, c) {
  let res = [];
  let cIndex = -Infinity;
  for (let i = 0; i < s.length; i++) {
    if (s[i] === c) cIndex = i;
    res[i] = i - cIndex;
  }
  let rcIndex = Infinity;
  for (let i = s.length - 1; i >= 0; i--) {
    if (s[i] === c) rcIndex = i;
    res[i] = Math.min(res[i], rcIndex - i);
  }
  return res;
};

复杂度分析

PFyyh commented 2 years ago

思路

借鉴了滑动窗口算法,找到第一个和第二个出现字符的位置。

比较下标-头的距离和尾巴-下标的距离,填入数组。

当下标到达尾巴的时候,说明已经

当S字符串只有一个符合的c的时候,从符合位置点往两边填充距离。

代码

class Solution {
    public int[] shortestToChar(String s, char c) {
        //存储结果
        int[] result = new int[s.length()];
        //判断滑动窗口
        int head = s.indexOf(c);
        int tail = s.indexOf(c, head + 1);
        //说明没有窗口,直接填充两边值即可
        if(tail==-1){
            int absLength = 0;
            int lP = head;
            int rP = head;
            //从唯一的下标开始往两边扩展
            while(lP>=0||rP<s.length()){
                if(lP>=0){
                    result[lP]=absLength;
                    lP--;
                }
                if(rP<s.length()){
                    result[rP]=absLength;
                    rP++;
                }
                absLength++;
            }
            return result;

        }
        char[] chars = s.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            result[i] = Math.min(Math.abs(head - i), Math.abs(tail - i));
            //遍历到了尾巴,尾巴变头,找下一个尾巴。
            if (i == tail) {
                head = tail;
                //如果尾巴没了,tail = -1 tail-i的绝对值永远大于head-i的绝对值,永远是head-i
                tail = s.indexOf(c, tail + 1);
            }
        }
        return result;
    }
}

复杂度分析

时间复杂度:O(n)

空间复杂度:O(n)

duantao74520 commented 2 years ago

思路:

维护两个指针,一个代表着离左边的c的位置,一个代表着离右边的c的位置

遍历数组:

  1. 从左往右遍历s1,直到找到c,然后赋值左右c。
  2. 再次从左往右遍历s2,开始记录离左右两边最近的c。
  3. 直到s2遍历到c的位置,继续遍历上一个遍历队列s1,直到数组尽头
  4. 继续遍历s2,输出位置

代码:

class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
       int c_l = -1, c_r = -1;
        int i = 0, j = 0;
        vector<int> ret_vec;
        while (j < s.size()) {
            for (i ; i < s.size(); i++) {
                if (s[i] == c) {
                    c_l = c_r;
                    c_r = i;
                    if (c_l == -1) { // 第一个c
                        c_l = c_r;
                    }
                    i++;
                    break;
                }
                if (i == s.size()-1) { // 最后一个c
                    c_l = c_r;
                }
            }
            for (j ; j < i; j++) {
                ret_vec.emplace_back(min(abs(j - c_l) , abs(j-c_r)));
            }
            cout << c_l << c_r << i << j <<endl;
        }
        return ret_vec;
    }
};

复杂度:

时间: o(n)

空间: o(1)

LQyt2012 commented 2 years ago

思路

两次遍历字符串,取其中较短的距离作为返回值

代码

class Solution:
    def find_smallest_dist(self, s:str, c:str) -> List[int]:
         nearest_dist = len(s)
         result = [0]*len(s)
         for i in range(len(s)):
             nearest_dist = 0 if s[i] == c else nearest_dist + 1
             result[i] = nearest_dist
         nearest_dist = len(s)
         for i in range(len(s)-1, -1, -1):
             nearest_dist = 0 if s[i] == c else nearest_dist + 1
             result[i] = min(nearest_dist, result[i])
         return result

复杂分析

空间复杂度:O(N)
时间复杂度:O(N)

AConcert commented 2 years ago
var shortestToChar = function (s, c) {
    let arrStr = s.split('');
    let result = [];
    let index = null;
    for (let i = 0; i < arrStr.length; i++) {
        if (arrStr[i] !== c && index === null) {
            result[i] = null;
        } else if (arrStr[i] === c) {
            result[i] = 0;
            index = i;
        } else {
            result[i] = i - index;
        }
    }
    index = null;
    for (let i = arrStr.length - 1; i >= 0; i--) {
        if (arrStr[i] === c) {
            index = i;
        } else if (index !== null && result[i] && index - i < result[i]) {
            result[i] = index - i;
        } else if (!result[i]) {
            result[i] = index - i;
        }
    }
    return result;
};

复杂度分析 - 时间复杂度:O(N) - 空间复杂度:O(N)

liuajingliu commented 2 years ago

解题思路

代码实现

/**
 * @param {string} S
 * @param {character} C
 * @return {number[]}
 */
var shortestToChar = function (S, C) {
  const res = Array(S.length).fill(0);

  for (let i = 0; i < S.length; i++) {
    if (S[i] === C) continue;
    // 定义两个指针 l, r 分别向左、右两个方向寻找目标字符 C,取最短距离
    let l = i,
      r = i,
      shortest = Infinity;

    while (l >= 0) {
      if (S[l] === C) {
        shortest = Math.min(shortest, i - l);
        break;
      }
      l--;
    }

    while (r < S.length) {
      if (S[r] === C) {
        shortest = Math.min(shortest, r - i);
        break;
      }
      r++;
    }

    res[i] = shortest;
  }
  return res;
};

复杂度分析

webcoder-hk commented 2 years ago
class Solution:
    def shortestToChar(self, S:str, C:str)-> List[int]:
        n = len(S)
        result = [0 for _ in range(n)]
        m,p = 0,0
        for i in range(n):
            if S[i]==C:
                if m == 0:
                    m = i
                p = i
                v = 0
                while p+1<n and S[p+1]!=C:
                    p += 1
                    v += 1
                    result[p] = v
                q = p
                v = 0
                while q>i and p+1<n and S[p+1] == C:
                    v += 1
                    result[q] = min(result[q],v)
                    q -= 1
        v = 0
        while m-1>=0 and S[0]!=C:
            m -= 1
            v += 1
            result[m] = v
        return result

time: O(n^2) space: O(n)

All-Sunday commented 2 years ago

思路

先遍历一次字符串s,获得字符串s种所有c的小标,并存在cIndexs数组;

双层循环,外层遍历字符串s,内层遍历cIndexs数组,即将字符串s种每一个字字符的小标与所有的字符c小标分别求绝对值,所得值中最小的即为所求目标,存入结果answer数组。

暂没有其他思路,就暴力求解了。😥

代码

class Solution {
    public int[] shortestToChar(String s, char c) {
        int n = s.length();
        int[] answer = new int[n];
        int[] cIndexs = new int[n];
        int cNum = 0;
        for(int i = 0; i < s.length(); i++){
            if(s.charAt(i) == c){
                cIndexs[cNum++] = i;
            }
        }

        for(int i = 0; i < s.length(); i++){
            int minDistance = n;
            for(int j = 0; j < cNum; j++){
                int distance = Math.abs(i - cIndexs[j]);
                if(distance < minDistance){
                    minDistance = distance;
                }
            }
            answer[i] = minDistance;
        }

        return answer;
    }
}

复杂度分析

ZacheryCao commented 2 years ago

Idea

Deque q for the index of character c. For each index i in s check whether abs(i - q[0])>abs(i - q[1]) and q has more than 1 element. If it is, pop the most front element from the q.

Code

class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        position = collections.deque()
        for i in range(len(s)):
            if s[i] == c:
                position.append(i)
        ans = []
        for i in range(len(s)):
            if len(position)>1 and abs(i-position[0])>abs(i-position[1]):
                position.popleft()
            ans.append(abs(i-position[0]))
        return ans

Complexity:

Time: O(N) Space: O(N)

maggiexie00 commented 2 years ago

思路

两次遍历

记录上一个字符c出现的位置,从头走一遍,计算距离,再从尾部走一遍,更新距离为两次计算中的较小值。

代码

def shortestToChar(self, s, c):
    last=-10000
    ans=[]
    for i in range(len(s)):
        if s[i]==c:
            last=i
        ans.append(i-last)
    last=10000
    for i in range(len(s)-1,-1,-1):
        if s[i]==c:
            last=i
        ans[i]=min(ans[i],last-i)
    return ans

复杂度

时间 O(N) 空间 O(N)

577961141 commented 2 years ago

题目思路

  1. 先遍寻左边,记录上一次字符C出现的位置prev,那么答案就是i-prev
  2. 再遍寻右边,记录上一次字符C出现的位置prev,那么答案就是prev-i
  3. 最后比较相同位置的数值,谁小取谁

题目的题解code

<?php

class Solution {

    /**
     * @param String $s
     * @param String $c
     * @return Integer[]
     */
    function shortestToChar($s, $c) {
        $ans = [];
        $len = mb_strlen($s);

        // 计算左边
        $prev = PHP_INT_MIN / 2;
        for ($i = 0; $i < $len; $i++) {
            if ($s[$i] == $c) {
                $prev = $i;
            }

            $ans[] = $i - $prev;
        }

        // 计算右边
        $prev = PHP_INT_MAX / 2;
        for ($j = $len - 1; $j >= 0; $j--) {
            if ($s[$j] == $c) {
                $prev = $j;
            }

            $ans[$j] = min($ans[$j], $prev - $j);
        }

        return $ans;
    }
}

时间和空间复杂度

时间复杂度: O(N),N是字符串的长度,我们需要遍历两次 空间复杂度: O(N),ans的长度

liuguang520-lab commented 2 years ago

思路

使用的是暴力解法没有使用官方的前后遍历所以时间复杂度和空间复杂度比较高

class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
        vector<int> result;
        vector<int > index;
        int len = s.length();
        for(int i = 0; i< len; i++)
        {
            if(s.at(i) == c)//将字符串转换成字符在进行比较
            {
                index.push_back(i);
            }
        }
        int len_index = index.size();
        for(int i = 0; i < len; i++)
        {
            int dis_min = len;//初始化为len
            for(int j =0; j<len_index; j++)
            {
                dis_min = min(abs(i-index[j]),dis_min);
            }
            result.push_back(dis_min);
        }
    return result;
    }
};

复杂度分析

revisegoal commented 2 years ago

idea

左右遍历数组

code

class Solution {
    public int[] shortestToChar(String s, char c) {
        int len = s.length();
        int[] res = new int[len];
        int pre = Integer.MIN_VALUE / 2;
        for (int i = 0; i < len; i++) {
            if (s.charAt(i) == c) {
                pre = i;
            }
            res[i] = i - pre;
        }
        pre = Integer.MAX_VALUE / 2;
        for (int i = len - 1; i >= 0; i--) {
            if (s.charAt(i) == c) {
                pre = i;
            }
            res[i] = Math.min(res[i], pre - i);
        }
        return res;
    }
}

complexity

houyanlu commented 2 years ago

思路

先从后往前遍历一遍, 再从前往后遍历一遍,查漏补缺以及比较出最近的值

代码


class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
        int length = s.length();
        vector<int> resultVector(length, -1);

        int preIndex = -1;

        for (int i = length - 1; i >= 0; i--) {
            if (s.at(i) == c) {
                preIndex = i;
                resultVector[i] = 0;
            }

            if (preIndex != -1) {
                resultVector[i] = preIndex - i;        
            }

        }

        preIndex = -1;
        for (int i = 0; i < length; i++) {
            if (s.at(i) == c) {
                preIndex = i;
            } else if (resultVector.at(i) == -1 && preIndex != -1) {
                 resultVector[i] = i - preIndex;        
            } else if (resultVector.at(i) != -1 && preIndex != -1) {
                resultVector[i] = std::min(i - preIndex, resultVector[i]);
            }
        }

        return resultVector;
    }
};

复杂度分析

ViviXu-qiqi commented 2 years ago
class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        result = [];
        for i in range(len(s)):
            if (s[i] == c):
                result.append(0)
                continue
            for left in range(i, -1, -1):
                dist1 = 0
                if (s[left] == c):
                    dist1 = i - left
                    break
            for right in range(i, len(s)):
                dist2 = 0
                if (s[right] == c):
                    dist2 = right - i
                    break
            if (dist1 == 0):
                result.append(dist2)
            if (dist2 == 0):
                result.append(dist1)   
            if (dist1 <= dist2 and dist1 != 0):
                result.append(dist1)
            if (dist1 > dist2 and dist2 != 0):
                result.append(dist2)    

        return result;

Time Complexity: O(N) Space Complexity: O(N)

zhulin1110 commented 2 years ago

题目

字符的最短距离 https://leetcode-cn.com/problems/shortest-distance-to-a-character/

思路1(菜鸡的我自己写的,吐了)

找到 s 中所有与 c 相同的字符,并将其索引存放到一个数组中。将数组中的元素索引依次与相同字符的索引做差,并比较得出最小值。值得注意的是,当 s 中与 c 相同的字符只有一个时,无需比较,直接做差即可。

代码1(JavaScript)

var shortestToChar = function(s, c) {
    var curr = [];
    var res = [];
    for (let i = 0; i < s.length; i++) {
        if (s[i] == c) {
            curr.push(i);
        }
    }
    if (curr.length == 1) {
        for (let i = 0; i < s.length; i++) {
            res[i] = Math.abs(i - curr[0]);
        }
        return res;
    }
    for (let i = 0; i < s.length; i++) {
        let j = 0;
        let data = Math.abs(curr[j] - i);
        while (curr && (j < curr.length - 1)) {
            data = Math.min(data, (Math.abs(curr[j + 1] - i)));
            j++;
            res[i] = data;
        }
    }
    return res;
};

代码1改进(看了题解,稍稍改进)

var shortestToChar = function(s, c) {
    var curr = [];
    var res = [];
    for (let i = 0; i < s.length; i++) {
        if (s[i] == c) {
            curr.push(i);
        }
    }
    for (let i = 0; i < s.length; i++) {
        if (s[i] == c) {
            res[i] = 0;
            continue;
        }
        for (const j of curr) {
            const dist = Math.abs(j - i);
            if (dist >= res[i]) break; // 小小剪枝,跟上次存的比较,j是不断增大的,目的就是为了找最小值,设置阈值
            res[i] = dist;
        }  
    }
    return res;
};

复杂度1

思路2 (看了题解-贪心算法)

两遍循环,先从左到右遍历s,找到左边第一个c的距离。再从右到左遍历,找到值右边第一个c的距离。最后,取两个值中的最小值。

代码2 (评论区大佬的)

var shortestToChar = function(s, c) {
  let res = [];
  let lcIndex = -Infinity;
  for (let i = 0; i < s.length; i++) {
    if (s[i] === c) lcIndex = i;
    res[i] = i - lcIndex;
  }
  let rcIndex = Infinity;
  for (let i = s.length - 1; i >= 0; i--) {
    if (s[i] === c) rcIndex = i;
    res[i] = Math.min(res[i], rcIndex - i);
  }
  return res;
};

复杂度2

思路3 (滑动窗口)

将 c 看做分界线,将 s 划分为一个个窗口,然后对每个窗口进行遍历,每个窗口分别计算每个字符距离窗口左右边界的距离,并比较得到最小值。

代码3

var shortestToChar = function(s, c) {
    let res = [];
    let l = 0;
    if (s[0] === c) {
        l = 0;
    } else {
        l = Infinity;
    }
    r = s.indexOf(c, 1);
    for (let i = 0; i < s.length; i++) {
        res[i] = Math.min(Math.abs(i - l), Math.abs(r - i));
        if (i === r) {
            l = r;
            r = s.indexOf(c, l + 1);
        }
    }
    return res;
};

复杂度3

Mapo0102 commented 2 years ago

思路: 首先先从左向右遍历一遍,将ans数组中的所有元素标志成对应位。 再从右往左遍历一遍,再比较大小,将ans对应位置中更小的数放入对应ans。

代码: class Solution { public int[] shortestToChar(String S, char C) { int N = S.length(); int[] ans = new int[N]; int prev = Integer.MIN_VALUE / 2;

    for (int i = 0; i < N; ++i) {
        if (S.charAt(i) == C) prev = i;
        ans[i] = i - prev;
    }

    prev = Integer.MAX_VALUE / 2;
    for (int i = N-1; i >= 0; --i) {
        if (S.charAt(i) == C) prev = i;
        ans[i] = Math.min(ans[i], prev - i);
    }

    return ans;
}

}

时间复杂度:O(n) 空间复杂度:O(n)

kite-fly6618 commented 2 years ago

思路:

两头遍历,取较小值

代码:

var shortestToChar = function(s, c) {
    let len = s.length
    let left = []
    let right = []
    for (let i = 0;i <len;i++) {
        if (s.indexOf(c,i)==-1) {
            left.push(Infinity)
        } else {
            left.push(s.indexOf(c,i)-i)
        }  
    }
    for (let i = len-1;i >= 0;i--) {
        if (s.lastIndexOf(c,i)==-1) {
            right.unshift(Infinity)
        } else {
            right.unshift(i-s.lastIndexOf(c,i))
        }

    }
    for (let i = 0;i < len;i++) {
        left[i] = Math.min(left[i],right[i])
    }
    return left
};

复杂度:

时间复杂度: O(n)
空间复杂度: O(n)

flyzenr commented 2 years ago
JasonHe-WQ commented 2 years ago

思路: 对于每一个等于c的字符,在其两侧分别计算距离,而对于每个字符,距离取最小值 优化方向: 将等于c的字符分为首个,中间,末尾,分别控制不同的区域 代码: ''' class Solution: def shortestToChar(self, s: str, c: str) -> List[int]: l = len(s) ans = [l for i in range(l)] for i in range(l): if s[i] == c: for j in range(l): ans[j]=min(ans[j],abs(i-j)) return ans '''

Oision-hub commented 2 years ago

思路

将两边遍历的结果存入数组,留下较小的值

解答

class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
        vector<int> ans(s.size(), 0);
        int left = INT_MAX;
        int right = INT_MAX;
        for(int i = 0; i < s.size(); i ++) {
            if (s[i] == c) {
                left = i;
            }
            ans[i] = i - left;
        }
        for(int i = s.size() - 1; i >= 0; i --) {
            if (s[i] == c) {
                right = i;
            }
            ans[i] = min(abs(ans[i]), right - i);
        }
        return ans;
    }
};

复杂度

时间复杂度:O(n) 空间复杂度:O(n)

babbomax98 commented 2 years ago

思路

使用双指针,然后遍历字符串

代码

class Solution {
    public int[] shortestToChar(String S, char C) {
        int N = S.length();
        int[] result=new int[N];
        int indexNext=S.indexOf(C);//双指针,indexNext表示下一个C的下标, 
        int index=indexNext;//index表示前一个C的坐标
    // 通过这里的赋值使在只有左边有C字符的时候(此时index = indexNext)的时候
    //index也在当前字符的右边,否则在左右都有C字符的时候,当前字符必在index和indexNext的中间。
       for(int i = 0; i < S.length(); i++){
            if(S.charAt(i) == C){//每当遍历到C就更新index和indexNext
                result[i] = 0;
                index = i;
                indexNext = S.indexOf(C, i+1);
                //这里如果当前是最后一个C时,此时indexNext为-1,这也保证了上面的情况
            }else{
                result[i] = Math.min(Math.abs(index - i), Math.abs(indexNext - i));
            }
        }
       return result;
    }
}

复杂度分析

时间复杂度:O(n)

bzlff commented 2 years ago

思路

  1. 先遍历列表s,找到每一个元素c的索引位置,并添加到一个c_pos列表中
  2. for循环len(s),如果当前位置的索引i小于c_pos[0],即在c_pos[0]的左侧, 那么就往ans列表中添加“c_pos[0] - i“
  3. 如果当前的位置索引i大于c_pos[-1],机在c_pos[-1]的右侧,那么就往ans列表中添加“i - c_pos[-1]”
  4. 如果当前的位置索引等于c_pos[p], p=0, 即当前的索引对于的就是元素c,那么就往ans列表中添加“0”, 同时p+=1
  5. 否则,如果恰巧当前位置前后都有元素c的索引,那么就判断离着谁更近,就往ans列表中“min(c_pos[p]-i, i-c_pos[p-1])”

代码

class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:

        c_pos, ans = [], []
        for idx, i in enumerate(s):
            if i == c:
                c_pos.append(idx)

        p = 0
        for i in range(len(s)):
            if i < c_pos[0]:
                ans.append(c_pos[0] - i)
            elif i > c_pos[-1]:
                ans.append(i - c_pos[-1])
            elif i == c_pos[p]:
                ans.append(0)
                p += 1
            else:
                ans.append(min(c_pos[p] - i, i - c_pos[p-1]))
        return ans

复杂度分析

momomoi commented 2 years ago

思路

第一次遍历进行位置确认,第二次遍历进行选最小值

复杂度

时间复杂度O(N)

空间复杂度O(N)

代码

class demo:
    def test(self, S:str, C:str) -> List[int]:
         sums = -1
         zero_sums = [0]*len(S)
         for i in range(len(S)):
            if S[i] == C:
                 sums = 0
            else:
                sums += 1
            zero_sums[i] = sums
         sums = -1
         for j in range(len(S)-1, -1, -1):
            if S[j] == C:
                 sums = 0
            else:
                sums +=1
            zero_sums[j] = min(sums, zero_sums[j])
         return sums
antmUp commented 2 years ago

思路

1、首先找到字符在数组中的下标数组; 2、先处理第一个字符之前的,以及最后一个字符之后; 3、如果当前元素等于目标字符,在数组中 push 0; 4、处理两个字符中间的距离问题;

代码

function beelineOfCharacter(targetString, targetCharacter) {
  // 判断目标字符是否处在数组字符串的末尾
  const isEnd = targetString[targetString.length - 1] === targetCharacter;
  console.log(isEnd);

  // 寻找目标字符在数组当中的位置
  let targetCharIndex = [];
  for (let i = 0; i < targetString.length; i++) {
    if (targetString[i] === targetCharacter) {
      targetCharIndex.push(i);
    }
  }
  console.log(targetCharIndex, 'targetCharIndex');

  let finalArray = [];
  for (let j = 0; j < targetString.length; j ++) {
    const item = targetString[j];
    console.log(targetString[j], '1111');
    // 等于目标元素就push0
    if (item === targetCharacter) {
      finalArray.push(0);
    }

    // 处理第一个目标字符之前的元素
    const firstCharIndex = targetCharIndex[0];
    if (j < firstCharIndex) {
      const tempArray = numberToIndex(firstCharIndex);
      finalArray.concat(tempArray);
    }

  }

}

function numberToIndex(number) {
  let indexArray = [];
  for (let i = 0; i < number; i++) {
    indexArray.unshift(i);
  }
  indexArray.pop()

  return indexArray;
}

beelineOfCharacter('acd', 'c')

复杂度分析

XXjo commented 2 years ago

思路

使用不定长滑动窗口,边界字符为c,left和right维护窗口`

代码

var shortestToChar = function(s, c) {
    let res = [];
    let left = -Infinity;
    let right = s.indexOf(c);
    for(let i = 0; i < s.length; i++){
        res.push(Math.min(Math.abs(i - left), Math.abs(i -right)));
        if(i === right){
            left = right;
            right = s.indexOf(c, right + 1);
        }
    }
    return res;
};

复杂度分析

时间复杂度:O(n) 空间复杂度:O(1)

zhishinaigai commented 2 years ago

思路

今天也是抄答案的一天呢

代码

vector<int> shortestToChar(string s, char c) {
        vector<int> ans(s.size(),-1);
        int len=s.size();
        int p=-1;
        for(int i=0;i<len;i++){
            if(s[i]==c){
                p=i;
                ans[i]=0;
            } 
            else if(p!=-1) ans[i]=i-p;
        }
        p=-1;
        for(int i=len-1;i>=0;--i){
            if(s[i]==c) p=i;
            if(p!=-1) ans[i]=min(ans[i],p-i);
            if(ans[i]==-1) ans[i]=p-i;

        }
        return ans;
    }
TT-Fantastic commented 2 years ago

public int[] shortestDistance(String s, char c) { int[] arr = new int[s.length()]; int distance = Integer.MIN_VALUE; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == c) { distance = i; } arr[i] = i - distance; }

    distance = Integer.MAX_VALUE;
    for (int j = s.length() - 1; j >= 0; j--) {
        if (s.charAt(j) == c) {
            distance = j;
        }
        arr[j] = Math.min(arr[j], distance - j);
    }
   return arr;
KWDFW commented 2 years ago

Day2

821、数组形式的整数加法

javascript

思路

1、遍历数组

2、对于每个字符都分别向左和右查找c

3、对比左和右的长度,取最小值填入数组中

代码

var shortestToChar = function(s, c) {
    var answer=Array(s.length).fill(0);//将数组中填满0
    for(let i=0;i<s.length;i++){
      if (s[i] === c) continue;//若该位置与字符相同,则不用管
      let short=Infinity
      for(let j=i;j<s.length;j++){
          if(s[j]===c){
              short=Math.min(short,j-i)
              break
          }
      }  
      for(let k=i;k>-1;k--){
          if(s[k]===c){
               short=Math.min(short,i-k)
               break
          }
      }
      answer[i]=short
    }
    return answer
};

复杂度分析

时间复杂度:O(n2)

空间复杂度:O(n)

yaya-bb commented 2 years ago

题目地址(821. 字符的最短距离)

https://leetcode-cn.com/problems/shortest-distance-to-a-character/

题目描述

给你一个字符串 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' 出现在下标 3、5、6 和 11 处(下标从 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 中至少出现一次

前置知识

思路

(本题参考了其他人的代码)

关键点

代码

JavaScript Code:


/**
 * @param {string} s
 * @param {character} c
 * @return {number[]}
 */
var shortestToChar = function(s, c) {
    let num = [];
    num.length === s.length;
    let indexNext=s.indexOf(c);//indexNext表示下一个c的下标, 
    let index=indexNext;//index表示前一个c的坐标
    //index也在当前字符的右边,否则在左右都有C字符的时候,当前字符必在index和indexNext的中间。
       for(let i = 0; i < s.length; i++){
            if(s[i] == c){//每当遍历到C就更新index和indexNext
                num[i] = 0;
                index = i;
                indexNext = s.indexOf(c, i+1);
            }else{
                num[i] = Math.min(Math.abs(index - i), Math.abs(indexNext - i));
            }
        }
    return num;
};

复杂度分析

令 n 为数组长度。

hyh331 commented 2 years ago

Day2 思路

两边都遍历,最后留下较小的值

代码

c++
class Solution 
{
public:
    vector<int> shortestToChar(string s, char c) 
    {
        vector<int> ans(s.size(), 0);
        int left = INT_MAX;
        int right = INT_MAX;
        for(int i = 0; i < s.size(); i ++) 
        {
            if (s[i] == c) 
            {
                left = i;
            }
            ans[i] = i - left;
        }
        for(int i = s.size() - 1; i >= 0; i --) 
        {
            if (s[i] == c) 
            {
                right = i;
            }
            ans[i] = min(abs(ans[i]), right - i);
        }
        return ans;
    }
};
KelvinG-LGTM commented 2 years ago

思路

分别记录两个数组:

  1. 当前位置到右边最近的c的距离
  2. 当前位置到左边最近的c的距离

代码

class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        occurrence = deque()
        for idx, i in enumerate(s): 
            if i == c: 
                occurrence.append(idx)

        # print(occurrence)
        occ_1, occ_2 = copy.deepcopy(occurrence), copy.deepcopy(occurrence)

        dis_right = []  # 当前距离右边最近的c的距离
        right_pos = occurrence[0]
        for idx, char in enumerate(s): 
            if char == c: 
                right_pos = occ_1.popleft()
                dis_right.append(0)
            else: 
                dis_right.append(abs(idx - occurrence[0]))
        # print(dis_right)

        dis_left = []  # 当前距离左边最近的c的距离
        left_pos = inf
        for idx, char in enumerate(s): 
            if char == c: 
                left_pos = occ_2.popleft()
                dis_left.append(0)
            else: 
                dis_left.append(abs(idx - left_pos))

        res = []
        for i in range(len(dis_left)): 
            res.append(min(dis_left[i], dis_right[i]))
        # print(dis_left)
        return res

复杂度

时间. 空间复杂度: 都是O(N)

BallerJay commented 2 years ago

var shortestToChar = function(s, c) {
    // 中心扩散法,从当前元素为中心,寻找左右两边的c值,然后找出最短距离
    const res = [] 
    for(let i = 0;i < s.length;i ++) {
    let l = r = i
    while(l >= 0) {
        if(s[l] == c) break
        l--
    }
    while(r < s.length) {
        if(s[r] == c) break
        r++
    }
    if(l < 0) l = -10000
    if(r === s.length) r = 10000
    res.push(Math.min(i - l, r - i))
    }
    return res
};
KennethAlgol commented 2 years ago

思路

双指针

语言

java

public int[] shortestToChar(String S, char C) {

        int[] res = new int[S.length()];
        int cur = S.indexOf(C), pre = cur;
        for(int i = 0; i < S.length(); i++){
            if(S.charAt(i) == C){//其实就是每当遍历到C就更新cur和pre
                res[i] = 0;
                pre = i;
                cur = S.indexOf(C, i+1);//注意:这里如果当前是最后一个C时,此时cur为-1,这也保证了上面的情况3

            }else{
                res[i] = Math.min(Math.abs(pre - i), Math.abs(cur - i));//
            }
        }
        return res;
    }

复杂度分析

时间 O(n) 空间O(n)

zenwangzy commented 2 years ago

思路

左右遍历 问题在于初始的c位置怎么算,算到数组中间好了 对于prev 因为如果不除以2的话,INT_MIN= -2^31,而刚开始的时候i-INT_MIN=i+2^31就会发生溢出,但是INT_MAX-i就不会发生溢出了,所以INT_MAX就没必要除以2了,为了看起来舒服点都除以2了

class Solution {
public:
   vector<int> shortestToChar(string S, char C) {
       vector<int> distance(S.size(), 0);
       int prev = INT_MIN/2;
       for(int i = 0; i < S.size(); i ++){
           if(S[i] == C) prev = i;
           distance[i] = i - prev;
       }
       prev = INT_MAX/2;
       for(int i = S.size() - 1; i >= 0; i --){
           if(S[i] == C) prev = i;
           distance[i] = min(distance[i], prev - i);
       }
       return distance;
   }
};

复杂度

时空O(N)

KesuCaso commented 2 years ago

思路

从后往前遍历,遇到等于C的字符就把pre指针置为当前的索引,然后对答案数组进行修改。再从前往后遍历,也是遇到等于C的字符就把pre指针置为当前的索引,对答案数组修改的时候需要对比刚刚已经修改的值和当前赋的值的中选最小值。

class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        ans = [0]*len(s)
        pre = float("inf")
        for i in range(len(s)-1,-1,-1):
            if s[i]==c:
                pre = i
            ans[i]=pre-i
        pre = float("-inf")
        for i in range(len(s)):
            if s[i]==c:
                pre = i
            ans[i]=min(abs(pre-i),ans[i])
        return ans

复杂度分析

时间:O(n)

空间:O(n)

CShowww commented 2 years ago

代码

class Solution {
    public int[] shortestToChar(String s, char c) {
        int prev = Integer.MIN_VALUE/2;
        int n = s.length();
        int ans[] = new int[n];

        for(int i=0;i<n;i++){
            if(s.charAt(i) == c){
                prev = i;
            }
            ans[i] = i-prev;
        }
        prev = Integer.MAX_VALUE/2;
        for(int i=n-1;i>=0;i--){
            if(s.charAt(i) == c){
                prev = i;
            }
            ans[i] = Math.min(ans[i],prev-i);
        }
        return ans;
    }
}

复杂度

时间:O(n)
空间:O(n)

思路

双指针,两次遍历,一次从头到尾,一次从尾到头。

BruceLeeQAQ commented 2 years ago
class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:

        c_pos, ans = [], []
        for idx, i in enumerate(s):
        class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:

        c_pos, ans = [], []
        for idx, i in enumerate(s):
            if i == c:
                c_pos.append(idx)

        p = 0
        for i in range(len(s)):
            if i < c_pos[0]:
                ans.append(c_pos[0] - i)
            elif i > c_pos[-1]:
                ans.append(i - c_pos[-1])
            elif i == c_pos[p]:
                ans.append(0)
                p += 1
            else:
                ans.append(min(c_pos[p] - i, i - c_pos[p-1]))
        return ans    if i == c:
                c_pos.append(idx)

        p = 0
        for i in range(len(s)):
            if i < c_pos[0]:
                ans.append(c_pos[0] - i)
            elif i > c_pos[-1]:
                ans.append(i - c_pos[-1])
            elif i == c_pos[p]:
                ans.append(0)
                p += 1
            else:
                ans.append(min(c_pos[p] - i, i - c_pos[p-1]))
        return ans

复杂度

时间复杂度:O(n) 空间复杂度:O(n)

shin-guid commented 2 years ago

思路

  1. 遍历字符串,找出所有c的索引,成为索引数组
  2. 遍历字符串,每个字符串遍历索引数组求绝对值,取最小

code

/**
 * @param {string} s
 * @param {character} c
 * @return {number[]}
 */
var shortestToChar = function(s, c) {
    // 转换为数组
    // 遍历找出所有c的索引
    // 遍历数组,比较距离,取最小值
    const strArray = s.split('');
    let cIndexArray = [];

    strArray.forEach((s, i) => {
        if (s === c) {
            cIndexArray.push(i);
        }
    })
    let result = [];
    strArray.forEach((s, i) => {
        let diff = Infinity;
        cIndexArray.forEach((cIndex) => {
            diff = Math.min(diff, Math.abs(cIndex - i));
        })

        result.push(diff);
    })

    return result;
};

## 复杂度

- 时间复杂度:O(n2)
- 空间复杂度:O(n)
liyubin117 commented 2 years ago

思路: 从左向右遍历,记录上一个字符 C 出现的位置 prev,那么答案就是 i - prev。 从右想做遍历,记录上一个字符 C 出现的位置 prev,那么答案就是 prev - i。 这两个值取最小就是答案。

    public int[] shortestToChar(String S, char C) {
        int N = S.length();
        int[] ans = new int[N];
        int prev = Integer.MIN_VALUE / 2;

        for (int i = 0; i < N; ++i) {
            if (S.charAt(i) == C) prev = i;
            ans[i] = i - prev;
        }

        prev = Integer.MAX_VALUE / 2;
        for (int i = N-1; i >= 0; --i) {
            if (S.charAt(i) == C) prev = i;
            ans[i] = Math.min(ans[i], prev - i);
        }

        return ans;
    }

复杂度 时间复杂度:O(N),其中 N 是 S 的长度,我们需要遍历字符串两次。 空间复杂度:O(N),ans 数组的大小。

GaoMinghao commented 2 years ago

代码

class Solution {
    public int[] shortestToChar(String s, char c) {
        int N = s.length();
        int[] ans = new int[N];
        int pre = -N;
        for(int i = 0; i<N;i++) {
            if(s.charAt(i) == c) pre = i;
            ans[i] = i-pre;
        }
        pre = 2*N;
        for(int i = N-1; i>=0;i--) {
            if(s.charAt(i) == c) pre = i;
            ans[i] = Math.min(ans[i],pre-i);
        }
        return ans;
    }
}
brainlds commented 2 years ago

class Solution { public int[] shortestToChar(String s, char c) { int len = s.length(); int[] res = new int[len]; int pre = Integer.MIN_VALUE / 2; for (int i = 0; i < len; i++) { if (s.charAt(i) == c) { pre = i; } res[i] = i - pre; } pre = Integer.MAX_VALUE / 2; for (int i = len - 1; i >= 0; i--) { if (s.charAt(i) == c) { pre = i; } res[i] = Math.min(res[i], pre - i); } return res; } }

easliec commented 2 years ago

思路

先把s中所有等于c的元素的下标值存入到数组sc中,然后利用双重循环遍历s,比较s中各个下标值与sc中元素值的大小,将当前下标值与sc[j]的差的绝对值最小值存入scret中

代码

class Solution {
public:
    vector<int> shortestToChar(string s, char c) {
        vector<int> sc; // 与c相同的值得索引
        vector<int> scret; // 距离结果
        for(int i =0; i<s.size(); i++){
            if(s[i] == c){
                sc.push_back(i);
            }
        }
        if(sc.size() == 1){
            for(int i = 0; i < s.size(); i++){
                scret.push_back(abs(i-sc[0]));
            }
        }
        for (int i = 0; i<s.size(); i++){
            for(int j = 0; j<sc.size()-1; j++){
                if(i<=sc[j]){
                    scret.push_back(abs(sc[j]-i));
                    break;
                }
                if(i>sc[j]&&i<=sc[j+1]){
                    scret.push_back(min(abs(i-sc[j]), abs(i-sc[j+1])));
                    break;
                }
                if(i>sc[sc.size()-1]){
                    scret.push_back(abs(i-sc[sc.size()-1]));
                    break;
                }
            }
        }
        return scret;
    }
};
christ36 commented 2 years ago

【Day 2】821. 字符的最短距离

思路:分别比较左边和右边距离最近的值,取最小。

从左向右遍历,记录上一个字符 C 出现的位置 prev,那么答案就是 i - prev。 从右想做遍历,记录上一个字符 C 出现的位置 prev,那么答案就是 prev - i。

class Solution {
    public int[] shortestToChar(String s, char c) {
        int n = s.length();
        int pre = -10000; //最大数据范围是10000
        int[] ans = new int[n];
        for (int i = 0; i < s.length(); i++) { //计算左段与c最近的距离
            if (s.charAt(i) == c) pre = i;
            ans[i] = i - pre;
        }
        pre = 10000;
        for (int i = s.length() - 1; i >= 0; i--) { //计算右段与c最近的距离,同时与之前记录的左段进行比较
            if (s.charAt(i) == c) pre = i;
            ans[i] = Math.min(ans[i], pre - i);
        }
        return ans;
    }
}

时间复杂度:O(N)O(N),其中 NN 是 S 的长度,我们需要遍历字符串两次。 空间复杂度:O(N)O(N),ans 数组的大小。

tensorstart commented 2 years ago

思路

用的双指针循环部分有待优化

代码


var shortestToChar = function(s, c) {
    const res=[];
    let l=0,r=0,pos=0;
    let length=s.length;
    for (let i = 0; i < length; i++) {
        let array_abs=0;
        l=r=pos=i;
        for (let j = r; j < length; j++) {
            if (s[j]===c) {
                r=j;
                break;
            }
        }
        for (let j = l; j >=0 ; j--) {
            if (s[j]===c){
                l=j;
                break;
            }
        }
        if (s[l]===c && s[r]===c)
            array_abs=Math.min(Math.abs(l-pos),Math.abs(r-pos));
        else if (s[l]===c && s[r]!==c)
            array_abs=Math.min(Math.abs(l-pos));
        else
            array_abs=Math.min(Math.abs(r-pos));
        res.push(array_abs);
    }
    return res;
};

复杂度分析

wwang4768 commented 2 years ago

Idea 1) Loop through the string s and note down and note down the index of occurance of target char c 2) Loop through s and array of all c occurance index again, create a temp int that stores the distance between current digit and each c occurance. If there is a shorter distance, update temp

Code

class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        occur = []
        result = []

        for i in range(len(s)):
            if s[i] == c:
                occur.append(i)

        for j in range(len(s)):
            min = len(s)
            for k in range(len(occur)):
                temp = abs(j-occur[k])

                if temp<min:
                    min = temp
            result.append(min)
        return result

Complexity
Time complexity: O(N^2) Memory space complexity: O(N)

BlueRui commented 2 years ago

Problem 821. Shortest Distance to a Character

Algorithm

  1. Walk through the array from the left to find the closest char c to the right of each char in s.
  2. Then work through the array from the right to find the closest char c to the left of each char in s.
  3. Find the min distance of step 1 and 2.
  4. Step 2 and 3 can be combined.

Complexity

Code

Language: Java

public int[] shortestToChar(String s, char c) {
        int n = s.length();
        int[] result = new int[n];
        Arrays.fill(result, n);
        // Find closest c on the right of each char
        int cur = 0;
        for (int i = 0; i < n; i++) {
            if (s.charAt(i) != c) {
                continue;
            }
            while (cur <= i) {
                result[cur] = i - cur;
                cur++;
            }
        }

        // Update to get the closest c from both sides by comparing left side
        cur = n - 1;
        for (int i = n - 1; i >=0; i--) {
            if (s.charAt(i) != c) {
                continue;
            }
            while (cur >= i) {
                result[cur] = Math.min(result[cur], cur - i);
                cur--;
            }
        }
        return result;
    }
hohojii commented 2 years ago

左右遍历

code

class Solution { public: vector shortestToChar(string s, char c) { int n = s.size(); vector ans(n, 1e6); int last = -1e6; for(int i = 0; i < n; i++) { if(s[i] == c) { ans[i] = 0; last = i; } else ans[i] = min(ans[i], i - last); } last = 1e6; for(int i = n - 1; i >= 0; i--) { if(s[i] == c) last = i; else ans[i] = min(ans[i], last - i); } return ans; } };

复杂度分析

时间复杂度:O(n) 空间复杂度:O(n)

Orangejuz commented 2 years ago

题目:【Day 2】821. 字符的最短距离

821. 字符的最短距离

思路1

  1. 新建列表存放字符 c 存在的位置
  2. 在 result 列表中,存放两次循环找出的最小 diff 距离
class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        L = []
        result = []
        for i in range(len(s)):
            if s[i] == c:
                L.append(i)
        for i in range(len(s)):
            diff = 10000
            for j in L:
                if (abs(j - i)) < diff:
                    diff = abs(j - i)
            result.append(diff)
        return result

复杂度

时间复杂度:O(N^2) 空间复杂度:O(N)

思路2

  1. 循环找到字符 c 存在的位置
  2. 前后循环找到最短的距离
class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        result = [99999 for i in s]
        n = len(s)
        for i in range(n):
            if s[i] != c:
                continue
            result[i] = 0
            for j in range(i-1, -1, -1):
                if s[j] == c:
                    result[j] = 0
                    break
                result[j] = min(abs(i-j), result[j])
            if i == n-1:
                break
            for j in range(i+1, n):
                if s[j] == c:
                    result[j] = 0
                    break
                result[j] = min(abs(i-j), result[j])
        return result

复杂度

时间复杂度:O(N) 空间复杂度:O(N)