数据结构与算法实例(Java实现)

数据结构与算法实例(Java实现)

以下是涵盖数据结构与算法的Java实例,涉及数组、链表、栈、队列、树、图、排序、搜索等核心内容。每个实例包含简要说明和关键代码片段。

数组相关

反转数组
public static void reverseArray(int[] arr) {
    int left = 0, right = arr.length - 1;
    while (left < right) {
        int temp = arr[left];
        arr[left++] = arr[right];
        arr[right--] = temp;
    }
}
使用临时数组

通过创建一个新数组并按逆序填充元素,实现反转。时间复杂度为 O(n),空间复杂度为 O(n)。

public static int[] reverseWithTempArray(int[] arr) {
    int[] reversed = new int[arr.length];
    for (int i = 0; i < arr.length; i++) {
        reversed[i] = arr[arr.length - 1 - i];
    }
    return reversed;
}
原地交换法

直接在原数组上进行首尾交换,无需额外空间。时间复杂度为 O(n),空间复杂度为 O(1)。

public static void reverseInPlace(int[] arr) {
    int start = 0;
    int end = arr.length - 1;
    while (start < end) {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
}
使用 Java 集合工具类

借助 Collections.reverse() 方法反转数组,需先将数组转为列表。时间复杂度为 O(n),但转换过程可能增加额外开销。

public static void reverseWithCollections(Integer[] arr) {
    List<Integer> list = Arrays.asList(arr);
    Collections.reverse(list);
}
运行时间对比
  • 临时数组法:适合需要保留原数组的场景,但空间占用较高。
  • 原地交换法:效率最高,适合对原数组直接修改的情况。
  • Collections 工具类:写法简洁,但可能因装箱/拆箱操作影响性能。
使用 Collections.reverse() 方法

对于 List 类型的数组,可以使用 Collections.reverse() 方法进行反转。这种方法简洁且高效。

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ReverseArray {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        Collections.reverse(list);
        System.out.println(list); // [5, 4, 3, 2, 1]
    }
}
使用临时数组进行反转

通过创建一个临时数组,将原数组的元素按逆序存入临时数组,从而实现反转。

public class ReverseArray {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int[] reversed = new int[arr.length];
        
        for (int i = 0; i < arr.length; i++) {
            reversed[i] = arr[arr.length - 1 - i];
        }
        
        System.out.println(Arrays.toString(reversed)); // [5, 4, 3, 2, 1]
    }
}
原地反转数组

通过交换数组的首尾元素,实现原地反转,无需额外空间。

public class ReverseArray {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int left = 0;
        int right = arr.length - 1;
        
        while (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
        
        System.out.println(Arrays.toString(arr)); // [5, 4, 3, 2, 1]
    }
}
使用 Stream API 反转数组

利用 Java 8 的 Stream API 实现数组反转,代码简洁但性能可能不如其他方法。

import java.util.Arrays;
import java.util.stream.IntStream;

public class ReverseArray {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int[] reversed = IntStream.range(0, arr.length)
                                .map(i -> arr[arr.length - 1 - i])
                                .toArray();
        
        System.out.println(Arrays.toString(reversed)); // [5, 4, 3, 2, 1]
    }
}
使用 StringBuilder 反转字符串数组

对于字符串数组,可以先将数组转换为字符串,再通过 StringBuilder.reverse() 方法反转。

public class ReverseArray {
    public static void main(String[] args) {
        String[] arr = {"a", "b", "c", "d", "e"};
        StringBuilder sb = new StringBuilder(Arrays.toString(arr));
        String reversed = sb.reverse().toString();
        
        System.out.println(reversed); // ]e ,d ,c ,b ,a[
    }
}
查找数组中的最大值
public static int findMax(int[] arr) {
    int max = arr[0];
    for (int num : arr) {
        if (num > max) max = num;
    }
    return max;
}

两数之和(哈希表优化)
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        if (map.containsKey(target - nums[i])) {
            return new int[]{map.get(target - nums[i]), i};
        }
        map.put(nums[i], i);
    }
    return new int[0];
}


链表操作

单链表反转
public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    while (head != null) {
        ListNode next = head.next;
        head.next = prev;
        prev = head;
        head = next;
    }
    return prev;
}

检测链表环(快慢指针)
public boolean hasCycle(ListNode head) {
    ListNode slow = head, fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
        if (slow == fast) return true;
    }
    return false;
}

合并两个有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode dummy = new ListNode(0);
    ListNode curr = dummy;
    while (l1 != null && l2 != null) {
        if (l1.val < l2.val) {
            curr.next = l1;
            l1 = l1.next;
        } else {
            curr.next = l2;
            l2 = l2.next;
        }
        curr = curr.next;
    }
    curr.next = l1 != null ? l1 : l2;
    return dummy.next;
}
递归反转单链表

递归方法通过不断递归到链表末尾,然后反向修改指针实现反转。优点是代码简洁,但需要注意栈溢出风险(链表过长时)。

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

迭代反转单链表(双指针)

通过双指针(前驱prev和当前curr)遍历链表,逐个修改节点指向。空间复杂度为O(1),适合处理长链表。

public ListNode reverseList(ListNode head) {
    ListNode prev = null, curr = head;
    while (curr != null) {
        ListNode nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

头插法反转单链表

利用虚拟头节点(dummy),将遍历到的节点逐个插入到虚拟头节点之后,最终得到反转链表。

public ListNode reverseList(ListNode head) {
    ListNode dummy = new ListNode(-1);
    while (head != null) {
        ListNode next = head.next;
        head.next = dummy.next;
        dummy.next = head;
        head = next;
    }
    return dummy.next;
}

使用栈辅助反转

通过栈的“后进先出”特性反转链表。需额外空间,适合需要保留原链表的场景。

public ListNode reverseList(ListNode head) {
    Stack<ListNode> stack = new Stack<>();
    while (head != null) {
        stack.push(head);
        head = head.next;
    }
    ListNode dummy = new ListNode(-1);
    ListNode curr = dummy;
    while (!stack.isEmpty()) {
        curr.next = stack.pop();
        curr = curr.next;
    }
    curr.next = null;
    return dummy.next;
}

反转链表区间(局部反转)

反转链表中指定区间内的节点,如LeetCode 92题。结合双指针和头插法实现局部反转。

public ListNode reverseBetween(ListNode head, int left, int right) {
    ListNode dummy = new ListNode(-1);
    dummy.next = head;
    ListNode pre = dummy;
    for (int i = 0; i < left - 1; i++) {
        pre = pre.next;
    }
    ListNode curr = pre.next;
    for (int i = left; i < right; i++) {
        ListNode next = curr.next;
        curr.next = next.next;
        next.next = pre.next;
        pre.next = next;
    }
    return dummy.next;
}

每个方法适用于不同场景:递归简洁但需注意栈深度,迭代法通用高效,头插法适合部分问题,栈辅助可保留原链表,局部反转解决特定需求。


树结构

二叉树前序遍历(递归)
public void preorder(TreeNode root) {
    if (root == null) return;
    System.out.print(root.val + " ");
    preorder(root.left);
    preorder(root.right);
}

二叉树层序遍历(队列)
public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if (root == null) return res;
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        int size = queue.size();
        List<Integer> level = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KENYCHEN奉孝

您的鼓励是我的进步源泉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值