实战Java:用乐趣驱动高效学习和编程实践

本文介绍了10个常见的编程算法问题的Java实现,包括字符串反转、斐波那契数列、判断回文数、单链表反转、数组去重、查找两个数组的交集、实现栈和队列、二叉树的前序、中序和后序遍历以及二分查找。这些算法涉及数据结构和基础算法,是编程面试中常见的题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

1. 反转字符串:

给定一个字符串,将其反转并返回。
以下是一个简单的 Java 代码示例,用于反转给定字符串并返回结果:

public class StringReversal {
    public static String reverseString(String str) {
        if (str == null || str.length() <= 1) {
            return str;
        }
        
        char[] charArray = str.toCharArray();
        int left = 0;
        int right = charArray.length - 1;
        
        while (left < right) {
            char temp = charArray[left];
            charArray[left] = charArray[right];
            charArray[right] = temp;
            left++;
            right--;
        }
        
        return new String(charArray);
    }
    
    public static void main(String[] args) {
        String input = "Hello World!";
        String reversed = reverseString(input);
        System.out.println(reversed);
    }
}

在上述代码中,我们定义了一个名为 reverseString 的静态方法,它接受一个字符串作为输入,并返回反转后的字符串。我们使用双指针法,将左指针从字符串的起始位置开始,右指针从字符串的末尾位置开始,并不断交换左右指针所指向的字符,直到左指针大于或等于右指针为止。最后,我们将字符数组转换回字符串并返回反转后的结果。

main 方法中,我们演示了如何使用 reverseString 方法来反转一个字符串,并将结果打印输出。

以上代码输出的结果将是:!dlroW olleH,即给定字符串 “Hello World!” 反转后的结果。

请注意,上述代码只是一个简单的实现示例,可能不考虑一些特殊情况(例如空字符串或 null 值)。在实际应用中,我们需要根据具体需求进行适当的边界检查和错误处理。

2. 斐波那契数列:

实现一个函数,返回斐波那契数列的第 n 项。

下面是一个简单的 Java 代码示例,用于返回斐波那契数列的第 n 项:

public class Fibonacci {
    public static int fibonacci(int n) {
        if (n <= 0) {
            throw new IllegalArgumentException("输入的 n 必须大于等于 1");
        }
        
        if (n == 1 || n == 2) {
            return 1;
        }
        
        int prev1 = 1;
        int prev2 = 1;
        int current = 0;
        
        for (int i = 3; i <= n; i++) {
            current = prev1 + prev2;
            prev1 = prev2;
            prev2 = current;
        }
        
        return current;
    }
    
    public static void main(String[] args) {
        int n = 6;
        int result = fibonacci(n);
        System.out.println("斐波那契数列的第 " + n + " 项是:" + result);
    }
}

在上述代码中,我们定义了一个名为 fibonacci 的静态方法,它接受一个整数n作为输入,并返回斐波那契数列的第 n 项。

我们使用了迭代的方式来计算斐波那契数列,设置三个变量 prev1prev2current 分别表示前两个数、当前数以及计算过程中的临时变量。我们从 n=3 开始迭代计算,每次将前两个数相加来得到当前数,并通过更新 prev1prev2 来保持计算的连续性,直到计算到第 n 项。

main 方法中,我们演示了如何使用 fibonacci 方法来计算斐波那契数列的第 n 项,并将结果打印输出。

以上代码输出的结果将是:斐波那契数列的第 6 项是:8。

请注意,上述代码对于输入的边界情况可能没有进行全面的检查,例如输入负数或零时会抛出异常。在实际应用中,我们需要根据具体需求进行适当的错误处理。

3. 判断回文数:

判断一个整数是否是回文数,例如,121 是回文数,而 123 不是。

下面是一个简单的 Java 代码示例,用于判断一个整数是否是回文数:

public class PalindromeNumber {
    public static boolean isPalindrome(int x) {
        if (x < 0) {
            return false;
        }
        
        int reversed = 0;
        int original = x;
        
        while (x != 0) {
            int digit = x % 10;
            reversed = reversed * 10 + digit;
            x /= 10;
        }
        
        return original == reversed;
    }
    
