跟着博主一起刷题
这里使用的是题库:
https://leetcode.cn/problem-list/xb9nqhhg/?page=1
目录
- 剑指 Offer 37. 序列化二叉树
- 剑指 Offer 38. 字符串的排列
- 剑指 Offer 40. 最小的k个数
剑指 Offer 37. 序列化二叉树
剑指 Offer 37. 序列化二叉树
序列化:
观察发现,序列化就是对我们二叉树的一个层序遍历。这样就可以使用层序遍历的方法来序列化这颗二叉树。
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root==null)return "";
StringBuilder sbr=new StringBuilder();
List<TreeNode> queue=new ArrayList<>();//Queue和Deque不能存null
queue.add(root);
while(!queue.isEmpty()){
TreeNode cur=queue.get(0);
queue.remove(0);
if(cur!=null){
sbr.append(cur.val+",");
queue.add(cur.left);
queue.add(cur.right);
}else{
sbr.append("null,");
}
}
//把末尾的null和多的”,“抹除
int i=sbr.length()-1;
for(;i>=0;i--){
if(Character.isDigit(sbr.charAt(i))){
break;
}
}
return sbr.substring(0,i+1);
}
那么反序列化就是根据我们的字符串一层一层的构建二叉树
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if(data.equals(""))return null;
//根据,分割字符串
String[] nodes=data.split(",");
Deque<TreeNode> queue=new ArrayDeque<>();
int i=0;//用于遍历nodes数组
TreeNode root=new TreeNode(Integer.parseInt(nodes[i++]));
queue.offer(root);
while(i<nodes.length){
TreeNode node=queue.poll();
if(!nodes[i].equals("null")){
node.left=new TreeNode(Integer.parseInt(nodes[i++]));
queue.offer(node.left);
}else{
i++;
}
if(i>=nodes.length){
break;
}
if(!nodes[i].equals("null")){
node.right=new TreeNode(Integer.parseInt(nodes[i++]));
queue.offer(node.right);
}else{
i++;
}
}
return root;
}
剑指 Offer 38. 字符串的排列
剑指 Offer 38. 字符串的排列
通过哈希表来记录该位置填过哪些字母
class Solution {
List<String> list=new ArrayList<>();
List<Character> line=new ArrayList<>();
int n=0;
public String[] permutation(String s) {
//先转为字符数组
char[] arr=s.toCharArray();
rank(arr,0);
String[] ss=new String[n];
return list.toArray(ss);
}
private void rank(char[] arr,int start){
if(start==arr.length){
StringBuilder sbr=new StringBuilder();
for(int i=0;i<line.size();i++){
sbr.append(line.get(i));
}
n++;
list.add(sbr.toString());
}
Set<Character> set=new HashSet<>();
for(int i=start;i<arr.length;i++){
if(set.contains(arr[i])&&i!=start){
continue;
}
//记录该元素
set.add(arr[i]);
swap(arr,start,i);
line.add(arr[start]);
rank(arr,start+1);
line.remove(start);
swap(arr,start,i);
}
}
private void swap(char[] arr,int i,int j){
char c=arr[i];
arr[i]=arr[j];
arr[j]=c;
}
}
剑指 Offer 40. 最小的k个数
剑指 Offer 40. 最小的k个数
40.这道题典型的利用堆的性质,要求k个我们就用k大小的堆,这里是求最小值,我们采用大根堆。
为了巩固代码,这里手写堆解题。
class Solution {
int[] nums;
int valid=0;//有效数据
int size;//最大容量
private void createHeap(int[] arr,int k){
nums=new int[k];
size=k;
valid=0;
for(int i=0;i<k;i++){
addHeap(arr[i]);
}
}
private void addHeap(int val){
//先加进去,再调节
if(valid>=size){
//和堆顶元素比较,堆顶是最大的,如果比他小就加入进去
if(val<nums[0]){
nums[0]=val;//加入后进行向下调节
setDown(0);
}
}else{
nums[valid++]=val;//加入后进行向上调节
setUp(valid-1);
}
}
private void setDown(int parent){
if(parent>=size-1)return;
//先判断左右孩子那个大
int child=2*parent+1;//左孩子 右孩子=child+1
if(child+1<size&&nums[child]<nums[child+1]){
child++;
}
if(child>=size)return;//没有孩子的情况
if(nums[parent]<nums[child]){
swap(parent,child);
setDown(child);
}
}
private void setUp(int child){
//parent不是根节点,继续向上调整
if(child==0)return;
//获得父节点下标
int parent=(child-1)/2;
if(nums[child]>nums[parent]){
swap(child,parent);
setUp(parent);
}
}
private void swap(int i,int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
public int[] getLeastNumbers(int[] arr, int k) {
if(arr.length==0||k==0)return new int[0];
createHeap(arr,k);
for(int i=k;i<arr.length;i++){
addHeap(arr[i]);
}
return nums;
}
}
共勉