54. Spiral Matrix

This problem is a two-dimensional array processing problem.The test point is how to loop and iterate when facing different situations.We can draw a picture to better understand.

 title=

We can get the the array location [row,col].So we only need to proceed according to the requirements of the question.The difficulty of this question is that every time the position of the element is determined,it is easy to confirm the error.When we search for a complete row or column,we must subtract the current row or column,otherwise an error will occur.

Solution

  public List<Integer> spiralOrder(int[][] matrix) {
    ArrayList<Integer> list = new ArrayList<>();
    //define row and col
    int rowStart = 0, rowEnd = matrix.length - 1;
    int colStart = 0, colEnd = matrix[0].length - 1;
    //the number of all elements
    int allElement = (rowEnd + 1) * (colEnd + 1);
    //count the number of the elements what we add
    int counter = 0;
    while (rowStart <= rowEnd || colStart <= colEnd) {
      //top from left to right
      for (int i = colStart; i <= colEnd; i++) {
        list.add(matrix[rowStart][i]);
        counter++;
      }
      //we must subtract the current row or column,otherwise an error will occur
      rowStart++;
      if (counter == allElement) {
        break;
      }
      //right from top to bottom
      for (int i = rowStart; i <= rowEnd; i++) {
        list.add(matrix[i][colEnd]);
        counter++;
      }
      colEnd--;
      if (counter == allElement) {
        break;
      }
      //bottom from right to left
      for (int i = colEnd; i >= colStart; i--) {
        list.add(matrix[rowEnd][i]);
        counter++;
      }
      rowEnd--;
      if (counter == allElement) {
        break;
      }
      //left from bottom to top
      for (int i = rowEnd; i >= rowStart; i--) {
        list.add(matrix[i][colStart]);
        counter++;
      }
      colStart++;
      if (counter == allElement) {
        break;
      }
    }
    return list;
  }

55. Jump Game

If you have already written the question 45. Jump Game II.So you can know this problem is also a greedy problem.The main idea to solve this question is the farthest distance every time you jump.The distance that each position can jump out is i+nums[i].So we can set a value maxMove,but we can;t judge the maxMove at last.For example [0,2,3].The maxMove is larger than the array's length,but we will stuck at first.So we will set another value endIndex.This value is we can actually reach the location.If we reach the endIndex,we just need to update this value and judge this value whether larger than the array's length.

Solution

  public boolean canJump(int[] nums) {
    //for example [0,2,3],the maxMove is larger than the array's length,but we will stuck at first
    int l = nums.length - 1, maxMove = 0, endIndex = 0;
    for (int i = 0; i < nums.length - 1; i++) {
      //the farthest you can reach in theory
      maxMove = Math.max(maxMove, i + nums[i]);
      //if you reach the actual end location,just update the end location
      if (i == endIndex) {
        endIndex = maxMove;
      }
    }
    return endIndex >= l;
  }

56. Merge Intervals

This problem is an abstract double pointer porblem.First of this we must sort this Two-dimensional array.Why we must sort,i will draw a picture to describe it.

 title=

Why can merge [1,3] to [2,6],for convenience,we call it A B array.Because A[1] is larger than B[0],so we can merge theme.But if this array is unordered,it will very difficult.For example [1,3] [8,10] [2,6] [15,18],so that's why we should sort it at first.

We can override the sort function,the comparison is the size of the first element of each array.We must pay attention to one small point,which is the end of the new array.For example [1,8] [5,7] the new array is [1,8].So the new array's end is Math.max(A[1],B[1]).

Why i say this problem is an abstract double pointer porblem.Because we can treat each small array as a pointer.We set the current pointer is slow pointer,and set the next position pointer is the faster pointer.And use double pointer can traverse all the arrays.

 title=

Solution

  public int[][] merge(int[][] intervals) {
    //the special situation
    if (intervals.length == 1) {
      return intervals;
    }
    //override the sort function
    Arrays.sort(intervals, new Comparator<int[]>() {
      @Override
      public int compare(int[] o1, int[] o2) {
        return o1[0] - o2[0];
      }
    });
    //because we don't know how long the result will be,so we use arraylist
    ArrayList<int[]> list = new ArrayList<>();
    //set a slow pointer
    int[] current_interval = intervals[0];
    //and add it at first,if don't add it,we will miss the first of the result array
    list.add(current_interval);
    //traverse the array
    for (int[] interval : intervals) {
      //because we don't need to judge the current[0],we just need to judge the current[1],so we
      // don't need this step
      //int current_begin = current_interval[0];
      int current_end = current_interval[1];
      //the faster pointer
      int next_begin = interval[0];
      int next_end = interval[1];
      //merge the two arrays to be a new result array
      if (current_end >= next_begin) {
        current_interval[1] = Math.max(current_end, next_end);
      } else {
        //we just need to update the two pointers
        current_interval = interval;
        list.add(current_interval);
      }
    }
    return list.toArray(new int[list.size()][]);
  }

