mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
**/.DS_Store
|
|
@ -247,6 +247,24 @@ class Solution:
|
|||||||
|
|
||||||
### Go:
|
### Go:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// 暴力法
|
||||||
|
// 时间复杂度 O(n^2)
|
||||||
|
// 空间复杂度 O(1)
|
||||||
|
func removeElement(nums []int, val int) int {
|
||||||
|
size := len(nums)
|
||||||
|
for i := 0; i < size; i ++ {
|
||||||
|
if nums[i] == val {
|
||||||
|
for j := i + 1; j < size; j ++ {
|
||||||
|
nums[j - 1] = nums[j]
|
||||||
|
}
|
||||||
|
i --
|
||||||
|
size --
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
```
|
||||||
```go
|
```go
|
||||||
// 快慢指针法
|
// 快慢指针法
|
||||||
// 时间复杂度 O(n)
|
// 时间复杂度 O(n)
|
||||||
@ -289,7 +307,6 @@ func removeElement(nums []int, val int) int {
|
|||||||
right--
|
right--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println(nums)
|
|
||||||
return left
|
return left
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -440,6 +440,33 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
双指针优化
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int trap(int[] height) {
|
||||||
|
if (height.length <= 2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 从两边向中间寻找最值
|
||||||
|
int maxLeft = height[0], maxRight = height[height.length - 1];
|
||||||
|
int l = 1, r = height.length - 2;
|
||||||
|
int res = 0;
|
||||||
|
while (l <= r) {
|
||||||
|
// 不确定上一轮是左边移动还是右边移动,所以两边都需更新最值
|
||||||
|
maxLeft = Math.max(maxLeft, height[l]);
|
||||||
|
maxRight = Math.max(maxRight, height[r]);
|
||||||
|
// 最值较小的一边所能装的水量已定,所以移动较小的一边。
|
||||||
|
if (maxLeft < maxRight) {
|
||||||
|
res += maxLeft - height[l ++];
|
||||||
|
} else {
|
||||||
|
res += maxRight - height[r --];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
单调栈法
|
单调栈法
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -285,6 +285,24 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
状态压缩
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int uniquePaths(int m, int n) {
|
||||||
|
// 在二维dp数组中,当前值的计算只依赖正上方和正左方,因此可以压缩成一维数组。
|
||||||
|
int[] dp = new int[n];
|
||||||
|
// 初始化,第一行只能从正左方跳过来,所以只有一条路径。
|
||||||
|
Arrays.fill(dp, 1);
|
||||||
|
for (int i = 1; i < m; i ++) {
|
||||||
|
// 第一列也只有一条路,不用迭代,所以从第二列开始
|
||||||
|
for (int j = 1; j < n; j ++) {
|
||||||
|
dp[j] += dp[j - 1]; // dp[j] = dp[j] (正上方)+ dp[j - 1] (正左方)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Python
|
### Python
|
||||||
递归
|
递归
|
||||||
|
@ -287,9 +287,6 @@ class Solution {
|
|||||||
return dp[1];
|
return dp[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
|
||||||
```Java
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Python:
|
### Python:
|
||||||
|
@ -218,7 +218,7 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Python:
|
### Python:
|
||||||
|
解法一:
|
||||||
```python
|
```python
|
||||||
#时间复杂度:O(nlogk)
|
#时间复杂度:O(nlogk)
|
||||||
#空间复杂度:O(n)
|
#空间复杂度:O(n)
|
||||||
@ -246,6 +246,31 @@ class Solution:
|
|||||||
result[i] = heapq.heappop(pri_que)[1]
|
result[i] = heapq.heappop(pri_que)[1]
|
||||||
return result
|
return result
|
||||||
```
|
```
|
||||||
|
解法二:
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
|
||||||
|
# 使用字典统计数字出现次数
|
||||||
|
time_dict = defaultdict(int)
|
||||||
|
for num in nums:
|
||||||
|
time_dict[num] += 1
|
||||||
|
# 更改字典,key为出现次数,value为相应的数字的集合
|
||||||
|
index_dict = defaultdict(list)
|
||||||
|
for key in time_dict:
|
||||||
|
index_dict[time_dict[key]].append(key)
|
||||||
|
# 排序
|
||||||
|
key = list(index_dict.keys())
|
||||||
|
key.sort()
|
||||||
|
result = []
|
||||||
|
cnt = 0
|
||||||
|
# 获取前k项
|
||||||
|
while key and cnt != k:
|
||||||
|
result += index_dict[key[-1]]
|
||||||
|
cnt += len(index_dict[key[-1]])
|
||||||
|
key.pop()
|
||||||
|
|
||||||
|
return result[0: k]
|
||||||
|
```
|
||||||
|
|
||||||
### Go:
|
### Go:
|
||||||
|
|
||||||
|
@ -173,6 +173,63 @@ class Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
> 修改遍历顺序后,可以利用滚动数组,对dp数组进行压缩
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public boolean isSubsequence(String s, String t) {
|
||||||
|
// 修改遍历顺序,外圈遍历t,内圈遍历s。使得dp的推算只依赖正上方和左上方,方便压缩。
|
||||||
|
int[][] dp = new int[t.length() + 1][s.length() + 1];
|
||||||
|
for (int i = 1; i < dp.length; i++) { // 遍历t字符串
|
||||||
|
for (int j = 1; j < dp[i].length; j++) { // 遍历s字符串
|
||||||
|
if (t.charAt(i - 1) == s.charAt(j - 1)) {
|
||||||
|
dp[i][j] = dp[i - 1][j - 1] + 1;
|
||||||
|
} else {
|
||||||
|
dp[i][j] = dp[i - 1][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(Arrays.toString(dp[i]));
|
||||||
|
}
|
||||||
|
return dp[t.length()][s.length()] == s.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> 状态压缩
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public boolean isSubsequence(String s, String t) {
|
||||||
|
int[] dp = new int[s.length() + 1];
|
||||||
|
for (int i = 0; i < t.length(); i ++) {
|
||||||
|
// 需要使用上一轮的dp[j - 1],所以使用倒序遍历
|
||||||
|
for (int j = dp.length - 1; j > 0; j --) {
|
||||||
|
// i遍历的是t字符串,j遍历的是dp数组,dp数组的长度比s的大1,因此需要减1。
|
||||||
|
if (t.charAt(i) == s.charAt(j - 1)) {
|
||||||
|
dp[j] = dp[j - 1] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[s.length()] == s.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> 将dp定义为boolean类型,dp[i]直接表示s.substring(0, i)是否为t的子序列
|
||||||
|
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public boolean isSubsequence(String s, String t) {
|
||||||
|
boolean[] dp = new boolean[s.length() + 1];
|
||||||
|
// 表示 “” 是t的子序列
|
||||||
|
dp[0] = true;
|
||||||
|
for (int i = 0; i < t.length(); i ++) {
|
||||||
|
for (int j = dp.length - 1; j > 0; j --) {
|
||||||
|
if (t.charAt(i) == s.charAt(j - 1)) {
|
||||||
|
dp[j] = dp[j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[dp.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Python:
|
### Python:
|
||||||
|
|
||||||
|
@ -186,7 +186,23 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
> 动态规划状态压缩
|
||||||
|
```java
|
||||||
|
class Solution {
|
||||||
|
public int findLengthOfLCIS(int[] nums) {
|
||||||
|
// 记录以 前一个元素结尾的最长连续递增序列的长度 和 以当前 结尾的......
|
||||||
|
int beforeOneMaxLen = 1, currentMaxLen = 0;
|
||||||
|
// res 赋最小值返回的最小值1
|
||||||
|
int res = 1;
|
||||||
|
for (int i = 1; i < nums.length; i ++) {
|
||||||
|
currentMaxLen = nums[i] > nums[i - 1] ? beforeOneMaxLen + 1 : 1;
|
||||||
|
beforeOneMaxLen = currentMaxLen;
|
||||||
|
res = Math.max(res, currentMaxLen);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
> 贪心法:
|
> 贪心法:
|
||||||
|
|
||||||
```Java
|
```Java
|
||||||
|
@ -244,6 +244,24 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```Java
|
||||||
|
// 状态压缩,使用三个变量来代替数组
|
||||||
|
class Solution {
|
||||||
|
public int minCostClimbingStairs(int[] cost) {
|
||||||
|
// 以下三个变量分别表示前两个台阶的最少费用、前一个的、当前的。
|
||||||
|
int beforeTwoCost = 0, beforeOneCost = 0, currentCost = 0;
|
||||||
|
// 前两个台阶不需要费用就能上到,因此从下标2开始;因为最后一个台阶需要跨越,所以需要遍历到cost.length
|
||||||
|
for (int i = 2; i <= cost.length; i ++) {
|
||||||
|
// 此处遍历的是cost[i - 1],不会越界
|
||||||
|
currentCost = Math.min(beforeOneCost + cost[i - 1], beforeTwoCost + cost[i - 2]);
|
||||||
|
beforeTwoCost = beforeOneCost;
|
||||||
|
beforeOneCost = currentCost;
|
||||||
|
}
|
||||||
|
return currentCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Python
|
### Python
|
||||||
|
|
||||||
动态规划(版本一)
|
动态规划(版本一)
|
||||||
|
@ -146,17 +146,42 @@ for (int i = 0; i < a.size(); i++) {
|
|||||||
```java
|
```java
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
|
||||||
Scanner in = new Scanner(System.in);
|
public static String replaceNumber(String s) {
|
||||||
String s = in.nextLine();
|
int count = 0; // 统计数字的个数
|
||||||
StringBuilder sb = new StringBuilder();
|
int sOldSize = s.length();
|
||||||
for (int i = 0; i < s.length(); i++) {
|
for (int i = 0; i < s.length(); i++) {
|
||||||
if (Character.isDigit(s.charAt(i))) {
|
if(Character.isDigit(s.charAt(i))){
|
||||||
sb.append("number");
|
count++;
|
||||||
}else sb.append(s.charAt(i));
|
}
|
||||||
}
|
}
|
||||||
System.out.println(sb);
|
// 扩充字符串s的大小,也就是每个空格替换成"number"之后的大小
|
||||||
|
char[] newS = new char[s.length() + count * 5];
|
||||||
|
int sNewSize = newS.length;
|
||||||
|
// 将旧字符串的内容填入新数组
|
||||||
|
System.arraycopy(s.toCharArray(), 0, newS, 0, sOldSize);
|
||||||
|
// 从后先前将空格替换为"number"
|
||||||
|
for (int i = sNewSize - 1, j = sOldSize - 1; j < i; j--, i--) {
|
||||||
|
if (!Character.isDigit(newS[j])) {
|
||||||
|
newS[i] = newS[j];
|
||||||
|
} else {
|
||||||
|
newS[i] = 'r';
|
||||||
|
newS[i - 1] = 'e';
|
||||||
|
newS[i - 2] = 'b';
|
||||||
|
newS[i - 3] = 'm';
|
||||||
|
newS[i - 4] = 'u';
|
||||||
|
newS[i - 5] = 'n';
|
||||||
|
i -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String(newS);
|
||||||
|
};
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Scanner scanner = new Scanner(System.in);
|
||||||
|
String s = scanner.next();
|
||||||
|
System.out.println(replaceNumber(s));
|
||||||
|
scanner.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
Reference in New Issue
Block a user