Leetcode面T17(11-20)树

返回转换后的单向链表的头节点。

注意:本题相对原题稍作改动

示例:

输入: [4,2,5,1,3,null,6,0]

输出: [0,null,1,null,2,null,3,null,4,null,5,null,6]

提示:

节点数量不会超过 100000。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/binode-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

简单的递归,借用一个先驱节点当做链表一样

/**

  • Definition for a binary tree node.

  • public class TreeNode {

  • int val;
    
  • TreeNode left;
    
  • TreeNode right;
    
  • TreeNode(int x) { val = x; }
    
  • }

*/

class Solution {

TreeNode f;

public TreeNode convertBiNode(TreeNode root) {

f = new TreeNode(Integer.MIN_VALUE);

TreeNode pre = f;

dfs(root);

return pre.right;

}

public void dfs(TreeNode root) {

if (root == null) return;

dfs(root.left);

f.right = root;

root.left = null;

f = f.right;

dfs(root.right);

}

}

Q17.13 恢复空格

哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。像句子"I reset the computer. It still didn’t boot!“已经变成了"iresetthecomputeritstilldidntboot”。在处理标点符号和大小写之前,你得先把它断成词语。当然了,你有一本厚厚的词典dictionary,不过,有些词没在词典里。假设文章用sentence表示,设计一个算法,把文章断开,要求未识别的字符最少,返回未识别的字符数。

注意:本题相对原题稍作改动,只需返回未识别的字符数

示例:

输入:

dictionary = [“looked”,“just”,“like”,“her”,“brother”]

sentence = “jesslookedjustliketimherbrother”

输出: 7

解释: 断句后为"jess looked just like tim her brother",共7个未识别字符。

提示:

0 <= len(sentence) <= 1000

dictionary中总字符数不超过 150000。

你可以认为dictionary和sentence中只包含小写字母。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/re-space-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:直接求最少匹配的字符数比较复杂,所以反过来我们求能匹配的最大字符数。这道题相当于一个 完全0-1背包问题,背包容量为字符串长度,物品(字典中的单词)数量没有限制。我们要做的就是尽可能的填满这个背包。

1.定义状态: dp[i][j] 表示字符串(0i),字典(0i)的状态下,匹配的最大字符数。

2.状态转移:从背包末尾开始考虑:

当单词能塞进背包末尾的时候,即 sentence.substring(i-len,i) 与 当前单词相等,len 为单词长度。此时单词有两种状态,塞进背包,和不塞进背包,记住单词可以重复取用,取这两种状态的最大值:dp[i][j] = max(dp[i-len][j]+len,dp[i][j-1])。

当单词不能塞进背包末尾的时候,取字符串(0~i-1)与当前单词的组合dp[i-1][j],和当前字符串与前一个单词组合dp[i][j-1]这两种组合的最大值。即:dp[i][j] = max(dp[i-1][j],dp[i][j-1]).

3.返回值:sentence.length() - dp[m][n];

4.状态压缩:二维dp数组可以压缩为一维数组。

5.如果有帮到您,请不吝啬点赞~

class Solution {

public int respace(String[] dictionary, String sentence) {

int m = sentence.length();

int[] dp = new int[m+1];

for(int i=1;i<=m;i++){ //外层循环字符串

for(String word:dictionary){ //内层循环字典

int len = word.length();

if(i >= len && word.equals(sentence.substring(i-len,i))){

dp[i] = Math.max(dp[i],dp[i-len]+len); //状态转移

}else{

dp[i] = Math.max(dp[i],dp[i-1]);

}

}

}

return m-dp[m];

}

}

Q17.14 最小K个数

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4

输出: [1,2,3,4]

提示:

0 <= len(arr) <= 100000

0 <= k <= min(100000, len(arr))

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/smallest-k-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

快速排序递归版

class Solution {

public int[] smallestK(int[] arr, int k) {

select(arr, 0, arr.length - 1, k);

int[] ans = new int[k];

System.arraycopy(arr, 0, ans, 0, k);

return ans;

}

public void select(int[] arr, int p, int q, int k) {

if (p >= q) return;

int l = p, r = q;

int m = arr[p];

while (l < r) {

while (l < r && arr[r] >= m) {

r–;

}

arr[l] = arr[r];

while (l < r && arr[l] <= m) {

l++;

}

arr[r] = arr[l];

}

arr[l] = m;

int t = l - p + 1;

if (t == k) return;

if (t < k) {

select(arr, l + 1, q, k - t);

} else {

select(arr, p, l - 1, k);

}

}

}

Q17.15 最长单词

给定一组单词words,编写一个程序,找出其中的最长单词,且该单词由这组单词中的其他单词组合而成。若有多个长度相同的结果,返回其中字典序最小的一项,若没有符合要求的单词则返回空字符串。

示例:

输入: [“cat”,“banana”,“dog”,“nana”,“walk”,“walker”,“dogwalker”]

输出: “dogwalker”

解释: "dogwalker"可由"dog"和"walker"组成。

提示:

0 <= len(words) <= 200

1 <= len(words[i]) <= 100

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/longest-word-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路简单:

按照长度降序排序,如果长度相等就按照字典序排序。这样的话如果每个单词都是组合单词,那么最前面的单词就是题目要求的返回单词。

遍历排序后的单词数组,如果是复合单词就返回

复合单词检测思路: 目标单词的前i个字母是单词列表里面的单词 && 剩下的字母是组合单词

