mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-12-27 04:46:17 +00:00
添加了python代码(数组篇)
为数组篇文件夹下的代码增加了python语言版本
This commit is contained in:
parent
4e661354d4
commit
7dd5ce1f3d
@ -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
|
||||
```
|
||||
|
||||
|
@ -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]
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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;
|
||||
|
@ -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 数组内,将值换到对应的索引处,与上个方法思路一致,只不过没有使用辅助数组,理解起来也稍微难理解一些。
|
||||
|
@ -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)
|
||||
```
|
||||
|
||||
|
||||
刚才的效率虽然相对高一些,但是代码不够优美,欢迎各位改进,下面我们说一下另外一种情况,一个特别容易理解的方法。
|
||||
|
@ -46,6 +46,8 @@
|
||||
|
||||
题目代码:
|
||||
|
||||
Java Code:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public List<Integer> 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
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -66,6 +66,8 @@
|
||||
|
||||
题目代码:
|
||||
|
||||
Java Code:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public List<Integer> 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()
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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
|
||||
```
|
@ -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
|
||||
```
|
||||
|
@ -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
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user