    public static void main(String[] args) {
        int number1 = 121;
        boolean result1 = isPalindrome(number1);
        System.out.println(number1 + " 是回文数吗?" + result1);
        
        int number2 = 123;
        boolean result2 = isPalindrome(number2);
        System.out.println(number2 + " 是回文数吗?" + result2);
    }
}

在上述代码中,我们定义了一个名为 isPalindrome 的静态方法,它接受一个整数 x 作为输入,并判断 x 是否是回文数。

我们首先判断 x 是否小于零,如果是,则直接返回 false,因为负数不可能是回文数。

然后,我们使用一个变量 reversed 来存储 x 的反转结果,初始值为 0。我们使用一个变量 original 来保存原始的 x 值。

接下来,我们通过循环从 x 的个位开始逐位取数字,将其添加到 reversed 的末尾,并将 x 降低一个位数。循环结束后,reversed 存储的就是 x 的反转结果。

最后,我们判断 original 是否等于 reversed,如果相等,则 x 是回文数,返回 true,否则返回 false

main 方法中,我们演示了如何使用 isPalindrome 方法来判断两个整数是否是回文数,并将判断结果打印输出。

以上代码输出的结果将是:

121 是回文数吗?true
123 是回文数吗?false

请注意,上述代码对于负数的判断是直接返回 false,因为负数不可能是回文数。具体要根据实际需求来确定对负数的处理方式。

4. 单链表反转:

实现一个函数,反转一个单链表。

下面是一个简单的 Java 代码示例,用于反转一个单链表:

public class ListNode {
    int val;
    ListNode next;
    
    ListNode(int val) {
        this.val = val;
    }
}

public class LinkedListReversal {
    public static ListNode reverseList(ListNode head) {
        ListNode prev = null;
        
        while (head != null) {
            ListNode nextNode = head.next;
            head.next = prev;
            prev = head;
            head = nextNode;
        }
        
        return prev;
    }
    
    public static void main(String[] args) {
        // 创建链表 1->2->3->4->5
        ListNode head = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        head.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        
        // 反转链表
        ListNode reversedHead = reverseList(head);
        
        // 打印反转后的链表
        ListNode current = reversedHead;
        while (current != null) {
            System.out.print(current.val + " ");
            current = current.next;
        }
    }
}

在上述代码中,我们定义了一个名为 ListNode 的类,用于表示链表的节点。每个节点包含一个整数类型的值 val 和一个指向下一个节点的指针 next

然后,我们定义了一个名为 reverseList 的静态方法,它接受链表的头节点 head 作为输入,并返回反转后的链表头节点。

我们使用三个指针 headprevnextNode 来进行反转操作。初始化时,prev 指针为空,然后我们循环遍历链表,每次将当前节点的 next 指针指向上一个节点 prev,然后将 prev 指针更新为当前节点,当前节点更新为下一个节点。当遍历结束后,prev 指向的节点即为反转后的链表的头节点。

main 方法中,我们创建了一个链表 1->2->3->4->5,并将其反转。最后,我们打印输出反转后的链表的值。

以上代码输出的结果将是:5 4 3 2 1,即给定链表反转后的结果。

请注意,上述代码只是一个简单的实现示例,可能不考虑一些特殊情况(例如空链表或只有一个节点的链表)。在实际应用中,我们需要根据具体需求进行适当的边界检查和错误处理。

5. 数组去重:

给定一个数组,删除其中重复的元素并返回新的数组。

下面是一个简单的 Java 代码示例,用于删除数组中重复的元素并返回新的数组:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ArrayDuplicateRemoval {
    public static int[] removeDuplicates(int[] nums) {
        Set<Integer> set = new HashSet<>();
        
        for (int num : nums) {
            set.add(num);
        }
        
        int[] result = new int[set.size()];
        int i = 0;
        
        for (int num : set) {
            result[i++] = num;
        }
        
        return result;
    }
    
    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 2, 4, 1, 5, 6, 3, 4};
        int[] result = removeDuplicates(nums);
        
        for (int num : result) {
            System.out.print(num + " ");
        }
    }
}