class Solution {

// 检测word是否是由set里面的单词组成

private boolean isComposeWord(Set set, String word) {

if (word.length() == 0) {

return true;

}

for (int i = 0; i < word.length(); i++) {

if (set.contains(word.substring(0, i + 1)) && isComposeWord(set, word.substring(i + 1))) {

return true;

}

}

return false;

}

public String longestWord(String[] words) {

// 将单词列表按照长度降序,长度相同按照字典序

Arrays.sort(words, (o1, o2) -> {

if (o1.length() == o2.length()) {

return o1.compareTo(o2);

} else {

return Integer.compare(o2.length(), o1.length());

}

});

// 把数组做成set,提高检测的效率

Set set = new HashSet<>(Arrays.asList(words));

// 遍历检测当前单词是不是组合单词,是的话直接返回

for (String word :words ) {

set.remove(word);

if (isComposeWord(set, word)) {

return word;

}

set.add(word);

}

return “”;

}

}

Q17.16 按摩师

一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

注意:本题相对原题稍作改动

示例 1:

输入: [1,2,3,1]

输出: 4

解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。

示例 2:

输入: [2,7,9,3,1]

输出: 12

解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。

示例 3:

输入: [2,1,4,5,3,1,1,3]

输出: 12

解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/the-masseuse-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

递推方程:dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])

class Solution {

public int massage(int[] nums) {

int n = nums.length;

if (n == 0) {

return 0;

}

if (n == 1) {

return nums[0];

}

int[] dp = new int[n];

dp[0] = nums[0];

dp[1] = Math.max(nums[0], nums[1]);

for (int i = 2; i < n; i++) {

dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);

}

return dp[n - 1];

}

}

Q17.17 多次搜索

给定一个较长字符串big和一个包含较短字符串的数组smalls,设计一个方法,根据smalls中的每一个较短字符串,对big进行搜索。输出smalls中的字符串在big里出现的所有位置positions,其中positions[i]为smalls[i]出现的所有位置。

示例:

输入:

big = “mississippi”

smalls = [“is”,“ppi”,“hi”,“sis”,“i”,“ssippi”]

输出: [[1,4],[8],[],[3],[1,4,7,10],[5]]

提示:

0 <= len(big) <= 1000

0 <= len(smalls[i]) <= 1000

smalls的总字符数不会超过 100000。

你可以认为smalls中没有重复字符串。

所有出现的字符均为英文小写字母。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/multi-search-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

public int[][] multiSearch(String big, String[] smalls) {

if (smalls == null || big == null || smalls.length == 0) return new int[0][];

List<List> tempRes = new LinkedList<>();

for (String small : smalls) {

List tmp = new LinkedList<>();

if (small.length() == 0) {

tempRes.add(tmp);

continue;

}

int index = 0;

while (index < big.length() && big.indexOf(small, index) != -1) {

int pos = big.indexOf(small, index);

tmp.add(pos);

index = pos + 1;

}

tempRes.add(tmp);

}

int[][] res = new int[tempRes.size()][];

for (int i = 0; i < res.length; i++) {

int[] ints = new int[tempRes.get(i).size()];

for (int i1 = 0; i1 < ints.length; i1++) {

ints[i1] = tempRes.get(i).get(i1);

}

res[i] = ints;

}

return res;

}

Q17.18 最短超串

假设你有两个数组,一个长一个短,短的元素均不相同。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。

返回最短子数组的左端点和右端点,如有多个满足条件的子数组,返回左端点最小的一个。若不存在,返回空数组。

示例 1:

输入:

big = [7,5,9,0,2,1,3,5,7,9,1,1,5,8,8,9,7]

small = [1,5,9]

输出: [7,10]

示例 2:

输入:

big = [1,2,3]

small = [4]

输出: []

提示:

big.length <= 100000

1 <= small.length <= 100000

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/shortest-supersequence-lcci

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

滑动窗口

class Solution {

public int[] shortestSeq(int[] big, int[] small) {

Map<Integer,Integer> window = new HashMap<>(); //window记录窗口内元素的情况

Set set = new HashSet<>(); //set作为查找表

for(int e : small)

set.add(e);

int[] res = {big.length,big.length};

int minLen = big.length + 1;

for(int l=0,r=0;r<big.length;r++) {

if(set.contains(big[r])) //考虑big[r]要不要进窗口【在set中的值才允许进入】

window.put(big[r],window.getOrDefault(big[r],0)+1);

while(window.size()==set.size()) { //当窗口符合要求,左边界收缩,注意要不要更新window

if(set.contains(big[l])) { //此时,需要更新window

int n = window.get(big[l]);

if(n==1) {

window.remove(big[l]); //。。。

if(r-l+1<minLen) { //看要不要更新答案

res[0] = l;

res[1] = r;

minLen = r-l+1;

}

}else {

window.put(big[l],n-1);

}

最后

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

Android 基础知识点

Java 基础知识点

Android 源码相关分析

常见的一些原理性问题

希望大家在今年一切顺利,进到自己想进的公司,共勉!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
e(window.size()==set.size()) { //当窗口符合要求,左边界收缩,注意要不要更新window

if(set.contains(big[l])) { //此时,需要更新window

int n = window.get(big[l]);

if(n==1) {

window.remove(big[l]); //。。。

if(r-l+1<minLen) { //看要不要更新答案

res[0] = l;

res[1] = r;

minLen = r-l+1;

}

}else {

window.put(big[l],n-1);

}

最后

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

Android 基础知识点

Java 基础知识点

Android 源码相关分析

常见的一些原理性问题

[外链图片转存中…(img-cI1NcD3U-1715789720599)]

希望大家在今年一切顺利,进到自己想进的公司,共勉!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值