leetcode hot100 (面试复习用)

数组

最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

  • 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
  • 输出:6
  • 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
public static int maxSubArray(int[] nums) {
   
    if (nums == null || nums.length == 0) {
   
        throw new IllegalArgumentException("Array is empty");
    }

    int n = nums.length;
    int[] dp = new int[n];
    dp[0] = nums[0];
    int maxSum = dp[0];

    for (int i = 1; i < n; i++) {
   
        dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
        maxSum = Math.max(maxSum, dp[i]);
    }

    return maxSum;
}
合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例:

  • 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
  • 输出:[[1,6],[8,10],[15,18]]
  • 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
public static int[][] merge(int[][] intervals) {
   
   if (intervals == null || intervals.length == 0) {
   
       return new int[0][0];
   }

   // Sort intervals by starting time
   Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));

   List<int[]> merged = new LinkedList<>();
   int[] currentInterval = intervals[0];
   merged.add(currentInterval);

   for (int i = 1; i < intervals.length; i++) {
   
       int[] interval = intervals[i];
       // If the current interval overlaps with the new interval
       if (currentInterval[1] >= interval[0]) {
   
           // Merge the current interval with the new interval
           currentInterval[1] = Math.max(currentInterval[1], interval[1]);
       } else {
   
           // If no overlap, add the current interval to the result
           // and start a new interval
           currentInterval = interval;
           merged.add(currentInterval);
       }
   }

   return merged.toArray(new int[merged.size()][]);
}
轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例:

  • 输入: nums = [1,2,3,4,5,6,7], k = 3
  • 输出: [5,6,7,1,2,3,4]
  • 解释:

向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

public class ArrayRotation {
   

    // 向右轮转数组
    public static void rotate(int[] nums, int k) {
   
        int n = nums.length;
        if (n == 0 || k % n == 0) {
   
            return; // 如果数组为空或 k 是数组长度的倍数,则不需要旋转
        }
        k = k % n; // 处理 k 大于数组长度的情况
        
        reverse(nums, 0, n - 1); // 反转整个数组
        reverse(nums, 0, k - 1); // 反转前 k 个元素
        reverse(nums, k, n - 1); // 反转后 n - k 个元素
    }
    
    // 反转数组的部分
    private static void reverse(int[] nums, int start, int end) {
   
        while (start < end) {
   
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }
}
除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请 不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例:

  • 输入: nums = [1,2,3,4]
  • 输出: [24,12,8,6]
public class ProductArray {
   

    // 计算除自身以外的数组乘积
    public static int[] productExceptSelf(int[] nums) {
   
        int n = nums.length;
        int[] leftProducts = new int[n];
        int[] rightProducts = new int[n];
        int[] result = new int[n];

        // 计算左侧乘积
        leftProducts[0] = 1;
        for (int i = 1; i < n; i++) {
   
            leftProducts[i] = leftProducts[i - 1] * nums[i - 1];
        }

        // 计算右侧乘积
        rightProducts[n - 1] = 1;
        for (int i = n - 2; i >= 0; i--) {
   
            rightProducts[i] = rightProducts[i + 1] * nums[i + 1];
        }

        // 计算结果数组
        for (int i = 0; i < n; i++) {
   
            result[i] = leftProducts[i] * rightProducts[i];
        }

        return result;
    }
}
缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

示例:

  • 输入:nums = [3,4,-1,1]
  • 输出:2
  • 解释:1 在数组中,但 2 没有。
public static int firstMissingPositive(int[] nums) {
   
    int n = nums.length;

    // 标记所有小于等于 0 或大于 n 的数为 n + 1
    for (int i = 0; i < n; i++) {
   
        if (nums[i] <= 0 || nums[i] > n) {
   
            nums[i] = n + 1;
        }
    }

    // 将每个正整数映射到对应的索引位置
    for (int i = 0; i < n; i++) {
   
        int num = Math.abs(nums[i]);
        if (num <= n) {
   
            nums[num - 1] = -Math.abs(nums[num - 1]);
        }
    }

    // 查找第一个未出现的正整数
    for (int i = 0; i < n; i++) {
   
        if (nums[i] > 0) {
   
            return i + 1;
        }
    }

    // 如果所有 1 到 n 的正整数都出现了,则返回 n + 1
    return n + 1;
}
矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

示例:
leetcode hot100 (面试复习用)_第1张图片

