📜  排序数组中距离字符K最近的小字符(1)

📅  最后修改于: 2023-12-03 14:54:42.518000             🧑  作者: Mango

题目描述

给定一个排序后的字符数组,以及一个字符 K,找出数组中距离 K 最近的小写字符(ASCII 码比 K 小的字符)。

距离指的是两个字符之间的 ASCII 码值的差值(例如,'a' 和 'c' 之间的距离为 2)。

如果数组中有多个这样的字符,则返回字典序最小的字符。

示例

输入:["a","b","c","d","f","g","h","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"], K = "k"

输出:"h"

解释:

字符 'h' 和字符 'k' 之间的距离为 3。

字符 'i' 和 'j' 之间的距离为 2。

字符 'g' 和字符 'h' 之间的距离为 1。

字符 'h' 和字符 'i' 之间的距离为 1。

因此,最近的小写字符是 'h'。

解题思路

由于数组是已经排好序的,我们可以采用二分查找的思路找到距离字符 K 最近的字符。

具体来说,我们可以先找到字符 K 在数组中的位置,然后分别向左和向右遍历,找到满足条件的字符即可。

在查找过程中,我们可以维护两个变量,分别代表左边和右边距离字符 K 最近的小写字符。

代码实现

class Solution:
    def nearest(self, arr: List[str], K: str) -> str:
        left, right = None, None
        # 二分查找 K 在数组中的位置
        l, r = 0, len(arr) - 1
        while l <= r:
            mid = (l + r) // 2
            if arr[mid] == K:
                left, right = mid - 1, mid + 1
                break
            elif arr[mid] < K:
                l = mid + 1
            else:
                r = mid - 1
        else:
            if r == -1:
                return arr[0]  # K 比数组中所有都小
            elif l == len(arr):
                return arr[-1]  # K 比数组中所有都大
            left, right = r, l  # K 在 arr[l] 和 arr[r] 之间
        
        # 遍历左右两边,找到距离 K 最近且小于 K 的字符
        while True:
            if left >= 0 and ord(arr[left]) >= ord("a"):
                return arr[left]
            elif right < len(arr) and ord(arr[right]) >= ord("a"):
                return arr[right]
            else:
                left -= 1
                right += 1

复杂度分析

  • 时间复杂度:$O(\log n)$,其中 $n$ 为字符数组的长度。查找字符 K 所在的位置的时间复杂度为 $O(\log n)$;遍历左右两边的过程中,每次只会将左右两个指针之一加 1,因此时间复杂度为 $O(n)$,总时间复杂度为 $O(\log n+n)=O(\log n)$。
  • 空间复杂度:$O(1)$,只需要维护常数个指针。