LeetCode(Java)练习

数组

数组的改变、移动

453.最小移动次数使数组元素相等

class Solution {
    public int minMoves(int[] nums) {
       if (nums == null || nums.length == 0) {
            return 0;
       }

       int min = nums[0];
       for (int num : nums) {
            min = Math.min(min, num);
       }

       int times = 0;
       for (int num : nums) {
            times += num - min;
       }

       return times;
    }
}

665.非递减数列

class Solution {
    public boolean checkPossibility(int[] nums) {
        int count = 0;
        for (int i = 0; i < nums.length - 1; i++) {
            if (nums[i] > nums[i+1]) {
                count++;
                if (count > 1) {
                    return false;
                }

                if (i > 0 && nums[i-1] > nums[i+1]) {
                    nums[i+1] = nums[i];
                }else {
                    nums[i] = nums[i+1];
                }
            }
        }
        return true;
    }
}

283.移动零

class Solution {
    public void moveZeroes(int[] nums) {
        if (nums == null || nums.length == 0)
            return;

        int nonZeroIndex = 0;

        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[nonZeroIndex] = nums[i];
                nonZeroIndex++;
            }
        }

        while (nonZeroIndex < nums.length) {
            nums[nonZeroIndex] = 0;
            nonZeroIndex++;
        }
    }
}

数组的旋转

189.旋转数组

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k %= n;
        int[] temp = new int[n];
        //将原数组的后k个元素复制到目标数组的开头
        System.arraycopy(nums, n - k, temp, 0 , k);
        //arraycopy(原数组,所需要元素在数组的开头,目标数组,复制到目标的开始位置,元素个数)
        
        //将原数组的前n-k个元素复制到目标数组的后部
        System.arraycopy(nums, 0, temp, k, n-k);

        //将目标数组复制回原数组
        System.arraycopy(temp, 0, nums, 0, n);

    }
}

396.旋转函数

class Solution {
    public int maxRotateFunction(int[] nums) {
        int n = nums.length;
        int sum = 0;
        int F = 0;

        //计算F(0)和数组元素之和
        for (int i = 0; i < n; i++) {
            F += i * nums[i];
            sum += nums[i];
        }

        int max = F;

        //计算F(1)到F(n-1)
        for (int i = 1; i < n; i++) {
            F = F + sum - n * nums[n - i];
            max = Math.max(max, F);
        }
        return max;
    }
}

/*F(0)=0×nums[0]+1×nums[1]+…+(n−1)×nums[n−1]
  F(1)=1×nums[0]+2×nums[1]+…+0×nums[n−1]=F(0)+numSum−n×nums[n−1]
*/

统计数组中的元素

645.错误的集合

class Solution {
    public int[] findErrorNums(int[] nums) {
        int n = nums.length;
        int[] result = new int[2];
        int[] count = new int[n + 1];

        int expectedSum = n * (n + 1) / 2;//期望的和
        int actualSum = 0;//实际和

        for (int num : nums) {
            count[num]++;
            actualSum += num;
            if (count[num] == 2) {
                result[0] = num;//重复的数字
            }
        }

        result[1] = expectedSum - (actualSum - result[0]);

        return result;
    }
}

697.数组的度

import java.util.*;

class Solution {
    public int findShortestSubArray(int[] nums) {
        Map<Integer, Integer> count = new HashMap<>();
        Map<Integer, Integer> left = new HashMap<>();
        Map<Integer, Integer> right = new HashMap<>();

        int maxCount = 0;

        for (int i = 0; i < nums.length; i++) {
            int x = nums[i];

            count.put(x, count.getOrDefault(x, 0) + 1);

            maxCount = Math.max(maxCount, count.get(x));

            if (!left.containsKey(x)) {
                left.put(x, i);
            }

            right.put(x, i);
        }

        int shortestLength = nums.length;

        for (int x : count.keySet()) {
            if (count.get(x) == maxCount) {
                shortestLength = Math.min(shortestLength,right.get(x) - left.get(x) + 1);
            }
        }

        return shortestLength;
    }
}