57. Insert Interval

This problem is very similar with problem 56. Merge Intervals.If you want to understand this problem easier.You should understand that problem at first.

This problem has three situations.I will use pictures to explain.

 title=

There has two special situations,one is array interval are all less than new,another situation is new are all less than array interval.I circled it in the picture.

 title=

The last situation is merger two arrays into a new array.As long as the two arrays have intersecting parts,so just merge it.The result of the merge is the new newInterval.So we only need to traversal this array,from the head to the end can get the result.

Solution

  public int[][] insert(int[][] intervals, int[] newInterval) {
    //we don't know how long the result will be,so use arraylist to store
    ArrayList<int[]> list = new ArrayList<>();
    //special situation
    if (intervals.length == 0 && intervals == null) {
      list.add(newInterval);
      return list.toArray(new int[list.size()][]);
    }
    //traversal the intervals
    for (int[] interval : intervals) {
      //situation1,interval < new
      if (interval[1] < newInterval[0]) {
        list.add(interval);
      } else if (newInterval[1] < interval[0]) {
        //situation2,new < interval
        list.add(newInterval);
        newInterval = interval;
      } else {
        //situation3,merge the two arrays into a new array
        newInterval[0] = Math.min(interval[0], newInterval[0]);
        newInterval[1] = Math.max(interval[1], newInterval[1]);
      }
    }
    //if we don't add it at last,we will lose the last answer of array
    list.add(newInterval);
    return list.toArray(new int[list.size()][]);
  }

59. Spiral Matrix II

This problem is the same as problem 54. Spiral Matrix.If you want to solve this problem,just need to create a counter.Because each step moves to the position you need to fill in a number.But this number is exactly the number of steps you move.

Solution

  public int[][] generateMatrix(int n) {
    int[][] matrix = new int[n][n];
    int rowStart = 0, rowEnd = n - 1;
    int colStart = 0, colEnd = n - 1;
    int allElement = n * n;
    //creat the counter
    int counter = 0;
    while (rowStart <= rowEnd || colStart <= colEnd) {
      for (int i = colStart; i <= colEnd; i++) {
        //because the first number is 1,the counter is 0,so need +1
        matrix[rowStart][i] = counter + 1;
        counter++;
      }
      if (counter == allElement) {
        break;
      }
      rowStart++;
      for (int i = rowStart; i <= rowEnd; i++) {
        matrix[i][colEnd] = counter + 1;
        counter++;
      }
      if (counter == allElement) {
        break;
      }
      colEnd--;
      for (int i = colEnd; i >= colStart; i--) {
        matrix[rowEnd][i] = counter + 1;
        counter++;
      }
      if (counter == allElement) {
        break;
      }
      rowEnd--;
      for (int i = rowEnd; i >= rowStart; i--) {
        matrix[i][colStart] = counter + 1;
        counter++;
      }
      if (counter == allElement) {
        break;
      }
      colStart++;
    }
    return matrix;
  }

61. Rotate List

This problem is a list problem,let's take a closer look.If the k is larger than the list's length.So it is equivalent to doing it all over again.So in order to go around and search for the unnecessary ones,we should get the list's length L.And k%L can get the position of the node that needs to be rotated.

 title=

This problem is very easy,we just make a new node key point to head,and the list last position is temp,just just let temp point to head,and key point to rotate position.At last,don't forget to make the cut note point to null,otherwise it will create a circle.

Solution

  public ListNode rotateRight(ListNode head, int k) {
    //the special situation
    if (head == null || k == 0) {
      return head;
    }
    //get the list's length
    ListNode temp = head;
    int length = 1;
    while (temp.next != null) {
      temp = temp.next;
      length++;
    }
    //get the position of the node that needs to be rotated
    k %= length;
    //special situation
    if (k == 0) {
      return head;
    }
    //find the position before the rotating node
    ListNode cut = head;
    for (int i = 0; i < length - k - 1; i++) {
      cut = cut.next;
    }
    ListNode rotate = cut.next;
    ListNode key = new ListNode(0);
    //key point to rotate
    key.next = rotate;
    //temp point to head
    temp.next = head;
    //cut point to null
    cut.next = null;
    //key -> rotate -> temp -> head ->cut -> null
    return key.next;
  }

62. Unique Paths

This problem is a very interesting problem.It has a very important requirement,the robot can only move either down or right at any point in time.I draw a picture to explain.

 title=

