刷leetcode300道中等题错题本/难题本

1. 链表大整数相加题(链表)
总结错误:即便有其中一个链表已经遍历完了,在遍历第二个链表的时候也要注意进位。此外,进位的部分还要注意添加新链表节点。
输入:
[9,9,9,9,9,9,9] [9,9,9,9]
输出:
[8,9,9,9,9,9,9]
预期结果:
[8,9,9,9,0,0,0,1]
 
2. 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。(字符串)
方法1: 使用map实现滑动窗口 (似乎跟kmp有异曲同工之妙)
 
3. 给你一个字符串 s,找到 s 中最长的回文子串。(字符串)
方法1:中心扩散法 O(n^2)    我用的
方法2:动态规划法 O(N^2)
方法3:马拉车法 O(N)    https://www.cxyxiaowu.com/2869.html
 
4. 字符串转证书atoi
方法1:像这种题目可以考虑使用FSM  https://leetcode-cn.com/problems/string-to-integer-atoi/solution/zi-fu-chuan-zhuan-huan-zheng-shu-atoi-by-leetcode-/
 
5. 最大容积
方法1:双指针 https://leetcode-cn.com/problems/container-with-most-water/solution/sheng-zui-duo-shui-de-rong-qi-by-leetcode-solution/
 
6. 整数转罗马
方法1:列出所有可能数字和罗马数字组合 1000-M 900-CM 。。。 然后两个循环搞定
 
7. 三数之和 / 最接近三数之和
方法1:排序+双指针
 
8. 电话号码的字母组合
方法:回溯算法 or 深度优先搜索
 
9. 剪绳子
方法1:数学推导/贪心思想(生而为人,我很抱歉    其实也没那么难?)
方法2:动态规划 (这个我看得懂)
 
10. 数值的整数次方
方法:快速幂
 
11. 移除链表中的倒数第n个节点
方法1:递归
方法2:快慢指针
 
方法1:使用有限状态自动机。其实,大部分跟字符串相关的题目都可以用FSM来做。
方法2:使用C++ <regex>库。由于每个FSM都对应一个正则表达式,因此字符串的题目用regex来做其实更适合,这里有C++ regex库的使用方法:https://blog.csdn.net/qq_34802416/article/details/79307102
注意:对性能敏感程序中尽量避免使用正则表达式。因为正则表达式会慢。因为正则匹配是通用算法,所以会引入很多额外的判断和分支,导致时间常数偏大。如果以后JIT技术进步了的话,也许就没有这些性能问题了。
 
13. 给出栈的压入序列和弹出序列,判断该弹出序列是否合理
方法:模拟,即使用一个栈,根据压入序列和弹出序列去压入弹出,看是否能成功。
 
14. 括号生成
方法1:回溯法
方法2:按括号序列长度递归
 

检查括号是否匹配的充要条件:为了检查序列是否有效,我们遍历这个序列,并使用一个变量 balance 表示左括号的数量减去右括号的数量。如果在遍历过程中 balance 的值小于零,或者结束时 balance 的值不为零,那么该序列就是无效的,否则它是有效的。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/generate-parentheses/solution/gua-hao-sheng-cheng-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

15. 二叉搜索树的后序遍历序列

方法1: 递归分治 O(n^2)
方法2: 辅助单调栈 O(n)
 
16. 复杂链表的复制
方法1:回溯+哈希表
方法2:迭代+节点拆分
 
 
17. 剑指 Offer 56 - I. 数组中数字出现的次数

方法1:分组异或 (excellent idea!)

方法2:(自己想的)使用hashmap

 

18 . while ((div & ret) == 0)

注意:在进行位运算的时候,要加上括号,否则条件判断可能会这样认为:div 与上 (ret == 0),作为条件判断语句

 

 

