diff --git a/算法/A类:基本算法/3.9 位运算算法.md b/算法/A类:基本算法/3.9 位运算算法.md index a7ac887d..74d059f8 100644 --- a/算法/A类:基本算法/3.9 位运算算法.md +++ b/算法/A类:基本算法/3.9 位运算算法.md @@ -9,7 +9,7 @@ & | 按位与 | 只要有0,返回0 \| | 按位或| 只要有1,返回1 ^ | 按位异或| 相同返回0。不同返回1 -\~ | 按位取反| 全部反转 +\~ | 按位取反| 全部反转。不重复的数字 \>\> | 右移| << | 左移| diff --git a/算法/B类:数据结构算法/2.1 深搜与广搜.md b/算法/B类:数据结构算法/2.1 深搜与广搜.md index 12c6ad88..dfe07888 100644 --- a/算法/B类:数据结构算法/2.1 深搜与广搜.md +++ b/算法/B类:数据结构算法/2.1 深搜与广搜.md @@ -15,4 +15,54 @@ * 请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。 * [链接](https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof/) +## 4 二叉搜索树的第k大节点 +* 给定一棵二叉搜索树,请找出其中第k大的节点。 +* 示例 1: +``` +输入: root = [3,1,4,null,2], k = 1 + 3 + / \ + 1 4 + \ +  2 +输出: 4 +示例 2: +``` +* [链接](https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof) + +## 5 二叉树的深度 + +* 输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。 + +* 例如: +``` +给定二叉树 [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +返回它的最大深度 3 。 +``` +* [链接](https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof) + +## 6 平衡二叉树 + +* 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。 + +  + +* 示例 1: +``` +给定二叉树 [3,9,20,null,null,15,7] + + 3 + / \ + 9 20 + / \ + 15 7 +返回 true 。 +``` +* [链接](https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof) \ No newline at end of file diff --git a/算法/B类:数据结构算法/4.2 链表与双指针.md b/算法/B类:数据结构算法/4.2 链表与双指针.md index 5044415e..973f314c 100644 --- a/算法/B类:数据结构算法/4.2 链表与双指针.md +++ b/算法/B类:数据结构算法/4.2 链表与双指针.md @@ -96,4 +96,50 @@ public: return node1; } }; +``` + +## 3 和为s的两个数字 +### 问题描述 + +* 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。 +* 示例 1: +``` +输入:nums = [2,7,11,15], target = 9 +输出:[2,7] 或者 [7,2] +``` +### 问题分析 + + +### 策略选择 + +* 数据结构:线型数组 +* 算法思想:双指针搜搜 +### 算法设计 +始化: 双指针 ii , jj 分别指向数组 numsnums 的左右两端 (俗称对撞双指针)。 +循环搜索: 当双指针相遇时跳出; +计算和 s = nums[i] + nums[j]s=nums[i]+nums[j] ; +若 s > targets>target ,则指针 jj 向左移动,即执行 j = j - 1j=j−1 ; +若 s < targets twoSum(vector& nums, int target) { + vector vec; + int i=0,j=nums.size()-1; + while(nums[i]+nums[j]!=target){ + if(nums[i]+nums[j]>target)j--; + if(nums[i]+nums[j] singleNumbers(vector& nums) { + int ret = 0; + for (int n : nums) + ret ^= n; + int div = 1; + while ((div & ret) == 0) + div <<= 1; + //可以优化while循环 + //div = n & ((~n)-1)//lowbit()运算保留最后一位1 + int a = 0, b = 0; + for (int n : nums) + if (div & n) + a ^= n; + else + b ^= n; + return vector{a, b}; + } +}; +``` + +## 4 数组中数字出现的次数II + +### 问题描述 +在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。 + +* 示例 1: +``` +输入:nums = [3,4,3,3] +输出:4 +``` + +### 问题分析 +* 问题分类:查找重复 +* 问题抽象:如下图所示,考虑数字的二进制形式,对于出现三次的数字,各 二进制位 出现的次数都是 33 的倍数。因此,统计所有数字的各二进制位中 11 的出现次数,并对 33 求余,结果则为只出现一次的数字 + +![](image/2021-03-26-22-07-44.png) + +### 策略选择 + +* 算法思想:变治法 + +### 算法设计 + +* 使用 与运算 ,可获取二进制数字 num 的最右一位$n_1$ $n_1 = num \& 1$ +* 配合 无符号右移操作 ,可获取 num 所有位的$n_1$ $num = num >> 1$ +* 建立一个长度为 32 的数组 countscounts ,通过以上方法可记录所有数字的各二进制位的 11 的出现次数。 +* 将 countscounts 各元素对 33 求余,则结果为 “只出现一次的数字” 的各二进制位。 + + +### 算法分析 +* 时间复杂度 O(N) +* 空间复杂度 O(1) + +### 算法实现 + +```java +class Solution { + public int singleNumber(int[] nums) { + int[] counts = new int[32]; + for(int num : nums) { + for(int j = 0; j < 32; j++) { + counts[j] += num & 1; + num >>>= 1; + } + } + int res = 0, m = 3; + for(int i = 0; i < 32; i++) { + res <<= 1; + res |= counts[31 - i] % m; + } + return res; + } +} +``` diff --git a/算法/C类:问题类型算法/image/2021-03-26-22-07-44.png b/算法/C类:问题类型算法/image/2021-03-26-22-07-44.png new file mode 100644 index 00000000..e9cd31ef Binary files /dev/null and b/算法/C类:问题类型算法/image/2021-03-26-22-07-44.png differ