剑指 Offer 37. 序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树。
- 层序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null){
return "[]";
}
//1.得到层序遍历列表
List nodeList = new ArrayList<>();
Deque queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
if(node != null){
nodeList.add(String.valueOf(node.val));
queue.offer(node.left);
queue.offer(node.right);
}else{
nodeList.add("null");
}
}
//2.去掉最末尾的null
int right = nodeList.size() - 1;
while(right > 0){
if(!"null".equals(nodeList.get(right))){
break;
}
right--;
}
//3.拼接结果字符串
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i = 0; i <= right; i++){
if(i != 0){
sb.append(",");
}
sb.append(nodeList.get(i));
}
sb.append("]");
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] nodeValues = data.substring(1, data.length() - 1).split(",");
int len = nodeValues.length;
//System.out.println(len);
if(len == 0 || data.equals("[]")){
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(nodeValues[0]));
Queue nodes = new LinkedList<>();
//根节点入队
nodes.offer(root);
int i = 1;
while(!nodes.isEmpty() && i < len){
TreeNode temp = nodes.poll();
if(!nodeValues[i].equals("null")){
temp.left = new TreeNode(Integer.valueOf(nodeValues[i]));
nodes.offer(temp.left);
}
i++;
if(i < len && !nodeValues[i].equals("null")){
temp.right = new TreeNode(Integer.valueOf(nodeValues[i]));
nodes.offer(temp.right);
}
i++;
}
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
剑指 Offer 38. 字符串的排列
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
- 典型的全排列问题,采用回溯法;哈希表去重
class Solution {
HashSet res = new HashSet<>();
char[] chars;
int[] visited;
public String[] permutation(String s) {
chars = s.toCharArray();
Arrays.sort(chars);
visited = new int[chars.length];
List track = new ArrayList<>();
dfs(track);
String[] resStr = new String[res.size()];
int i = 0;
for(String str : res){
resStr[i++] = str;
}
return resStr;
}
public void dfs(List track) {
if(track.size() == chars.length){
String s = list2Str(track);
if(!res.contains(s)){
res.add(s);
}
return;
}
for(int i = 0; i < chars.length; i++){
if(visited[i] == 1){
continue;
}
track.add(chars[i]);
visited[i] = 1;
dfs(track);
track.remove(track.size() - 1);
visited[i] = 0;
}
}
public String list2Str(List track){
StringBuilder sb = new StringBuilder();
for(Character c : track){
sb.append(c);
}
return sb.toString();
}
}
剑指 Offer 39. 数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
- 排序后返回最中间的元素
class Solution {
public int majorityElement(int[] nums) {
int len = nums.length;
Arrays.sort(nums);
return nums[len/2];
}
}
剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
- 调用Array.sort
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int[] res = new int[k];
Arrays.sort(arr);
for(int i = 0; i < k; i++){
res[i] = arr[i];
}
return res;
}
}
- 基于快排
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
quickSort(arr, 0 , arr.length - 1, k);
int[] res = new int[k];
for(int i = 0; i < k; i++){
res[i] = arr[i];
}
return res;
}
public void quickSort(int[] arr, int left , int right, int k){
if(left >= right){
return;
}
int index = partition(arr, left, right);
if(left >= k){
return;
}
quickSort(arr, left, index - 1, k);
quickSort(arr, index + 1, right, k);
}
public int partition(int[] arr, int left , int right){
int temp = arr[left];
while(left < right){
while(left < right && arr[right] > temp){
right--;
}
arr[left] = arr[right];
while(left < right && arr[left] <= temp){
left++;
}
arr[right] = arr[left];
}
arr[left] = temp;
return left;
}
}