Skip to content

数组

1.移除元素

https://leetcode.cn/problems/remove-element/submissions/637689538/

下面就是双指针的实现方案

java
    public int removeElement(int[] nums, int val) {
        int length = nums.length;
        int i = 0;
        while (i < length) {
            // 如果数组元素相等
            if (nums[i] == val) {
                // 将元素最后一个元素放到当前位置
                nums[i] = nums[length - 1];
                length--;
            } else {
                i++;
            }
        }
        return length;
    }

2.有序数组的平方

https://leetcode.cn/problems/squares-of-a-sorted-array/description/

java
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] res = new int[n];
        int start = 0;
        int end = n - 1;
        int i = n - 1;
        while (start <= end && i >= 0) {
            if (Math.abs(nums[start]) < Math.abs(nums[end])) {
                res[i] = nums[end] * nums[end];
                end--;
            } else {
                res[i] = nums[start] * nums[start];
                start++;
            }
            i--;
        }
        return res;
    }

3.长度最小的数组

这里需要注意的是,这里是连续的子数组

java
      public int minSubArrayLen(int target, int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        int count = Integer.MAX_VALUE;
        int sum = 0;
        int left = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            // 缩小窗口
            while (sum >= target) {
                count = Math.min(count, i - left + 1);
                sum -= nums[left];
                left++;
            }
        }
        return count == Integer.MAX_VALUE ? 0 : count;
    }

4.螺旋矩阵

https://leetcode.cn/problems/spiral-matrix-ii/description/

这里需要注意的是。边界的处理,当一条边遍历完,对应的边界也应该有处理

java
  public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        int count = 1;
        int left = 0, right = n - 1, top = 0, bottom = n - 1;
        // 0 表示向右 1 表示向下 2 表示向左 3 表示向上
        int direction = 0;
        while (count <= n * n) {
            switch (direction) {
                // 当向右时,从左到右,
                case 0:
                    for (int i = left; i <= right; i++) {
                        matrix[top][i] = count++;
                    }
                    top++;
                    direction = 1;
                    break;
                case 1:
                    for (int i = top; i <= bottom; i++) {
                        matrix[i][right] = count++;
                    }
                    right--;
                    direction = 2;
                    break;
                case 2:
                    for (int i = right; i >= left; i--) {
                        matrix[bottom][i] = count++;
                    }
                    bottom--;
                    direction = 3;
                    break;
                case 3:
                    for (int i = bottom; i >= top; i--) {
                        matrix[i][left] = count++;
                    }
                    left++;
                    direction = 0;
                    break;
            }
        }
        return matrix;
    }

双调数组

如果一个数组中的所有元素是先递增后递减的,则称这个数组为双调的。编写一个程序,给定一个含有N 个不同int 值的双调数组,判断它是否含有给定的整数。

java
public class BitonicArraySearch {
    
    /**
     * 在双调数组中查找目标值
     * @param arr 双调数组
     * @param target 目标值
     * @return 目标值在数组中的索引,如果不存在返回-1
     */
    public static int searchInBitonicArray(int[] arr, int target) {
        if (arr == null || arr.length == 0) {
            return -1;
        }
        
        int n = arr.length;
        
        // 1. 首先找到峰值点(双调点)
        int peakIndex = findPeakIndex(arr);
        
        // 2. 在递增部分查找
        int result = binarySearchAscending(arr, 0, peakIndex, target);
        if (result != -1) {
            return result;
        }
        
        // 3. 在递减部分查找
        return binarySearchDescending(arr, peakIndex + 1, n - 1, target);
    }
    
    /**
     * 找到双调数组的峰值索引
     */
    private static int findPeakIndex(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            // 边界情况处理
            if (mid == 0) {
                if (arr.length == 1 || arr[mid] > arr[mid + 1]) {
                    return mid;
                } else {
                    left = mid + 1;
                }
            } else if (mid == arr.length - 1) {
                if (arr[mid] > arr[mid - 1]) {
                    return mid;
                } else {
                    right = mid - 1;
                }
            } else {
                if (arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]) {
                    return mid; // 找到峰值
                } else if (arr[mid] > arr[mid - 1]) {
                    left = mid + 1; // 峰值在右侧
                } else {
                    right = mid - 1; // 峰值在左侧
                }
            }
        }
        
        return -1; // 理论上不会执行到这里
    }
    
    /**
     * 在递增部分进行二分查找
     */
    private static int binarySearchAscending(int[] arr, int left, int right, int target) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
    
    /**
     * 在递减部分进行二分查找
     */
    private static int binarySearchDescending(int[] arr, int left, int right, int target) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] > target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
    
    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 测试用例
        int[] bitonicArray1 = {1, 3, 8, 12, 4, 2};
        int[] bitonicArray2 = {3, 8, 10, 15, 20, 18, 12, 7};
        int[] bitonicArray3 = {5, 10, 15, 20, 25, 20, 15, 10, 5};
        
        // 测试查找
        testSearch(bitonicArray1, 8, "数组1");  // 应该找到
        testSearch(bitonicArray1, 5, "数组1");  // 应该找不到
        testSearch(bitonicArray1, 12, "数组1"); // 应该找到(峰值)
        
        testSearch(bitonicArray2, 15, "数组2"); // 应该找到
        testSearch(bitonicArray2, 25, "数组2"); // 应该找不到
        testSearch(bitonicArray2, 7, "数组2");  // 应该找到(最后一个元素)
        
        testSearch(bitonicArray3, 25, "数组3"); // 应该找到(峰值)
        testSearch(bitonicArray3, 10, "数组3"); // 应该找到(有重复值但位置不同)
    }
    
    private static void testSearch(int[] arr, int target, String arrayName) {
        int result = searchInBitonicArray(arr, target);
        if (result != -1) {
            System.out.println(arrayName + "中找到目标值 " + target + ",索引为: " + result);
        } else {
            System.out.println(arrayName + "中未找到目标值 " + target);
        }
    }
}

链表

1. 移除链表元素

java
 public ListNode removeElements(ListNode head, int val) {
        if (head == null) {
            return null;
        }

        ListNode pre = head;
        // 当下一个结点不为空的情况下
        while (pre.next != null) {
            // 如果下一个结点的值等于val,则删除下一个结点
            if (pre.next.val == val) {
                // 删除下一个结点
                pre.next = pre.next.next;
            } else {
                // 否则,将pre移到下一个结点
                pre = pre.next;
            }
        }
        return head.val == val ? head.next : head;
    }