448.找到所有数组中消失的数字

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        int n = nums.length;

        for (int i = 0; i < n; i++) {
            int index = Math.abs(nums[i]) -1;
            if (nums[index] > 0) {
                nums[index] = -nums[index];
            }
        }

        List<Integer> result = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            if (nums[i] > 0) {
                result.add(i + 1);
            }
        }

        return result;
    }
}

442.数组中重复的数据

import java.util.*;

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> result = new ArrayList<>();

        for (int i = 0; i < nums.length; i++) {
            int index = Math.abs(nums[i]) - 1;
            if (nums[index] > 0) {
                nums[index] = -nums[index];
            }else {
                result.add(Math.abs(nums[i]));
            }
        }

        return result;
    }
}

41.缺失的第一个正数

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;

        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;
            }
        }

        return n + 1;
    }
}

数组的遍历

485.最大连续1的个数

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int maxCount = 0;
        int currentCount = 0;

        for (int num : nums) {
            if (num == 1) {
                currentCount++;
                maxCount = Math.max(maxCount, currentCount);
            }else {
                currentCount = 0;
            }
        }
        return maxCount;
    }
}

495.提莫攻击

class Solution {
    public int findPoisonedDuration(int[] timeSeries, int duration) {
        if (timeSeries.length == 0) {
            return 0;
        }

        int totalPoisonedTime = 0;

        for (int i = 0; i < timeSeries.length - 1; i++) {
            totalPoisonedTime += Math.min(timeSeries[i + 1] - timeSeries[i], duration);
        }

        totalPoisonedTime += duration;

        return totalPoisonedTime;
    }
}

414.第三大的数

class Solution {
    public int thirdMax(int[] nums) {
        Long first = null;
        Long second = null;
        Long third = null;

        for (int num : nums) {
            Long n = Long.valueOf(num);
            if (n.equals(first) || n.equals(second) || n.equals(third)) {
                continue;
            }

            if (first == null || n > first) {
                third = second;
                second = first;
                first = n;
            } else if (second == null || n > second) {
                third = second;
                second = n;
            } else if (third == null || n > third) {
                third = n;
            }
        }

        if (third == null) {
            return first.intValue();
        }

        return third.intValue();
    }
}

628.三个数的最大乘积

class Solution {
    public int maximumProduct(int[] nums) {
        Arrays.sort(nums);

        int n = nums.length;

        int product1 = nums[n-1] * nums[n-2] * nums[n-3];

        int product2 = nums[0] * nums[1] * nums[n-1];

        return Math.max(product1, product2);
    }
}

二维数组及滚动数组

118.杨辉三角

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> triangle = new ArrayList<>();

        if (numRows == 0) {
            return triangle;
        }

        //添加第一行
        triangle.add(new ArrayList<>());
        triangle.get(0).add(1);

        for (int rowNum = 1; rowNum < numRows; rowNum++) {
            List<Integer> row = new ArrayList<>();
            List<Integer> prevRow = triangle.get(rowNum - 1);

            row.add(1);

            for (int j = 1; j < rowNum; j++) {
                row.add(prevRow.get(j - 1) + prevRow.get(j)); 
            }

            row.add(1);

            triangle.add(row);
        }

        return triangle;
    }
}

119.杨辉三角 ||

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> row = new ArrayList<>(rowIndex + 1);

        row.add(1);

        for (int i = 1; i <= rowIndex; i++) {
            for (int j = i - 1; j > 0; j--) {
                row.set(j, row.get(j - 1) + row.get(j));
            }
            row.add(1);
        }
        return row;
    }
}

661.图片平滑器

