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.用pre[i]表示num[0]到num[i]的和

2.num[i + 1]到num[j]的和为 pre[j] - pre[i]

3.其和为k, 那么,nums[j]位置需要找到和为pre[j] - 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. 除自身以外数组的乘积

还是想用前缀和做,计算num[i]的乘积,就是计算pre[i -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.ans[i] = pre;

3.pre *= nums[i];

先把pre[i -1]放到ans[i],再乘

后缀和

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

2.ans[i] *= sum2;

3.sum2 *= nums[i];

前缀乘以back[i+1]到back.end() - 1

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

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

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

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

如:v[0]=1、if(v[0])、v[0]等情况都会报错

这种情况需要先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;
    }
};
相关推荐
1 9 J4 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
passer__jw7672 小时前
【LeetCode】【算法】3. 无重复字符的最长子串
算法·leetcode
passer__jw7672 小时前
【LeetCode】【算法】21. 合并两个有序链表
算法·leetcode·链表
sweetheart7-72 小时前
LeetCode22. 括号生成(2024冬季每日一题 2)
算法·深度优先·力扣·dfs·左右括号匹配
__AtYou__3 小时前
Golang | Leetcode Golang题解之第557题反转字符串中的单词III
leetcode·golang·题解
2401_858286113 小时前
L7.【LeetCode笔记】相交链表
笔记·leetcode·链表
景鹤4 小时前
【算法】递归+回溯+剪枝:78.子集
算法·机器学习·剪枝
_OLi_5 小时前
力扣 LeetCode 704. 二分查找(Day1:数组)
算法·leetcode·职场和发展
丶Darling.5 小时前
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
c++·算法·动态规划·记忆化搜索·回溯
风影小子5 小时前
IO作业5
算法