19. 面试题56 - II. 数组中数字出现的次数 II(位运算 + 有限状态自动机,清晰图解

---

方法1:有限状态自动机    

如下图所示,考虑数字的二进制形式,对于出现三次的数字,各 二进制位 出现的次数都是 33 的倍数。
因此,统计所有数字的各二进制位中 11 的出现次数,并对 33 求余,结果则为只出现一次的数字。

作者:jyd
链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/solution/mian-shi-ti-56-ii-shu-zu-zhong-shu-zi-chu-xian-d-4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

---

方法2:遍历统计

---

 

20. 队列的最大值

方法:维护单调双端队列

 

21. 剑指 Offer 60. n个骰子的点数

方法:动态规划

 

22. 剑指 Offer 63. 股票的最大利润

方法:一次遍历法,历史最低点

 

23. 快速乘(俄罗斯农民乘法)

来源:https://blog.csdn.net/iteye_4501/article/details/81682160 (注意,这个答案下的俄罗斯农民乘法不一定等于题目要求的快速乘,具体参考下面的说明)

方法二:快速乘
思路和算法

考虑 A 和 B 两数相乘的时候我们如何利用加法和位运算来模拟,其实就是将 B 二进制展开,如果 B 的二进制表示下第 ii 位为 1,那么这一位对最后结果的贡献就是 A*(1<<i)A∗(1<<i) ,即 A<<iA<<i。我们遍历 B 二进制展开下的每一位,将所有贡献累加起来就是最后的答案,这个方法也被称作「俄罗斯农民乘法」,感兴趣的读者可以自行网上搜索相关资料。这个方法经常被用于两数相乘取模的场景,如果两数相乘已经超过数据范围,但取模后不会超过,我们就可以利用这个方法来拆位取模计算贡献,保证每次运算都在数据范围内。

下面给出这个算法的 C++ 实现:

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/qiu-12n-lcof/solution/qiu-12n-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

24. 剑指 Offer 66. 构建乘积数组

方法:构建乘法表:上三角和下三角

 

25. 防止整数溢出的时候可以试试 double bndry = INT_MAX/10;

更保险的方法如下

if(res > bndry || res == bndry && str.charAt(j) > '7')
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;

作者:jyd
链接:https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/solution/mian-shi-ti-67-ba-zi-fu-chuan-zhuan-huan-cheng-z-4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

26. 面试题 02.08. 环路检测 (要求返回入环点的节点)

方法:快慢指针 + 数学推导( a = c + (n-1)(b+c) )

在fast和slow相遇后,新增一个节点ptr = 链表开头,随后ptr和slow同步移动,它们会在入环点相遇。

 

27. 旋转矩阵

方法1:使用辅助数组

方法2:原地旋转

方法3:先水平翻转,再主对角线翻转

 

28. 查找一个数字中二进制表示法中1的个数

方法二:位运算优化
思路及解法

观察这个运算:n~\&~(n - 1)n & (n−1),其预算结果恰为把 nn 的二进制位中的最低位的 11 变为 00 之后的结果。

如:6~\&~(6-1) = 4, 6 = (110)_2, 4 = (100)_26 & (6−1)=4,6=(110)
2

,4=(100)
2

,运算结果 44 即为把 66 的二进制位中的最低位的 11 变为 00 之后的结果。

这样我们可以利用这个位运算的性质加速我们的检查过程,在实际代码中,我们不断让当前的 nn 与 n - 1n−1 做与运算,直到 nn 变为 00 即可。因为每次运算会使得 nn 的最低位的 11 被翻转,因此运算次数就等于 nn 的二进制位中 11 的个数。

代码

C++JavaC#Python3GolangJavaScriptC

class Solution {
public:
int hammingWeight(uint32_t n) {
int ret = 0;
while (n) {
n &= n - 1;
ret++;
}
return ret;
}
};
复杂度分析

时间复杂度:O(\log n)O(logn)。循环次数等于 nn 的二进制位中 11 的个数,最坏情况下 nn 的二进制位全部为 11。我们需要循环 \log nlogn 次。

空间复杂度:O(1)O(1),我们只需要常数的空间保存若干变量。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/solution/er-jin-zhi-zhong-1de-ge-shu-by-leetcode-50bb1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 29 . 二次二分,我们复制一下

 1 class Solution {
 2 public:
 3     int binarySearch(vector<int>& nums, int target, bool lower) {
 4         int left = 0, right = (int)nums.size() - 1, ans = (int)nums.size();
 5         while (left <= right) {
 6             int mid = (left + right) / 2;
 7             if (nums[mid] > target || (lower && nums[mid] >= target)) {
 8                 right = mid - 1;
 9                 ans = mid;
10             } else {
11                 left = mid + 1;
12             }
13         }
14         return ans;
15     }
16 
17     int search(vector<int>& nums, int target) {
18         int leftIdx = binarySearch(nums, target, true);
19         int rightIdx = binarySearch(nums, target, false) - 1;
20         if (leftIdx <= rightIdx && rightIdx < nums.size() && nums[leftIdx] == target && nums[rightIdx] == target) {
21             return rightIdx - leftIdx + 1;
22         }
23         return 0;
24     }
25 };

 

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/solution/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-wl6kr/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

30. 剑指 Offer 62. 圆圈中最后剩下的数字 (挺经典的数学归纳题)

方法:O(n),动态规划,数学归纳法

 

31. 求nums的所有子集

方法1:二进制遍历

求nums的所有子集可以这样想:

nums中有n个元素,可以使用 n-bit {10}串 来表示nums的子集,表示每一个元素在子集中是否存在,于是总共有2^n个子集

于是乎,0~(2^n-1)十进制数的二进制串实际上与nums的子集构成了双射(一一对应),我们只需要遍历0~2^n-1的数字,并且把它们二进制串中的”1“对应的nums的元素添加到子集中,就完成了对nums所有子集的遍历

算法复杂度:n * 2^n

class Solution {
public:
  vector<vector<int>> subsets(vector<int>& nums) {
    int n=nums.size(); // 获得nums的长度n,总共有2^n个集合
    vector<vector<int>> res;
    for(int i=0;i<(1<<n);++i)  // (1<<n)就是2^n,这里要遍历一次所有集合
    {
      vector<int> temp;
      for(int j=0;j<n;++j)    // 这里的循环是要遍历一次nums数组中的所有元素,看它们是否应该被添加到当前集合,循环n次,因此二进制枚举算法复杂度是 n*2^n
      {
        if((i>>j)&1) temp.push_back(nums[j]);
      }
      res.push_back(temp);
    }
    return res;
  }
};
 

 

方法2:非递归

复杂度:2^n

 

方法3:递归方法/回溯方法

由于集合是不区分排序的,因此{1,2}和{2,1}是同一个集合,在回溯算法中,以2为节点,则它的分支节点只需要考虑3,4,5,6.。。而不需要考虑1.

算法复杂度  2^n

 

方法4:另一种回溯算法

复杂度 2^n

 

32. 无重复字符串的排列组合

方法: dfs,枚举每一种在"k"位上的可能性,然后排列字符串之后的部分

复杂度:n! (n的阶乘)

 

 33. 有重复字符的字符串排列组合(其实就是上边的方法剪枝)

复杂度:每个dfs都要调用n次dfs,递归深度达到n次时结束,因此复杂度是n*n*n*...*n(n个n) = n^n

剪枝后是 n!

class Solution {
private:
    // index是起始的编号
    void dfs(const string& s,  bool* used,  int index, int n, string& curr, vector<string>& res)
    {
        if (index == n)
        {
            res.push_back(curr);
            return;
        }

        for (int i = 0; i <n ; ++i)
        {
            if (!used[i])
            {
                // 忽略重复元素的第二次出现的情况
                if (i > 0 && !used[i-1] && s[i-1] == s[i])
                {
                    continue;
                }
                used[i] = true;
                curr[index] = s[i];
                dfs(s, used, index+1, n, curr, res);
                // 回溯后要考虑恢复回去
                used[i] = false;
            }
        }
    }
public:
    vector<string> permutation(string S) {
        int n = S.size();
        //  表示是否被使用
        bool used[n];
        memset(used, 0, sizeof(bool)*n);

        // 返回的结果
        vector<string> res;

        // 排序
        sort(S.begin(), S.end());

        // 当前的结果
        string curr = S;
        dfs(S, used, 0, n, curr, res);
        return res;
    }
};

作者:ffreturn
链接:https://leetcode-cn.com/problems/permutation-ii-lcci/solution/0808-cshuang-bai-de-di-gui-hui-su-jie-fa-fmpj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 34. 括号生成题

方法:dfs,剪枝,发现left < right || left > n时就剪枝

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2022-03-19 16:28  yinhuachen  阅读(79)  评论(0编辑  收藏  举报