这是一篇灌水的博客。
今天收到了华为2012实验室的面试通知,HR老师说手撕代码很重要,遂在LeetCode上进行了一次华为题库的模拟面试,下面是这次模拟面试的三道题目。
华为的面试一般要求在记事本中写代码,有时也会要求在纸上写代码,所以建议大家在练习的时候尽量还是不要在本地IDE写代码。像这种模拟面试尽量还是直接在LeetCode的网页上编写程序。
面试结果:全部通过
总时长:1 小时 30 分
耗时:46 分 19 秒
答题数:3/3
一、二叉搜索树转化为累加和
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node
的新值等于原树中大于或等于 node.val
的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
**注意:**本题和 1038: https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/ 相同
示例 1:
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
示例 2:
输入:root = [0,null,1]
输出:[1,null,1]
示例 3:
输入:root = [1,0,2]
输出:[3,3,2]
示例 4:
输入:root = [3,2,4,1]
输出:[7,9,4,10]
提示:
- 树中的节点数介于
0
和104
之间。 - 每个节点的值介于
-104
和104
之间。 - 树中的所有值 互不相同 。
- 给定的树为二叉搜索树。
我的解法
树中的节点根据值从大到小的顺序依次改变就可以了。二叉树的三个遍历中,中序遍历是按照排序顺序的,不过这里需要先遍历右孩子,最后遍历左孩子。整个过程需要遍历所有的节点一次,所以时间复杂度为 O ( n ) O(n) O(n)。具体的代码如下所示
/**
* 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 TreeNode convertBST(TreeNode root) {
if(root==null){
return root;
}
convertBST(root, 0);
return root;
}
private int convertBST(TreeNode root, int base){
if(root.right==null){
root.val = root.val + base;
base = root.val;
}else{
base = convertBST(root.right, base);
root.val = root.val + base;
base = root.val;
}
if(root.left!=null){
base = convertBST(root.left, base);
}
return base;
}
}
二、 最大的以1为边界的正方形
给你一个由若干 0
和 1
组成的二维网格 grid
,请你找出边界全部由 1
组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0
。
示例 1:
输入:grid = [[1,1,1],[1,0,1],[1,1,1]]
输出:9
示例 2:
输入:grid = [[1,1,0,0]]
输出:1
提示:
1 <= grid.length <= 100
1 <= grid[0].length <= 100
grid[i][j]
为0
或1
我的解法
这道题没有想到太好的解法,写了个大遍历,只是在遍历的时候先判断目标正方向的最左上和最右下位置的元素,并且只考察比当前最大正方形更大的正方形,来起到一个剪枝的作用。这个算法的时间复杂度的分析比较复杂。下面是具体的Java程序实现
class Solution {
public int largest1BorderedSquare(int[][] grid) {
int n = grid.length;
int m = grid[0].length;
if(n==0 || m==0){
return 0;
}
int max = -1;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(grid[i][j]==1){
max = 0;
break;
}
}
}
if(max==-1){
return 0;
}
for(int i=0; i+max<n; i++){
for(int j=0; j+max<m; j++){
int b = Math.min(n-i, m-j)-1;
for(int max1=max; max1<=b; max1++){
if(grid[i][j]==1 && grid[i+max1][j+max1]==1){
boolean flag = true;
for(int k=0; k<=max1; k++){
if(grid[i][j+k]==0 || grid[i+max1][j+k]==0 ||
grid[i+k][j]==0 || grid[i+k][j+max1]==0){
flag = false;
break;
}
}
if(flag){
max = max1;
}
}
}
}
}
return (max+1)*(max+1);
}
}
三、串联所有单词的子串
给定一个字符串 s 和一些长度相同的单词 **words。**找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]
我的解法
看到这道题的时候,一度想放弃,因为没有想到什么巧妙的解法。最后也是用了一个大暴力的方法,最后提交到LeetCode系统结果显示运行时间1500多毫秒。下面是具体的Java程序实现
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new LinkedList<>();
int n = s.length();
int k = words.length;
if(n==0 || k==0 || n<k){
return res;
}
int m = words[0].length();
if(m==0){
return res;
}
for(int i=0; i+k*m<=n; i++){
int[] visited = new int[k];
int ptr = i;
while(ptr<n){
boolean flag = false;
for(int j=0; j<k; j++){
if(visited[j]==0 && words[j].equals(s.substring(ptr, ptr+m))){
visited[j] = 1;
ptr += m;
flag = true;
break;
}
}
if(!flag){
break;
}
}
if(ptr==i+k*m){
res.add(i);
}
}
return res;
}
}