在上述代码中,我们定义了一个名为 removeDuplicates 的静态方法,它接受一个整型数组 nums 作为输入,并返回去重后的新数组。

我们使用 HashSet 来存储数组中的不重复元素。遍历数组 nums,将每个元素添加到 HashSet 中。由于 HashSet 中不允许重复的元素存在,所以最终得到的 HashSet 中就是数组中去重后的元素。

接下来,我们根据 HashSet 的大小创建一个新的整型数组 result,并将 HashSet 中的元素依次复制到 result 数组中。

最后,我们将 result 数组作为函数的返回值。

main 方法中,我们演示了如何使用 removeDuplicates 方法来删除数组中的重复元素,并将结果打印输出。

以上代码输出的结果将是:1 2 3 4 5 6,即给定数组去重后的结果。

请注意,上述代码中使用了 HashSet 来存储去重后的元素。这是因为 HashSet 具有自动去重的特性,并且可以快速的插入和查询操作。如果要保持原始数组的顺序,可以考虑使用 LinkedHashSet 来存储元素。同时,上述代码也可以适用于其他类型的数组,只需要将方法中的数据类型改为对应的类型即可。

6. 查找两个数组的交集:

给定两个数组,找出它们的交集并返回。

下面是一个简单的 Java 代码示例,用于找出两个数组的交集并返回:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ArrayIntersection {
    public static int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new HashSet<>();
        
        // 将 nums1 中的元素添加到 set1 中
        for (int num : nums1) {
            set1.add(num);
        }
        
        // 查找 nums2 中同时存在于 set1 和 set2 的元素
        for (int num : nums2) {
            if (set1.contains(num)) {
                set2.add(num);
            }
        }
        
        int[] result = new int[set2.size()];
        int i = 0;
        
        // 将 set2 中的元素复制到 result 数组
        for (int num : set2) {
            result[i++] = num;
        }
        
        return result;
    }
    
    public static void main(String[] args) {
        int[] nums1 = {1, 2, 2, 1};
        int[] nums2 = {2, 2, 3};
        int[] result = intersection(nums1, nums2);
        
        for (int num : result) {
            System.out.print(num + " ");
        }
    }
}

在上述代码中,我们定义了一个名为 intersection 的静态方法,它接受两个整型数组 nums1nums2 作为输入,并返回这两个数组的交集。

我们使用两个 HashSet 分别保存数组 nums1nums2 中的元素。

首先,我们使用第一个 HashSet set1 遍历 nums1,将 nums1 中的元素添加到 set1 中。这样,set1 中就存储了 nums1 中的不重复元素。

然后,我们遍历 nums2 数组,如果当前元素在 set1 中存在,则将其添加到第二个 HashSet set2 中。这样,set2 中就存储了 nums1nums2 的交集元素。

接下来,我们将 set2 中的元素复制到一个新的整型数组 result 中,并返回 result 数组作为函数的结果。

main 方法中,我们演示了如何使用 intersection 方法来找出两个数组的交集,并将结果打印输出。

以上代码输出的结果将是:2,即给定两个数组的交集。

请注意,上述代码中使用了两个 HashSet 来存储数组的元素,这是为了利用 HashSet 的去重特性和快速的添加和查询操作。同时,上述代码也可以适用于其他类型的数组,只需要将方法中的数据类型改为对应的类型即可。

7. 实现栈:

使用数组或链表实现一个栈,并实现栈的基本操作,如入栈(push)、出栈(pop)等。

下面是一个使用数组实现的简单栈的示例代码:

public class ArrayStack {
    private int[] stack;  // 数组实现栈的存储结构
    private int top;  // 栈顶指针

    public ArrayStack(int capacity) {
        stack = new int[capacity];
        top = -1;  // 初始化栈顶指针为-1,表示栈为空
    }

    public void push(int item) {
        if (top == stack.length - 1) {
            System.out.println("栈已满,无法入栈。");
            return;
        }
        stack[++top] = item;
    }

    public int pop() {
        if (top == -1) {
            System.out.println("栈为空,无法出栈。");
            return -1;
        }
        return stack[top--];
    }

