
数据结构与算法(刷题篇)
刷算法题,从简单到复杂,慢慢见证质变
hurricane&&storming
Not being impetuous
展开
-
浅谈 Pow(x, n) 问题
问题实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。思路:将 n 进行二进制拆分,为 1 的位多乘一个 x 。然后每次都将 x 平方,最后结果即 xn。class Solution {public: double quickMul(double x, long long N) { double ans = 1.0; // 贡献的初始值为 x double x_contribute = x; // .原创 2021-07-16 10:23:45 · 349 阅读 · 0 评论 -
浅谈 山脉数组的峰顶索引 问题
山脉数组的峰顶索引问题:符合下列属性的数组 arr 称为 山脉数组 :arr.length >= 3存在 i(0 < i < arr.length - 1)使得:arr[0] < arr[1] < ... arr[i-1] < arr[i]arr[i] > arr[i+1] > ... > arr[arr.length - 1]给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < .原创 2021-06-15 23:25:01 · 204 阅读 · 1 评论 -
浅谈 相交链表 问题
相交链表问题:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。思路:(双指针法)如果有链表为空则不会相交创建两个指针指向两链表的头节点。如果两节点不等则往下指。当一个链表遍历到最后一个节点时,将它指向另一个链表的头节点继续遍历。返回遍历的最后一个节点即为相交节点,如不相交则最后会遍历到表尾返回后一个空指针。/** * Definition for singly-linked list. *原创 2021-06-04 23:29:40 · 148 阅读 · 2 评论 -
浅谈 4 的幂 问题
4 的幂问题:给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回 true ;否则,返回 false 。整数 n 是 4 的幂次方需满足:存在整数 x 使得 n == 4x思路:思路 1如果所给整数小于等于 0 直接返回 0;如果所给整数大于 0,且是 4 的倍数(先确保它可能成为 4 的幂),然后不断将 n / 4, 最后 n 如果变为 1 则证明 n 是 4 的幂,返回 1。思路 24 的幂一定是 2 的幂,如果 (n & (n - 1))==原创 2021-05-31 10:39:10 · 791 阅读 · 1 评论 -
浅谈 2 的幂 问题
2 的幂题目:给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。如果存在一个整数 x 使得 n == 2^x ,则认为 n 是 2 的幂次方。思路:思路一如果所给整数小于等于 0 直接返回 0;如果所给整数大于 0,且是 2 的倍数(先确保它可能成为 2 的幂),然后不断将 n / 2, 最后 n 如果变为 1 则证明 n 是 2 的幂,返回 1。思路二(n & (n - 1))== 0 则证明 n 为 2 的原创 2021-05-31 00:41:37 · 274 阅读 · 1 评论 -
浅谈 只出现一次的数字 II 问题
只出现一次的数字 II问题:给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。思路:直接法;统计数组中每个数字出现的次数返回仅出现一次的数字unordered_map 学习class Solution {public: int singleNumber(vector<int>& nums) const { unordered_map<int, int>原创 2021-04-30 09:52:16 · 190 阅读 · 0 评论 -
浅谈 平方数之和 问题
平方数之和问题:给定一个 非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a^2 + b^2 == c 。思路:依次遍历 c^(1/2) 前的数,看 c - i ^ 2 再开根后的数是否为整数是则存在,否则不存在class Solution {public: bool judgeSquareSum(int const& c) const { auto sc = sqrt(c); // 这里 sc 为 double 型 fo原创 2021-04-28 19:47:41 · 470 阅读 · 0 评论 -
浅谈 二叉搜索树的范围和 问题
二叉搜索树的范围和问题:给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和。思路:法一:深度优先搜索(dfs)如果没有根节点返回 0;遍历节点值,如果比 low 小则去掉左子树,比 high 大则去掉右子树;返回符合条件的所有节点值。法二:广度优先搜索(bfs)用 队列 来实现树的广度优先搜索使用广度优先搜索的方法,用一个队列 q 存储需要计算的节点。每次取出队首节点时,若节点为空则跳过该节点,否则按方法一中给出的大小关系来决原创 2021-04-27 22:21:52 · 238 阅读 · 1 评论 -
浅谈 递增顺序搜索树 问题
递增顺序搜索树给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。思路:例:将中序遍历结果放入临时数组。创建新树,将数组中的值放入新树的右子树。返回新树的右子树指针。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * T原创 2021-04-25 20:11:18 · 168 阅读 · 0 评论 -
浅谈 移动元素 问题
移动元素问题:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 ==原地 ==修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。思路:思路简单清晰遍历整个数组,将与 val 相等的值覆盖即可最后返回新数组长度class Solution {public: int removeElement(vector<int原创 2021-04-19 11:01:38 · 145 阅读 · 0 评论 -
浅谈 打家劫舍 II 问题
打家劫舍 II问题:你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果 两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。给定一个代表每个房屋存放金额的 非负整数数组 ,计算你 在不触动警报装置的情况下 ,能够偷窃到的 最高金额。思路:参考 打家劫舍 问题。本题多了一个房屋是围成一圈的,所以要么盗第一间要么盗最后一间,这由动态规划导致,最后比较盗原创 2021-04-15 10:54:48 · 158 阅读 · 0 评论 -
浅谈 打家劫舍 问题
打家劫舍问题:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 , 一夜之内 能够偷窃到的最高金额。思路:先讨论简单情况,数组为空和元素只有 1 个 2 各的情况。后面情况采用动态规划处理。由于相邻房屋不能盗窃,所以有 Max = max(num[i] + num[i + 2原创 2021-04-15 10:39:28 · 148 阅读 · 0 评论 -
浅谈 实现 Trie (前缀树) 问题
实现 Trie (前缀树)问题:Trie(发音类似 “try”)或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。请你实现 Trie 类:Trie() 初始化前缀树对象。void insert(String word) 向前缀树中插入字符串 word 。boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false原创 2021-04-14 15:04:58 · 168 阅读 · 0 评论 -
浅谈 二叉搜索树节点最小距离 问题
二叉搜索树节点最小距离问题:给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。思路:采用递归中序遍历二叉搜索树。(中序遍历二叉搜索树节点是按有序序列遍历的)记录中间相邻节点的最小值。返回最小值。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; *原创 2021-04-13 23:21:54 · 168 阅读 · 0 评论 -
浅谈 最大数 问题
最大数问题:给定一组 非负 整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。思路:官方思路其实就是字符串比较法,当两字符串比较时是逐字符进行比较也就是说 “456” < “93”,此时 93 会移到前面。移位完成后将数字转为字符串拼接返回。class Solution {public: string largestNumber(vector<int> &原创 2021-04-12 18:29:01 · 228 阅读 · 0 评论 -
浅谈 丑数 II 问题
丑数 II问题:给你一个整数 n ,请你找出并返回第 n 个 丑数 。丑数 就是只包含质因数 2、3 和 5 的正整数。思路:动态规划。意图将从 1 ~ n 的丑数都求出来,然后返回最后一个丑数。创建一个存放过程中丑数的数组。分别计算下一个丑数,将最小的放入数组,得出的数字指针加一。持续重复上一步骤,直到算出第 n 个丑数。class Solution {public: int nthUglyNumber(int const n) const { i原创 2021-04-11 12:23:55 · 74 阅读 · 0 评论 -
浅谈 丑数 问题
丑数问题:给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。丑数 就是只包含质因数 2、3 和 5 的正整数。思路:首先进行特殊判断。将参数与 2,3,5取余运算,如果为 0 则立即求模。如果最后结果为 1 则证明为丑数。class Solution {public: bool isUgly(int n) { if(n < 1) return false; if(n < 7原创 2021-04-10 17:29:09 · 116 阅读 · 0 评论 -
浅谈 寻找旋转排序数组中的最小值 II 问题
寻找旋转排序数组中的最小值 II已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。原创 2021-04-09 14:12:22 · 86 阅读 · 0 评论 -
浅谈 寻找旋转排序数组中的最小值 问题
寻找旋转排序数组中的最小值问题:已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。原创 2021-04-08 20:15:36 · 183 阅读 · 0 评论 -
浅谈 搜索旋转排序数组 II 问题
搜索旋转排序数组 II问题:已知存在一个按非降序排列的整数数组 nums ,数组中的值 不必互不相同。在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,原创 2021-04-07 16:29:43 · 84 阅读 · 0 评论 -
浅谈 搜索旋转排序数组 问题
搜索旋转排序数组问题:整数数组 nums 按升序排列,数组中的值 互不相同 。在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。给你原创 2021-04-07 15:16:28 · 125 阅读 · 0 评论 -
浅谈 删除有序数组中的重复项 II 问题
删除有序数组中的重复项 II问题:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。思路:参考 数组去重 思路如果数组长度小于 3,无需操作。因为每个元素都可出现两次。假定两个指针,slow 指针用于为新数组下标赋值。fast 指针用于查找下下个不相同的元素。返回新数组长度。class Solution {publ原创 2021-04-06 12:44:36 · 144 阅读 · 0 评论 -
浅谈 删除有序数组中的重复项 问题
删除有序数组中的重复项问题:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。思路:判断数组是否为空,为空则返回 0。对原数组去重操作。返回新数组的长度。class Solution {public: int removeDuplicates(vector<int>& nums) const原创 2021-04-06 12:13:56 · 134 阅读 · 1 评论 -
浅谈 合并两个有序数组 问题
合并两个有序数组问题:给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。思路:法一:超简单,将两数组直接合并后排序。class Solution {public: void merge(vector<int>&原创 2021-04-05 20:03:51 · 119 阅读 · 0 评论 -
浅谈 笨阶乘 问题
笨阶乘问题:通常,正整数 n 的阶乘是所有小于或等于 n 的正整数的乘积。例如,factorial(10) = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1。相反,我们设计了一个笨阶乘 clumsy:在整数的递减序列中,我们以一个固定顺序的操作符序列来依次替换原有的乘法操作符:乘法(*),除法(/),加法(+)和减法(-)。例如,clumsy(10) = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1。然而,这些运算仍然使用通原创 2021-04-01 18:05:20 · 100 阅读 · 0 评论 -
浅谈 子集 II 问题
子集 II问题:给你一个整数数组 nums ,其中 可能包含重复元素,请你返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。思路:参考 子集 问题在递归时,若发现没有选择上一个数,且当前数字与上一个数相同,则可以跳过当前生成的子集。class Solution {public: vector<int> t; vector<vector<int>> ans; void原创 2021-03-31 22:53:54 · 112 阅读 · 0 评论 -
浅谈 子集 问题
子集问题:给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。思路:采用递归回溯的方法,借助临时数组进行回溯。class Solution {public: vector<int> t; vector<vector<int>> ans; void dfs(int cur, vector<int>& nums原创 2021-03-31 22:49:02 · 193 阅读 · 0 评论 -
浅谈 搜索二维矩阵 问题
搜索二维矩阵问题:编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:每行中的整数从左到右按升序排列。每行的第一个整数大于前一行的最后一个整数。思路:先进行搜索,再进行列搜索。由于二维数组元素升序排列,所以都采用从后往前搜索,比较方便确定 target 所在行可以采用二分查找的方法使时间复杂度从 mn 降到 log(mn) 。class Solution {public: bool searchMatrix(vector<原创 2021-03-30 11:53:43 · 404 阅读 · 0 评论 -
浅谈 颠倒二进制位 问题
颠倒二进制位颠倒给定的 32 位无符号整数 的二进制位。思路:从最低位遍历 n,并将 n 右移一位。将 n 的最低位依次变为最高,第二高位,……直到 n 变为 0 则结束。返回倒叙。class Solution {public: uint32_t reverseBits(uint32_t n) { uint32_t res = 0; auto i = 0; while(n) { res |= (n &原创 2021-03-29 16:34:15 · 244 阅读 · 0 评论 -
浅谈 二叉搜索树迭代器 问题
二叉搜索树迭代器实现一个二叉搜索树迭代器类 BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:BSTIterator (TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。int next()将指针向右移动,原创 2021-03-28 15:06:36 · 184 阅读 · 0 评论 -
浅谈 二叉树中序遍历 问题
二叉树中序遍历给定一个二叉树的根节点 root ,返回它的 中序 遍历。思路:采用自然的递归方式是最简洁的方法,因为我们知道递归、递归就是顺向遍历,然后逆向返回结果的过程,所以很容易的将中序遍历结果存入数组。下面也给出迭代法以及Morris 中序遍历法。 // 递归/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * Tree原创 2021-03-28 14:30:03 · 258 阅读 · 0 评论 -
浅谈 旋转链表 问题
旋转链表问题:给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。思路:判断特殊情况。采用构建循环链表并找出尾节点位置的方法。计算链表长度,并算出实际所需移动位置数(len % k)。观察发现算出移动位置数对应的尾节点位置。将尾节点与下一节点断开。本题并未将临时创建节点释放。/** * Definition for singly-linked list. * struct ListNode { * int val; * Li原创 2021-03-27 13:01:04 · 101 阅读 · 0 评论 -
浅谈 二进制求和 问题
二进制求和问题:给你两个二进制字符串,返回它们的和(用二进制表示)。输入为 非空 字符串且只包含数字 1 和 0。思路:题目给出非空字符条件,但我觉得为了函数的完整性应该进行判断。将字符串倒序后判断是否进位,进位加入到 carry 中存储以便后一加法判断是否继续进位。遍历完所有字符,若还有进位则在最后添上字符 ‘0’。将结果字符串反转并返回。class Solution {public: string addBinary(string& a, string原创 2021-03-26 20:54:31 · 125 阅读 · 0 评论 -
浅谈 删除排序链表中的重复元素 II 问题
删除排序链表中的重复元素 II问题:存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。返回同样按升序排列的结果链表。思路:参考 使排序链表中的元素唯一化问题,本题将多删除那个保留下来的节点。考虑到头节点可能会被删除,所以新建一个链表,并创建哑结点指向头指针域。如果为空链表则直接返回头节点。将指向重复元素的指针指向直到不相等的指针域为止。否则直接指向下一节点。直接方便地返回新链表的下一节原创 2021-03-25 12:18:36 · 164 阅读 · 0 评论 -
浅谈 删除排序链表中的重复元素 问题
删除排序链表中的重复元素给定一个 排序 链表,删除所有重复的元素,使得每个元素只出现一次。思路:采用动态操作指针的方法删除链表重复元素,但没有释放删除节点和哑结点空间。如果链表头指针为空返回空链表头结点。申请哑结点指向头节点,由于第一步已经判断头节点不为空,则只需判断下一节点是否为空作为循环条件。若元素重复,则将后一个的指针指向下下个指针域。否则指向下一个节点指针域。由于并未实际操作 head 指针,故此时直接方便地返回 head 即可。( 这便是申请哑结点的好处之一 )/**原创 2021-03-25 11:22:04 · 254 阅读 · 2 评论 -
浅谈 132 模式 问题
132 模式给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。思路: 1 < 3 && 3 < 2 → 1 < 2采用单调栈法。如果数组元素个数小原创 2021-03-24 16:43:15 · 670 阅读 · 0 评论 -
浅谈 扁平化嵌套列表迭代器 问题
扁平化嵌套列表迭代器问题:给你一个嵌套的整型列表。请你设计一个迭代器,使其能够遍历这个整型列表中的所有整数。列表中的每一项或者为一个 整数 ,或者是另一个 列表 。其中列表的元素也可能是 ==整数 或是其他 列表 。思路:采用深度优先策略(dfs)递归嵌套整型列表,将所有整数放入数组。初始化迭代器 it 。/** * // This is the interface that allows for creating nested lists. * // You shoul原创 2021-03-23 13:20:19 · 149 阅读 · 0 评论 -
浅谈 省份数量 问题
省份数量问题:有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] == 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] == 0 表示二者不直接相连。返回矩阵中 省份 的数量。思原创 2021-03-22 23:00:08 · 318 阅读 · 0 评论 -
浅谈 位 1 的个数 问题
位 1 的个数问题:编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。思路:通过前人发现,n & ( n - 1 ) 这个式子总是把 n 的最低位 1 变为 0.例: 7 → 1117 - 1 = 6 → 110 → 7 & 6 == 11010 == 101010 - 1 == 9 → 100110 & 9 == 1000故可根据此式将 n 的所有位逐一变为 0,并计数。c原创 2021-03-22 14:34:28 · 151 阅读 · 0 评论 -
浅谈 矩阵置零 问题
矩阵置零问题:给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。思路:第一次遍历数组,用两个标志位数组记录原数组中出现 0 的位置。flag[i] == 1 表示第 i 行有 0;flag[j] == 0 表示第 j 列有 0;再次遍历数组,将有 0 的行和列统统置零。class Solution {public: void setZeroes(vector<vector<int>>&原创 2021-03-21 13:13:29 · 432 阅读 · 0 评论