LeetCode 31-40题

 

正文

本博客记录的是 LeetCode 31 到 40 题的题解

之前很少使用的语法

reverse(nums.begin() + k, nums.end());
stk.top();
stk.size();
stk.pop();
t += to_string(k - j) + s[j]; // 注意 += 原地操作
nums.reverse()
nums.append(12)
x = nums.pop() #会返回数值
nums[-1]

31. Next Permutation

C++ code

class Solution {
public:
// 有点类似于找规律的题目,直接多写几个就可以找到规律了
void nextPermutation(vector<int>& nums) {
int n = nums.size(), l = nums.size() - 1, r = nums.size() - 1;
for (int i = n - 2; i >= 0; i -- ) {
if (nums[i] < nums[i + 1]) {
break;
}
l -= 1;
}
int i = l, j = r;
while (i < j) {
swap(nums[i], nums[j]);
i ++, j --;
}
if (l == 0) {
return;
} else {
for (int i = l; i <= r; i ++ ) {
if (nums[i] > nums[l - 1]) {
swap(nums[i], nums[l - 1]);
break;
}
}
}
}
};

STL写法

class Solution {
public:
// 有点类似于找规律的题目,直接多写几个就可以找到规律了
void nextPermutation(vector<int>& nums) {
int n = nums.size();
int k = n - 1;
while (k > 0 && nums[k - 1] >= nums[k]) k --;
if (k <= 0) {
reverse(nums.begin(), nums.end());
} else {
int t = k;
while (t + 1 < n && nums[k - 1] < nums[t + 1]) t += 1;
swap(nums[k - 1], nums[t]);
reverse(nums.begin() + k, nums.end());
}
}
};

python code

class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
l, r = n - 1, n - 1
for i in range(n - 2, -1, -1):
if nums[i] >= nums[i + 1]: # 这里需要有个等号
l -= 1
else:
break
i, j = l, r
while i < j:
nums[i], nums[j] = nums[j], nums[i]
i, j = i + 1, j - 1
if l == 0:
return
else:
print(nums)
for i in range(l, n):
if nums[i] > nums[l - 1]:
nums[i], nums[l - 1] = nums[l - 1], nums[i]
break
print(nums)
return

32. Longest Valid Parentheses

这个题目就是恶心在思路上,即使你能想到需要使用栈来解决到匹配问题,也很难想到上一个未匹配的括号位置,就是他丫的最大的匹配边界。
所以说,我们使用栈来记录他的'('位置,然后查看他所匹配的pop后的top位置,可以得知')'的最大匹配,然后更新res

c++代码

class Solution {
public:
int longestValidParentheses(string s) {
int res = 0, n = s.size();
stack<int> stk;
for (int i = 0, start = -1; i < n; i ++ ) {
if (s[i] == '(') stk.push(i);
else {
if (stk.size()) {
stk.pop();
if (stk.size()) {
res = max(res, i - stk.top());
} else {
res = max(res, i - start);
}
} else {
start = i;
}
}
}
return res;
}
};

python 代码

class Solution:
def longestValidParentheses(self, s: str) -> int:
n, start, res = len(s), -1, 0
stk = []
for i in range(n):
if s[i] == '(':
stk.append(i)
else:
if not stk:
start = i
else:
stk.pop()
if not stk:
res = max(res, i - start)
else:
res = max(res, i - stk[-1])
return res

33. Search in Rotated Sorted Array

两次二分,第一次是找旋转点,第二次是在有序数组中找target

c++代码

class Solution {
public:
int get_idx(vector<int>& nums, int l, int r, int target) {
int mid;
if (target > nums[r] || target < nums[l]){
return -1;
} else {
while (l < r) {
mid = l + r + 1 >> 1;
if (nums[mid] <= target) {
l = mid;
} else {
r = mid - 1;
}
}
if (nums[l] == target) {
return l;
} else {
return -1;
}
}
}
int search(vector<int>& nums, int target) {
// 首先,二分找分界点
int n = nums.size();
if (nums[0] <= nums[n - 1]) { // 没有旋转
return get_idx(nums, 0, n - 1, target);
} else { // 旋转了,需要二分找分界点 mid
int l = 0, r = n - 1, mid, x = nums[0];
while (l < r) {
mid = l + r >> 1;
if (nums[mid] < x) {
r = mid;
} else {
l = mid + 1;
}
}
printf("split mid=%d\n", l);
if (target > nums[n - 1]) {
return get_idx(nums, 0, l - 1, target);
} else {
return get_idx(nums, l, n - 1, target);
}
}
}
};

python 代码

