• Java中数组的实际经典案例


    数组不仅是Java中学习的重点,也是数据结构与算法中学习的重点,我们不仅要熟悉它,也要懂得运用它。

    1. 数组的拷贝

    数组的拷贝分为两种,一种是对值得拷贝,一种是对地址的拷贝。

    上一章中我们已经知道了数组是储存在堆上的,在栈上new出来的只是一个局部变量,用于储存堆山的地址。

    上代码:

    1. import java.util.Arrays;
    2. public class demo {
    3. public static int[] copyArray(int[] arr){
    4. int[] copyArr = arr;
    5. return copyArr;
    6. }
    7. public static void main(String[] args) {
    8. int[] arr = {1,2,3,4,5,6};
    9. System.out.println(Arrays.toString(copyArray(arr)));
    10. }
    11. }

     两个变量同时存储同一个地址。

    1. import java.util.Arrays;
    2. public class demo {
    3. public static int[] copyArray(int[] arr){
    4. int[] copyArr = new int[arr.length];
    5. copyArr = arr;
    6. return copyArr;
    7. }
    8. public static void main(String[] args) {
    9. int[] arr = {1,2,3,4,5,6};
    10. System.out.println(Arrays.toString(copyArray(arr)));
    11. }
    12. }

     

     总结:只要是new出来的都是一个新地址。

    2. 查找数组中指定元素(二分查找)

    针对 有序数组 , 可以使用更高效的二分查找 .
    啥叫有序数组?
    有序分为 " 升序 " " 降序 "
    1 2 3 4 , 依次递增即为升序 .
    4 3 2 1 , 依次递减即为降序

    那么顺序查找可不可以呢?

    当然是可行的,但是如果数组非常大,我们需要找的值在后面,那就会造成速度非常慢,效果非常差。

    那可以选择用二分查找(也可以选择其他 更快更有效的算法)。

    思路分析:

    以升序数组为例 , 二分查找的思路是先取中间位置的元素 , 然后使用待查找元素与数组中间元素进行比较:
    如果相等,即找到了返回该元素在数组中的下标
    如果小于,以类似方式到数组左半侧查找
    如果大于,以类似方式到数组右半侧查找
    图解:
    假设我们需要找5这个元素。
    第一次查找:发现mid指向的值小于我们目的元素,letf就指向mid,right不移动,mid重新计算。
    第二次查找: 发现mid指向的值任然小于我们目的元素,letf就指向mid,right不移动,mid重新计算。

     第三次查找:依旧和前两次查找一样。

     直到找到这个目标元素。

    1. public class demo {
    2. public static void main(String[] args) {
    3. int[] arr = {1,2,3,4,5,6};
    4. System.out.println(binarySearch(arr, 6));
    5. }
    6. public static int binarySearch(int[] arr, int toFind) {
    7. int left = 0;
    8. int right = arr.length - 1;
    9. while (left <= right) {
    10. int mid = (left + right) / 2;
    11. if (toFind < arr[mid]) {
    12. // 去左侧区间找
    13. right = mid - 1;
    14. } else if (toFind > arr[mid]) {
    15. // 去右侧区间找
    16. left = mid + 1;
    17. } else {
    18. // 相等, 说明找到了
    19. return mid;
    20. }
    21. }
    22. // 循环结束, 说明没找到
    23. return -1;
    24. }
    25. }

    这样三次就可以找到目标元素了。

    3. 数组排序(冒泡排序) 

    给定一个数组 , 让数组升序 ( 降序 ) 排序。
    算法思路
    假设排升序:
    1. 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素 就在数组的末尾
    2. 依次从上上述过程,直到数组中所有的元素都排列好

    上代码:

    1. import java.util.Arrays;
    2. public class demo {
    3. public static void main(String[] args) {
    4. int[] arr = {9, 5, 2, 6, 8, 12, 7};
    5. bubbleSort(arr);
    6. System.out.println(Arrays.toString(arr));
    7. }
    8. public static void bubbleSort(int[] arr) {
    9. for (int i = 0; i < arr.length; i++) {
    10. for (int j = 1; j < arr.length-i; j++) {
    11. if (arr[j-1] > arr[j]) {
    12. int tmp = arr[j - 1];
    13. arr[j - 1] = arr[j];
    14. arr[j] = tmp;
    15. }
    16. }
    17. } // end for
    18. } // end bubbleSort
    19. }

    当然了,冒泡排序是一种比较低效的的算法,我们Java提供了更高效的算法

    1. public static void main(String[] args) {
    2. int[] arr = {9, 5, 2, 7};
    3. Arrays.sort(arr);
    4. System.out.println(Arrays.toString(arr));
    5. }

    4. 转轮数组

    最简单的解法:使用额外的数组

    我们可以使用额外的数组来将每个元素放至正确的位置。用 nn 表示数组的长度,我们遍历原数组,将原数组下标为 ii 的元素放至新数组下标为 (i+k)\bmod n(i+k)modn 的位置,最后将新数组拷贝至原数组即可。

    1. import java.util.Arrays;
    2. public class demo {
    3. public static void main(String[] args) {
    4. int[] arr = {1,2,3,4,5,6,7};
    5. rotate(arr,3);
    6. System.out.println(Arrays.toString(arr));
    7. }
    8. public static void rotate(int[] nums, int k) {
    9. int n = nums.length;
    10. int[] newArr = new int[n];
    11. for (int i = 0; i < n; ++i) {
    12. newArr[(i + k) % n] = nums[i];
    13. }
    14. System.arraycopy(newArr, 0, nums, 0, n);
    15. }
    16. }

    也有其他的方法:数组翻转

    思路:

    三步翻转法,其实轮转数组类似于之前介绍过的倒置字符串,即整体先翻转,左半部分翻转,右半部分翻转,就能得到最终结果。假设数组 nums 为 1、2、3、4、5,轮转 3 次,先整体翻转(0 ~ numsSize - 1),数组为 5、4、3、2、1,再翻转左半部分(0 ~ k - 1),数组为 3、4、5、2、1,最后再翻转右半部分(k ~ numsSize - 1),数组为 3、4、5、1、2,结果出来了,这就是 三步翻转法 的奇妙解法

    图示:

    1. import java.util.Arrays;
    2. public class demo {
    3. public static void main(String[] args) {
    4. int[] arr = {1,2,3,4,5,6,7};
    5. rotate(arr,3);
    6. System.out.println(Arrays.toString(arr));
    7. }
    8. public static void rotate(int[] nums, int k) {
    9. k %= nums.length;
    10. reverse(nums, 0, nums.length - 1);
    11. reverse(nums, 0, k - 1);
    12. reverse(nums, k, nums.length - 1);
    13. }
    14. public static void reverse(int[] nums, int start, int end) {
    15. while (start < end) {
    16. int temp = nums[start];
    17. nums[start] = nums[end];
    18. nums[end] = temp;
    19. start += 1;
    20. end -= 1;
    21. }
    22. }
    23. }

    当然力扣官方还有一种解法:

    我把链接放在这里:旋转数组 - 轮转数组 - 力扣(LeetCode) 感兴趣的可以去了解一下。

     数组是个非常重要的点,以后刷题会经常用到数组,这里先介绍一些,后面遇到有趣的题目我还会在写进我的博客里。

  • 相关阅读:
    C笔记:引用调用,通过指针传递
    SV/UVM学习资料
    当找不到对应版本依赖的时候,点击右上角的maven标志来解决!
    KubeSphere 社区双周报 | OpenFunction v1.2.0 发布 | 2023.09.15-09.28
    Word控件Spire.Doc 【段落处理】教程(十七):在 C#、VB.NET 中的 Word 中按样式名称获取段落
    【mycat】mycat水平分表
    【SpringBoot学习】51、MybatisPlus 代码生成器、定制代码模板
    Qt 自定义控件-支持换行和点击事件的Label
    Echarts简单使用
    Apache网页优化
  • 原文地址:https://blog.csdn.net/weixin_67807492/article/details/127744561