• 左神高级提升班1 很重要的题目


    【案例1】

    【题目描述 难度非常高】

     【思路解析】

    因为要求额外空间复杂度为O(1),所以我们只能使用有限几个变量,来得到整个数组所在的城市距离首都的距离。因为数组paths[i]表示,i城市指向paths[i]城市,我们可以利用这个指向关系(next为下次要去的城市,last为当前城市。并且在往前遍历时,要记录回去的信息,即paths[next的值]=last的值,这样我们就可以再通过last和next往回走),一直往前遍历,直到next==paths[next],或者paths[next] < 0,我们便开始往回走,并且回走时,如果城市i距离首都为x,则给paths[i]赋值为-x。

    然后得到了这个距离数组后,再通过判断距离数组的正负来统计距离(通过指向关系来进行循环计数)的个数。

    【代码实现】

    1. import java.util.Arrays;
    2. /**
    3. * @ProjectName: study3
    4. * @FileName: Ex1
    5. * @author:HWJ
    6. * @Data: 2023/9/14 22:30
    7. */
    8. public class Ex1 {
    9. public static void main(String[] args) {
    10. int[] paths = {9, 1, 4, 9, 0, 4, 8, 9, 0, 1};
    11. pathToDistance(paths);
    12. distanceToCount(paths);
    13. System.out.println(Arrays.toString(paths));
    14. }
    15. public static void pathToDistance(int[] paths) {
    16. int n = paths.length;
    17. int capital = -1;
    18. for (int start = 0; start < n; start++) {
    19. if (paths[start] == start) {
    20. capital = start;
    21. } else if (paths[start] > -1) {
    22. int last = start;
    23. int next = paths[last];
    24. while (paths[next] != next && paths[next] > -1) {
    25. int num = paths[next];
    26. paths[next] = last;
    27. last = next;
    28. next = num;
    29. }
    30. int i = paths[next] == next ? 0 : paths[next];
    31. while (last != start) {
    32. int num = paths[last];
    33. paths[last] = --i;
    34. last = num;
    35. }
    36. paths[last] = --i;
    37. }
    38. }
    39. paths[capital] = 0;
    40. }
    41. public static void distanceToCount(int[] paths){
    42. for (int i = 0; i < paths.length; i++) {
    43. int cur = paths[i];
    44. paths[i] = Math.max(paths[i], 0);
    45. while (cur <= 0){
    46. int next = paths[-cur];
    47. if (next < 0){
    48. paths[-cur] = 1;
    49. cur = next;
    50. }else {
    51. paths[-cur]++;
    52. break;
    53. }
    54. }
    55. }
    56. }
    57. }

    【案例2】

    【题目描述 分糖果问题】

    一群孩子做游戏,现在请你根据游戏得分来发糖果,要求如下:

    1. 每个孩子不管得分多少,起码分到一个糖果。

    2. 任意两个相邻的孩子之间,得分较多的孩子必须拿多一些糖果。

    3. 【进价】要求相邻的两个孩子如果得分相同,得到的糖果应该相同。

    4. 要求时间复杂度为O(N)

    【思路解析】

    我们可以通过得分数组得到一个得分的折线图(即升降情况),然后通过从左向右遍历这个升降情况得到每个人应该分到的糖果数。然后通过从右向左遍历这个升降情况得到每个人应该分到的糖果数。然后对应求最大即为每个孩子的糖果数。遍历时要求升序糖果数++,如果降序或者保持不变,使糖果数变回1.

    【进价思路分析】

    我们可以通过得分数组得到一个得分的折线图(即升降情况),然后通过从左向右遍历这个升降情况得到每个人应该分到的糖果数。然后通过从右向左遍历这个升降情况得到每个人应该分到的糖果数。然后对应求最大即为每个孩子的糖果数。遍历时要求升序糖果数++,如果降序使糖果数变回1,如果保持不变,则使糖果数保持不变。

    【代码实现】

    1. /**
    2. * @ProjectName: study3
    3. * @FileName: Ex2
    4. * @author:HWJ
    5. * @Data: 2023/9/15 0:07
    6. */
    7. public class Ex2 {
    8. public static void main(String[] args) {
    9. int[] scores = {1, 2, 2};
    10. System.out.println(candy1(scores));
    11. System.out.println(candy2(scores));
    12. }
    13. public static int candy1(int[] scores){
    14. int[] left = new int[scores.length];
    15. int[] right = new int[scores.length];
    16. left[0] = 1;
    17. for (int i = 1; i < scores.length; i++) {
    18. if(scores[i] > scores[i - 1]){
    19. left[i] = left[i - 1] + 1;
    20. }else {
    21. left[i] = 1;
    22. }
    23. }
    24. right[scores.length - 1] = 1;
    25. for (int i = scores.length - 2; i >= 1; i--) {
    26. if(scores[i] > scores[i + 1]){
    27. right[i] = right[i + 1] + 1;
    28. }else {
    29. right[i] = 1;
    30. }
    31. }
    32. int res = 0;
    33. for (int i = 0; i < scores.length; i++) {
    34. res += Math.max(left[i], right[i]);
    35. }
    36. return res;
    37. }
    38. public static int candy2(int[] scores){
    39. int[] left = new int[scores.length];
    40. int[] right = new int[scores.length];
    41. left[0] = 1;
    42. for (int i = 1; i < scores.length; i++) {
    43. if(scores[i] > scores[i - 1]){
    44. left[i] = left[i - 1] + 1;
    45. }else if (scores[i] < scores[i - 1]){
    46. left[i] = 1;
    47. }else {
    48. left[i] = left[i - 1];
    49. }
    50. }
    51. right[scores.length - 1] = 1;
    52. for (int i = scores.length - 2; i >= 1; i--) {
    53. if(scores[i] > scores[i + 1]){
    54. right[i] = right[i + 1] + 1;
    55. }else if (scores[i] < scores[i + 1]){
    56. right[i] = 1;
    57. }else {
    58. right[i] = right[i + 1];
    59. }
    60. }
    61. int res = 0;
    62. for (int i = 0; i < scores.length; i++) {
    63. res += Math.max(left[i], right[i]);
    64. }
    65. return res;
    66. }
    67. }

    【超级进阶   非常难】

    要求时间复杂度为O(N), 额外空间复杂度为O(1)。   实现特别困难。

    【案例3】

    【题目描述】

    【思路解析】二叉树递归套路类题目

    第一种思路,列出所有可能性,然后在递归时得到所有可能性,然后不断汇总求最优解。

    能获得最优解的可能性如下:

    (1)x结点以下都被照亮(包含x结点),且x上不放灯。

    (2)x结点以下都被照亮(包含x结点),且x上放灯。

    (3)x结点以下都被照亮(不包含x结点),但x上放灯。(因为这种情况可能引出下一个最优解,在x的父上放灯,影响的结点更多)。

    第二种思路,我们在传递的时候已知最优解需要的是什么信息,利用贪心加速常数时间。

    比如当左孩子和右孩子,未被覆盖时,x上必须放灯,如果左孩子和右孩子,被覆盖且放灯,则x上一定不放灯。如果左孩子和右子,被覆盖但没放灯,则x未被覆盖。

    【代码实现】 

    1. /**
    2. * @ProjectName: study3
    3. * @FileName: Ex3
    4. * @author:HWJ
    5. * @Data: 2023/9/15 0:16
    6. */
    7. public class Ex3 {
    8. public static void main(String[] args) {
    9. }
    10. public static class Node{
    11. Node left;
    12. Node right;
    13. }
    14. public static class ReturnData{
    15. public int unCovered;
    16. public int coveredNoCamera;
    17. public int coveredHasCamera;
    18. public ReturnData(int unCovered, int coveredNoCamera, int coveredHasCamera) {
    19. this.unCovered = unCovered;
    20. this.coveredNoCamera = coveredNoCamera;
    21. this.coveredHasCamera = coveredHasCamera;
    22. }
    23. }
    24. public static int getMin(Node head){
    25. ReturnData data = process(head);
    26. return Math.min(data.unCovered, Math.min(data.coveredHasCamera, data.coveredNoCamera));
    27. }
    28. public static ReturnData process(Node node){
    29. if (node == null){
    30. return new ReturnData(Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
    31. }
    32. ReturnData left = process(node.left);
    33. ReturnData right = process(node.right);
    34. int unCovered = left.coveredNoCamera + right.coveredNoCamera;
    35. int coveredNoCamera = Math.min(left.coveredHasCamera + right.coveredHasCamera,
    36. Math.min(left.coveredHasCamera + right.coveredNoCamera,
    37. left.coveredNoCamera + right.coveredHasCamera));
    38. int coveredHasCamera = Math.min(left.unCovered,
    39. Math.min(left.coveredHasCamera, left.coveredNoCamera)) +
    40. Math.min(right.unCovered,
    41. Math.min(right.coveredHasCamera, right.coveredNoCamera)) + 1;
    42. return new ReturnData(unCovered, coveredNoCamera, coveredHasCamera);
    43. }
    44. public enum Status{
    45. UNCOVERED, COVERED_NO_CAMERA, COVERED_HAS_CAMERA;
    46. }
    47. public static class ReturnData2{
    48. public Status status;
    49. public int cameras;
    50. public ReturnData2(Status status, int cameras) {
    51. this.status = status;
    52. this.cameras = cameras;
    53. }
    54. }
    55. public static int getMin2(Node head){
    56. ReturnData2 data = process2(head);
    57. return data.cameras + (data.status == Status.UNCOVERED ? 1 : 0);
    58. }
    59. public static ReturnData2 process2(Node node){
    60. if (node == null){
    61. return new ReturnData2(Status.COVERED_NO_CAMERA, 0);
    62. }
    63. ReturnData2 left = process2(node.left);
    64. ReturnData2 right = process2(node.right);
    65. int cameras = left.cameras + right.cameras;
    66. if (left.status == Status.UNCOVERED || right.status == Status.UNCOVERED){
    67. return new ReturnData2(Status.COVERED_HAS_CAMERA, cameras + 1);
    68. }
    69. if (left.status == Status.COVERED_HAS_CAMERA && right.status == Status.COVERED_HAS_CAMERA){
    70. return new ReturnData2(Status.COVERED_NO_CAMERA, cameras);
    71. }
    72. return new ReturnData2(Status.UNCOVERED, cameras);
    73. }
    74. }

  • 相关阅读:
    os模块介绍
    开源:分享4个非常经典的CMS开源项目
    数据结构刷题:第十一天
    认真聊聊中断(软中断)
    赫夫曼树的创建(思路分析)
    C++之分水岭——类和对象【上】
    jmeter做性能测试
    线性回归模型
    YOLO-World技术小结
    [ArcGIS].txt或.xlxs(Excel)格式如何转为.shp格式?
  • 原文地址:https://blog.csdn.net/weixin_73936404/article/details/132862975