class Solution:
def get_idx(self, nums, l, r, target):
if nums[l] > target or nums[r] < target:
return -1
while l < r:
mid = (l + r + 1) // 2
if nums[mid] <= target:
l = mid
else:
r = mid - 1
return l if nums[l] == target else -1
def search(self, nums: List[int], target: int) -> int:
n = len(nums)
if nums[0] <= nums[n - 1]: # no rotation
return self.get_idx(nums, 0, n - 1, target)
else:
l, r = 0, n - 1
while l < r:
mid = (l + r) // 2
if nums[mid] < nums[0]:
r = mid
else:
l = mid + 1
if nums[n - 1] >= target:
return self.get_idx(nums, l, n - 1, target)
else:
return self.get_idx(nums, 0, l - 1, target)

34. Find First and Last Position of Element in Sorted Array

二分查找的基础题目

c++ 代码

class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> res;
if (nums.size() <= 0) {
return vector<int>{-1, -1};
}
int x = target;
int l, r, mid, n = nums.size();
l = 0, r = n - 1;
// 大于等于 x 的最小值
while (l < r) {
mid = l + r >> 1;
if (nums[mid] >= x) {
r = mid;
} else {
l = mid + 1;
}
}
int res1, res2;
if (nums[l] != target) {
return vector<int> {-1, -1};
}
res.push_back(l);
// 小于等于 x 的最大值
l = 0, r = n - 1;
while (l < r) {
mid = l + r + 1 >> 1;
if (nums[mid] <= x) {
l = mid;
} else {
r = mid - 1;
}
}
res.push_back(l);
return res;
}
};

python 代码

class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
if n == 0 or target > nums[-1] or target < nums[0]:
return [-1, -1]
# higher target min value
l, r = 0, n - 1
while l < r:
mid = (l + r) // 2
if nums[mid] >= target:
r = mid
else:
l = mid + 1
if nums[l] != target:
return [-1, -1]
res = [l]
# lower target max value
l, r = 0, n - 1
while l < r:
mid = (l + r + 1) // 2
if nums[mid] <= target:
l = mid
else:
r = mid - 1
res.append(l)
return res

35. Search Insert Position

就是寻找大于等于 target 的最小值所在的位置,相当于 34 题一半的代码量

class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
# 寻找大于等于 target 的最小值所在的位置
n = len(nums)
if nums[-1] < target:
return n
l, r = 0, n - 1
while l < r:
mid = (l + r) // 2
if nums[mid] >= target:
r = mid
else:
l = mid + 1
return l

36. Valid Sudoku

按照数独给出的3条规则进行暴力模拟即可
python 代码

class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
visited = [False] * 12
for i in range(9):
for k in range(10):
visited[k] = False
for j in range(9):
if board[i][j] == '.':
continue
elif visited[int(board[i][j])] == True:
return False
else:
visited[int(board[i][j])] = True
for k in range(10):
visited[k] = False
for j in range(9):
if board[j][i] == '.':
continue
elif visited[int(board[j][i])] == True:
return False
else:
visited[int(board[j][i])] = True
for i in range(0, 7, 3):
for j in range(0, 7, 3):
for k in range(10):
visited[k] = False
for u in range(3):
for v in range(3):
if board[i+u][j+v] == '.':
continue
elif visited[int(board[i+u][j+v])] == True:
return False
else:
visited[int(board[i+u][j+v])] = True
return True

37. Sudoku Solver

暴力 DFS即可,不过需要提前打好表(行列以及小3X3矩阵)进行加速

