数组常见算法总结

数组排序

冒泡排序

基本思路

相邻元素进行比较,如前者比后者大(小)交换位置,实现大(小)元素向后移动。
口诀(第0轮开始
n个数字排序
两两比较(大/小靠前)
共比较n-1轮
每轮比较n-1-i次

代码实现

        int[] nums1 = {8, 9, 7, 4, 3}; //无序数组
        System.out.println("排序前"+Arrays.toString(nums1));
        //n个数字排序,两两比较(大/小靠前),共比较n-1轮,第i(i=0,i++)轮比(n-1-i)次
        //比n-1轮 数组长度为5,比4轮(0,1,2,3,)
        for (int i = 0, n = nums1.length; i < n - 1; i++) {
            //每轮比较n-1-i次 (第0轮:4次;第1轮:3次;第2轮:2次;第3轮:1次)
            //也可以表示下标
            for (int j = 0; j < n - 1 - i; j++) {
                //升序判断:nums1[j] > nums1[j + 1];降序判断:nums1[j] < nums1[j + 1]
                if (nums1[j] > nums1[j + 1]) {
                    //交换(本程序中,前一个>后一个,则交换,大的靠后)
                    nums1[j] ^= nums1[j + 1];
                    nums1[j + 1] ^= nums1[j];
                    nums1[j] = nums1[j] ^ nums1[j + 1];
                }
            }
        }
        System.out.println("排序后"+Arrays.toString(nums1));

输出结果

排序前[8, 9, 7, 4, 3]
排序后[3, 4, 7, 8, 9]

优化冒泡排序

基本思路

在进行每轮排序之前,检查该数组是否处于“有序”状态.
优化后,越有序,轮数越少

代码实现

        //优化冒泡排序 优化后,越有序,轮数越少
        int[] nums2 = {9, 8, 7, 3, 4};
        int count = 0;  //表示比较的次数
        for (int i = 0, n = nums2.length; i < n - 1; i++) {
            boolean isSort = true;  //是否已经处于”有序“状态,true代表有序
            for (int j = 0; j < n - 1 - i; j++) {
                count++;
                if (nums2[j] < nums2[j + 1]) {
                    nums2[j] ^= nums2[j + 1];
                    nums2[j + 1] ^= nums2[j];
                    nums2[j] = nums2[j] ^ nums2[j + 1];
                    isSort = false;
                }
            }
            if (isSort){
                break;
            }
        }
        System.out.println("比较次数"+count);
        System.out.println("排序后"+Arrays.toString(nums2));

输出结果

比较次数7
排序后[9, 8, 7, 4, 3]

数组查找

无序数组查找

基本思路

通过循环遍历整个数组的方式对指定元素进行查找:遍历数组中的每个元素并于目标元素进行比较,从而确定该数组中是否存在指定元素

代码实现

查找第一次/最后一次出现目标值的下标

        //eg1:找第一个出现的元素
        int[] nums = {1, 2, 3, 4, 5, 1, 2, 3};
        int target = 1;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                System.out.println("第一次出现目标值:" + target + "的下标是:" + i);
                break;
            }
        }
        //eg2:找最后个出现的元素(即:逆序查找第一个)
        int[] nums1 = {1, 2, 3, 4, 5, 1, 2, 3};
        int target1 = 1;
        int index = -1;
        //方式1
        /*for(int i=0;i<nums.length;i++){
            if(nums[i]==target){
                index=i;
            }
        }
        System.out.println("最后一次出现目标值:"+target1+"的下标是:"+index);*/
        //方式2
        for (int i = nums1.length - 1; i >= 0; i--) {
            if (nums[i] == target) {
                index = i;
                break;
            }
        }
        System.out.println("最后一次出现目标值:" + target1 + "的下标是:" + index);

双指针查找

        //双指针查找
        String[] singerArray = {"李荣浩", "盘尼西林", "王菲", "王贰浪",
                "鹿先森乐队", "孙燕姿", "G.E.M.邓紫棋", "方大同", "品冠儿子"};
        try(Scanner input =new Scanner(System.in)){
            System.out.println("请输入目标元素");
            String target = input.next();
            int index=-1;//若没有则返回-1
            for(int i=0,k=singerArray.length-1;i<=k;i++,k--){
                //字符串比较用equals()
                //从头开始查找
                if(singerArray[i].equals(target)){
                    index=i;
                    break;
                }
                //从尾部开始查找
                if(singerArray[k].equals(target)){
                    index=k;
                    break;
                }
            }
            if(index>=0){
                System.out.println("出现目标元素" + target + "的下标是:" + index);
            }else
                System.out.println("该数组没有出现您所查找的目标元素");
        }

输出结果

第一次出现目标值:1的下标是:0
最后一次出现目标值:1的下标是:5
请输入目标元素
方大同
出现目标元素方大同的下标是:7

有序数组查找

基本思路

对于有序数组查找指定元素可以采用的方法是:二分查找
二分查找的前提是数组必须处于有序状态,处于无序态的数组应先进行排序
判断数组中的中位元素目标元素是否相等

  1. 相等:查找成功
  2. 中位元素>目标元素:当前数组的前半部分作为新的搜索数组
  3. 中位元素<目标元素:当前数组的后半部分作为新的搜索数组

在新的搜索数组上,重复以上步骤

代码实现

整型类型

        //整数类型
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8}; //有序数组
        int target = 2; //查找的目标值
        //定义低位(首元素的下标)、高位(尾元素的下标)
        int low = 0, high = nums.length - 1;
        int index = -1;
        while (low <= high) {
            //计算中间位下标
            int mid = (low + high) / 2;
            //判断中间位下标的元素是否与目标值相等
            if (nums[mid] == target) {
                index = mid;
                break; //找到后退出循环
            } else if (nums[mid] > target) {
                high = mid - 1;
            } else
                low = mid + 1;
        }
        System.out.println("该数组中,目标值所在位置为:" + index);

