由于刷题也比较多了,现在开始每周二总结一下上周的每日一题的比较不错的题目。并且由于打算转后端,会附上java的代码。
- java 无sum函数
- java 中先进先出队列的实现
Queue<int[]> queue = new LinkedList<int []>()
queue.offer(new int[] {x,y})
- 判断是否空队列
!queue.isEmpty()
len = queue.size()
- java 中枚举
for (int [] dir:dis)
- java 中树类问题的解决方法
1. 410分割数组的最大值(最大化最小值)
猛地一看思路并不十分明显,好像题目要求我们找到一种具体的分割方法,然后这种方法满足一种特性。其实并不是的。我们的实际要求是找到一个bar
,这个bar是具有单调性的。这个子数组各自的和我们定义为target
,最小值定义为bar
。可以看出,当target >= bar
的情况下时,我们是可以容易(贪心)找到一种分割让子数组的和都小于bar
的。但是一但target<bar
则无法。
因此我们实际上可以用二分的思路。在区间[max(nums, sum(nums)]
之间寻找出来这个bar
。
# python
class Solution:
def splitArray(self, nums: List[int], m: int) -> int:
left, right = 0, sum(nums)
while left<=right:
mid = left+(right-left)//2
if self.isvalid(nums, mid, m):
right = mid-1
else:
left = mid+1
return left
def isvalid(self, nums, bar, m):
cur = 0
k = 1
for i in nums:
if cur+i<=bar:
cur += i
else:
k += 1
cur = i
if cur>bar:
return False
return k<=m
需要注意,java没有sum函数的,因此我们需要手动实现。
// java
class Solution {
public int splitArray(int[] nums, int m) {
int left = 0;
int right = 0;
for (int i = 0; i < nums.length; i++){
right += nums[i];
left = Math.max(left, nums[i]);
}
while (left<=right){
int mid = left + (right - left)/2;
if (check(nums, m, mid)){
right = mid - 1;
}
else{
left = mid + 1;
}
//System.out.println(mid);
}
return left;
}
private boolean check(int[] nums, int m, int bar){
int cur = 0;
for (int i = 0; i<nums.length; i++){
if (cur + nums[i] > bar){
m -= 1;
cur = nums[i];
}
else{
cur += nums[i];
}
}
return m-1 >= 0;
}
}
2. 329矩阵最长递增路径
基本思路是类似DP思路的一种BFS,但是需要提前处理好每个位置的入度。首先我们需要遍历一边数组,保存每个位置附近比自己大的数字的个数,也就是出度。这样如果出度为0,表示自己是周围最大的,可以作为起点,将该点压入队列。
然后,进行每次整体弹出的bfs,每次将队头点四周的点的出度减一,表示已经可以到达,当某周围节点的出度变为0时,表示该点周围大于它的点都被遍历了,可以入队了。最终返回整体出队的次数。
class Solution:
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
if not matrix:
return 0
n = len(matrix)
m = len(matrix[0])
queue = collections.deque()
ans = 0
outdegree = [[0]*(m) for _ in range(n)]
dis = [[0,1], [1,0],[0,-1], [-1,0]]
for i in range(n):
for j in range(m):
for mx, my in dis:
cx,cy = mx+i,my+j
if 0<=cx<n and 0<=cy<m and matrix[cx][cy]>matrix[i][j]:
outdegree[i][j] += 1
if outdegree[i][j] == 0:
queue.append((i,j))
while queue:
n1 = len(queue)
ans += 1
for i in range(n1):
x,y = queue.popleft()
for mx, my in dis:
cx, cy = x+mx, y+my
if 0<=cx<n and 0<=cy<m and matrix[cx][cy]<matrix[x][y]:
outdegree[cx][cy] -= 1
if outdegree[cx][cy] == 0:
queue.append((cx,cy))
return ans
class Solution {
public int longestIncreasingPath(int[][] matrix) {
if (matrix == null || matrix.length == 0 ||matrix[0].length == 0) return 0;
int n = matrix.length;
int m = matrix[0].length;
int[][] grid = new int[n][m];
int [][] dis = {{0,1}, {1,0}, {0,-1}, {-1,0}};
Queue<int[]> queue = new LinkedList<int[]>();
for (int i = 0; i < n; i++){
for (int j = 0; j<m; j++){
for (int [] dir:dis){
int mx = i+dir[0], my = j + dir[1];
if (0<=mx && n>mx && 0<=my && m>my&&matrix[mx][my]>matrix[i][j]){
grid[i][j]++;
}
}
if (grid[i][j] == 0) queue.offer(new int[] {i,j}); // 最大值
}
}
int ans = 0;
while (!queue.isEmpty()){
int len = queue.size();
ans ++;
for (int i = 0; i< len; i++){
int[] cell = queue.poll();
int cx = cell[0], cy = cell[1];
for (int[] dir:dis){
int mx = cx+dir[0], my = cy+dir[1];
if (0<=mx && n>mx && 0<=my && m>my && matrix[mx][my]<matrix[cx][cy]){
grid[mx][my]--;
if (grid[mx][my] == 0) queue.offer(new int[] {mx,my});
}
}
}
}
return ans;
}
}
3. 95不同的二叉搜索树
一道挺有意思的题目,要求生成不一样的二叉搜索树。其实考察的还是递归的思路,我们每次只考虑根节点为root = cur
,因此左侧可能的二叉树就是[star, cur-1]
这个区间内的二叉搜索树,右侧就是[cur+1, end]
这个区间里的二叉搜索树。最后进行组合即可。
class Solution:
def generateTrees(self, n: int) -> List[TreeNode]:
if n == 0:
return []
return self.helper(1, n)
def helper(self, star, end):
if end < star:
return [None] # 需要注意这里的边界条件,此时返回None对应的就是不存在,而不是返回空数组
ans = []
for i in range(star, end+1):
left = self.helper(star, i-1)
right = self.helper(i+1, end)
for item_l in left:
for item_r in right:
cur = TreeNode(i)
cur.left = item_l
cur.right = item_r
ans.append(cur)
return ans
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<TreeNode> generateTrees(int n) {
if (n == 0) return new LinkedList<TreeNode>();
return helper(1, n);
}
private List<TreeNode> helper(int star, int end){
List<TreeNode> all = new LinkedList<TreeNode>();
if (end<star){
all.add(null);
return all;
}
for (int i = star; i <= end; i++){
List<TreeNode> lefts = helper(star, i-1);
List<TreeNode> rights = helper(i+1, end);
for (TreeNode left:lefts){
for (TreeNode right:rights){
TreeNode cur = new TreeNode(i);
cur.left = left;
cur.right = right;
all.add(cur);
}
}
}
return all;
}
}