排序算法例题

小和问题

在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例子: [1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16

//利用归并排序
public static int smallSum(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        return mergeSort(arr, 0, arr.length - 1);
    }

    public static int mergeSort(int[] arr, int l, int r) {
        if (l == r) {
            return 0;
        }
        int mid = l + ((r - l) >> 1);
        return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r);
    }

    public static int merge(int[] arr, int l, int m, int r) {
        int[] help = new int[r - l + 1];
        int i = 0;
        int p1 = l;
        int p2 = m + 1;
        int res = 0;
        while (p1 <= m && p2 <= r) {
            //计算小于的值的个数
            res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
            help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
        while (p1 <= m) {
            help[i++] = arr[p1++];
        }
        while (p2 <= r) {
            help[i++] = arr[p2++];
        }
        for (i = 0; i < help.length; i++) {
            arr[l + i] = help[i];
        }
        return res;
    }

    // test
    public static void main(String[] args) {
        int[] res = new int[5];
        res = new int[]{3, 6, 8, 9, 0};
        System.out.println(smallSum(res));
    }

结果:29

荷兰国旗问题

给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。

//利用快速排序
   public static int[] partition(int[] arr, int l, int r, int p) {
        int less = l - 1;
        int more = r + 1;
        while (l < more) {
            if (arr[l] < p) {
                swap(arr, ++less, l++);
            } else if (arr[l] > p) {
                swap(arr, --more, l);
            } else {
                l++;
            }
        }
        return new int[] { less + 1, more - 1 };
    }

    // 交换
    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }


    // 打印
    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] res1 = new int[5];
        res1 = new int[]{3, 6, 8, 9, 0};

        printArray( res1);
        int[] res = partition( res1, 0,  res1.length - 1, 10);
        printArray(res1);
        System.out.println(res[0]);
        System.out.println(res[1]);
    }

旋转正方形矩阵

给定一个整型正方形矩阵matrix,请把该矩阵调整成 顺时针旋转90度的样子。
【要求】 额外空间复杂度为O(1)。
思路:位置对应,对应下标变化