字符类型

        //字符类型
        char[] keys = {'a', 'b', 'c', 'd', 'e', 'f', 'g',
                'h', 'i', 'j', 'k', 'l', 'm', 'n'};
        int target = 'h';
        int index = -1;
        int low = 0, high = keys.length - 1;
        while (low <= high) {
            int mid = (low + high) / 2;
            if (keys[mid] == target) {
                index = mid;
                break;
            } else if (keys[mid] > target) {
                high = mid - 1;
            } else
                low = mid + 1;
        }
        if(index>=0){
            System.out.println("该数组中,目标值所在位置为:" + index);
        }else
            System.out.println("没有找到该元素");

字符串类型

        //字符串类型
        String[] contactArray = {"Megatron", "s司马铁锤", "Laden",
                "angelababy", "b比尔盖饭", "l林平之", "BIGBANG", "Adele Adkins",
                "m马云", "Gaddafi", "g郭德纲", "m马伯庸", "Ma Tong Seok"};
        Arrays.sort(contactArray); //排序
        System.out.println(Arrays.toString(contactArray)); //输出排序之后的数组
        String target = "g郭德纲"; //所查找的目标值
        int low = 0, high = contactArray.length - 1;
        int index = -1;
        while (low <= high) {
            int mid = (low + high) / 2;
            //a.compareTo(b)==0:a=b;a.compareTo(b)>0:a>b
            if (contactArray[mid].compareTo(target) == 0) {
                index = mid;
                break; //找到后终止循环
            } else if (contactArray[mid].compareTo(target) > 0) {
                high = mid - 1;
            } else
                low = mid + 1;
        }
        System.out.println("该数组中,目标值所在位置为:" + index);

输出结果

该数组中,目标值所在位置为:1
该数组中,目标值所在位置为:7
排序后的数组:[Adele Adkins, BIGBANG, Gaddafi, Laden, Ma Tong Seok, Megatron, angelababy, b比尔盖饭, g郭德纲, l林平之, m马云, m马伯庸, s司马铁锤]
该数组中,目标值所在位置为:8

数组乱序

基本思路

假设数组长度为i(ns.length-1),产生一个i以内的随即下标,第i位的值与随机下标的值交换

代码实现

        //eg1:
        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        for (int i = nums.length - 1; i > 0; i--) {
            //随机产生一个i以内的随机下标
            int index = (int) (Math.random() * i);
            //第i位的值与随机下标的值交换
            nums[index] = nums[index] ^ nums[i];
            nums[i] = nums[index] ^ nums[i];
            nums[index] = nums[index] ^ nums[i];
            //中间效果展示
//            System.out.println(i + "vs" + index);
//            System.out.println();
//            System.out.printf("第%d个参与交换的结果:", i);
        }
        System.out.println(Arrays.toString(nums));
        //eg2:
        String[] singer = {"1可能", "2如愿", "3上下五千年", "4我爱你", "5晴天", "6青花瓷", "7一路向北", "8稻香"};
        //经过两次乱序
        for (int k = 0; k <= 1; k++) {
            for (int i = singer.length - 1; i > 0; i--) {
                //Math.random() 产生的是一个随机小数,需要强制类型转换
                int randIndex = (int) (Math.random() * i);
                String temp = singer[i];
                singer[i] = singer[randIndex];
                singer[randIndex] = temp;
            }
        }
        System.out.println(Arrays.toString(singer));

输出结果

eg1乱序结果:[13, 10, 11, 7, 9, 8, 1, 4, 14, 6, 15, 3, 5, 12, 2]
eg2乱序结果:[1可能, 3上下五千年, 2如愿, 7一路向北, 5晴天, 8稻香, 6青花瓷, 4我爱你]

数组旋转

基本思路

向右旋转
具体实现:从后不断向前交换,逆序遍历
具体实现:尾元素通过不断向前交换,交换至头元素
向左旋转:从前不断向后交换,顺序遍历
具体实现:头元素通过不断向前后交换,至尾元素

代码实现

向右旋转

        //向右旋转:尾部移动到头部
        int[] ns = {1, 2, 3, 4, 5, 6};
        //控制循环次数,即旋转几位
        for (int i = 0; i < 3; i++) {
            //控制旋转方向:向右旋转一位:整体向右推一位,尾元素则溢出转到第一个位置
            for (int k = ns.length - 1; k > 0; k--) {
                //从结果来看,就是从后不断地向前交换,即遍历方向是:逆序,将尾元素通过不断地向前交换,交换至头元素
                ns[k] ^= ns[k - 1];
                ns[k - 1] ^= ns[k];
                ns[k] ^= ns[k - 1];
            }
        }
        System.out.println("向右旋转三位" + Arrays.toString(ns));

向左旋转

        //向左循环:头部移动到尾部
        int[] us = {1, 2, 3, 4, 5, 6};
        for (int i = 0; i < 3; i++) {
            //前一个与后一个交换,当k=us.length-2(倒数第二个元素)k+1=us.length-1(尾元素)交换
            for (int k = 0; k < us.length - 1; k++) {
                us[k] ^= us[k + 1];
                us[k + 1] ^= us[k];
                us[k] ^= us[k + 1];
            }
        }
        System.out.println("向左旋转三位" + Arrays.toString(us));

输出结果

向右旋转三位[4, 5, 6, 1, 2, 3]
向左旋转三位[4, 5, 6, 1, 2, 3]
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值