题目十一:二叉树递归套路

二叉树的每个节点都有一个int型权值,给定一棵二叉树,要求计算出从根节点到叶节点的所有路径中,权值和 最大的值为多少。

package class02;public class Code07_BSTRecursiveFormula {static class Node{public int value;public Node left;public Node right;public Node(int value){this.value = value;}}//方法一:全局变量,只有在达到叶子节点的时候,才会进行修改public static int maxSum = Integer.MIN_VALUE;public static int maxPath(Node head){process(head,0);return maxSum;}//pre 表示根节点到当前节点x上方的路径和public static void process(Node x,int pre){if(x.left == null && x.right == null){maxSum = Math.max(maxSum,pre + x.value);}if(x.left != null){process(x.left,pre + x.value);}if(x.right != null){process(x.right,pre + x.value);}}//方法二:使用递归套路  将要得到的信息进行包装public static int maxPath2(Node head){if(head == null) return 0;return p(head).maxPath;}static class ReturnType{public int maxPath;public ReturnType(int maxSum){this.maxPath = maxSum;}}//当前以x为头节点的权值和最大public static ReturnType p(Node x){if (x.left == null && x.right == null){return new ReturnType(x.value);}//获得左右子树的最大路径和int leftMaxPath = (x.left == null) ? Integer.MIN_VALUE : p(x.left).maxPath;int righrMaxPath = (x.right == null) ? Integer.MIN_VALUE : p(x.right).maxPath;//获得当前树的最大路径和int maxPath = Math.max(leftMaxPath,righrMaxPath) + x.value;return new ReturnType(maxPath);}}

题目十二:二维数组规律寻找

给定一个元素为非负整数的二维数组matrix,每行和每列都是从小到达排序的。

再给定一个非负整数aim,请判断aim是否在matrix中。

package class02;import org.junit.Test;/*** 给定一个元素为非负整数的二维数组matrix,每行和每列都是从小到达排序的。* 再给定一个非负整数aim,请判断aim是否在matrix中。*/
public class Code08_SearchInDoubleArray {//从右上角开始查询  查询最多一行+一列// arr 行列是从小到大的 非负整数public static boolean isInDoubleArray(int[][] arr,int num){if(arr == null || num < 0){return false;}int N = arr.length;int M = arr[0].length;int row = 0;int col = M - 1;  //初始位置在右上角while(row < N && col >= 0){int cur = arr[row][col];if(cur > num){col--;}else if(cur < num) {row++;}else {return true;}}return false;}
}

对于一个只有01的二维数组,0始终在1的左边,返回具有1最多的行。

package class02;import java.util.ArrayList;
import java.util.List;/*** 对于一个只有01的二维数组,0始终在1的左边,返回具有1最多的行。*/
public class Code09_SearchMaxOne {public static List<Integer> getMaxOne(int[][] arr){int N = arr.length;int M = arr[0].length;int row = 0;int col = M - 1;  //初始化位置在左上角List<Integer> list = new ArrayList<>();int maxSize = 0;while (row < N && col >= 0){int cur = maxSize;if(arr[row][col] == 1) {while (col - 1 >= 0 && arr[row][col - 1] == 1) {col--;maxSize++;}//如果最大值变化,则需要把原来的最大值行数全部清空//如果最大值没有变化,则直接添加新的行就可if(maxSize != cur){list.clear();}list.add(row);}row++;}return list;}
}

题目十三:洗衣机问题、打包问题(看当前i位置情况)

有n个打包机器从左到右一字排开,上方有一个自动装置会抓取一批放物品到每个打包机上,放到每个机器上的这些物品数量有多有少,由于物品数量不同,需要工人将每个机器上的物品移动从而达到物品数量下相等才能打包。每个物品重量太大、每次只能搬一个物品进行移动,为了省力,只在相邻的机器上移动。请计算在搬动最小轮数的前提下,使每个机器上的物品数量相等。如果不能使每个机器上的物品相同,返回-1。

eg:[1,0,5]表示有三个机器,每个机器上分别有1,0,5个物品,经过这些轮后:

第一轮:1 0 <- 5 ==> 1 1 4

第二轮:1 <- 1 <- 4 ==> 2 1 3

第三轮:2 1 <- 3 ==> 2 2 2

移动了三轮,每个机器上的物品相等,所以返回3

eg:[2,2,3]表示有3个机器,每个机器上分别有2、2、3个物品,这些物品不管怎么移动,都不能使三个机器上物品数量相等,返回-1。

只需要看当前位置左边和右边的衣服总数

package class03;import org.junit.Test;import java.util.Arrays;/*** eg:[2,2,3]表示有3个机器,每个机器上分别有2、2、3个物品,* 这些物品不管怎么移动,都不能使三个机器上物品数量相等,返回-1。*/
public class Code01_AveragePackage {//arr中只有相邻的两个才可以搬运public int minTimesOfPackage(int[] arr){if(arr == null || arr.length == 0){return 0;}int sum = 0;for(int i : arr){sum += i;}if(sum % arr.length != 0){return -1;}int avg = sum / arr.length;int maxTimes = Integer.MIN_VALUE;int leftSum = 0;int rightSum = sum - arr[0];for(int i = 0;i < arr.length;i++){int leftPoor = leftSum - avg * i;   //i位置左侧衣服总和的差值int rightPoor = rightSum - avg * (arr.length - 1 - i); //右侧衣服总和的差值int curTimes = 0;if(leftPoor < 0 && rightPoor < 0){  //左负右负  i位置每次只能拿一个curTimes = Math.abs(leftPoor) + Math.abs(rightPoor);}else if((leftPoor < 0 && rightPoor > 0)|| (leftPoor > 0 && rightPoor < 0)){  //左负右正 或者 左正右负curTimes = Math.max(Math.abs(leftPoor),Math.abs(rightPoor));}else if(leftPoor > 0 && rightPoor > 0){  //左正右正curTimes = Math.max(leftPoor,rightPoor);}else {  //左0 右0curTimes = 0;}maxTimes = Math.max(maxTimes,curTimes);  //取每次情况最差的leftSum += arr[i];  //向后移动rightSum -= arr[i];}return maxTimes;}public int[] getRandomArr(){int N = (int)(Math.random() * 20) + 1;  //长度1~20int[] arr = new int[N];for (int i = 0;i < N;i++){arr[i] = (int)(Math.random() * 101);  //个数为0~100}return arr;}@Testpublic void test(){int N = 20;for(int i = 0;i < N;i++){int[] arr = getRandomArr();int min = minTimesOfPackage(arr);System.out.println(Arrays.toString(arr));System.out.println(min);}}
}

题目十四:宏观调控-Zigzag打印、螺旋打印

用zigzag的方式打印矩阵,比如如下的矩阵

0 1 2 3

4 5 6 7

8 9 10 11

打印顺序为:0 1 4 8 5 2 3 6 9  10 7 11

package class03;import org.junit.Test;/*** zigzag打印*/
public class Code02_ZigzagPrint {//给两个点,都是在左上角,一个向右,一个向下,打印斜角public void zigzagPrint(int[][] arr){//定义两个点,都在左上角int a_row = 0;int a_col = 0;int b_row = 0;int b_col = 0;int N = arr.length - 1;int M = arr[0].length - 1;boolean flag = false;while (a_row != N + 1){printObliqueLine(arr,a_row,a_col,b_row,b_col,flag);//a 点向右移动,当到达末端时,向下移动a_row = a_col == M ? a_row + 1 : a_row;  //a点先判断行,在判断列 (列的变化会导致行变化)a_col = a_col == M ? a_col : a_col + 1;//b 点向下移动,当到达底端时,向右移动b_col = b_row == N ? b_col + 1 : b_col;  //b点先判断列,在判断行 (行的变化会导致列变化)b_row = b_row == N ? b_row : b_row + 1;flag = !flag;}System.out.println();}public void printObliqueLine(int[][] arr,int a_row,int a_col,int b_row,int b_col,boolean flag){if(flag){while (a_row != b_row + 1){  //上向下打印System.out.print(arr[a_row++][a_col--] + "\t");}}else {while (b_col != a_col + 1){  //下向上打印System.out.print(arr[b_row--][b_col++] + "\t");}}}
}

用螺旋的方式打印矩阵,比如如下的矩阵:

0 1 2 3

4 5 6 7

8 9 10 11

打印顺序为:0 1 2 3 7 11 10 9  8 4 5 6

package class03;import org.junit.Test;/*** 螺旋打印*/
public class Code03_SpiralPrint {//定义左上角和右下角形成一个框,来打印框的边界,再缩小框,继续打印即可public void spiralPrint(int[][] arr){if(arr == null || arr.length == 0){System.out.println();}int leftRow = 0;  //左上角int leftCol = 0;int rightRow = arr.length - 1;  //右下角int rightCol = arr[arr.length - 1].length - 1;while (leftCol < rightCol && leftRow < rightRow){  //打印标准情况下的数字(左上角和右上角不同行也不同列)for (int i = leftCol;i <= rightCol;i++){System.out.print(arr[leftRow][i] + "\t");}for (int i = leftRow + 1;i <= rightRow;i++){System.out.print(arr[i][rightCol] + "\t");}for (int i = rightCol - 1;i >= leftCol;i--){System.out.print(arr[rightRow][i] + "\t");}for (int i = rightRow - 1;i >= leftRow + 1;i--){System.out.print(arr[i][leftCol] + "\t");}leftCol++;   //左上角下移leftRow++;rightCol--;   //右下角上移rightRow--;}//剩余同行或者同列的没有打印if (leftRow == rightRow){for (int i = leftCol;i <= rightCol;i++){System.out.print(arr[leftRow][i] + "\t");}}else if(leftCol == rightCol){for (int i = leftRow;i <= rightRow;i++){System.out.print(arr[i][rightCol] + "\t");}}}
}

给定一个正方形矩阵,只用有限几个变量,实现矩阵中每个位置的顺时针转动90度,比如如下这个矩阵:

0 1 2 3

4 5 6 7

8 9 10 11

12 13 14 15

矩阵应该被调整为:

12 8 4 0

13 9 5 1

14 10 6 2

15 11 7 3

package class03;import org.junit.Test;/*** 正方形矩阵翻转90度*/
public class Code04_SquareFlipped90 {//根据螺旋打印,进行每次的边界翻转,每次四条边上的数据一起变//  arr为正方形数组public int[][] squareFlipped90(int[][] arr){int N = arr.length;int M = arr[0].length;//定义左上角和右下角  由于正方形,左上角和右下角的行列相等int left = 0;int right = N - 1 - left;int temp = 0;while (left < right){  //对边框数据进行变换 因为是正方形,left=right时只有一个值,省去for (int i = left,j = right;i < right;i++,j--){temp = arr[left][i];arr[left][i] = arr[j][left];  //左边框 -> 上边框arr[j][left] = arr[right][j]; // 下边框 -> 左边框arr[right][j] = arr[i][right]; // 下边框 -> 右边框arr[i][right] = temp;  //右边框 -> 上边框}left++;right--;}return arr;}
}

题目十五:最小操作数(神仙题)

假设s和m初始化,s=”a”;m=s;

再定义两种操作,第一种操作:

m=s;

s=s+s;

第二种操作:

s=s+m;

求最小的操作步骤数,可以将s拼接到长度等于n

package class03;/*** 假设s和m初始化,s=”a”;m=s;* 再定义两种操作,第一种操作:* m=s;* s=s+s;* 第二种操作:* s=s+m;* 求最小的操作步骤数,可以将s拼接到长度等于n*/
public class Code05_MinOperation {//判断n是不是质数  n >= 2public boolean isPrim(int n){for(int i = 2;i < n;i++){  //质数除了自己和1的乘积,其余没有while (n % i == 0){return false;}}return true;}public int[] divsSumAndCount(int n){int sum = 0;int count = 0;for(int i = 2;i <= n;i++){  //求出n分解为质数的乘积,质数之和,以及质数的个数while (n % i == 0){sum += i;count++;n /= i;}}return new int[]{sum,count};}//如果n时质数,调用操作二就是最小的操作步骤//n = a * b * c * d  合数分解为质数的乘积public int minOps(int n){if(n < 2){return 0;}if(isPrim(n)){return n - 1;}int[] divsSumAndCount = divsSumAndCount(n);return divsSumAndCount[0] - divsSumAndCount[1];}
}

题目十六:字符串出现次数最多的前K个(大根堆、小根堆)

给定一个字符串类型的数组arr,求其中出现次数最多的前k个

package class03;import java.util.*;/*** 给定一个字符串类型的数组arr,求其中出现次数最多的前k个*/
public class Code06_OccurrenceNumberPre_K {//通过建立词频表,放在大根堆,根据出现次数排列的大根堆public String[] pre_KOfMaxTimes1(String[] arr,int K){HashMap<String,Integer> hashMap = new HashMap<>();for(String s : arr){if(!hashMap.containsKey(s)){hashMap.put(s,1);}else {hashMap.put(s,hashMap.get(s) + 1);}}//根据词出现的个数建立对应的大根堆PriorityQueue<Map.Entry<String,Integer>> priorityQueue= new PriorityQueue<>(new Comparator<Map.Entry<String, Integer>>() {@Overridepublic int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {return o2.getValue() - o1.getValue();}});//存入大根堆for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {priorityQueue.add(entry);}//取出前K个String[] str = new String[K];for(int i = 0;i < K;i++){String key = priorityQueue.poll().getKey();str[i] = key;}return str;}//也可以建立只具有K个容量的小根堆,这样存放词频表,能进入门槛的放入(多了就开始删门槛放入)public String[] pre_KOfMaxTimes2(String[] arr,int K){HashMap<String,Integer> hashMap = new HashMap<>();for(String s : arr){if(!hashMap.containsKey(s)){hashMap.put(s,1);}else {hashMap.put(s,hashMap.get(s) + 1);}}//建立小根堆PriorityQueue<Map.Entry<String,Integer>> priorityQueue= new PriorityQueue<>(new Comparator<Map.Entry<String, Integer>>() {@Overridepublic int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {return o1.getValue() - o2.getValue();}});for (Map.Entry<String, Integer> entry : hashMap.entrySet()){if(priorityQueue.size() <= 7){priorityQueue.add(entry);}else if (priorityQueue.size() > K&& priorityQueue.peek().getValue() < entry.getValue()){ //小根堆顶部词数小于后序添加的priorityQueue.poll();priorityQueue.add(entry);}}//取出前K个String[] str = new String[K];for(int i = 0;i < K;i++){String key = priorityQueue.poll().getKey();str[i] = key;}return str;}
}

实时显示前K个,需要自己创建堆结构

package class03;import java.util.HashMap;/*** 实时的显示最多K系统*/
public class Code07_TopKTimes {//存放字符串和字符串出现次数的节点 Nodeclass Node{public String str;public int times;public Node(String str,int times){this.str = str;this.times = times;}}class TopKRecord{private  Node[] heap;  //堆private int heapSize; //堆的大小private HashMap<String,Node> strNodeMap;    // 字符串表  相当于词频表private HashMap<Node,Integer> nodeIndexMap; // 节点位置表public TopKRecord(int size){heap = new Node[size];heapSize = 0;strNodeMap = new HashMap<String,Node>();nodeIndexMap = new HashMap<Node,Integer>();}//添加字符串public void add(String str){Node curNode = null;  //当前str对应的节点对象int preIndex = -1;  //当前str节点对象是否在堆上if(!strNodeMap.containsKey(str)){//先看词频表里面有没有,没有词频表添加,且数为1;并且在节点的位置表中,初始化位置为-1curNode = new Node(str,1);strNodeMap.put(str,curNode);nodeIndexMap.put(curNode,-1);}else {  //词频表已经有,修改词频表对应字符串节点的次数,并获得该字符串节点之前在节点位置表的位置curNode = strNodeMap.get(str);curNode.times++;preIndex = nodeIndexMap.get(curNode);}//判断是否在堆上if(preIndex == -1){ //不在堆上,词频增加,是否要上堆if(heapSize == heap.length){ //堆满if(heap[0].times < curNode.times){ //干掉堆顶,替换,并把位置表中对应节点位置改变nodeIndexMap.put(heap[0],-1);nodeIndexMap.put(curNode,0);heap[0] = curNode;heapify(0,heapSize);  //堆中以小根堆方式变化}}else { //堆没有满,直接添加,堆的大小增加nodeIndexMap.put(curNode,heapSize);heap[heapSize] = curNode;heapInsert(heapSize++);}}else {  //在堆上heapify(preIndex,heapSize);}}//把堆按照词频次数从小到大,节点位置表也需要对应修改public void heapify(int start,int end){for(int i = start;i < end;i++) {if (heap[i].times > heap[i+1].times){Node temp = heap[i];heap[i] = heap[i + 1]; //交换两个位置的节点heap[i + 1] = temp;nodeIndexMap.put(heap[i],i+1);  //对应节点的位置也需要改变nodeIndexMap.put(heap[i+1],i);}}}//当前堆中已有节点的数加一public void heapInsert(int index){this.heapSize = heapSize;}}
}

题目十七:猫狗队列

实现一种猫狗队列的结构,要求如下:

用户可以调用add方法将cat类或dog类的实例放入队列中;

用户可以调用pollAll方法,将队列中所有的实例按照进队列的先后顺序依次弹出;

用户可以调用pollDog方法,将队列中dog类的实例按照进队列的先后顺序依次弹出;

用户可以调用pollCat方法,将队列中cat类的实例按照进队列的先后顺序依次弹出;

用户可以调用isEmpty方法,检查队列中是否还有dog或cat实例;

用户可以调用isDogEmpty方法,检查队列中是否有dog类的实例;

用户可以调用isCatEmpty方法,检查队列中是否有cat类的实例;

要求以上所有的方法时间复杂度都是O(1)

使用两个队列,记录他们进队列的先后顺序即可

题目十八:特殊栈

实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小元素的操作。

要求:1.pop、push、getMin操作的时间复杂度都是O(1),2.设计的栈类型可以使用现成的栈结构。

使用两个栈,一个存放数据,一个存放数据栈中的最小值

package class04;import com.sun.java.swing.plaf.windows.WindowsTextAreaUI;import java.util.Stack;/*** 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小元素的操作。* 要求:1.pop、push、getMin操作的时间复杂度都是O(1),2.设计的栈类型可以使用现成的栈结构。*/
public class MinNumStack {Stack<Integer> numstack;  //数据栈Stack<Integer> minstack;  //最小值栈private int min;public MinNumStack(){numstack = new Stack<Integer>();min = Integer.MAX_VALUE;}public Integer poll() throws Exception{if (!numstack.isEmpty()){minstack.pop();return numstack.pop();}else {throw new RuntimeException("空栈");}}public void push(Integer num){min = Math.min(min,num);numstack.push(num);minstack.push(min);}public Integer getMin() throws Exception{if(!minstack.isEmpty()){return minstack.peek();}else {throw new RuntimeException("栈空,没有最小值");}}
}

题目十九:队列实现栈,栈实现队列

如何仅用队列结构实现栈结构?  两个队列

如何仅用栈结构实现队列结构?  两个栈

题目二十:动态规划的空间压缩技巧

给你一个二维数组matrix,其中每个数都是正数,要求从左上角走到右下角。每一步只能向右或者向下,沿途经过的数字要累加起来。最后请返回最小的路径和。

左神数据结构与算法(中级提升)——02相关推荐

  1. 左神数据结构与算法 笔记(二)

    文章目录 第七节课 1.二叉树 1.1.二叉树的先序.中序.后序遍历 1.2二叉树的按层遍历 二叉树的最大宽度: 1.3二叉树的序列化和反序列化 第八节课 1.题目一 2.题目二 3.折纸 4.二叉树 ...

  2. 左神数据结构与算法(基础)——表、树、图、贪心、递归

    2.1 哈希表.有序表.单链表和双链表 ①哈希表的简单介绍 1>哈希表在使用层面可以理解为一种集合结构. 2>如果只有key,没有伴随数据value,可以使用HashSet结构 3> ...

  3. 判断是否为二叉排序树的递归算法_左神直通BAT算法笔记(基础篇)

    时间复杂度 空间复杂度 经典例题 找出B中不属于A的数 荷兰国旗问题 矩阵打印问题 岛问题 经典结构和算法 字符串 KMP算法 前缀树 数组 冒泡排序 选择排序 插入排序 归并排序 快速排序 堆排序 ...

  4. 数据结构与算法之美02

    二.算法复杂度分析 如何分析.统计算法的执行效率和资源消耗? 时间.空间复杂度分析. 为什么需要复杂度分析? 你可能会有些疑惑,我把代码跑一遍,通过统计.监控,就能得到算法执行的时间和占用的内存大 小 ...

  5. 数据结构与算法之美 02 | 如何抓住重点

    什么是数据结构? 数据结构是指一组数据的存储结构. 什么是算法? 算法就是操作数据结构的一组方法. 数据结构是为算法服务的,算法要作用在特定的数据结构之上. 想要学习数据结构与算法,首先要掌握一个数据 ...

  6. 数据结构与算法:队列——02

    文章目录 三.队列 1.队列概述: 2.单向队列[数组表现形式]: 3.环形队列[数组表现形式]: 三.队列 1.队列概述: 定义: 队列定义 队列简称队,它也是一种操作受限的线性表.其限制为仅允许在 ...

  7. 数据结构和算法-2023.07.02

    核心介绍

  8. 跟着左神刷爆算法——链表

    哈希表: 1)哈希表在使用层面上可以理解为一种集合结构 2)如果只有key,没有伴随数据value,可以使用HashSet结构 3)如果既有key,又有伴随数据value,可以使用HashMap结构 ...

  9. 左神讲算法——二分法及其拓展

    目录 1. 经典二分例题 2. 拓展例题一:寻找大于等于某数最左侧位置 3. 拓展例题二:局部最小值问题 参考链接:2021最新左神数据结构算法全家桶 1. 经典二分例题 题目一:在一个有序数组中,找 ...

