剑指offer 打卡计划 | 每日进步一点点 | 第十八天

113 阅读3分钟

图片.png

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

剑指 Offer 48. 最长不含重复字符的子字符串

思路

(双指针扫描) O(n)

定义两个指针 i,j(i<=j),表示当前扫描到的子串是 [i,j] (闭区间)。扫描过程中维护一个哈希表unordered_map <chat,int>hash,表示 [i,j]中每个字符出现的次数。

线性扫描时,每次循环的流程如下:

  • 1.指针 j 向后移一位, 同时将哈希表中 s[j] 的计数加一:hash[s[j]]++;
  • 2.假设 j 移动前的区间 [i,j]中没有重复字符,则 j 移动后,只有 s[j]​可能出现2次。因此我们不断向后移动i,直至区间 [i,j]s[j] 的个数等于1为止;

时间复杂度分析: 由于 ij 均最多增加n次,且哈希表的插入和更新操作的复杂度都是 O(1),因此,总时间复杂度 O(n).

c++代码

 class Solution {
 public:
     int lengthOfLongestSubstring(string s) {
         unordered_map<char, int> hash; //存贮每个字符出现的次数
         int res = 0;
         for(int j = 0, i = 0; j < s.size(); j++){   //[j, i]
             hash[s[j]]++;
             while(hash[s[j]] > 1) hash[s[i++]]--;
             res = max(res, j - i + 1);
         }
         return res;
     }
 };

剑指 Offer 49. 丑数

思路

(三路归并) O(n)

我们把只包含质因子 235 的数称作丑数,使用vector<int> res 存储每个丑数,且已知第一个丑数是 1,即 res[0] = 1

i,j,k,三个指针分别指向三个序列:

  • i指向质因子包含 2 的所有数组成的序列 II。
  • j 指向质因子包含 3 的所有数组成的序列 III。
  • k 指向质因子包含 5的所有数组成的序列 V。

初始状态下三个指针都是0,指向第一个丑数 res[0] = 1

三路归并,每次取 res[i]∗2res[j]∗3res[k]∗5中的最小值,就是下一个丑数。 其中 res[i] 是序列 II 的第 i个数,那么 res[i]∗2 就是第 i + 1 个数,res[j] 是序列 III 的第 j 个数,那么 res[j]∗3 就是第 j + 1 个数,res[k] 是序列 V 的第 k 个数,那么 res[k]∗5就是第 k + 1个数。

res[0] = 1 不属于任何序列。

如果下一个丑数为 res[i]∗2,则 i指针向往后移,如果 为res[j]∗3,则 j指针往后移,如果为res[k]∗5,则 k 指针往后移。

细节:

如果下一个丑数即是 2 的倍数也是 3 的倍数,那么指针 ij 都要往后移。

时间复杂度分析: 求第 n 个丑数,已知第一个丑数是 1,循环 n - 1 次即可求得,时间复杂度为 O(n)。

c++代码

 class Solution {
 public:
     int nthUglyNumber(int n) {
         vector<int> res;
         res.push_back(1);
         int i = 0, k = 0, j = 0;
         while(--n){
             int t = min(res[i] * 2, min(res[j] * 3, res[k] * 5));
             res.push_back(t);
             if(t % 2 == 0)  i++;
             if(t % 3 == 0)  j++;
             if(t % 5 == 0)  k++;
         }
         return res.back();
     }
 };
 ​

剑指 Offer 50. 第一个只出现一次的字符

思路

(哈希) O(n)

1、定义一个hash表,存贮字符串s中每个字符出现的次数。

2、遍历整个字符串,如果字符串s中的某个字符出现的次数为1,则我们返回该字符。

3、如果没有,则返回空格。

时间复杂度分析: O(n)。

c++代码

class Solution {
public:
    char firstUniqChar(string s) {
        unordered_map<char, int> hash;
        for(char c : s) hash[c]++;
        for(char c : s){
            if(hash[c] == 1) return c;
        }
        return ' ';
    }
};