class Solution {
    public int[][] imageSmoother(int[][] img) {
        int m = img.length;
        int n = img[0].length;
        int[][] result = new int[m][n];

        for (int i = 0;i < m; i++) {
            for (int j = 0; j < n; j++) {
                result[i][j] = calculateAverage(img, i, j, m, n);
            }
        }

        return result;
    }

    private int calculateAverage(int[][] img, int row, int col, int m, int n) {
        int sum = 0;
        int count = 0;

        for (int i = row - 1; i <= row + 1; i++) {
            for (int j = col - 1; j <= col + 1; j++) {
                if (i >= 0 && i < m && j >=0 && j < n) {
                    sum += img[i][j];
                    count++;
                }
            }
        }
        return sum / count;
    }
}

598.范围求和 ||

class Solution {
    public int maxCount(int m, int n, int[][] ops) {
        if (ops == null || ops.length == 0) {
            return m * n; 
        }

        int minA = m;
        int minB = n;

        for (int[] op : ops) {
            minA = Math.min(minA, op[0]);
            minB = Math.min(minB, op[1]);
        }

        return minA * minB;
    }
}

419.甲板上的战舰

class Solution {
    public int countBattleships(char[][] board) {
        if (board == null || board.length == 0 || board[0].length == 0) {
            return 0;
        }

        int count = 0;
        int m = board.length;
        int n = board[0].length;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'X') {
                    if (i > 0 && board[i - 1][j] == 'X') continue;
                    if (j > 0 && board[i][j - 1] == 'X') continue;
                    count++;
                }
            }
        }
        return count;
    }
    
}

特定顺序遍历二维数组

54.螺旋矩阵

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return result;
        }

        int m = matrix.length;
        int n = matrix[0].length;
        int left = 0, right = n - 1, top = 0, bottom = m - 1;

        while (left <= right && top <= bottom) {
            for (int i = left; i <= right; i++) {
                result.add(matrix[top][i]);
            }
            top++;

            for (int i = top; i <= bottom; i++) {
                result.add(matrix[i][right]);
            }
            right--;

            if (top <= bottom) {
                for (int i = right; i >= left; i--) {
                    result.add(matrix[bottom][i]);
                }
                bottom--;
            }

            if(left <= right) {
                for (int i = bottom; i >= top; i--) {
                    result.add(matrix[i][left]);
                }
                left++;
            }
        }
        return result;
    }
}

59.螺旋矩阵 ||

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        int num = 1;
        int left = 0, right = n - 1, top = 0, bottom = n - 1;

        while (num <= n * n) {
            // 从左到右
            for (int i = left; i <= right; i++) {
                matrix[top][i] = num++;
            }
            top++;
            
            // 从上到下
            for (int i = top; i <= bottom; i++) {
                matrix[i][right] = num++;
            }
            right--;
            
            // 从右到左
            for (int i = right; i >= left; i--) {
                matrix[bottom][i] = num++;
            }
            bottom--;
            
            // 从下到上
            for (int i = bottom; i >= top; i--) {
                matrix[i][left] = num++;
            }
            left++;
        } 
        return matrix;
    }
}

498.对角线遍历

class Solution {
    public int[] findDiagonalOrder(int[][] mat) {
        if (mat == null || mat.length == 0)
            return new int[0];
        int m = mat.length;
        int n = mat[0].length;
        int[] result = new int[m * n];
        int row = 0, col = 0;

        for (int i = 0; i < m * n; i++) {
            result[i] = mat[row][col];

            if ((row + col) % 2 == 0) {
                if (col == n - 1) {
                    row++;
                } else if (row == 0) {
                    col++;
                } else {
                    row--;
                    col++;
                }
            } else {
                if (row == m - 1) {
                    col++;
                } else if (col == 0) {
                    row++;
                } else {
                    row++;
                    col--;
                }
            }
        }
        return result;
    }
}

二维数组变换

566.重塑矩阵

class Solution {
    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int m = mat.length;//行数
        int n = mat[0].length;//列数

        if (m * n != r * c) {
            return mat;
        }

