📜  直觉面试经验| 6套(1)

📅  最后修改于: 2023-12-03 15:41:00.023000             🧑  作者: Mango

直觉面试经验 | 6套

简介

本篇主题介绍面试中常见的6种直觉类算法题,并提供解题思路和代码实现。

1. 反转字符串
题目描述

给定一个字符串,将其翻转。例如,给定 s = "hello",返回 "olleh"。

解题思路

从字符串的两端逐步向中间推进,每次交换两个字符的位置,最终得到翻转后的字符串。

代码实现
def reverse_string(s: str) -> str:
    chars = list(s)
    i, j = 0, len(chars) - 1
    while i < j:
        chars[i], chars[j] = chars[j], chars[i]
        i += 1
        j -= 1
    return ''.join(chars)
复杂度分析

该算法时间复杂度为 O(n),空间复杂度为 O(n)。

2. 寻找最大公共前缀
题目描述

给定一个字符串数组,找到这些字符串的最长公共前缀。例如,给定 ["flower","flow","flight"],返回 "fl"。

解题思路

从第一个字符串的第一个字符开始,按字符顺序逐个比较每个字符串的对应字符,直到找到最长的公共前缀为止。

代码实现
def longest_common_prefix(strs: List[str]) -> str:
    if not strs:
        return ""
    prefix = strs[0]
    for s in strs[1:]:
        i = 0
        while i < min(len(prefix), len(s)) and prefix[i] == s[i]:
            i += 1
        prefix = prefix[:i]
        if not prefix:
            break
    return prefix
复杂度分析

该算法时间复杂度为 O(nk),其中 n 是字符串数组的长度,k 是最长公共前缀的长度。空间复杂度为 O(1)。

3. 判断回文字符串
题目描述

给定一个字符串,判断它是否是回文字符串。例如,给定 s = "A man, a plan, a canal: Panama",返回 True。

解题思路

将字符串中的非字母或数字字符去除,然后将字符串反转,最后判断反转后的字符串是否与原字符串相同。

代码实现
def is_palindrome(s: str) -> bool:
    s = ''.join(filter(str.isalnum, s)).lower()
    return s == s[::-1]
复杂度分析

该算法时间复杂度为 O(n),空间复杂度为 O(n)。

4. 寻找有效的括号组合
题目描述

给定一个仅包含字符 '(',')','{','}','[' 和 ']' 的字符串,判断字符串是否合法。例如,给定 s = "()[]{}",返回 True。

解题思路

使用栈来判断括号的有效性。遍历字符串,若遇到左括号则将其入栈,遇到右括号则将其与栈顶元素比较,若匹配则将栈顶元素出栈,否则返回 False。

代码实现
def is_valid(s: str) -> bool:
    stack = []
    parentheses = {')': '(', ']': '[', '}': '{'}
    for c in s:
        if c in parentheses.values():
            stack.append(c)
        elif c in parentheses.keys():
            if not stack or stack[-1] != parentheses[c]:
                return False
            stack.pop()
    return not stack
复杂度分析

该算法时间复杂度为 O(n),空间复杂度为 O(n)。

5. 整数翻转
题目描述

给定一个 32 位有符号整数,将整数翻转。例如,给定 x = 123,返回 321。

解题思路

将整数按位拆解成数组,然后从数组两端逐个交换元素的位置,最终组成翻转后的整数。

代码实现
def reverse_integer(x: int) -> int:
    sign = -1 if x < 0 else 1
    x *= sign
    nums = []
    while x:
        nums.append(x % 10)
        x //= 10
    i, j = 0, len(nums) - 1
    while i < j:
        nums[i], nums[j] = nums[j], nums[i]
        i += 1
        j -= 1
    result = sign * sum(n * 10 ** i for i, n in enumerate(nums[::-1]))
    return result if -2 ** 31 <= result <= 2 ** 31 - 1 else 0
复杂度分析

该算法时间复杂度为 O(log(x)),空间复杂度为 O(log(x))。

6. 约瑟夫环问题
题目描述

有 n 个人围成一圈,从第 k 个人开始顺时针数 m 个人,把这个人移出圈子,然后继续从下一个人开始顺时针数 m 个人,重复这个过程,直到圈子里只剩一个人,求这个人的编号。

解题思路

使用队列模拟圈子的出队入队过程,直到队列中只剩下一个元素。

代码实现
def josephus(n: int, k: int, m: int) -> int:
    queue = list(range(1, n + 1))
    i = k - 1
    while len(queue) > 1:
        i = (i + m - 1) % len(queue)
        queue.pop(i)
    return queue[0]
复杂度分析

该算法时间复杂度为 O(nm),空间复杂度为 O(n)。