冒泡排序
java
public class OptimizedBubbleSort {
public static void bubbleSort(int[] arr) {
int n = arr.length;
boolean swapped;
for (int i = 0; i < n - 1; i++) {
swapped = false;
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交换 arr[j+1] 和 arr[j]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
// 如果没有发生交换,说明数组已经有序
if (!swapped) {
break;
}
}
}
public static void main(String[] args) {
int[] arr = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(arr);
for (int num : arr) {
System.out.print(num + " ");
}
}
}
选择排序
插入排序
java
public class BinaryInsertionSort {
public static void binaryInsertionSort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int key = arr[i];
int left = 0;
int right = i - 1;
// 使用二分查找找到插入位置
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] > key) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// 移动元素
for (int j = i - 1; j >= left; j--) {
arr[j + 1] = arr[j];
}
// 插入元素
arr[left] = key;
}
}
public static void main(String[] args) {
int[] arr = {64, 34, 25, 12, 22, 11, 90};
binaryInsertionSort(arr);
for (int num : arr) {
System.out.print(num + " ");
}
}
}
快速排序
归并排序
堆排序
Dijkstra 算法是一种贪心算法,用于求解带权有向图或无向图中单个源点到其他所有顶点的最短路径。它的基本思想是:从源点开始,逐步扩展到距离源点最近的顶点,更新这些顶点到源点的最短距离,直到所有顶点都被访问过。
代码示例
java
import java.util.*;
class Dijkstra {
static final int INF = Integer.MAX_VALUE;
public static int[] dijkstra(int[][] graph, int src) {
int n = graph.length;
int[] dist = new int[n];
boolean[] visited = new boolean[n];
Arrays.fill(dist, INF);
dist[src] = 0;
PriorityQueue pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
pq.offer(new int[]{src, 0});
while (!pq.isEmpty()) {
int[] curr = pq.poll();
int u = curr[0];
if (visited[u]) continue;
visited[u] = true;
for (int v = 0; v < n; v++) {
if (!visited[v] && graph[u][v] != 0 && dist[u] != INF && dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
pq.offer(new int[]{v, dist[v]});
}
}
}
return dist;
}
public static void main(String[] args) {
int[][] graph = {
{0, 4, 0, 0, 0, 0, 0, 8, 0},
{4, 0, 8, 0, 0, 0, 0, 11, 0},
{0, 8, 0, 7, 0, 4, 0, 0, 2},
{0, 0, 7, 0, 9, 14, 0, 0, 0},
{0, 0, 0, 9, 0, 10, 0, 0, 0},
{0, 0, 4, 14, 10, 0, 2, 0, 0},
{0, 0, 0, 0, 0, 2, 0, 1, 6},
{8, 11, 0, 0, 0, 0, 1, 0, 7},
{0, 0, 2, 0, 0, 0, 6, 7, 0}
};
int[] dist = dijkstra(graph, 0);
for (int i = 0; i < dist.length; i++) {
System.out.println("Shortest distance from source to vertex " + i + " is " + dist[i]);
}
}
}
旋转数组是将一个有序数组在某个点进行旋转得到的。可以使用二分查找来找出目标数。通过比较中间元素和数组两端元素的大小关系,判断目标数可能存在的区间。
代码示例
java
public class SearchInRotatedSortedArray {
public static int search(int[] nums, int target) {
int left = 0, 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 (target >= nums[left] && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
if (target > nums[mid] && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
public static void main(String[] args) {
int[] nums = {4, 5, 6, 7, 0, 1, 2};
int target = 0;
int index = search(nums, target);
System.out.println("Index of target: " + index);
}
}
哲学家问题是一个经典的并发编程问题,描述了多个哲学家围坐在圆桌旁,每个哲学家之间有一根筷子,哲学家交替进行思考和进餐。进餐时需要同时拿起左右两根筷子,否则会挨饿。该问题主要探讨如何避免死锁和资源竞争。
哲学家问题可以推广到更一般的资源竞争问题,如多个线程对多个共享资源的竞争。在实际开发中,需要根据具体情况选择合适的解决方法来避免死锁和资源竞争。
可以使用动态规划的思想来解决该问题。定义一个数组 dp
,其中 dp[i]
表示以第 i
个元素结尾的最大连续子序列和。状态转移方程为 dp[i] = max(dp[i - 1] + nums[i], nums[i])
。
代码示例
java
public class MaximumSubarray {
public static int maxSubArray(int[] nums) {
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(dp[i - 1] + nums[i], nums[i]);
maxSum = Math.max(maxSum, dp[i]);
}
return maxSum;
}
public static void main(String[] args) {
int[] nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
int maxSum = maxSubArray(nums);
System.out.println("Maximum subarray sum: " + maxSum);
}
}
dp[i]
只与 dp[i - 1]
有关,可以使用一个变量来代替 dp
数组。以下是优化后的代码示例:java
public class MaximumSubarrayOptimized {
public static int maxSubArray(int[] nums) {
int n = nums.length;
int currentSum = nums[0];
int maxSum = nums[0];
for (int i = 1; i < n; i++) {
currentSum = Math.max(currentSum + nums[i], nums[i]);
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}
public static void main(String[] args) {
int[] nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
int maxSum = maxSubArray(nums);
System.out.println("Maximum subarray sum: " + maxSum);
}
}
2. 可以拓展到二维数组,求最大子矩阵和。可以通过枚举矩阵的上下边界,将二维问题转化为一维问题,然后使用一维最大连续子序列和的方法来求解。
最左前缀匹配通常用于数据库的索引优化。在数据库中,当查询条件使用了索引的最左前缀时,可以利用索引来加速查询。例如,对于复合索引 (col1, col2, col3)
,查询条件 WHERE col1 = 'value1' AND col2 = 'value2'
可以使用该索引进行最左前缀匹配。
EXPLAIN
语句来查看查询的执行计划,判断是否使用了索引。可以使用迭代或递归的方法来反转单链表。迭代方法通过遍历链表,依次改变节点的指针方向;递归方法则是先递归地反转后续节点,再调整当前节点的指针方向。
代码示例(迭代)
java
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class ReverseLinkedList {
public static ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
public static void printList(ListNode head) {
ListNode curr = head;
while (curr != null) {
System.out.print(curr.val + " ");
curr = curr.next;
}
System.out.println();
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
System.out.println("Original list:");
printList(head);
ListNode reversedHead = reverseList(head);
System.out.println("Reversed list:");
printList(reversedHead);
}
}
代码示例(递归)
java
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class ReverseLinkedListRecursive {
public static ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
public static void printList(ListNode head) {
ListNode curr = head;
while (curr != null) {
System.out.print(curr.val + " ");
curr = curr.next;
}
System.out.println();
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
System.out.println("Original list:");
printList(head);
ListNode reversedHead = reverseList(head);
System.out.println("Reversed list:");
printList(reversedHead);
}
}
可以使用数组本身作为哈希表来解决该问题。首先将数组中所有小于等于 0 或大于数组长度的数置为一个特殊值(如数组长度加 1),然后遍历数组,将出现过的正整数对应的数组位置的元素置为负数,最后再次遍历数组,找到第一个正数所在的位置,该位置加 1 就是未出现的第一个正整数。
代码示例
java
public class FirstMissingPositive {
public static 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;
}
public static void main(String[] args) {
int[] nums = {3, 4, -1, 1};
int firstMissing = firstMissingPositive(nums);
System.out.println("First missing positive: " + firstMissing);
}
}
可以使用求和公式或异或运算来解决该问题。求和公式方法是先计算 0 到 n 的和,再减去数组中所有元素的和,得到的差值就是缺少的数;异或运算方法是将 0 到 n 的所有数与数组中的所有数进行异或运算,最终结果就是缺少的数。
a ^ a = 0
,a ^ 0 = a
。代码示例(异或运算)
java
public class MissingNumber {
public static int missingNumber(int[] nums) {
int n = nums.length;
int xor = 0;
for (int i = 0; i < n; i++) {
xor ^= nums[i];
}
for (int i = 0; i <= n; i++) {
xor ^= i;
}
return xor;
}
public static void main(String[] args) {
int[] nums = {3, 0, 1};
int missing = missingNumber(nums);
System.out.println("Missing number: " + missing);
}
}
可以使用快慢指针的方法来判断链表中是否有环路。快指针每次移动两步,慢指针每次移动一步,如果链表中有环路,快指针最终会追上慢指针。
代码示例
java
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class LinkedListCycle {
public static 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;
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
head.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node2;
boolean hasCycle = hasCycle(head);
System.out.println("Linked list has cycle: " + hasCycle);
}
}
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90535485