特斯拉一面,竟是简单算法题

写在前面

这道题不要说是特斯拉,可能放眼所有存在"算法笔面"环节的互联网公司,也是标准 Easy 水平。

以至于遇到该题目的同学都有"准备过于充分"的感觉: 🤣

题目描述

平台:LeetCode

题号:3

给定一个字符串,请你找出其中不含有重复字符的「最长子串」的长度。

示例 1:

ini 复制代码
输入: s = "abcabcbb"

输出: 3 

解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

ini 复制代码
输入: s = "bbbbb"

输出: 1

解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

makefile 复制代码
输入: s = "pwwkew"

输出: 3

解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

示例 4:

ini 复制代码
输入: s = ""

输出: 0

提示:

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 < = s . l e n g t h < = 5 × 1 0 4 0 <= s.length <= 5 \times 10^4 </math>0<=s.length<=5×104
  • s 由英文字母、数字、符号和空格组成

滑动窗口

定义两个指针 startend[start:end] 表示当前处理到的子串。

子串 [start:end] 始终满足要求:无重复字符。

从前往后进行扫描 s,用哈希表记录 [start:end] 中每字符的出现次数。

遍历过程中,end 不断自增,将第 end 个字符在哈希表中出现的次数加一。

right 为下标 end 对应的字符,当满足 map.get(right) > 1 时,代表此前出现过第 end 位对应的字符。

此时更新 start 的位置(使其右移),直到不满足 map.get(right) > 1 (代表 [start:end] 恢复满足无重复字符的条件),再用 [start:end] 长度更新答案。

Java 代码:

Java 复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> map = new HashMap<>();
        int ans = 0;
        for (int start = 0, end = 0; end < s.length(); end++) {
            char right = s.charAt(end);
            map.put(right, map.getOrDefault(right, 0) + 1);
            while (map.get(right) > 1) {
                char left = s.charAt(start);
                map.put(left, map.get(left) - 1);
                start++;
            }
            ans = Math.max(ans, end - start + 1);
        }
        return ans;
    }
}

Python 代码:

Python 复制代码
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        map = {}
        ans = 0
        start = 0
        for end in range(len(s)):
            right = s[end]
            map[right] = map.get(right, 0) + 1
            while map[right] > 1:
                left = s[start]
                map[left] = map[left] - 1
                start += 1
            ans = max(ans, end - start + 1)
        return ans

C++ 代码:

C++ 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> map;
        int ans = 0;
        for (int start = 0, end = 0; end < s.length(); end++) {
            char right = s[end];
            map[right] = map[right] + 1;
            while (map[right] > 1) {
                char left = s[start];
                map[left] = map[left] - 1;
                start++;
            }
            ans = max(ans, end - start + 1);
        }
        return ans;
    }
};

TypeScript 代码:

TypeScript 复制代码
function lengthOfLongestSubstring(s: string): number {
  const map: { [key: string]: number } = {};
  let ans = 0;
  let start = 0;
  for (let end = 0; end < s.length; end++) {
      const right = s.charAt(end);
      map[right] = (map[right] || 0) + 1;
      while (map[right] > 1) {
          const left = s.charAt(start);
          map[left] = (map[left] || 0) - 1;
          start++;
      }
      ans = Math.max(ans, end - start + 1);
  }
  return ans;
};
  • 时间复杂度:虽然有两层循环,但每个字符在哈希表中最多只会被插入和删除一次,复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n)
  • 空间复杂度:使用了哈希表进行字符记录,复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n)

总结

现在看来这道题确实简单到离谱。

但在 LeetCode 平台中,这道题的难度标签却是「中等」。

其实从 3 这样较小的题号就能发现,这是属于最早期的那批题目。

说明在那个算法笔面刚出现,甚至是 LeetCode 刚建站,总共只有 150 道题目的那个年代,像「滑动窗口」这样的知识点,还不被大家所掌握,绝大多数只能给出双层循环的 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2) 解法。

反观现在的笔试面试,一些在招聘市场"供过于求"的公司,有时候还会把网络流搬上桌面 ...

可见,算法内卷的道路只会放缓,不会停止,没有尽头。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关推荐
Victor356几秒前
Redis(60) Redis的复制延迟如何优化?
后端
reembarkation2 分钟前
vue 右键菜单的实现
前端·javascript·vue.js
00后程序员张2 小时前
Fiddler抓包工具使用教程,代理设置与调试方法实战解析(含配置技巧)
前端·测试工具·ios·小程序·fiddler·uni-app·webview
.格子衫.6 小时前
Spring Boot 原理篇
java·spring boot·后端
2301_768350238 小时前
Vue第二期:组件及组件化和组件的生命周期
前端·javascript·vue.js
Jabes.yang8 小时前
Java求职面试实战:从Spring Boot到微服务架构的技术探讨
java·数据库·spring boot·微服务·面试·消息队列·互联网大厂
聪明的笨猪猪8 小时前
Java Redis “高可用 — 主从复制”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
兮动人8 小时前
Spring Bean耗时分析工具
java·后端·spring·bean耗时分析工具
倔强青铜三8 小时前
苦练Python第64天:从零掌握多线程,threading模块全面指南
人工智能·python·面试
华洛9 小时前
公开一个AI产品的商业逻辑与设计方案——AI带来的涂色卡自由
前端·后端·产品