The start point can only move either down or right.If the down point has m possible unique paths and the right point has n unique paths.So obviously,the start point has m+n unique paths. When the point moves to the bottom or the right.Because it can only move either down or right,so it can just only move follow the yellow arrow. So we make a summary.[m][n] possible = [m-1][n] possible + [m][n-1] possible

We can write down the possibility of each position.

 title=

Solution

  public int uniquePaths(int m, int n) {
    int[][] array = new int[m][n];
    //the bottom or the right,it can only move either down or right,so the possible are all 1
    for (int i = 0; i < array.length; i++) {
      array[i][0] = 1;
    }
    for (int i = 0; i < array[0].length; i++) {
      array[0][i] = 1;
    }
    //[m][n]=[m-1][n]+[m][n-1]
    for (int i = 1; i < array.length; i++) {
      for (int j = 1; j < array[0].length; j++) {
        array[i][j] = array[i - 1][j] + array[i][j - 1];
      }
    }
    return array[m - 1][n - 1];
  }

63. Unique Paths II

This problem caused me a lot of trouble.Because it's an incomplete description of the problem.

  • There may be a lot of obstacles,there may be more than one
  • The obstacles' location may be anywhere,it may appear in the start,or it may be at the target place.

This problem's main idea are very same with problem 62,but there are some differences.Because if the obstacles appear the bottom place or the right place,so we can't go that way.We should mark all the.And set the initial value of 1 for the boundary between the bottom and the right,if the position is a marked obstacle,set it to -1.There is a note here,in the boundary,if one location is marked it can't walk there,so the next boundary location beside it also can't walk.When we judge the location,we need to judge the down location and the right location.If one of them is marked,we can't add it.

 title=

Solution

  public int uniquePathsWithObstacles(int[][] obstacleGrid) {
    //creat the array,and mark the obstacle
    int rowNumber = obstacleGrid.length;
    int colNumber = obstacleGrid[0].length;
    int[][] array = new int[rowNumber][colNumber];
    for (int i = 0; i < rowNumber; i++) {
      for (int i1 = 0; i1 < colNumber; i1++) {
        if (obstacleGrid[i][i1] == 1) {
          array[i][i1] = -1;
        }
      }
    }
    //the special situation,the target is obstacle
    array[0][0] = obstacleGrid[0][0] == 1 ? -1 : 1;
    //judge this location and beside location,if is marked,it also marked
    for (int i = 1; i < rowNumber; i++) {
      array[i][0] = obstacleGrid[i][0] == 1 ? -1 : array[i - 1][0] == -1 ? -1 : 1;
    }
    for (int i = 1; i < colNumber; i++) {
      array[0][i] = obstacleGrid[0][i] == 1 ? -1 : array[0][i - 1] == -1 ? -1 : 1;
    }
    //judge location,have four situation,we need also judge down and right
    for (int i = 1; i < rowNumber; i++) {
      for (int j = 1; j < colNumber; j++) {
        //is marked
        if (array[i][j] == -1) {
          continue;
        } else if (array[i - 1][j] != -1 && array[i][j - 1] != -1) {
          array[i][j] = array[i - 1][j] + array[i][j - 1];
        } else if (array[i - 1][j] != -1) {
          array[i][j] = array[i - 1][j];
        } else {
          array[i][j] = array[i][j - 1];
        }
      }
    }
    //the special situation,the start place is marked
    return array[rowNumber - 1][colNumber - 1] == -1 ? 0 : array[rowNumber - 1][colNumber - 1];
  }

64. Minimum Path Sum

This problem is a very interesting problem.We can find an interesting phenomenon,no matter how to move the target,the number of steps we have to reach the end must be the same.

 title=

So we don't need to consider whether to go down or to the right to save steps.We only need to consider which side to go has less value.

We can find the boundary first,because it can only go down or to the right,so the boundary value should be unique.

 title=

  • When at the top boundary,just continue move right.
  • When on the left boundary,just continue move down.
  • When in the matrix,just move to the lower value side

Solution

  public int minPathSum(int[][] grid) {
    for (int i = 0; i < grid.length; i++) {
      for (int i1 = 0; i1 < grid[0].length; i1++) {
        //the start place,just continue
        if (i == 0 && i1 == 0) {
          continue;
        } else if (i == 0) {
          //the top boundary
          grid[i][i1] = grid[i][i1 - 1] + grid[i][i1];
        } else if (i1 == 0) {
          //the left boundary
          grid[i][i1] = grid[i - 1][i1] + grid[i][i1];
        } else {
          //in the matrix,add the lower value
          grid[i][i1] = Math.min(grid[i - 1][i1], grid[i][i1 - 1]) + grid[i][i1];
        }
      }
    }
    //return the value of end place
    return grid[grid.length - 1][grid[0].length - 1];
  }
最后修改:2023 年 05 月 10 日
如果觉得我的文章对你有用,请随意赞赏