Morris 遍历是一种用于二叉树遍历的算法,它利用树中大量空闲的空指针,在不使用额外栈空间和递归的情况下,完成树的遍历。通过建立临时的线索连接,使得可以按照中序遍历的顺序访问节点,访问完后再将这些线索连接恢复。
java
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class MorrisInorderTraversal {
public void inorderTraversal(TreeNode root) {
TreeNode current = root;
while (current != null) {
if (current.left == null) {
System.out.print(current.val + " ");
current = current.right;
} else {
TreeNode pre = current.left;
while (pre.right != null && pre.right != current) {
pre = pre.right;
}
if (pre.right == null) {
pre.right = current;
current = current.left;
} else {
pre.right = null;
System.out.print(current.val + " ");
current = current.right;
}
}
}
}
}
快速选择算法是基于快速排序思想的一种选择算法,用于在未排序的数组中找到第 k 小(或第 k 大)的元素。通过选择一个基准元素,将数组分为两部分,使得左边部分的元素都小于等于基准元素,右边部分的元素都大于等于基准元素,然后根据基准元素的位置与 k 的关系,决定在左边或右边部分继续查找。
java
public class KthSmallestElement {
public int findKthSmallest(int[] nums, int k) {
return quickSelect(nums, 0, nums.length - 1, k - 1);
}
private int quickSelect(int[] nums, int left, int right, int k) {
if (left == right) {
return nums[left];
}
int pivotIndex = partition(nums, left, right);
if (k == pivotIndex) {
return nums[k];
} else if (k < pivotIndex) {
return quickSelect(nums, left, pivotIndex - 1, k);
} else {
return quickSelect(nums, pivotIndex + 1, right, k);
}
}
private int partition(int[] nums, int left, int right) {
int pivot = nums[right];
int i = left - 1;
for (int j = left; j < right; j++) {
if (nums[j] <= pivot) {
i++;
swap(nums, i, j);
}
}
swap(nums, i + 1, right);
return i + 1;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
埃拉托斯特尼筛法(Sieve of Eratosthenes)是一种用于找出一定范围内所有素数的算法。其基本思想是从 2 开始,将每个素数的倍数标记为合数,直到遍历完所有小于等于根号n的数,剩下未被标记的数即为素数。
java
import java.util.ArrayList;
import java.util.List;
public class PrimeNumbers {
public List findPrimes(int n) {
boolean[] isPrime = new boolean[n + 1];
for (int i = 2; i <= n; i++) {
isPrime[i] = true;
}
for (int p = 2; p * p <= n; p++) {
if (isPrime[p]) {
for (int i = p * p; i <= n; i += p) {
isPrime[i] = false;
}
}
}
List primes = new ArrayList<>();
for (int i = 2; i <= n; i++) {
if (isPrime[i]) {
primes.add(i);
}
}
return primes;
}
}
希尔排序是一种改进的插入排序算法,也称为缩小增量排序。它通过将原始数据分成多个子序列来改善插入排序的性能,先比较距离较远的元素,而不是像插入排序那样比较相邻元素,这样可以使元素更快地移动到它们应该在的位置附近。然后逐渐缩小间隔,直到间隔为 1,此时就是普通的插入排序。
java
public class ShellSort {
public void shellSort(int[] arr) {
int n = arr.length;
for (int gap = n / 2; gap > 0; gap /= 2) {
for (int i = gap; i < n; i++) {
int temp = arr[i];
int j;
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
arr[j] = arr[j - gap];
}
arr[j] = temp;
}
}
}
}
循环队列是一种线性数据结构,它使用数组来存储元素,并通过两个指针(front 和 rear)来表示队列的头部和尾部。当队列的尾部指针到达数组的末尾时,可以通过取模运算将其重新指向数组的开头,从而实现循环利用数组空间。
(rear + 1) % capacity == front
,队列为空的条件是 front == rear
。java
class CircularQueue {
private int[] queue;
private int front;
private int rear;
private int capacity;
public CircularQueue(int capacity) {
this.capacity = capacity;
this.queue = new int[capacity];
this.front = 0;
this.rear = 0;
}
public boolean isFull() {
return (rear + 1) % capacity == front;
}
public boolean isEmpty() {
return front == rear;
}
public void enqueue(int item) {
if (isFull()) {
System.out.println("Queue is full");
return;
}
queue[rear] = item;
rear = (rear + 1) % capacity;
}
public int dequeue() {
if (isEmpty()) {
System.out.println("Queue is empty");
return -1;
}
int item = queue[front];
front = (front + 1) % capacity;
return item;
}
}
汉诺塔问题是一个经典的递归问题。假设有三根柱子 A、B、C,要将 n 个盘子从柱子 A 移动到柱子 C,可以将问题分解为以下三个步骤:先将 n - 1 个盘子从柱子 A 移动到柱子 B,再将第 n 个盘子从柱子 A 移动到柱子 C,最后将 n - 1 个盘子从柱子 B 移动到柱子 C。
java
public class HanoiTower {
public void hanoi(int n, char source, char auxiliary, char target) {
if (n == 1) {
System.out.println("Move disk 1 from " + source + " to " + target);
return;
}
hanoi(n - 1, source, target, auxiliary);
System.out.println("Move disk " + n + " from " + source + " to " + target);
hanoi(n - 1, auxiliary, source, target);
}
}
前序遍历是一种二叉树的遍历方式,按照根节点 -> 左子树 -> 右子树的顺序访问节点。可以使用递归或栈来实现。递归实现是先访问根节点,然后递归地遍历左子树,最后递归地遍历右子树;栈实现是将根节点入栈,然后不断从栈中取出节点,访问该节点,将其右子节点和左子节点依次入栈(注意顺序,先右后左)。
java
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
import java.util.Stack;
public class PreorderTraversal {
// 递归实现
public void preorderRecursive(TreeNode root) {
if (root != null) {
System.out.print(root.val + " ");
preorderRecursive(root.left);
preorderRecursive(root.right);
}
}
// 栈实现
public void preorderIterative(TreeNode root) {
if (root == null) {
return;
}
Stack stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.val + " ");
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
}
}
多叉树是一种每个节点可以有多个子节点的树结构。层次遍历是按照树的层次依次访问节点,通常使用队列来实现。将根节点入队,然后不断从队列中取出节点,访问该节点,并将其所有子节点入队。
java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
class TreeNode {
int val;
List children;
TreeNode(int val) {
this.val = val;
this.children = new ArrayList<>();
}
}
public class NaryTreeLevelOrderTraversal {
public void levelOrderTraversal(TreeNode root) {
if (root == null) {
return;
}
Queue queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.print(node.val + " ");
for (TreeNode child : node.children) {
queue.offer(child);
}
}
}
}
可以使用哈希集合(HashSet)来去除字符串中重复的字符。遍历字符串中的每个字符,将其添加到哈希集合中,由于哈希集合不允许重复元素,重复的字符会自动被过滤掉。最后将哈希集合中的字符拼接成字符串输出。
java
import java.util.HashSet;
import java.util.Set;
public class RemoveDuplicateCharacters {
public String removeDuplicates(String str) {
Set set = new HashSet<>();
StringBuilder result = new StringBuilder();
for (char c : str.toCharArray()) {
if (set.add(c)) {
result.append(c);
}
}
return result.toString();
}
}
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90546476