    public int peek() {
        if (top == -1) {
            System.out.println("栈为空,无数据可查看。");
            return -1;
        }
        return stack[top];
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public int size() {
        return top + 1;
    }

    public void printStack() {
        if (top == -1) {
            System.out.println("栈为空。");
            return;
        }
        System.out.print("栈元素:");
        for (int i = 0; i <= top; i++) {
            System.out.print(stack[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(5);

        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);

        stack.printStack();  // 栈元素:1 2 3 4 5

        System.out.println("栈顶元素:" + stack.peek());  // 栈顶元素:5

        stack.pop();
        stack.pop();

        stack.printStack();  // 栈元素:1 2 3

        System.out.println("栈大小:" + stack.size());  // 栈大小:3
    }
}

上述代码中,我们通过一个 int 数组 stack 实现了栈的存储结构,使用 top 变量记录栈顶指针。

栈的基本操作包括:

  • push(int item):入栈操作,将元素 item 加入栈顶。
  • pop():出栈操作,从栈顶弹出一个元素并返回。
  • peek():查看栈顶元素,返回栈顶元素的值但不移除。
  • isEmpty():判断栈是否为空。
  • size():返回栈中元素的数量。
  • printStack():打印栈中的所有元素。

main 方法中,我们演示了如何使用 ArrayStack 类来创建并操作一个栈。首先,我们依次将元素 1、2、3、4、5 入栈。然后,打印栈中的元素、查看栈顶元素、出栈两次,并再次打印栈中元素和栈的大小。

输出的结果将是:

栈元素:1 2 3 4 5
栈顶元素:5
栈元素:1 2 3
栈大小:3

你也可以根据自己的需求扩展其他操作或完善异常处理。此外,你也可以使用链表来实现栈的存储结构,只需对节点进行插入和删除操作即可。

8. 实现队列:

使用数组或链表实现一个队列,并实现队列的基本操作,如入队(enqueue)、出队(dequeue)等。

下面是一个使用数组实现的简单队列的示例代码:

public class ArrayQueue {
    private int[] queue;  // 数组实现队列的存储结构
    private int front;  // 队头指针
    private int rear;  // 队尾指针
    private int size;  // 队列当前元素数量

    public ArrayQueue(int capacity) {
        queue = new int[capacity];
        front = 0;
        rear = -1;
        size = 0;
    }

    public void enqueue(int item) {
        if (size == queue.length) {
            System.out.println("队列已满,无法入队。");
            return;
        }
        rear = (rear + 1) % queue.length;
        queue[rear] = item;
        size++;
    }

    public int dequeue() {
        if (size == 0) {
            System.out.println("队列为空,无法出队。");
            return -1;
        }
        int item = queue[front];
        front = (front + 1) % queue.length;
        size--;
        return item;
    }

    public int getFront() {
        if (size == 0) {
            System.out.println("队列为空。");
            return -1;
        }
        return queue[front];
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public int size() {
        return size;
    }

    public void printQueue() {
        if (size == 0) {
            System.out.println("队列为空。");
            return;
        }
        System.out.print("队列元素:");
        for (int i = 0; i < size; i++) {
            int index = (front + i) % queue.length;
            System.out.print(queue[index] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        ArrayQueue queue = new ArrayQueue(5);

        queue.enqueue(1);
        queue.enqueue(2);
        queue.enqueue(3);
        queue.enqueue(4);
        queue.enqueue(5);

        queue.printQueue();  // 队列元素:1 2 3 4 5

        System.out.println("队列头部元素:" + queue.getFront());  // 队列头部元素:1

        queue.dequeue();
        queue.dequeue();

        queue.printQueue();  // 队列元素:3 4 5

        System.out.println("队列大小:" + queue.size());  // 队列大小:3
    }
}

在上述代码中,我们通过一个 int 数组 queue 实现了队列的存储结构,使用 frontrear 变量分别记录队头和队尾指针,size 变量记录当前队列中的元素数量。

队列的基本操作包括:

  • enqueue(int item):入队操作,将元素 item 加入队尾。
  • dequeue():出队操作,从队头移除一个元素并返回。
  • getFront():获取队头元素,返回队头元素的值但不移除。
  • isEmpty():判断队列是否为空。
  • size():返回队列中元素的数量。
  • printQueue():打印队列中的所有元素。

main 方法中,我们演示了如何使用 ArrayQueue 类来创建并操作一个队列。首先,我们依次将元素 1、2、3、4、5 入队。然后,打印队列中的元素、获取队头元素、出队两次,并再次打印队列中的元素和队列的大小。

输出的结果将是:

队列元素:1 2 3 4 5
队列头部元素:1
队列元素:3 4 5
队列大小:3

你也可以根据实际需求扩展其他操作或完善异常处理。同样,你也可以使用链表来实现队列的存储结构,只需对节点进行插入

9. 实现二叉树的前序、中序和后序遍历:

给定一个二叉树,实现其前序、中序和后序遍历。

下面是一个使用递归方式实现二叉树的前序、中序和后序遍历的示例代码:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public class BinaryTreeTraversal {
    // 前序遍历:根 -> 左 -> 右
    public void preOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.val + " ");  // 访问根节点
        preOrderTraversal(root.left);  // 遍历左子树
        preOrderTraversal(root.right);  // 遍历右子树
    }

    // 中序遍历:左 -> 根 -> 右
    public void inOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        inOrderTraversal(root.left);  // 遍历左子树
        System.out.print(root.val + " ");  // 访问根节点
        inOrderTraversal(root.right);  // 遍历右子树
    }

    // 后序遍历:左 -> 右 -> 根
    public void postOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        postOrderTraversal(root.left);  // 遍历左子树
        postOrderTraversal(root.right);  // 遍历右子树
        System.out.print(root.val + " ");  // 访问根节点
    }

    public static void main(String[] args) {
        // 构建一个二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);

        BinaryTreeTraversal traversal = new BinaryTreeTraversal();

        System.out.println("前序遍历结果:");
        traversal.preOrderTraversal(root);  // 1 2 4 5 3
        System.out.println();

        System.out.println("中序遍历结果:");
        traversal.inOrderTraversal(root);  // 4 2 5 1 3
        System.out.println();

        System.out.println("后序遍历结果:");
        traversal.postOrderTraversal(root);  // 4 5 2 3 1
        System.out.println();
    }
}

在上述代码中,我们首先定义了一个 TreeNode 类,表示二叉树的节点。每个节点包含一个值 val,以及左右子节点的引用。

接下来,我们实现了一个 BinaryTreeTraversal 类,包含三个方法:preOrderTraversalinOrderTraversalpostOrderTraversal

10. 实现二分查找:

给定一个已排序的数组和一个目标值,使用二分查找算法在数组中找到目标值的索引。

当给定的数组是已排序的,你可以使用二分查找算法来有效地找到目标值。以下是一个实现二分查找的示例代码:

def binary_search(arr, target):
    left = 0
    right = len(arr) - 1

    while left <= right:
        mid = (left + right) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1  # 如果目标值不在数组中,则返回 -1

# 测试代码
arr = [1, 3, 5, 7, 9, 11, 13]
target = 9
index = binary_search(arr, target)

if index != -1:
    print("目标值在数组中的索引为", index)
else:
    print("目标值不在数组中")

这段代码首先定义了一个 binary_search 函数,接受一个已排序的数组 arr 和一个目标值 target 作为参数。函数内部使用 leftright 两个指针来表示搜索范围的左右边界。

然后,使用一个 while 循环来进行二分查找。在每次循环中,计算出中间元素的索引 mid。如果中间元素等于目标值,那么查找成功,返回该索引。如果中间元素小于目标值,说明目标值在数组的右半部分,更新 left 指针为 mid + 1。如果中间元素大于目标值,说明目标值在数组的左半部分,更新 right 指针为 mid - 1

left 大于 right 时,说明目标值不在数组中,返回 -1。

最后,使用示例代码进行测试,输出结果是目标值在数组中的索引。在上面的示例中,目标值 9 在数组中的索引为 4。如果目标值不在数组中,则输出 “目标值不在数组中”。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值