leetcode 2.27

leetcode hot 100

哈希

1.字母异位词分组

49. 字母异位词分组

方法一:排序

由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。

cpp 复制代码
unordered_map<string, vector<string>>​ 

主要是理解,key是排序后的字母序列,value是vector,存放了多个string

cpp 复制代码
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        int n = strs.size();
        unordered_map<string, vector<string>> map;
        for (auto s : strs) {
            string tmp = s;
            sort(tmp.begin(), tmp.end());
            map[tmp].emplace_back(s);
        }
        vector<vector<string>> ans;
        for (unordered_map<string, vector<string>>::iterator it = map.begin(); it != map.end(); it++) {
            ans.emplace_back(it->second);
        }
        return ans;
    }
};

2.最长连续序列

128. 最长连续序列

重要的是思路,

1.用set去除重复数

2.找到一个序列起点最小的数num,开始在容器里while找num++是否存在,如果存在那么len++

3.怎么找到最小数,也不能说是最小数,是一个连续数种的最小数,num - 1如果存在那么他就不是连续的最小数

cpp 复制代码
unordered_set<int> mp;
...
for (auto num: mp) {
	if (mp.count(num -1)) continue;
	int curnum = num;
	int len = 1;

	while (mp.count(curnum + 1)) {
		curnum += 1;
		len += 1;
	}
	longestlen = max(len, longestlen);
}
cpp 复制代码
class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int res = 0;    // 记录最长连续序列的长度
        unordered_set<int> num_set(nums.begin(), nums.end());   // 记录nums中的所有数值
        int seqLen;
        for(int num: num_set){
            // 如果当前的数是一个连续序列的起点,统计这个连续序列的长度
            if(!num_set.count(num - 1)){
                seqLen = 1;     // 连续序列的长度,初始为1
                while(num_set.count(++num))seqLen++;    // 不断查找连续序列,直到num的下一个数不存在于数组中
                res = max(res, seqLen);     // 更新最长连续序列长度
            }
        }
        return res;
    }
};

双指针

1.盛最多水的容器

11. 盛最多水的容器

两个for循环找最大值会超时,那么就有小心机,如果当前高度不比之前高,那么答案一定小于之前的值,就不必再循环了

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, ans = 0, high = 0;
        for (; left < height.size() - 1; left++) {
            if (height[left] > high) high = height[left];
            if (height[left] < high) continue;
            for (int right = left + 1; right < height.size(); right++) {
                int tmp = (right - left) * min(height[left], height[right]);
                ans = max(ans, tmp); 
            }
        }
        return ans;
    }
};

正经的比较快的算法是,两端向中间移动,每次移动较小的边,计算最大值

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int l = 0, r = height.size() - 1;
        int ans = min(height[l], height[r]) * (r - l);
        while (l < r) {
            if (height[l] < height[r]) {
                l++;
            } else {
                r--;
            }
            ans = max(ans, (r - l) * min(height[l], height[r]));
        }
        return ans;
    }
};

2.和为 K 的子数组

560. 和为 K 的子数组

题目需要注意的是和为K的子数组,那么:

1.用prei表示num0到numi的和

2.numi + 1到numj的和为 prej - prei

3.其和为k, 那么,numsj位置需要找到和为prej - k的前缀和

cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> mp;
        mp[0] = 1;
        int pre = 0, ans = 0;
        for (auto &c : nums) {
            pre += c;
            if (mp.count(pre - k)) {
                ans += mp[pre - k];
            }
            mp[pre]++;
        }
        return ans;
    }
};

数组

1.除自身以外数组的乘积

238. 除自身以外数组的乘积

还是想用前缀和做,计算numi的乘积,就是计算prei -1 * 后缀和

但是超时了

cpp 复制代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> ans;
        int pre = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (i == 0) 
                pre = 1;
            else 
                pre *= nums[i - 1];
            int tmp = pre;
            for (int j = i + 1; j < nums.size(); j++) {
                tmp *= nums[j];
            }
            ans.emplace_back(tmp);
        }
        return ans;
    }
};

前缀和 + 后缀和
前缀和

1.i从0开始向后

2.ansi = pre;

3.pre *= numsi;

先把prei -1放到ansi,再乘

后缀和

1.i从size()-1开始向前

2.ansi *= sum2;

3.sum2 *= numsi;

前缀乘以backi+1到back.end() - 1

https://blog.csdn.net/qq_43553082/article/details/118620364

vector在还没有分配任何空间时还不能像数组一样用下标形式去访问vector的(v0也不行)!!!否则编译通过但报运行错误runtime error!

如vector创建的时候是使用:vector<int> v;

或者vector还是\[\]的时候(考虑官方测试数据的输入可能为\[\]的情况,使用 前需要判断一下是否为空)会报错!

如:v0=1、if(v0)、v0等情况都会报错

这种情况需要先push_back()或v={1,2}等形式给其分配了空间后,才能用【】形式访问!

本题中:
vector<int> ans(nums.size());

cpp 复制代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> ans(nums.size());
        int sum = 1;
        for (int i = 0; i < nums.size(); i++) {
            ans[i] = sum;
            sum *= nums[i];
        }
        int sum2 = 1;
        for (int i = nums.size() - 1; i >= 0; i--) {
            ans[i] *= sum2;
            sum2 *= nums[i];
        }
        return ans;
    }
};
相关推荐
Tisfy2 小时前
LeetCode 0836.矩形重叠:xy两方向分别看
数学·leetcode·题解·模拟
宣宣猪的小花园.2 小时前
【机器学习】损失函数与梯度下降:机器如何通过“犯错”不断变好
人工智能·算法·机器学习
青山木3 小时前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划
土司大王3 小时前
LeetCode hot100——33.搜索旋转排序数组:Java 二分模板与 O(log n) 实现
数据结构·算法·leetcode
不穿鞋的懒羊羊3 小时前
STL容器
算法
huang5791474 小时前
多线程环境下的共享数据结构安全问题分析4
算法
地平线开发者4 小时前
模型部署|征程6 量化路线怎么选:PTQ 还是 QAT?
神经网络·算法·机器学习
辰辉创聚4 小时前
禽流感病毒分子基础:表面抗原与内部转录复合体的功能解析
ide·leetcode·rabbitmq·重组血凝素蛋白·甲型流感病毒核蛋白·禽流感单抗
不会就选b4 小时前
算法日常・每日刷题--<贪心>12
算法
小羊没烦恼!5 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#