        int[][] result = new int[r][c];
        int row = 0, col = 0;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                result[row][col] = mat[i][j];
                col++;
                if (col == c) {
                    col = 0;
                    row++;
                }
            }
        }
        return result;
    }
}

48.旋转图像

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        
        //沿着对角线翻转
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }

        //反转每一行
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n / 2; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][n - 1 - j];
                matrix[i][n - 1 - j] = temp;
            }
        }
    }
}

73.矩阵置零

/*O(mn)额外空间
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        boolean[][] zero = new boolean[m][n];

        //标记零的位置
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    zero[i][j] = true;
                }
            }
        }

        //设置零
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (zero[i][j]) {
                    for (int k = 0; k < n; k++) matrix[i][k] = 0;
                    for (int k = 0; k < m; k++) matrix[k][j] = 0;
                }
            }
        }
    }
}*/

/*O(m + n)额外空间
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        boolean[] row = new boolean[m];
        boolean[] col = new boolean[n];

        //标记包含零的行和列
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    row[i] = true;
                    col[j] = true;
                }
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (row[i] || col[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}*/

//常量空间
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        boolean firstRow = false, firstCol = false;

        for (int j = 0; j < n; j++) {
            if (matrix[0][j] == 0) {
                firstRow = true;
                break;
            }
        }

        for (int i = 0; i < m; i++) {
            if (matrix[i][0] == 0) {
                firstCol = true;
                break;

            }
        }

         // 使用第一行和第一列来标记其他行列是否需要置零
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        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;
                }
            }
        }
        
        // 处理第一行
        if (firstRow) {
            for (int j = 0; j < n; j++) {
                matrix[0][j] = 0;
            }
        }
        
        // 处理第一列
        if (firstCol) {
            for (int i = 0; i < m; i++) {
                matrix[i][0] = 0;
            }
        }
    }
}

289.生命游戏

class Solution {
    public void gameOfLife(int[][] board) {
        int m = board.length;
        int n = board[0].length;

        int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1};
        int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1};

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int liveNeighbors = 0;

                for (int k = 0; k < 8; k++) {
                    int newX = i + dx[k];
                    int newY = j + dy[k];

                    if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
                        liveNeighbors += board[newX][newY] & 1;
                    }
                }

                if (board[i][j] == 1) {
                    if (liveNeighbors == 2 || liveNeighbors == 3) {
                        board[i][j] = 3;//01 -> 11
                    }
                } else if (liveNeighbors == 3) {
                    board[i][j] = 2; // 00 -> 10
                }
            }
        }
        // 更新board
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] >>= 1;
            }
        }
    }
}

前缀和数组

303.区域和检索 - 数组不可变

class NumArray {
    private int[] prefixSum;
    public NumArray(int[] nums) {
        prefixSum = new int[nums.length + 1];
        for (int i = 0;i < nums.length; i++) {
            prefixSum[i+1] = prefixSum[i] + nums[i];
        }
    }
    
    public int sumRange(int left, int right) {
        return prefixSum[right + 1] - prefixSum[left];
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(left,right);
 */

304.二维区域和检索 - 矩阵不可变

class NumMatrix {
    private int[][] prefixSum;

    public NumMatrix(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0)  {return;}
       int m = matrix.length;
       int n = matrix[0].length;

        //构造前缀和矩阵
       prefixSum = new int[m + 1][n + 1];

       for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1] + matrix[i - 1][j - 1];
            }
       } 
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return prefixSum[row2 + 1][col2 + 1] - prefixSum[row1][col2 + 1] 
               - prefixSum[row2 + 1][col1] + prefixSum[row1][col1];
    }
}

/**
 * Your NumMatrix object will be instantiated and called as such:
 * NumMatrix obj = new NumMatrix(matrix);
 * int param_1 = obj.sumRegion(row1,col1,row2,col2);
 */

