class Solution {
public boolean verifyPostorder(int[] postorder) {
//递归,左闭右闭
return recursive(postorder, 0, postorder.length - 1);
}
//递归判断当前节点左子树所有节点是否小于该节点,右子树所有节点是否大于该节点
private boolean recursive(int[] postorder, int left, int right){
//左边界大于右边界遍历结束返回true
if(left >= right) return true;
//求取左子树右边界(开区间),即右子树左边界(闭区间)
int leftTreeR = left;
while(postorder[leftTreeR] < postorder[right]) leftTreeR++;
//求取右子树右边界(开区间)
int rightTreeR = leftTreeR;
while(postorder[rightTreeR] > postorder[right]) rightTreeR++;
//未到达根节点时说明非法
if(rightTreeR != right) return false;
//开始下一轮判断,分别判断左子树和右子树
return recursive(postorder, left, leftTreeR - 1) && recursive(postorder, leftTreeR, right - 1);
}
}
class Solution {
public boolean verifyPostorder(int[] postorder) {
//辅助栈
Deque<Integer> stack = new LinkedList<>();
int root = Integer.MAX_VALUE; //当前父节点
for(int i = postorder.length - 1; i >= 0; i--){
//查找栈中大于且最接近该元素的父节点
while(!stack.isEmpty() && stack.peek() > postorder[i]){
root = stack.pop();
}
if(postorder[i] > root) return false;
stack.push(postorder[i]);
}
return true;
}
}
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int target) {
//递归存储当前路径和符合条件的路径
LinkedList<Integer> path = new LinkedList<>();
LinkedList<List<Integer>> result = new LinkedList<>();
//判断特殊情况
if(root == null) return result;
//开始递归
recursive(root, target, path, result);
return result;
}
//递归函数,输入当前节点,目标值,当前路径和符合条件的路径集合
private void recursive(TreeNode root, int target, List<Integer> path, List<List<Integer>> result){
path.add(root.val); //当前路径
if(root.left == null && root.right == null){ //到达叶子节点
if(target == root.val){
result.add(new LinkedList<>(path)); //存储符合条件的路径,注意新建对象
}
return;
}
//递归回溯
if(root.left != null){
recursive(root.left, target - root.val, path, result);
path.remove(path.size() - 1); //回溯
}
if(root.right != null){
recursive(root.right, target - root.val, path, result);
path.remove(path.size() - 1); //回溯
}
}
}
class Solution {
public Map<Node, Node> nodeMap = new HashMap<>(); //使用Map
public Node copyRandomList(Node head) {
//判断特殊情况
if(head == null) return null;
Node headNew = creatNode(head);
return headNew;
}
//构建新节点
private Node creatNode(Node node){
if(nodeMap.containsKey(node)) return nodeMap.get(node);
Node nodeNew = new Node(node.val);
nodeMap.put(node, nodeNew); //递归前需要加入map,否则死循环
if(node.next != null) nodeNew.next = creatNode(node.next);
if(node.random != null && nodeNew.random == null) nodeNew.random = creatNode(node.random);
return nodeNew;
}
}
class Solution {
public Node copyRandomList(Node head) {
//判断特殊情况
if(head == null) return null;
//迭代同时拆分
Node temp = head;
//第一次遍历,复制新节点
while(temp != null){
Node nodeNew = new Node(temp.val);
nodeNew.next = temp.next;
temp.next = nodeNew;
temp = nodeNew.next;
}
//第二次遍历,修改新节点的random
temp = head;
while(temp != null){
if(temp.random != null) temp.next.random = temp.random.next;
temp = temp.next.next;
}
//第三次遍历,拆分两个原链表和新链表
temp = head.next;
Node pre = head;
Node res = head.next;
while(temp.next != null){
pre.next = temp.next;
temp.next = temp.next.next;
pre = pre.next;
temp = temp.next;
}
pre.next = null; //复原原链表最后一个节点
return res;
}
}
class Solution {
Node pre, head;
public Node treeToDoublyList(Node root) {
//判断特殊情况
if(root == null) return root;
//递归
recursive(root);
//首尾相接
head.left = pre;
pre.right = head;
return head;
}
//递归修改左右孩子
private void recursive(Node cur){
//中序遍历
if(cur == null) return;
recursive(cur.left);
if(pre != null){
pre.right = cur;
cur.left = pre;
}else{ //保存链表头结点,不一定是二叉树根节点!
head = cur;
}
pre = cur;
recursive(cur.right);
}
}
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
//层序遍历,使用队列
Queue<TreeNode> queue = new LinkedList<>();
LinkedList<String> res = new LinkedList<>();
//初始化
queue.offer(root);
while(!queue.isEmpty()){
int leng = queue.size(); //每层长度
for(int i = 0; i < leng; i++){
TreeNode temp = queue.poll();
//保存结果
if(temp != null){
queue.offer(temp.left);
queue.offer(temp.right);
res.add(String.valueOf(temp.val));
}else{
res.add("null");
}
}
}
String result = "";
for(int i = 0; i < res.size() - 1; i++){
result += res.get(i) + ",";
}
result += res.get(res.size() - 1);
return result;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] dataArray = data.split(",");
TreeNode[] nodeArray = new TreeNode[dataArray.length];
//层序遍历,使用队列
Queue<TreeNode> queue = new LinkedList<>();
TreeNode root = null;
//初始化
for(int i = 0; i < dataArray.length; i++){
if(!dataArray[i].equals("null")){
TreeNode node = new TreeNode(Integer.parseInt(dataArray[i]));
nodeArray[i] = node;
}else{
nodeArray[i] = null;
}
}
queue.offer(nodeArray[0]);
int leng = 1; //初始长度
int index = 1; //初始位置
while(!queue.isEmpty() && index < nodeArray.length){
int l = leng;
for(int i = 0; i < leng; i++){
TreeNode cur = queue.poll();
if(cur != null){
if(l == 1) root = cur; //保存根结点
if(nodeArray[index] != null){
cur.left = nodeArray[index];
}
queue.offer(nodeArray[index++]);
if(nodeArray[index] != null){
cur.right = nodeArray[index];
}
queue.offer(nodeArray[index++]);
}
}
//下一轮循环
leng *= 2;
}
return root;
}
}
class Solution {
List<String> res = new LinkedList<>();
StringBuilder sb = new StringBuilder("");
public String[] permutation(String s) {
char[] sArr = s.toCharArray();
Arrays.sort(sArr);
//定义Map标记使用过的元素不能再次使用
boolean[] used = new boolean[sArr.length];
//回溯
backtracking(sArr, used);
String[] result = res.toArray(new String[res.size()]);
return result;
}
//回溯函数
private void backtracking(char[] sArr, boolean[] used){
if(sb.length() == sArr.length){
res.add(sb.toString()); //保存结果
return;
}
//递归
for(int i = 0; i < sArr.length; i++){
//跳过使用过的元素
if(i > 0 && sArr[i] == sArr[i - 1] && used[i - 1] == false) continue;
if(used[i] == true) continue;
sb.append(sArr[i]);
used[i] = true;
//回溯
backtracking(sArr, used);
sb.deleteCharAt(sb.length() - 1);
used[i] = false;
}
}
}
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return(nums[nums.length / 2]);
}
}
class Solution {
public int majorityElement(int[] nums) {
//遍历统计
Map<Integer, Integer> map = new HashMap<>();
int countMax = nums.length / 2;
int numMax = nums[0];
for(int num : nums){
if(!map.containsKey(num)) map.put(num, 0);
int count = map.get(num) + 1;
map.put(num, count);
if(count > countMax) return num;
}
return numMax;
}
}
class Solution {
public int majorityElement(int[] nums) {
//摩尔投票法
int res = nums[0]; //假设众数
int sum = 1; //票数和
for(int i = 1; i < nums.length; i++){
if(sum == 0){
res = nums[i]; //票数和为0重新假设众数
}
if(nums[i] != res){
sum--;
}else{
sum++;
}
}
return res;
}
}
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
//排序
Arrays.sort(arr);
int[] res = new int[k];
if(arr.length == 0 || k == 0) return res;
for(int i = 0; i < k; i++){
res[i] = arr[i];
}
return res;
}
}
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
//判断特殊情况
int[] result = new int[k];
if(arr.length == 0 || k == 0) return result;
//使用大根堆保存前k小
Queue<Integer> priqueue = new PriorityQueue<>((o1, o2) -> o2 - o1);
for(int a : arr){
if(priqueue.size() < k){
priqueue.offer(a);
}else{
if(priqueue.peek() > a){
priqueue.poll();
priqueue.offer(a);
}
}
}
for(int i = 0; i < k; i++){
result[i] = priqueue.poll();
}
return result;
}
}
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
//判断特殊情况
int[] result = new int[k];
if(arr.length == 0 || k == 0) return result;
//快排思想
quickSort(arr, k, 0, arr.length - 1);
for(int i = 0; i < k; i++){
result[i] = arr[i];
}
return result;
}
//快排函数,输入排序数组,要求的k个数,左右区间(左闭右闭)
private void quickSort(int[] arr, int k, int left, int right){
if(left > right) return;
//快排
int i = left;
int j = right;
while(i < j){ //选取左边界为哨兵
while(i < j && arr[j] >= arr[left]) j--; //这里先移动右下标
while(i < j && arr[i] <= arr[left]) i++; //先移动左下标会指向大于哨兵的数
swap(arr, i, j); //交换两数
}
swap(arr, left, i); //将哨兵换到中间
//注意,此时还是要求下标k,因为是相对整个数组的下标
if(j > k){ //如果返回下标大于k,则递归向左选取哨兵
quickSort(arr, k, left, j - 1);
}else if(j < k){ //如果返回下标小于k,则递归向右选取哨兵
quickSort(arr, k, j + 1, right);
}
return;
}
//交换函数,输入数组和两个下标,交换数组中两个下标的数
private void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
class MedianFinder {
//使用两个顶堆,将数据分为较大和较小两部分
//一个小顶堆A保存较大的一半,一个大顶堆B保存较小的一半
PriorityQueue<Integer> A;
PriorityQueue<Integer> B;
/** initialize your data structure here. */
public MedianFinder() {
A = new PriorityQueue<Integer>((o1, o2) -> o1 - o2); //小顶堆
B = new PriorityQueue<Integer>((o1, o2) -> o2 - o1); //大顶堆
}
//插入:
//若当前数据总量为偶数,则将新元素插入B,再将B堆顶元素插入A;
//若为奇数,则将新元素插入A,再将A堆顶元素插入B
public void addNum(int num) {
if(A.size() == B.size()){
B.offer(num);
A.offer(B.poll());
}else{
A.offer(num);
B.offer(A.poll());
}
}
//查找:
//偶数返回A和B堆顶元素的平均值,奇数返回A堆顶元素
public double findMedian() {
if(A.size() == 0) return 0.0;
if(A.size() == B.size()){
return (A.peek() + B.peek()) / 2.0;
}else{
return A.peek() * 1.0;
}
}
}
class Solution {
public int maxSubArray(int[] nums) {
//贪心
int sum = -101;
int max = -101;
for(int i = 0; i < nums.length; i++){
if(sum < 0){
sum = nums[i];
}else{
sum += nums[i];
}
max = Math.max(sum, max);
}
return max;
}
}
class Solution {
public int maxSubArray(int[] nums) {
//动态规划DP
// //定义dp数组dp[i]表示数组nums从下标x(-1
// int[] dp = new int[nums.length];
// //初始化
// dp[0] = nums[0];
//优化
int dp = nums[0];
//正序遍历
int max = nums[0];
for(int i = 1; i < nums.length; i++){
// dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
// max = Math.max(max, dp[i]);
dp = Math.max(nums[i], dp + nums[i]);
max = Math.max(max, dp);
}
return max;
}
}
分治法线段树思想*