From 7dd5ce1f3d8213117d065b060a1609ba4536a19a Mon Sep 17 00:00:00 2001 From: goodyong <50802846+goodyong@users.noreply.github.com> Date: Sat, 10 Jul 2021 12:20:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86python=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=88=E6=95=B0=E7=BB=84=E7=AF=87=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为数组篇文件夹下的代码增加了python语言版本 --- .../leetcode1438绝对值不超过限制的最长子数组.md | 35 ++++++++ .../数组篇/leetcode1两数之和.md | 35 ++++++++ .../数组篇/leetcode219数组中重复元素2.md | 53 ++++++++++++- .../数组篇/leetcode27移除元素.md | 27 ++++++- .../数组篇/leetcode41缺失的第一个正数.md | 23 ++++++ .../数组篇/leetcode485最大连续1的个数.md | 25 ++++++ .../数组篇/leetcode54螺旋矩阵.md | 37 +++++++++ .../数组篇/leetcode560和为K的子数组.md | 10 +++ .../数组篇/leetcode59螺旋矩阵2.md | 79 +++++++++++++++++++ animation-simulation/数组篇/leetcode66加一.md | 20 +++++ .../数组篇/leetcode75颜色分类.md | 61 ++++++++++++++ .../数组篇/剑指offer3数组中重复的数.md | 35 ++++++++ .../数组篇/长度最小的子数组.md | 24 ++++++ 13 files changed, 461 insertions(+), 3 deletions(-) diff --git a/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md b/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md index a3ac8b1..000facd 100644 --- a/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md +++ b/animation-simulation/数组篇/leetcode1438绝对值不超过限制的最长子数组.md @@ -43,6 +43,8 @@ 其实,我们只要把握两个重点即可,我们的 maxdeque 维护的是一个单调递减的双端队列,头部为当前窗口的最大值, mindeque 维护的是一个单调递增的双端队列,头部为窗口的最小值,即可。好啦我们一起看代码吧。 +Java Code: + ```java class Solution { public int longestSubarray(int[] nums, int limit) { @@ -76,3 +78,36 @@ class Solution { } ``` +Python Code: + +```python +from typing import List +import collections +class Solution: + def longestSubarray(self, nums: List[int], limit: int)->int: + maxdeque = collections.deque() + mindeque = collections.deque() + leng = len(nums) + right = 0 + left = 0 + maxwin = 0 + while right < leng: + while len(maxdeque) != 0 and maxdeque[-1] < nums[right]: + maxdeque.pop() + while len(mindeque) != 0 and mindeque[-1] > nums[right]: + mindeque.pop() + + maxdeque.append(nums[right]) + mindeque.append(nums[right]) + while (maxdeque[0] - mindeque[0]) > limit: + if maxdeque[0] == nums[left]: + maxdeque.popleft() + if mindeque[0] == nums[left]: + mindeque.popleft() + left += 1 + # 保留最大窗口 + maxwin = max(maxwin, right - left + 1) + right += 1 + return maxwin +``` + diff --git a/animation-simulation/数组篇/leetcode1两数之和.md b/animation-simulation/数组篇/leetcode1两数之和.md index 43be63b..89db733 100644 --- a/animation-simulation/数组篇/leetcode1两数之和.md +++ b/animation-simulation/数组篇/leetcode1两数之和.md @@ -33,6 +33,8 @@ **题目代码** +Java Code: + ```java class Solution { public int[] twoSum(int[] nums, int target) { @@ -55,6 +57,25 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def twoSum(nums: List[int], target: int)->List[int]: + if len(nums) < 2: + return [0] + rearr = [0] * 2 + # 查询元素 + for i in range(0, len(nums)): + for j in range(i + 1, len(nums)): + # 发现符合条件情况 + if nums[i] + nums[j] == target: + rearr[0] = i + rearr[1] = j + return rearr +``` + **哈希表** **解析** @@ -122,5 +143,19 @@ const twoSum = function (nums, target) { }; ``` +Python3 Code: +```python +from typing import List +class Solution: + def twoSum(self, nums: List[int], target: int)->List[int]: + m = {} + for i in range(0, len(nums)): + # 如果存在则返回 + if (target - nums[i]) in m.keys(): + return [m[target - nums[i]], i] + # 不存在则存入 + m[nums[i]] = i + return [0] +``` diff --git a/animation-simulation/数组篇/leetcode219数组中重复元素2.md b/animation-simulation/数组篇/leetcode219数组中重复元素2.md index c167d1e..d5b5d9d 100644 --- a/animation-simulation/数组篇/leetcode219数组中重复元素2.md +++ b/animation-simulation/数组篇/leetcode219数组中重复元素2.md @@ -29,6 +29,8 @@ 这个题目和我们上面那个数组中的重复数字几乎相同,只不过是增加了一个判断相隔是否小于K位的条件,我们先用 HashMap 来做一哈,和刚才思路一致,我们直接看代码就能整懂 +Java Code: + ```java class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { @@ -41,9 +43,9 @@ class Solution { for (int i = 0; i < nums.length; i++) { // 如果含有 if (map.containsKey(nums[i])) { - //判断是否小于K,如果小于则直接返回 + //判断是否小于K,如果小于等于则直接返回 int abs = Math.abs(i - map.get(nums[i])); - if (abs <= k) return true;//小于则返回 + if (abs <= k) return true;//小于等于则返回 } //更新索引,此时有两种情况,不存在,或者存在时,将后出现的索引保存 map.put(nums[i],i); @@ -53,6 +55,29 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def containsNearbyDuplicate(self, nums: List[int], k: int)->bool: + # 特殊情况 + if len(nums) == 0: + return False + # 字典 + m = {} + for i in range(0, len(nums)): + # 如果含有 + if nums[i] in m.keys(): + # 判断是否小于K,如果小于等于则直接返回 + a = abs(i - m[nums[i]]) + if a <= k: + return True# 小于等于则返回 + # 更新索引,此时有两种情况,不存在,或者存在时,将后出现的索引保存 + m[nums[i]] = i + return False +``` + **HashSet** **解析** @@ -65,6 +90,8 @@ class Solution { **题目代码** +Java Code + ```java class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { @@ -91,3 +118,25 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def containsNearbyDuplicate(self, nums: List[int], k: int)->bool: + # 特殊情况 + if len(nums) == 0: + return False + # 集合 + s = set() + for i in range(0, len(nums)): + # 如果含有,返回True + if nums[i] in s: + return True + # 添加新元素 + s.add(nums[i]) + # 维护窗口长度 + if len(s) > k: + s.remove(nums[i - k]) + return False +``` diff --git a/animation-simulation/数组篇/leetcode27移除元素.md b/animation-simulation/数组篇/leetcode27移除元素.md index 1a14c5b..db107bc 100644 --- a/animation-simulation/数组篇/leetcode27移除元素.md +++ b/animation-simulation/数组篇/leetcode27移除元素.md @@ -50,6 +50,8 @@ **题目代码** +Java Code: + ```java class Solution { public int removeElement(int[] nums, int val) { @@ -75,6 +77,29 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def removeElement(self, nums: List[int], val: int)->int: + # 获取数组长度 + leng = len(nums) + if 0 == leng: + return 0 + i = 0 + while i < leng: + # 发现符合条件的情况 + if nums[i] == val: + # 前移一位 + for j in range(i, leng - 1): + nums[j] = nums[j + 1] + i -= 1 + leng -= 1 + i += 1 + return i +``` + **双指针** 快慢指针的做法比较有趣,只需要一个 for 循环即可解决,时间复杂度为 O(n) ,总体思路就是有两个指针,前面一个后面一个,前面的用于搜索需要删除的值,当遇到需要删除的值时,前指针直接跳过,后面的指针不动,当遇到正常值时,两个指针都进行移动,并修改慢指针的值。最后只需输出慢指针的索引即可。 @@ -100,7 +125,7 @@ class Solution { if (nums[j] == val) { continue; } - // 不等于目标值时,则赋值给num[i],i++ + // 不等于目标值时,则赋值给nums[i],i++ nums[i++] = nums[j]; } return i; diff --git a/animation-simulation/数组篇/leetcode41缺失的第一个正数.md b/animation-simulation/数组篇/leetcode41缺失的第一个正数.md index 73dacaf..d22a7df 100644 --- a/animation-simulation/数组篇/leetcode41缺失的第一个正数.md +++ b/animation-simulation/数组篇/leetcode41缺失的第一个正数.md @@ -39,6 +39,8 @@ ![缺失的第一个正数](https://cdn.jsdelivr.net/gh/tan45du/github.io.phonto2@master/myphoto/缺失的第一个正数.1it1cow5aa8w.gif) +Java Code: + ```java class Solution { public int firstMissingPositive(int[] nums) { @@ -65,6 +67,27 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def firstMissingPositive(self, nums: List[int])->int: + if len(nums) == 0: + return 1 + # 因为是返回第一个正整数,不包括 0,所以需要长度加1,细节1 + res = [0] * (len(nums) + 1) + # 将数组元素添加到辅助数组中 + for x in nums: + if x > 0 and x < len(res): + res[x] = x + # 遍历查找,发现不一样时直接返回 + for i in range(1, len(res)): + if res[i] != i: + return i + # 缺少最后一个,例如 1,2,3此时缺少 4 ,细节2 + return len(res) +``` 我们通过上面的例子了解这个解题思想,我们有没有办法不使用辅助数组完成呢?我们可以使用原地置换,直接在 nums 数组内,将值换到对应的索引处,与上个方法思路一致,只不过没有使用辅助数组,理解起来也稍微难理解一些。 diff --git a/animation-simulation/数组篇/leetcode485最大连续1的个数.md b/animation-simulation/数组篇/leetcode485最大连续1的个数.md index 6157b54..dfdfa01 100644 --- a/animation-simulation/数组篇/leetcode485最大连续1的个数.md +++ b/animation-simulation/数组篇/leetcode485最大连续1的个数.md @@ -30,6 +30,8 @@ 下面我们直接看代码吧 +Java Code: + ```java class Solution { public int findMaxConsecutiveOnes(int[] nums) { @@ -58,6 +60,29 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def findMaxConsecutiveOnes(self, nums: List[int])->int: + leng = len(nums) + left = 0 + right = 0 + maxcount = 0 + while right < leng: + if nums[right] == 1: + right += 1 + continue + # 保存最大值 + maxcount = max(maxcount, right - left) + # 跳过 0 的情况 + while right < leng and nums[right] == 0: + right += 1 + # 同一起点继续遍历 + left = right + return max(maxcount, right - left) +``` 刚才的效率虽然相对高一些,但是代码不够优美,欢迎各位改进,下面我们说一下另外一种情况,一个特别容易理解的方法。 diff --git a/animation-simulation/数组篇/leetcode54螺旋矩阵.md b/animation-simulation/数组篇/leetcode54螺旋矩阵.md index 011e298..cb3c678 100644 --- a/animation-simulation/数组篇/leetcode54螺旋矩阵.md +++ b/animation-simulation/数组篇/leetcode54螺旋矩阵.md @@ -46,6 +46,8 @@ 题目代码: +Java Code: + ```java class Solution { public List spiralOrder(int[][] matrix) { @@ -83,5 +85,40 @@ class Solution { ``` +Python3 Code: + +```python +from typing import List +class Solution: + def spiralOrder(self, matrix: List[List[int]])->List[int]: + arr = [] + left = 0 + right = len(matrix[0]) - 1 + top = 0 + down = len(matrix) - 1 + while True: + for i in range(left, right + 1): + arr.append(matrix[top][i]) + top += 1 + if top > down: + break + for i in range(top, down + 1): + arr.append(matrix[i][right]) + right -= 1 + if left > right: + break + for i in range(right, left - 1, -1): + arr.append(matrix[down][i]) + down -= 1 + if top > down: + break + for i in range(down, top - 1, -1): + arr.append(matrix[i][left]) + left += 1 + if left > right: + break + return arr +``` + diff --git a/animation-simulation/数组篇/leetcode560和为K的子数组.md b/animation-simulation/数组篇/leetcode560和为K的子数组.md index 70402fe..8e81e3e 100644 --- a/animation-simulation/数组篇/leetcode560和为K的子数组.md +++ b/animation-simulation/数组篇/leetcode560和为K的子数组.md @@ -21,6 +21,8 @@ 这个题目的题意很容易理解,就是让我们返回和为 k 的子数组的个数,所以我们直接利用双重循环解决该题,这个是很容易想到的。我们直接看代码吧。 +Java Code: + ```java class Solution { public int subarraySum(int[] nums, int k) { @@ -41,6 +43,8 @@ class Solution { } ``` +Python3版本的代码会超时 + 下面我们我们使用前缀和的方法来解决这个题目,那么我们先来了解一下前缀和是什么东西。其实这个思想我们很早就接触过了。见下图 ![](https://cdn.jsdelivr.net/gh/tan45du/github.io.phonto2@master/myphoto/微信截图_20210113193831.4wk2b9zc8vm0.png) @@ -61,6 +65,8 @@ presum [2] = presum[1] + nums[1],presum[3] = presum[2] + nums[2] ... 所以我 直接上代码。 +Java Code: + ```java class Solution { public int subarraySum(int[] nums, int k) { @@ -86,6 +92,8 @@ class Solution { } ``` +Python3版本的代码也会超时 + 我们通过上面的例子我们简单了解了前缀和思想,那么我们如果继续将其优化呢? **前缀和 + HashMap** @@ -94,6 +102,8 @@ class Solution { 其实我们在之前的两数之和中已经用到了这个方法,我们一起来回顾两数之和 HashMap 的代码. +Java Code: + ```java class Solution { public int[] twoSum(int[] nums, int target) { diff --git a/animation-simulation/数组篇/leetcode59螺旋矩阵2.md b/animation-simulation/数组篇/leetcode59螺旋矩阵2.md index 6824ea6..50cf94c 100644 --- a/animation-simulation/数组篇/leetcode59螺旋矩阵2.md +++ b/animation-simulation/数组篇/leetcode59螺旋矩阵2.md @@ -66,6 +66,8 @@ 题目代码: +Java Code: + ```java class Solution { public List spiralOrder(int[][] matrix) { @@ -103,10 +105,45 @@ class Solution { ``` +Python3 Code: +```python +from typing import List +class Solution: + def spiralOrder(self, matrix: List[List[int]])->List[int]: + arr = [] + left = 0 + right = len(matrix[0]) - 1 + top = 0 + down = len(matrix) - 1 + while True: + for i in range(left, right + 1): + arr.append(matrix[top][i]) + top += 1 + if top > down: + break + for i in range(top, down + 1): + arr.append(matrix[i][right]) + right -= 1 + if left > right: + break + for i in range(right, left - 1, -1): + arr.append(matrix[down][i]) + down -= 1 + if top > down: + break + for i in range(down, top - 1, -1): + arr.append(matrix[i][left]) + left += 1 + if left > right: + break + return arr +``` 我们仅仅是将 54 反过来了,往螺旋矩阵里面插值,下面我们直接看代码吧,大家可以也可以对其改进,大家可以思考一下,如果修改能够让代码更简洁! +Java Code: + ```java class Solution { public int[][] generateMatrix(int n) { @@ -147,3 +184,45 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +import numpy as np +class Solution: + def generateMatrix(self, n: int)->List[List[int]]: + arr = np.array([[0] * n] * n) + left = 0 + right = n - 1 + top = 0 + buttom = n - 1 + num = 1 + numsize = n * n + while True: + for i in range(left, right + 1): + arr[top][i] = num + num += 1 + top += 1 + if num > numsize: + break + for i in range(top, buttom + 1): + arr[i][right] = num + num += 1 + right -= 1 + if num > numsize: + break + for i in range(right, left - 1, -1): + arr[buttom][i] = num + num += 1 + buttom -= 1 + if num > numsize: + break + for i in range(buttom, top - 1, -1): + arr[i][left] = num + num += 1 + left += 1 + if num > numsize: + break + return arr.tolist() +``` + diff --git a/animation-simulation/数组篇/leetcode66加一.md b/animation-simulation/数组篇/leetcode66加一.md index e22be1b..3030fee 100644 --- a/animation-simulation/数组篇/leetcode66加一.md +++ b/animation-simulation/数组篇/leetcode66加一.md @@ -44,6 +44,8 @@ 我们可以根据当前位 余10来判断,这样我们就可以区分属于第几种情况了,大家直接看代码吧,很容易理解的。 +Java Code: + ```java class Solution { public int[] plusOne(int[] digits) { @@ -65,3 +67,21 @@ class Solution { } ``` +Python Code: + +```python +from typing import List +class Solution: + def plusOne(self, digits: List[int])->List[int]: + # 获取长度 + leng = len(digits) + for i in range(leng - 1, -1, -1): + digits[i] = (digits[i] + 1) % 10 + # 第一种和第二种情况,如果此时某一位不为 0 ,则直接返回即可。 + if digits[i] != 0: + return digits + # 第三种情况,因为数组初始化每一位都为0,我们只需将首位设为1即可 + arr = [0] * (leng + 1) + arr[0] = 1 + return arr +``` diff --git a/animation-simulation/数组篇/leetcode75颜色分类.md b/animation-simulation/数组篇/leetcode75颜色分类.md index c14b9ae..7f125f1 100644 --- a/animation-simulation/数组篇/leetcode75颜色分类.md +++ b/animation-simulation/数组篇/leetcode75颜色分类.md @@ -38,6 +38,8 @@ 下面我们直接看代码吧,和三向切分基本一致。 +Java Code: + ```java class Solution { public void sortColors(int[] nums) { @@ -65,6 +67,35 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def sortColors(self, nums: List[int]): + leng = len(nums) + left = 0 + # 这里和三向切分不完全一致 + i = left + right = leng - 1 + while i <= right: + if nums[i] == 2: + self.swap(nums, i, right) + right -= 1 + elif nums[i] == 0: + self.swap(nums, i, left) + i += 1 + left += 1 + else: + i += 1 + return nums + + def swap(self, nums: List[int], i: int, j: int): + temp = nums[i] + nums[i] = nums[j] + nums[j] = temp +``` + 另外我们看这段代码,有什么问题呢?那就是我们即使完全符合时,仍会交换元素,这样会大大降低我们的效率。 例如:[0,0,0,1,1,1,2,2,2] @@ -83,6 +114,8 @@ class Solution { 另一种代码表示 +Java Code: + ```java class Solution { public void sortColors(int[] nums) { @@ -114,3 +147,31 @@ class Solution { } ``` +Python3 Code: + +```python +from typing import List +class Solution: + def sortColors(self, nums: List[int]): + left = 0 + leng = len(nums) + right = leng - 1 + i = 0 + while i <= right: + if nums[i] == 0: + self.swap(nums, i, left) + left += 1 + if nums[i] == 2: + self.swap(nums, i, right) + right -= 1 + # 如果不等于 1 则需要继续判断,所以不移动 i 指针,i-- + if nums[i] != 1: + i -= 1 + i += 1 + return nums + + def swap(self, nums: List[int], i: int, j: int): + temp = nums[i] + nums[i] = nums[j] + nums[j] = temp +``` \ No newline at end of file diff --git a/animation-simulation/数组篇/剑指offer3数组中重复的数.md b/animation-simulation/数组篇/剑指offer3数组中重复的数.md index f817fdd..9d09871 100644 --- a/animation-simulation/数组篇/剑指offer3数组中重复的数.md +++ b/animation-simulation/数组篇/剑指offer3数组中重复的数.md @@ -45,6 +45,22 @@ class Solution { } ``` +Python Code: + +```python +from typing import List +class Solution: + def findRepeatNumber(self, nums: List[int])->int: + s = set() + for x in nums: + # 如果发现某元素存在,则返回 + if x in s: + return x + # 存入集合 + s.add(x) + return -1 +``` + #### **原地置换** **解析** @@ -101,3 +117,22 @@ public: }; ``` +Python3 Code: + +```python +from typing import List +class Solution: + def findRepeatNumber(self, nums: List[int])->int: + if len(nums) == 0: + return -1 + for i in range(0, len(nums)): + while nums[i] != i: + # 发现重复元素 + if nums[i] == nums[nums[i]]: + return nums[i] + # 置换,将指针下的元素换到属于它的索引处 + temp = nums[i] + nums[i] = nums[temp] + nums[temp] = temp + return -1 +``` diff --git a/animation-simulation/数组篇/长度最小的子数组.md b/animation-simulation/数组篇/长度最小的子数组.md index 2e88fb0..a4dc825 100644 --- a/animation-simulation/数组篇/长度最小的子数组.md +++ b/animation-simulation/数组篇/长度最小的子数组.md @@ -82,3 +82,27 @@ public: }; ``` +Python3 Code: + +```python +from typing import List +import sys +class Solution: + def minSubArrayLen(self, s: int, nums: List[int])->int: + leng = len(nums) + windowlen = sys.maxsize + i = 0 + sum = 0 + for j in range(0, leng): + sum += nums[j] + while sum >= s: + windowlen = min(windowlen, j - i + 1) + sum -= nums[i] + i += 1 + + if windowlen == sys.maxsize: + return 0 + else: + return windowlen +``` +