class Solution:
def solveSudoku(self, a: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
rows = [[False] * 10 for i in range(10)]
cols = [[False] * 10 for i in range(10)]
place = [[[False] * 10 for i in range(4)] for j in range(4)]
for i in range(9):
for j in range(9):
if a[i][j] == '.':
continue
else:
rows[i][int(a[i][j])] = True
cols[j][int(a[i][j])] = True
place[i//3][j//3][int(a[i][j])] = True
self.dfs(0, 0, a, rows, cols, place)
def dfs(self, i, j, a, rows, cols, place):
if i >= 9:
return True
if a[i][j] != '.':
if j == 8:
return self.dfs(i + 1, 0, a, rows, cols, place)
else:
return self.dfs(i, j + 1, a, rows, cols, place)
for u in range(1, 10):
if rows[i][u] == False and cols[j][u] == False and place[i//3][j//3][u] == False:
rows[i][u] = cols[j][u] = place[i//3][j//3][u] = True
a[i][j] = str(u)
if j == 8:
if self.dfs(i + 1, 0, a, rows, cols, place):
return True
elif self.dfs(i, j + 1, a, rows, cols, place):
return True
rows[i][u] = cols[j][u] = place[i//3][j//3][u] = False
a[i][j] = '.'
return False

38. Count and Say

就是查找数字,进行模拟

class Solution {
public:
string countAndSay(int n) {
string s = "1";
for (int i = 2; i <= n; i ++ ) {
string t = "";
for (int j = 0; j < s.size();) {
int k = j + 1;
while (k < s.size() && s[k] == s[j]) k ++;
t += to_string(k - j) + s[j]; // 注意 += 原地操作
j = k;
}
s = t;
}
return s;
}
};
class Solution:
def countAndSay(self, n: int) -> str:
x = '1'
for i in range(1, n):
x += ' '
y = ''
cnt = 1
for j in range(1, len(x)):
if x[j] == x[j - 1]:
cnt += 1
else:
y += str(cnt) + x[j - 1]
cnt = 1
x = y
# print(f"cnt={i+1}, x={x}")
return x

39. Combination Sum

完全背包板子题

class Solution:
def combinationSum(self, t: List[int], m: int) -> List[List[int]]:
f = [[False] * 510 for i in range(40)]
f[0][0] = True
n = len(t)
a = [0]
a.extend(t)
print(a)
for i in range(1, n + 1):
for j in range(0, m + 1):
if j < a[i]:
f[i][j] = f[i - 1][j]
else:
f[i][j] = (f[i - 1][j] or f[i][j - a[i]])
if f[n][m] == False:
return []
res = []
tmp = []
self.dfs(n, m, a, f, tmp, res)
return res
def dfs(self, i, j, a, f, tmp, res):
if j == 0:
print(tmp)
res.append(tmp[:]) # 注意,这里需要是[:],不然dfs会修改他的共享内存
return
if j >= a[i] and f[i][j - a[i]] == True:
tmp.append(a[i])
self.dfs(i, j - a[i], a, f, tmp, res)
tmp.pop()
if i >= 1 and f[i - 1][j] == True:
self.dfs(i - 1, j, a, f, tmp, res)

40. Combination Sum II

感觉这个题目出的比较恶心,算法不难,但是出题人有意把你往01背包上绕,但是01背包很难解决方案输出不重复的这个问题,因为它将每一个物品都作为独一无二的,即使他们的 数值一样
所以说,这个题目还是作为多重背包比较好,将 candidate 数组处理成为 unique独一无二的数字配上他出现的次数 cnt 进行多重背包。
但是这个多重背包无法使用 二进制优化,否则还是会出现类似于01背包的问题,解决方案不重复这个问题仍会出现,并很难在时限内解决。
当然也可以直接暴搜

// c++暴搜
class Solution {
public:
vector<vector<int> > ans;
vector<int> path;
vector<vector<int>> combinationSum2(vector<int>& cs, int target) {
sort(cs.begin(), cs.end());
dfs(0, cs, target);
return ans;
}
void dfs(int i, vector<int> &cs, int target) {
if (target == 0) {
ans.push_back(path);
return;
}
if (i == cs.size()) {
return;
}
int j = i + 1;
while (j < cs.size() && cs[i] == cs[j]) j ++;
int cnt = j - i;
for (int k = 0; k <= cnt && target >= k * cs[i]; k ++ ) {
if (k) // 注意这个 if k
path.push_back(cs[i]);
dfs(j, cs, target - k * cs[i]);
}
for (int k = 1; k <= cnt && target >= k * cs[i]; k ++ )
path.pop_back();
}
};
# python 多重背包
class Solution:
def combinationSum2(self, a: List[int], m: int) -> List[List[int]]:
# 预处理成多重背包
s = [0] * len(a)
a.sort()
j, s[0], n = 1, 1, len(a)
for i in range(1, n):
if a[i] == a[i - 1]:
s[j - 1] += 1
else:
a[j] = a[i]
s[j] = 1
j += 1
for i in range(j, n):
s.pop()
a.pop()
# dp
f = [[False] * 40 for i in range(110)]
f[0][0] = True
n = len(a)
for i in range(1, n + 1):
for j in range(m + 1):
k, f[i][j] = 1, f[i - 1][j]
while f[i][j] == False and j >= k * a[i - 1] and k <= s[i - 1]:
f[i][j] = f[i - 1][j - k * a[i - 1]]
k += 1
if not f[n][m]:
return []
res, tmp = [], []
self.dfs(n, m, a, s, f, res, tmp)
return res
def dfs(self, i, j, a, s, f, res, tmp):
if j == 0: # recursion ending
res.append(tmp[:])
return
for k in range(0, s[i - 1] + 1): # count
if j >= k * a[i - 1]:
if f[i - 1][j - k * a[i - 1]]: # True
tmp.extend([a[i - 1]] * k)
self.dfs(i - 1, j - k * a[i - 1], a, s, f, res, tmp)
for u in range(k):
tmp.pop()
else:
break
return
posted @   lucky_light  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示