From 9103e4379fff598fa53927153b613e6fdfd1774a Mon Sep 17 00:00:00 2001 From: jaredliw Date: Fri, 23 Jul 2021 21:18:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0py=EF=BC=8Cjs=E5=92=8Ccpp?= =?UTF-8?q?=EF=BC=8C=E8=A7=A3=E5=86=B3java=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../求次数问题/只出现一次的数3.md | 193 ++++++++++++++++-- 1 file changed, 174 insertions(+), 19 deletions(-) diff --git a/animation-simulation/求次数问题/只出现一次的数3.md b/animation-simulation/求次数问题/只出现一次的数3.md index a33da9e..130f448 100644 --- a/animation-simulation/求次数问题/只出现一次的数3.md +++ b/animation-simulation/求次数问题/只出现一次的数3.md @@ -13,7 +13,7 @@ > 输入: [1,2,1,3,2,5] > 输出: [3,5] -这个也很容易理解,算是对第一题的升级,第一题有 1 个出现 1次的数,其余出现两次,这个题目中有 2 个出现 1次的数,其余数字出现两次。那么这个题目我们怎么做呢?我们看一下能不能利用第一题中的做法解决。 +这个也很容易理解,算是对第一题的升级,第一题有 1 个出现一次的数,其余出现两次,这个题目中有 2 个出现一次的数,其余数字出现两次。那么这个题目我们怎么做呢?我们看一下能不能利用第一题中的做法解决。 ### HashSet @@ -23,6 +23,8 @@ #### 题目代码 +Java Code: + ```java class Solution { public int[] singleNumber(int[] nums) { @@ -31,10 +33,10 @@ class Solution { //存在的则移除 if (set.contains(x)) { set.remove(x); - continue; + //不存在则存入 + } else { + set.add(x); } - //不存在存入 - set.add(x); } //存到数组里,然后返回 int[] arr = new int[2]; @@ -47,6 +49,77 @@ class Solution { } ``` +C++ Code: + +```cpp +class Solution { +public: + vector singleNumber(vector& nums) { + unordered_set set; + for (int x : nums) { + //存在的则移除 + if (set.find(x) == set.end()) { + set.insert(x); + //不存在则存入 + } else { + set.erase(x); + } + } + //存到数组里,然后返回 + vector arr; + for (int y : set) { + arr.push_back(y); + } + return arr; + } +}; +``` + +JS Code: + +```javascript +var singleNumber = function(nums) { + let set = new Set(); + for (let x of nums) { + //存在的则移除 + if (set.has(x)) { + set.delete(x); + //不存在则存入 + } else { + set.add(x); + } + } + //存到数组里,然后返回 + let arr = []; + for (let y of set) { + arr.push(y); + } + return arr; +}; +``` + +Python Code: + +```python +class Solution: + def singleNumber(self, nums: List[int]) -> List[int]: + set_ = set() + for x in nums: + # 存在的则移除 + if x in set_: + set_.remove(x) + # 不存在则存入 + else: + set_.add(x) + # 存到数组里,然后返回 + arr = [] + for y in set_: + arr.append(y) + return arr +``` + + + ### 位运算 #### 解析 @@ -55,53 +128,59 @@ class Solution { 我们试想一下,如果我们先将元素分成两组,然后每组包含一个目标值,那么异或之后,每组得到一个目标值,那么我们不就将两个目标值求出了吗? -> 例: **a,b,a,b,c,d,e,f,e,f ** 分组后 +> 例: **a, b, a, b, c, d, e, f, e, f ** > -> A组:a, a , b, b, c 异或得到 c +> 分组后: > -> B组:e, e, f, f, d 异或得到 d +> ​ A组:a, a, b, b, c 异或得到 c +> +> ​ B组:e, e, f, f, d 异或得到 d 原理懂了,那么我们应该依据什么规则对其进行分类呢? -c , d 两个不同的数,那么二进制上必定有一位是不同的,那么我们就可以根据这一位(分组位)来将 c , d 分到两个组中,数组中的其他元素,要么在 A 组中,要么在 B 组中。 +c,d 两个不同的数,那么二进制上必定有一位是不同的,那么我们就可以根据这一位(分组位)来将 c,d 分到两个组中,数组中的其他元素,要么在 A 组中,要么在 B 组中。 我们应该怎么得到分组位呢? -我们让 c , d 异或即可,异或运算就是对应位不同时得 1 ,异或之后值为 1 的其中一位则为我们分组。 +我们让 c,d 异或即可,异或运算就是对应位不同时得 1,异或之后值为 1 的其中一位则为我们分组。 -例 001 ⊕ 100 = 101,我们可以用最右边的 1 或最左边的 1 做为分组位,数组元素中,若我们将最右边的 1 作为我们的分组位,最后一位为 0 的则进入 A 组,为 1 的进入 B 组。 +例 001 ⊕ 100 = 101,我们可以用最右边的 1 或最左边的 1 做为分组位,数组元素中,若我们将最右边的 1 作为我们的分组位,最后一位为 0 的则进入 A 组,为 1 的进入 B 组。 那么我们应该怎么借助分组位进行分组呢? -我们处理 c , d 的异或值,可以仅保留异或值的分组位,其余位变为 0 ,例如 101 变成 001或 100 +我们处理 c , d 的异或值,可以仅保留异或值的分组位,其余位变为 0 ,例如 101 变成 001或 100。 -为什么要这么做呢?在第二题提到,我们可以根据 a & 1 来判断 a 的最后一位为 0 还是为 1,所以我们将 101 变成 001 之后,然后数组内的元素 x & 001 即可对 x 进行分组 。同样也可以 x & 100 进行分组. +为什么要这么做呢?在第二题提到,我们可以根据 a & 1 来判断 a 的最后一位为 0 还是为 1,所以我们将 101 变成 001 之后,然后数组内的元素 x & 001 即可对 x 进行分组 。同样也可以 x & 100 进行分组。 -那么我们如何才能仅保留分组位,其余位变为 0 呢?例 101 变为 001 +那么我们如何才能仅保留分组位,其余位变为 0 呢?例 101 变为 001。 -我们可以利用 x & (-x) 来保留最右边的 1 +我们可以利用 x & (-x) 来保留最右边的 1。 ![分组位](https://cdn.jsdelivr.net/gh/tan45du/tan45du.github.io.photo@master/photo/分组位.25gbi25kv7c0.png) #### 题目代码: +Java Code: + ```java class Solution { public int[] singleNumber(int[] nums) { - int temp = 0; + //小心溢出 + long temp = 0; //求出异或值 for (int x : nums) { temp ^= x; } + System.out.println(temp); + System.out.println(-temp); //保留最右边的一个 1 - int group = temp & (-temp); - System.out.println(group); + long group = temp & (-temp); int[] arr = new int[2]; for (int y : nums) { - //分组位为0的组,组内异或 + //分组位为 0 的组,组内异或 if ((group & y) == 0) { arr[0] ^= y; - //分组位为 1 的组,组内异或 + //分组位为 1 的组,组内异或 } else { arr[1] ^= y; } @@ -111,3 +190,79 @@ class Solution { } ``` +C++ Code: + +```cpp +class Solution { +public: + vector singleNumber(vector& nums) { + //小心 -temp 溢出 + long temp = 0; + //求出异或值 + for (int x : nums) { + temp ^= x; + } + //保留最右边的一个 1 + int group = temp & (-temp); + vector arr(2, 0); + for (int y : nums) { + //分组位为 0 的组,组内异或 + if ((group & y) == 0) { + arr[0] ^= y; + //分组位为 1 的组,组内异或 + } else { + arr[1] ^= y; + } + } + return arr; + } +}; +``` + +JS Code: + +```javascript +var singleNumber = function(nums) { + let temp = 0; + //求出异或值 + for (let x of nums) { + temp ^= x; + } + //保留最右边的一个 1 + let group = temp & (-temp); + let arr = [0, 0]; + for (let y of nums) { + //分组位为 0 的组,组内异或 + if ((group & y) == 0) { + arr[0] ^= y; + //分组位为 1 的组,组内异或 + } else { + arr[1] ^= y; + } + } + return arr; +}; +``` + +Python Code: + +```python +class Solution: + def singleNumber(self, nums: List[int]) -> List[int]: + temp = 0 + # 求出异或值 + for x in nums: + temp ^= x + # 保留最右边的一个 1 + group = temp & (-temp) + arr = [0, 0] + for y in nums: + # 分组位为 0 的组,组内异或 + if (group & y) == 0: + arr[0] ^= y + # 分组位为 1 的组,组内异或 + else: + arr[1] ^= y + return arr +``` +