238.除自身以外数组的乘积

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int[] answer = new int[n];

        //计算前缀积
        answer[0] = 1;
        for (int i = 1; i < n; i++) {
            answer[i] = answer[i-1] * nums[i-1];
        }

        //计算后缀积并与前缀积相乘
        int suffixProduct = 1;
        for (int i = n - 1; i >= 0; i--) {
            answer[i] *= suffixProduct;
            suffixProduct *= nums[i];
        }
        return answer;
    }
}

--------------------------------------------------------------------------------------------------------------------------------

链表

移除与插入链表元素

707.设置链表

class MyLinkedList {
    //内部类
    private class Node {
        int val;//整数值
        Node prev;//前一个节点
        Node next;//后一个节点

        Node (int val) {
            this.val = val;
        }
    }

    private Node head;//头部节点
    private Node tail;//尾部节点
    private int size;//实际节点数量
    
    //构造函数:初始化链表
    public MyLinkedList() {
        head = new Node(0);
        tail = new Node(0);
        //头尾节点相连
        head.next = tail;
        tail.prev = head;
        size = 0;
    }
    
    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        Node curr = getNode(index);
        return curr.val;
    }
    
    //头节点处添加节点
    public void addAtHead(int val) {
        addAtIndex(0, val);
    }
    
    //尾节点处添加节点
    public void addAtTail(int val) {
        addAtIndex(size, val);
    }
    
    public void addAtIndex(int index, int val) {
        if (index < 0 || index > size) {
            return;
        }
        Node prev = getNode(index - 1);//获取要插入位置的前一个节点
        Node next = prev.next;//获取要插入位置的后一个节点
        Node newNode = new Node(val);//创建一个新节点,值为val
        newNode.prev = prev;//设置新节点的前后引用
        newNode.next = next;
        prev.next = newNode;//更新前后节点的引用,将新节点插入到链表中
        next.prev = newNode;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        Node curr = getNode(index);//获取要删除的节点
        //更新要删除节点的前后节点的引用,跳过当前节点,实现删除操作
        curr.prev.next = curr.next;
        curr.next.prev = curr.prev;
        size--;
    }

    //获得指定节点
    private Node getNode(int index) {
        Node curr;
        if (index < size / 2) {
            curr = head;
            for (int i = 0; i <= index; i++) {
                curr = curr.next;//向后遍历
            }
        }else {
            curr = tail;
            for (int i = size;i > index; i--) {
                curr = curr.prev;//向前遍历
            }
        }
        return curr;
    }
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */

203.移除链表元素

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        //处理头节点可能需要被删除的情况
        while (head != null && head.val == val) {
            head =head.next;
        }

        //如果链表为空
        if (head == null) {
            return null;
        }

        ListNode current = head;
        while (current.next != null) {
            if (current.next.val == val) {
                current.next = current.next.next;
            }else {
                current = current.next;
            }
        }
        return head;
    }
}

237.删除链表中的节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void deleteNode(ListNode node) {
        // 将下一个节点的值复制到当前节点
        node.val = node.next.val;
        // 将当前节点的next指向下下个节点,effectively删除下一个节点
        node.next = node.next.next;
    }
}

19.删除链表的倒数第N个节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //创建一个哑节点,连接到链表头部
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        ListNode fast = dummy;
        ListNode slow = dummy;

        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }

        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }

        slow.next = slow.next.next;

        return dummy.next;
    }
}

83.删除排序链表中的重读元素

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        // 如果链表为空或只有一个节点,直接返回
        if (head == null || head.next == null) {
            return head;
        }

        ListNode current = head;

        while (current != null && current.next != null) {
            if (current.val == current.next.val) {
                current.next = current.next.next;
            }else {
                current = current.next;
            }
        } 
        return head;
    }
}

82.删除排序链表中的重读元素 ||

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        ListNode prev = dummy;
        ListNode current = head;

        while (current != null && current.next != null) {
            if (current.val == current.next.val) {
                while (current.next != null && current.val == current.next.val) {
                  current = current.next;  
                }
                // 跳过所有重复的节点
                prev.next = current.next;
            } else {
                prev = prev.next;
            }
            current = current.next;
        }
        return dummy.next;
    }
}

