常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法常见leetcode算法
递归排序
// 合并两个有序数组
private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
int i = left; // 左序列指针
int j = mid + 1; // 右序列指针
int t = 0; // 临时数组指针
// 比较左右两部分的元素,放入temp数组
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
temp[t++] = arr[i++];
} else {
temp[t++] = arr[j++];
}
}
// 将左边剩余元素填充进temp中
while (i <= mid) {
temp[t++] = arr[i++];
}
// 将右边剩余元素填充进temp中
while (j <= right) {
temp[t++] = arr[j++];
}
t = 0;
// 将temp中的元素全部拷贝到原数组中
while (left <= right) {
arr[left++] = temp[t++];
}
}
public class MergeSortRecursive {
// 主方法
public static void mergeSort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
int[] temp = new int[arr.length];
mergeSort(arr, 0, arr.length - 1, temp);
}
// 递归排序
private static void mergeSort(int[] arr, int left, int right, int[] temp) {
if (left < right) {
int mid = left + (right - left) / 2;
// 递归排序左半部分
mergeSort(arr, left, mid, temp);
// 递归排序右半部分
mergeSort(arr, mid + 1, right, temp);
// 合并两个有序数组
merge(arr, left, mid, right, temp);
}
}
public static void main(String[] args) {
int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
mergeSort(arr);
System.out.println("递归归并排序结果:");
for (int num : arr) {
System.out.print(num + " ");
}
}
}
public class MergeSortIterative {
public static void mergeSort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
int[] temp = new int[arr.length];
int length = arr.length;
// 初始子数组大小为1,然后依次加倍
for (int size = 1; size < length; size *= 2) {
// 遍历数组,合并相邻的子数组
for (int left = 0; left < length - size; left += 2 * size) {
int mid = left + size - 1;
int right = Math.min(left + 2 * size - 1, length - 1);
merge(arr, left, mid, right, temp);
}
}
}
public static void main(String[] args) {
int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
mergeSort(arr);
System.out.println("\n非递归归并排序结果:");
for (int num : arr) {
System.out.print(num + " ");
}
}
}
归并排序
快速排序
public class QuickSort {
public void sort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
private void quickSort(int[] arr, int low, int high) {
if (low < high) {
int partitionIndex = hoarePartition(arr, low, high);
quickSort(arr, low, partitionIndex);
quickSort(arr, partitionIndex + 1, high);
}
}
private int hoarePartition(int[] arr, int low, int high) {
// 选择中间元素作为基准(可改为其他选择方式)
int pivot = arr[(low + high) / 2];
int i = low - 1;
int j = high + 1;
while (true) {
// 从左向右找第一个大于等于pivot的元素
do {
i++;
} while (arr[i] < pivot);
// 从右向左找第一个小于等于pivot的元素
do {
j--;
} while (arr[j] > pivot);
if (i >= j) {
return j;
}
// 交换不符合条件的元素
swap(arr, i, j);
}
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 测试代码
public static void main(String[] args) {
int[] arr = {10, 7, 8, 9, 1, 5, 3, 2, 4, 6};
QuickSort qs = new QuickSort();
qs.sort(arr);
System.out.println("排序结果:");
for (int num : arr) {
System.out.print(num + " ");
}
}
}
二分查找方法
1。查到返回,查不到就返回要插入的位置 返回left
2。查某个数字在数组中出现的次数。0.5后0.5 返回left
4。旋转数组(括号,-1还是不加,有死循环啊)
返回要插入的数据:
class Solution {
public int searchAndInsert(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1;
while (left <= right) {
int mid = (right - left) /2 + left;
if (target ==nums[mid]) {
return mid;
}else if (nums[mid]<target){
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}
//最后一个数,或者大于的位置
class Solution {
public int searchAndInsert(int[] nums, int target+0.5) {
int n = nums.length;
int left = 0, right = n - 1;
while (left <= right) {
int mid = (right - left) /2 + left;
if (nums[mid]<target){
left = mid + 1;
} else {
right = mid - 1;
}
}
return left-1;
}
}
//第一个数,或者大于的位置
class Solution {
public int searchAndInsert(int[] nums, int target-0.5) {
int n = nums.length;
int left = 0, right = n - 1;
while (left <= right) {
int mid = (right - left) /2 + left;
if (nums[mid]<target){
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}
//最后一个数,或者大于的位置
class Solution {
public int searchAndInsert(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1;
while (left <= right) {
int mid = (right - left) /2 + left;
if (nums[mid]<=target){
left = mid + 1;
} else {
right = mid - 1;
}
}
return right;
}
}
//第一个数,或者大于的位置
class Solution {
public int searchAndInsert(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1;
while (left <= right) {
int mid = (right - left) /2 + left;
if (nums[mid]=>target){
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
}
背包问题
背包问题,n种物品,第i个物品体积为weight[i],价值为values[i]
定义 dp[w] 为背包容量为 w 时能获得的最大价值。所有初始化为0
01背包
for (int i = 0; i < n; i++) {
for (int w = W; w >= weights[i]; w--) {
// 决策:不选当前物品 或 选当前物品
dp[w] = Math.max(dp[w], dp[w - weights[i]] + values[i]);
}
}
完全背包
for (int i = 0; i < n; i++) {
for (int w = weights[i]; w <= W; w++) {
// 决策:不选当前物品 或 新增一个当前物品
dp[w] = Math.max(dp[w], dp[w - weights[i]] + values[i]);
}
恰好装满问题
public class CompleteKnapsackExactlyFull {
/**
* 完全背包恰好装满的最大价值
* @param W 背包容量
* @param weights 物品重量数组
* @param values 物品价值数组
* @return 最大价值(若无解返回-1)
*/
public static int knapCompleteExactlyFull(int W, int[] weights, int[] values) {
int[] dp = new int[W + 1];
// 初始化:除了容量0,其他状态都不可达
Arrays.fill(dp, Integer.MIN_VALUE);
dp[0] = 0;
for (int i = 0; i < weights.length; i++) {
for (int j = weights[i]; j <= W; j++) {
// 仅当减去当前物品重量的状态可达时,才能更新
if (dp[j - weights[i]] != Integer.MIN_VALUE) {
dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]);
}
}
}
return dp[W] < 0 ? -1 : dp[W]; // -1表示无解
}
/**
* 恰好装满的最小物品数量
* @param W 背包容量
* @param weights 物品重量数组
* @return 最小物品数量(若无解返回-1)
*/
public static int minItemsExactlyFull(int W, int[] weights) {
int[] dp = new int[W + 1];
// 初始化:除了容量0,其他状态都不可达
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int weight : weights) {
for (int j = weight; j <= W; j++) {
if (dp[j - weight] != Integer.MAX_VALUE) {
dp[j] = Math.min(dp[j], dp[j - weight] + 1);
}
}
}
return dp[W] == Integer.MAX_VALUE ? -1 : dp[W];}
}