数组
数组的改变、移动
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
}
}