链表的遍历

430.扁平化多级双向链表

/*
// Definition for a Node.
class Node {
    public int val;
    public Node prev;
    public Node next;
    public Node child;
};
*/

class Solution {
    public Node flatten(Node head) {
        if (head == null) return null;

        Node pseudoHead = new Node(0, null, head, null);
        flattenDFS(pseudoHead, head);

        //删除伪头节点
        pseudoHead.next.prev = null;
        return pseudoHead.next;
    }

    //返回扁平化后的最后一个节点
    private Node flattenDFS(Node prev, Node curr) {
        if (curr == null) return prev;//说明已经到达链表末尾,返回 prev
        
        //建立双向链接
        curr.prev = prev;
        prev.next = curr;

        //保存next节点,因为它可能会在处理child时被修改
        Node tempNext = curr.next;

        //处理child节点
        Node tail = flattenDFS(curr, curr.child);
        curr.child = null;

        //处理next节点
        return flattenDFS(tail, tempNext);
    }
}

114.二叉树展开为链表

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    private TreeNode prev = null;

    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }

        //保存右子树
        TreeNode right = root.right;

        if (prev != null) {
            prev.right = root;
            prev.left = null;
        }
         prev = root;
        
        // 递归处理左子树
        flatten(root.left);
        // 递归处理右子树
        flatten(right);
    
    }
}

链表的旋转与反转

61.旋转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        //如果链表为空或只有一个节点,或者k为0,直接返回
        if (head == null || head.next == null || k == 0) {
            return head;
        }

        //计算链表长度,并找到最后一个节点
        ListNode oldTail = head;
        int n = 1;
        while (oldTail.next != null) {
            oldTail = oldTail.next;
            n++;
        }

        //计算实际需要移动的步数
        k = k % n;
        // 如果k为0,说明不需要旋转,直接返回
        if (k == 0) {
            return head;
        }

        // 将链表首尾相连
        oldTail.next = head;
        
        // 找到新的尾节点
        ListNode newTail = head;
        for (int i = 0; i < n - k - 1; i++) {
            newTail = newTail.next;
        }
        
        // 新的头节点是新尾节点的下一个节点
        ListNode newHead = newTail.next;
        
        // 断开环
        newTail.next = null;
        
        return newHead;

    }
}

24.两两交换链表中的节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */

//迭代 
class Solution {
    public ListNode swapPairs(ListNode head) {
        //创建一个哑节点,简化操作
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode current = dummy;

        while (current.next != null && current.next.next != null) {
            ListNode first = current.next;
            ListNode second = current.next.next;

            //交换节点
            first.next = second.next;
            second.next = first;
            current.next = second;

            current = current.next.next;
        }
        return dummy.next;

    }
}

//递归
class Solution {
    public ListNode swapPairs(ListNode head) {
        // 基本情况:链表为空或只有一个节点
        if (head == null || head.next == null) {
            return head;
        }
        
        // 记录第二个节点
        ListNode second = head.next;
        
        // 递归调用,交换后面的节点对
        head.next = swapPairs(second.next);
        
        // 交换当前的两个节点
        second.next = head;
        
        // 返回新的头节点(原来的第二个节点)
        return second;
    }
}

206.反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */

 //迭代
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode current = head;

        while (current != null) {
            ListNode nextTemp = current.next;
            current.next = prev;
            prev = current;
            current = nextTemp;
        }

        return prev;
    }
}

//递归
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        
        return p;
    }
}

92.反转链表 ||

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 如果left和right相等,无需反转
        if (left == right) {
            return head;
        }

        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;

        // 找到需要反转的子链表的前一个节点
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }

        //反转
        ListNode start = pre.next;
        ListNode then = start.next;

        for (int i = 0; i < right - left; i++) {
            start.next = then.next;
            then.next = pre.next;
            pre.next = then;
            then = start.next;
        }

        return dummy.next;


    }
}