  • 输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
  • 输出:[[1,0,1],[0,0,0],[1,0,1]]
public class MatrixZeroes {
   
    public static void setZeroes(int[][] matrix) {
   
        if (matrix == null || matrix.length == 0) {
   
            return;
        }

        int m = matrix.length;
        int n = matrix[0].length;
        boolean firstRowZero = false;
        boolean firstColZero = false;

        // Check if the first row needs to be zeroed
        for (int j = 0; j < n; j++) {
   
            if (matrix[0][j] == 0) {
   
                firstRowZero = true;
                break;
            }
        }

        // Check if the first column needs to be zeroed
        for (int i = 0; i < m; i++) {
   
            if (matrix[i][0] == 0) {
   
                firstColZero = true;
                break;
            }
        }

        // Use the first row and first column as markers
        for (int i = 1; i < m; i++) {
   
            for (int j = 1; j < n; j++) {
   
                if (matrix[i][j] == 0) {
   
                    matrix[i][0] = 0; // Mark the row
                    matrix[0][j] = 0; // Mark the column
                }
            }
        }

        // Zero out cells based on markers in the first row and first column
        for (int i = 1; i < m; i++) {
   
            for (int j = 1; j < n; j++) {
   
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
   
                    matrix[i][j] = 0;
                }
            }
        }

        // Zero out the first row if needed
        if (firstRowZero) {
   
            for (int j = 0; j < n; j++) {
   
                matrix[0][j] = 0;
            }
        }

        // Zero out the first column if needed
        if (firstColZero) {
   
            for (int i = 0; i < m; i++) {
   
                matrix[i][0] = 0;
            }
        }
    }
}
旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例:

leetcode hot100 (面试复习用)_第2张图片

public void rotate(int[][] matrix) {
   
    int n = matrix.length;
    
    // Step 1: 转置矩阵
    for (int i = 0; i < n; i++) {
   
        for (int j = i; j < n; j++) {
   
            // 交换 matrix[i][j] 和 matrix[j][i]
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }
    
    // Step 2: 反转每一行
    for (int i = 0; i < n; i++) {
   
        for (int j = 0; j < n / 2; j++) {
   
            // 交换 matrix[i][j] 和 matrix[i][n-1-j]
            int temp = matrix[i][j];
            matrix[i][j] = matrix[i][n - 1 - j];
            matrix[i][n - 1 - j] = temp;
        }
    }
}
搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

示例:

  • 输入:nums = [4,5,6,7,0,1,2], target = 0
  • 输出:4
class Solution {
   
    public int search(int[] nums, int target) {
   
        int left = 0;
        int right = nums.length - 1;

        while (left <= right) {
   
            int mid = left + (right - left) / 2;

            // 找到目标值
            if (nums[mid] == target) {
   
                return mid;
            }

            // 判断哪一部分是有序的
            if (nums[left] <= nums[mid]) {
    // 左侧有序
                if (nums[left] <= target && target < nums[mid]) {
   
                    right = mid - 1; // 目标在左侧
                } else {
   
                    left = mid + 1; // 目标在右侧
                }
            } else {
    // 右侧有序
                if (nums[mid] < target && target <= nums[right]) {
   
                    left = mid + 1; // 目标在右侧
                } else {
   
                    right = mid - 1; // 目标在左侧
                }
            }
        }

        return -1; // 未找到目标值
    }
}
找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例:

  • 输入:nums = [3,4,5,1,2]
  • 输出:1
  • 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
class Solution {
   
    public int findMin(int[] nums) {
   
      int left = 0;
        int right = nums.length - 1;

        while (left < right) {
   
            int mid = left + (right - left) / 2;

            // 比较中间值与右边界值
            if (nums[mid] > nums[right]) {
   
                // 最小值在 mid 右侧
                left = mid + 1;
            } else {
   
                // 最小值在 mid 左侧或 mid 即为最小值
                right = mid;
            }
        }

        // 最终 left == right,即为最小值
        return nums[left];
    }
}
在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例:

  • 输入:nums = [5,7,7,8,8,10], target = 8
  • 输出:[3,4]
class Solution {
   
    private static int findFirstPosition(int[] nums, int target) {
   

你可能感兴趣的:(数据结构与算法,leetcode,面试,算法)