最新文章

  1. C++实现九九乘法表
  2. ospf专题二:虚链路
  3. oracle-sqlloader的简单使用
  4. 一个tomcat部署俩个java web项目
  5. c语言inline不起作用,C语言inline内联函数学习小结
  6. Java转置_Java实现单链表的逆转置
  7. Linux环境下查看IP不显示IPv4地址
  8. echarts常用方法(一)
  9. mapxtreme 常用实例
  10. 老机器上安装了kubuntu先尝试安装Manjaro但是鼠标按键无法使用彻底解决办法
  11. HTML5 Notification实现浏览器通知
  12. RADIUS协议基础原理
  13. 精忠报国用计算机弹,同人精忠报国岳飞传
  14. 气球java游戏_气球游戏-2019腾讯笔试
  15. 从都市丽人2022年财报,看专业内衣如何进阶突围
  16. Fiddler+雷电模拟器APP抓包
  17. word如何设置每一章节的页眉都不同
  18. 低功耗设计及其UPF实现第四节(最后一节)
  19. 如何利用安卓手机搭建WEB服务器
  20. 4-逻辑结构的二元组表示方法

热门文章

  1. Python 车主之家全系车型(包含历史停售车型)配置参数爬虫
  2. Windows、Word、常用快捷键
  3. String 字符分割
  4. 浪潮发布新型水冷服务器 可以快装移动式液冷集群
  5. 微信小程序与H5标签、样式对比
  6. Swagger(Api接口管理)
  7. mysql如何下载msi_Mysql5.5.62.msi下载与安装教程
  8. 有机农产品稀缺昂贵-农业大健康·万祥军:靠谱的功能农业
  9. 微信小程序使用Promise
  10. python画树林_python对随机森林分类结果绘制roc曲线