/*反转过程。我们需要重复 right - left 次:
start.next = then.next:将 start 的下一个节点指向 then 的下一个节点
then.next = pre.next:将 then 的下一个节点指向 pre 的下一个节点(即当前反转部分的第一个节点)
pre.next = then:将 pre 的下一个节点指向 then,完成 then 节点的插入
then = start.next:移动 then 指针到下一个需要处理的节点

假设我们有链表 1 -> 2 -> 3 -> 4 -> 5,要反转的部分是从第 2 个节点到第 4 个节点。

初始状态:
dummy -> 1 -> 2 -> 3 -> 4 -> 5
pre start then
第一次迭代后:
dummy -> 1 -> 3 -> 2 -> 4 -> 5
pre then start
第二次迭代后:
dummy -> 1 -> 4 -> 3 -> 2 -> 5
pre then start
迭代结束,得到最终结果:
1 -> 4 -> 3 -> 2 -> 5
*/

25.K个一组翻转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;

        while (head != null) {
            ListNode tail = prev;
            // 检查剩余部分长度是否大于等于k
            for (int i = 0; i < k; i++) {
                tail = tail.next;
                if (tail == null) {
                    return dummy.next;
                }
            }
            ListNode next = tail.next;
            ListNode[] reversed = reverse(head, tail);
            head = reversed[0];
            tail = reversed[1];
            //重新连接
            prev.next = head;
            tail.next = next;
            prev = tail;
            head = tail.next;
        }

        return dummy.next;
    }

    // 反转子链表,返回新的头和尾
    private ListNode[] reverse(ListNode head, ListNode tail) {
        ListNode prev = tail.next;
        ListNode p = head;
        while (prev != tail) {
            ListNode next = p.next;
            p.next = prev;
            prev = p;
            p = next;
        }
        return new ListNode[]{tail, head};
    }
}

链表高精度加法

2.两数相加

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(0);
        ListNode current = dummyHead;
        int carry = 0;

        while (l1 != null || l2 != null) {
            int x = (l1 != null) ? l1.val : 0;
            int y = (l2 != null) ? l2.val : 0;
            int sum = carry + x + y;
            carry = sum / 10;
            current.next = new ListNode(sum % 10);
            current = current.next;

            if (l1 != null) l1 = l1.next;
            if (l2 != null) l2 = l2.next;
        }

        if (carry > 0) {
            current.next = new ListNode(carry);
        }

        return dummyHead.next;
    }
}

445.两数相加 ||

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //反转链表
        l1 = reverseList(l1);
        l2 = reverseList(l2);

        ListNode dummyHead = new ListNode(0);
        ListNode current = dummyHead;
        int carry = 0;

        while (l1 != null || l2 != null || carry != 0) {
            int x = (l1 != null) ? l1.val : 0;
            int y = (l2 != null) ? l2.val : 0;
            int sum = carry + x + y;
            carry = sum / 10;
            current.next = new ListNode(sum % 10);
            current = current.next;

            if (l1 != null) l1 = l1.next;
            if (l2 != null) l2 = l2.next;  
        }

        //反转结果链表
        return reverseList(dummyHead.next);
    }

    private ListNode reverseList (ListNode head) {
        ListNode prev = null;
        ListNode current = head;
        while (current != null) {
            ListNode nextTemp = current.next;
            current.next = prev;
            prev = current;
            current = nextTemp;
        }
        return prev;
    }
}

链表的合并

