随笔分类 - 剑指Offer(第2版)
摘要:思路 方法:分组异或 1 class Solution { 2 public: 3 vector<int> singleNumbers(vector<int>& nums) { 4 int res = 0; 5 for(int &num: nums) { 6 res ^= num; 7 } 8 9
阅读全文
摘要:思路 方法一:暴力递归法 (自顶向下的递归) 使用递归编写一个求高度的函数,之后使用先序遍历每个结点,判断左右子树的高度差是否满足要求。 这种方法每次判断一个结点都需要使用递归先求出其左右子树的高度,比如下面这棵树,判断1的时候,使用递归求了2,3, 4的高度,判断2的时候,又递归求了3,4,的高度
阅读全文
摘要:思路 方法:递归 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x)
阅读全文
摘要:思路 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(
阅读全文
摘要:思路 方法一:顺序查找 顺序查找第一个nums[i]不等于下标 i 的数,这时的下标 i 就是缺少的数。 复杂度分析 时间复杂度:O(n) 空间复杂度:O(1) 方法二:二分法 复杂度分析 时间复杂度:O(logn) 空间复杂度:O(1) 1 class Solution { 2 public: 3
阅读全文
摘要:思路 排序数组中的搜索问题,首先想到 二分法 解决。 方法一:二分法之一 (类似暴力) (1) 用二分法找到其中一个target所在的位置 (2) 之后在此位置前后顺序查找依次计数target的出现次数。(有点暴力,在方法二对此有改进) 复杂度分析 时间复杂度:最坏情况下O(n) 空间复杂度:O(1
阅读全文
摘要:思路 方法一:暴力法 方法二:哈希表 方法三:双指针之一 (1) 遍历链表A, B,计算出他们分别的长度lenA, lenB。 (2) 链表长的指针向后移动到俩个链表长度差的位置。 (3) 之后一一进行比较。 复杂度分析 时间复杂度:O(lenA + lenB) 空间复杂度:O(1) 1 /** 2
阅读全文
摘要:思路 方法:归并排序求逆序对 题解思路来自:力扣官方题解 - 数组中的逆序对 复杂度分析 1 class Solution { 2 public: 3 int reversePairs(vector<int>& nums) { 4 vector<int> tmp(nums.size()); 5 re
阅读全文
摘要:思路 方法:哈希表 第一次遍历字符串s,用哈希表统计每个字符出现的次数,第二次遍历字符串s,当某字符出现次数为1时,返回之。 复杂度分析 时间复杂度:O(n)。 空间复杂度:O(1)。由于题目指出 s 只包含小写字母,因此最多有 26 个不同字符,最多需占用 O(26) = O(1) 的额外空间。
阅读全文
摘要:思路 方法一:小顶堆 生成丑数的规律:如果已知丑数ugly,那么ugly * 2,ugly * 3和ugly * 5也都是丑数。既然求第n小的丑数,可以采用最小堆来解决。每次弹出堆中最小的丑数,然后检查它分别乘以2、3和 5后的数是否生成过,如果是第一次生成,那么就放入堆中。第n个弹出的数即为第n小
阅读全文
摘要:思路 方法一:暴力法 对于字符串s,用f[i]表示以s[i]开头的无重复字符的字符串最大长度, 逐一求出f[0], f[1], ... ,f[s.length()-1] ,最后返回这些值中的最大值即可。 1 class Solution { 2 public: 3 int lengthOfLonge
阅读全文
摘要:思路 方法:动态规划 比较明显的动态规划问题。设f[i][j]表示从(0,0)走到(i, j)获取的最大价值。 状态转移方程为:f(x, y) = grid(x,y) + max {f(x-1,y), f(x, y-1)} 。 空间优化:这里不使用额外的数组f,而就地更改grid数组,可以将空间复杂
阅读全文
摘要:思路 方法一:暴力法 使用深度优先搜索枚举出全部情况,试探每一种可能性。 1 class Solution { 2 public: 3 int translateNum(int num) { 4 string s = to_string(num); 5 int res = 0; 6 dfs(s, r
阅读全文
摘要:思路 本题解来自:面试题45. 把数组排成最小的数(自定义排序,清晰图解) 方法:自定义排序 1 class Solution { 2 public: 3 string minNumber(vector<int>& nums) { 4 vector<string> vs; 5 for(int i =
阅读全文
摘要:思路 本题解来自:面试题44. 数字序列中某一位的数字(迭代 + 求整 / 求余,清晰图解) 方法:找规律 1 class Solution { 2 public: 3 int findNthDigit(int n) { 4 int digit = 1; 5 long long start = 1;
阅读全文
摘要:思路 这题如果直接用暴力法,1~n逐一判断,每个数逐位判断需要O(L)的时间,其中L为n的位数,所以总的时间复杂度为O(L*n),这显然会超时。 方法:逐位判断,找规律 假设n是4位数abcd, 即n=abcd,从右往左逐位分析: - 对于n中的第4位数d: - 如果d ≥ 1,对于1~n中第4位数
阅读全文
摘要:思路 方法一:简单排序 将数字存储在可调整大小的容器中。每次需要输出中间值时,对容器进行排序并输出中间值。 复杂度分析 时间复杂度:O(nlogn)+O(1)≃O(nlogn)。 添加一个数字对于一个有效调整大小方案的容器来说需要花费 O(1) 的时间。找到中间值主要取决于发生的排序。对于标准比较排
阅读全文
摘要:思路 方法一:动态规划 1 class Solution { 2 public: 3 int maxSubArray(vector<int>& nums) { 4 //memo[i]表示以nums[i]结尾并且包含nums[i]的子数组的最大和 5 vector<int> memo(nums.siz
阅读全文
摘要:思路 方法一:排序 对原数组从小到大排序后取出前 k 个数即可。 时间复杂度:O(nlogn),其中 n 是数组 arr 的长度。算法的时间复杂度即排序的时间复杂度。 方法二:堆 我们用一个大根堆实时维护数组的前 kk 小值。首先将前 kk 个数插入大根堆中,随后从第 k+1k+1 个数开始遍历,如
阅读全文
摘要:思路 下文使用majority来代表“数组中出现次数超过一半的数字 ” 。 方法一:哈希表 遍历数组 nums ,用 map 统计各数字的数量,即可找出 majority 。 时间复杂度:O(n) 空间复杂度:O(n) 1 class Solution { 2 private: 3 unordere
阅读全文