//注:必须是旋转正方形,长方形位数对应不上
public static void rotate(int[][] matrix) {
        //左上角位置,行列
        int tR = 0;
        int tC = 0;
        //右下角位置,行列
        int dR = matrix.length - 1;
        int dC = matrix[0].length - 1;
        //一直从最外圈到最里圈
        while (tR < dR) {
            rotateEdge(matrix, tR++, tC++, dR--, dC--);
        }
    }
    //旋转边界:对应下标变化
    public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) {
         //次数
        int times = dC - tC;
        int tmp = 0;
        for (int i = 0; i != times; i++) {
             //每次交换边界值(四个值交换一圈)
            tmp = m[tR][tC + i];
            m[tR][tC + i] = m[dR - i][tC];
            m[dR - i][tC] = m[dR][dC - i];
            m[dR][dC - i] = m[tR + i][dC];
            m[tR + i][dC] = tmp;
        }
    }

    public static void printMatrix(int[][] matrix) {
        for (int i = 0; i != matrix.length; i++) {
            for (int j = 0; j != matrix[0].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
                { 13, 14, 15, 16 } };
        printMatrix(matrix);
        rotate(matrix);
        System.out.println("=========");
        printMatrix(matrix);

    }

在这里插入图片描述

转圈打印矩阵

给定一个整型矩阵matrix,请按照转圈的方式打印它。 例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 打印结果为:1,2,3,4,8,12,16,15,14,13,9, 5,6,7,11, 10
【要求】 额外空间复杂度为O(1)。

public static void spiralOrderPrint(int[][] matrix) {
         //左上角位置,行列
        int tR = 0;
        int tC = 0;
         //右下角位置,行列
        int dR = matrix.length - 1;
        int dC = matrix[0].length - 1;
        //满足条件:左上角a的行号来到最后一行并且列号来到最后一列(两者同时满足)
        while (tR <= dR && tC <= dC) {
            printEdge(matrix, tR++, tC++, dR--, dC--);
        }
    }

    public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
        if (tR == dR) {
           //只有一行时
            for (int i = tC; i <= dC; i++) {
                System.out.print(m[tR][i] + " ");
            }
        } else if (tC == dC) {
           //只有一列时
            for (int i = tR; i <= dR; i++) {
                System.out.print(m[i][tC] + " ");
            }
        } else {
            int curC = tC;
            int curR = tR;
            //顺着打印某一行
            while (curC != dC) {
                System.out.print(m[tR][curC] + " ");
                curC++;
            }
            //顺着打印某一列
            while (curR != dR) {
                System.out.print(m[curR][dC] + " ");
                curR++;
            }
            //逆着打印某一行
            while (curC != tC) {
                System.out.print(m[dR][curC] + " ");
                curC--;
            }
            //逆着打印某一列
            while (curR != tR) {
                System.out.print(m[curR][tC] + " ");
                curR--;
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
                { 13, 14, 15, 16 } };
        spiralOrderPrint(matrix);
    }

“之”字形打印矩阵

给定一个矩阵matrix,按照“之”字形的方式打印这 个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 “之”字形打印的结果为:1,2,5,9,6,3,4,7,10,11, 8,12 【要求】 额外空间复杂度为O(1)。

在这里插入图片描述

public static void printMatrixZigZag(int[][] matrix) {
        //对角线右上方点A行列坐标
        int tR = 0;
        int tC = 0;
        //对角线左下方B行列坐标
        int dR = 0;
        int dC = 0;
        //矩阵右下角点行列坐标
        int endR = matrix.length - 1;
        int endC = matrix[0].length - 1;
        //标志从对角线右上方还是左下方开始打印
        boolean fromUp = false;
        //当A没有移动到最右端时
        while (tR != endR + 1) {
            printLevel(matrix, tR, tC, dR, dC, fromUp);
            //A的路线:先向右移动,不能再向右移动后,再向下移动
            tR = tC == endC ? tR + 1 : tR;
            tC = tC == endC ? tC : tC + 1;
            //B的路线:先向下移动,不能再向下移动后,再向右移动
            dC = dR == endR ? dC + 1 : dC;
            dR = dR == endR ? dR : dR + 1;
            fromUp = !fromUp;
        }
        System.out.println();
    }
    //打印对角线
    public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f) {
        if (f) {
           //从A向B打印
            while (tR != dR + 1) {
                System.out.print(m[tR++][tC--] + " ");
            }
        } else {
            //从B向A打印
            while (dR != tR - 1) {
                System.out.print(m[dR--][dC++] + " ");
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
        printMatrixZigZag(matrix);

    }

在行列都排好序的矩阵中找数

给定一个有N*M的整型矩阵matrix和一个整数K, matrix的每一行和每一 列都是排好序的。实现一个函数,判断K 是否在matrix中。 例如: 0 1 2 5 2 3 4 7 4 4 4 8 5 7 7 9 如果K为7,返回true;如果K为6,返 回false。
【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)。

//两种方法,从右上角或者左下角找都可以
public static boolean isContains(int[][] matrix, int K) {
       //从右上角出发开始找
        int row = 0;
        int col = matrix[0].length - 1;
        //终止位置在左下角
        while (row < matrix.length && col > -1) {
            if (matrix[row][col] == K) {
                return true;
            } else if (matrix[row][col] > K) {
                col--;   //大于k向左
            } else {
                row++;  //小于k向下
            }
        }
        return false;
    }

    public static void main(String[] args) {
        int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0
                { 10, 12, 13, 15, 16, 17, 18 },// 1
                { 23, 24, 25, 26, 27, 28, 29 },// 2
                { 44, 45, 46, 47, 48, 49, 50 },// 3
                { 65, 66, 67, 68, 69, 70, 71 },// 4
                { 96, 97, 98, 99, 100, 111, 122 },// 5
                { 166, 176, 186, 187, 190, 195, 200 },// 6
                { 233, 243, 321, 341, 356, 370, 380 } // 7
        };
        int K = 233;
        System.out.println(isContains(matrix, K));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值