21.合并两个有序链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        //创建一个虚拟头节点
        ListNode dummyHead = new ListNode(0);
        ListNode current = dummyHead;

        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                current.next =list1;
                list1 = list1.next;
            } else {
                current.next = list2;
                list2 = list2.next;
            }
            current = current.next;
        }

        //如果其中一个链表还有剩余节点,直接连接
        if (list1 != null) {
            current.next = list1;
        }
        if (list2 != null) {
            current.next = list2;
        }

        //返回合并后的链表,跳过虚拟头节点
        return dummyHead.next;
    }
}

23.合并k个升序链表

import java.util.PriorityQueue;

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        // 创建一个最小堆
        PriorityQueue<ListNode> minHeap = new PriorityQueue<>((a,b) -> a.val - b.val);
        
        // 将所有链表的头节点加入最小堆
        for (ListNode head : lists) {
            if (head != null) {
                minHeap.offer(head);
            }
        }

        ListNode dummy = new ListNode(0);
        ListNode current = dummy;

        while (!minHeap.isEmpty()) {
            ListNode node = minHeap.poll();
            current.next = node;
            current = current.next;

            if (node.next != null) {
                minHeap.offer(node.next);
            }
        }

        return dummy.next;
    }
}

链表中的双指针

86.分隔链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode partition(ListNode head, int x) {
        if (head == null || head.next == null) {
            return head;
        }

        //创建两个虚拟节点,分别作为小于x和大于等于x的链表的头节点
        ListNode lessHead = new ListNode(-1);
        ListNode greaterHead = new ListNode(-1);

        //创建两个指针,分别指向小于x和大于等于x的链表的尾节点
        ListNode lessTail = lessHead;
        ListNode greaterTail = greaterHead;

        //遍历原链表
        ListNode current = head;
        while (current != null) {
            //如果当前节点的值小于x,则将其添加到小于x的链表的尾部
            if (current.val < x) {
                lessTail.next = current;
                lessTail = lessTail.next;
            } else {
                // 否则,将当前节点添加到大于等于 x 的链表的尾部
                greaterTail.next = current;
                greaterTail = greaterTail.next;
            }
            current = current.next;
        }

         // 将大于等于 x 的链表连接到小于 x 的链表的尾部
        lessTail.next = greaterHead.next;
        // 将大于等于 x 的链表的尾节点的 next 指针置为 null,防止形成环
        greaterTail.next = null;

        // 返回小于 x 的链表的头节点的下一个节点,即为分隔后的链表的头节点
        return lessHead.next; 
    }
}

141.环形链表

/**
 * Definition for singly-linked list.//定义一个单链表的节点
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while (slow != fast) {
            if (fast == null || fast.next == null) {
                return false;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
        return true;
    }
}

142.环形链表 ||

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }

        ListNode slow = head;
        ListNode fast = head;

        // 使用快慢指针判断是否有环
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) { // 快慢指针相遇,说明有环
                break;
            }
        }

        // 如果没有环,返回 null
        if (fast == null || fast.next == null) {
            return null;
        }

        // 将 slow 指针重置到 head,然后 slow 和 fast 每次都走一步
        slow = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }

        // 此时 slow 和 fast 相遇的节点就是环的入口节点
        return slow;
    }
}

876.链表的中间结点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

143.重排链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) {
            return;
        }

        //1.找到链表中点
        //使用快慢指针 slow 和 fast,初始都指向链表头节点 head。
        //在循环中,fast 每次移动两步,slow 每次移动一步。
        //当 fast 到达链表尾部 (fast == null 或 fast.next == null) 时,slow 指向链表的中点。
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }

        //2.反转后半部分链表
        ListNode prev = null, curr = slow.next;
        slow.next = null; //断开前半部分和后半部分的连接
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }

        //3.合并两个链表
        ListNode first = head, second = prev;
        while (second != null) {
            ListNode nextFirst = first.next;
            ListNode nextSecond = second.next;
            first.next = second;
            second.next = nextFirst;
            first = nextFirst;
            second = nextSecond;
        }
    }
}

160.相交链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }

        ListNode pA = headA, pB = headB;
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }

        return pA; // or return pB, since pA == pB
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值