OJ排序

冒泡排序

import java.util.Scanner;

/**
 * 13 24 3 56 34 3 78 12 29 49 84 51 9 100
 */
public class Main {
    public static  void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int N=sc.nextInt();
        int[] nums=new int[N];
        for(int j=0;j<N;j++){
            nums[j]=sc.nextInt();
        }
        bubbleSort(nums);
        for(int j=0;j<N;j++){
            System.out.print(nums[j]+" ");
        }

    }

    /**
     *
     * @param arrays
     */
    public static void bubbleSort(int[] arrays){
        for(int i=0;i<arrays.length-1;i++){
            boolean flag=true;
            for(int j=0;j<arrays.length-1-i;j++){
                if(arrays[j]>arrays[j+1]){
                    swap(arrays,j,j+1);
                    flag=false;
                }


            }
            if (flag) break;
        }

    }
    public static void swap(int[] array,int i,int j){
        int temp=array[i];
        array[i]=array[j];
        array[j]=temp;
    }
}

按照另一个数组排序(冒泡排序变形)

按照数值个数排序
Description

对给定数组中的元素按照元素出现的次数排序,出现次数多的排在前面,如果出现次数相同,则按照数值大小排序。例如,给定数组为{2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12},则排序后结果为{3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5}。

Input

输入的第一行为用例个数;后面每一个用例使用两行表示,第一行为数组长度,第二行为数组内容,数组元素间使用空格隔开。

Output

每一个用例的排序结果在一行中输出,元素之间使用空格隔开。

Sample Input 1

1
4
2 3 2 5
Sample Output 1

2 2 3 5

public class Main {
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int T=sc.nextInt();
        for(int t=0;t<T;t++){
            int N=sc.nextInt();
            int arr[]=new int[N];
            for(int i=0;i<N;i++){
                arr[i]=sc.nextInt();
            }
            Map<Integer,Integer> map=sortByTime(arr,N);
            for(Map.Entry<Integer,Integer> entry:map.entrySet()){
                int mapKey = entry.getKey();
                int mapValue = entry.getValue();
                //打印
                for(int j=0;j<mapValue;j++){
                    System.out.print(mapKey+" ");
                }
            }
            System.out.println("");

        }
    }

    /**
     * 按照数字出现的次数进行排序
     * @param arr
     */
    private static Map<Integer,Integer> sortByTime(int[] arr,int n) {
       // Arrays.sort(arr);
        Map<Integer,Integer> map=new TreeMap<>();
        for(int i=0;i<n;i++){
            map.put(arr[i],map.getOrDefault(arr[i],0)+1);
        }
        Set<Integer> keySet=map.keySet();
        
        map.entrySet().stream().sorted(Map.Entry.comparingByValue());
        return map;
    }
}

插入排序

publi
c class Main {
    public  static void  main(String args[]){
        Scanner sc=new Scanner(System.in);
        int T=Integer.parseInt(sc.nextLine());
        for(int t=0;t<T;t++){

            String[] numStr=sc.nextLine().trim().split(" ");
            int nums[]=new int[numStr.length-1];
            int N=Integer.parseInt(numStr[0]);
            for(int i=0;i<nums.length;i++){
                nums[i]=Integer.parseInt(numStr[i+1]);
            }
            sort(nums);
            for(int i=0;i<N;i++){
                System.out.print(nums[i]);
                if(i!=nums.length-1) System.out.print(" ");
            }
            System.out.println("");

        }
    }

    /**
     * 插入排序
     * @param nums
     */
    static  void sort(int[] nums){
        for(int i=1;i<nums.length;i++){
            int temp=nums[i];
            int j;
            for(j=i;j>0&&nums[j-1]>temp;j--){
                nums[j]=nums[j-1];
            }
            nums[j]=temp;
        }
    }
}

希尔排序

shell排序,按照给定的间隔变化,打印排序结果。
知识点:
两种插入排序
1)简单插入排序:(稳定排序)
直接插入排序的排序思路是:每次将一个待排序的元素与已排序的元素进行逐一比较,直到找到合适的位置按大小插入。
2)希尔排序
按照步长进行分组,每组内进行希尔排序。

import java.util.Scanner;

/**
 * shell排序,按照给定的间隔变化,打印排序结果。
 * 第一行:用例个数T
 * 第二行 :数组
 * 第三行 :指定间隔,每个间隔用空格隔开
 *
 * Sample Input 1
 * 1
 * 49 38 65 97 76 13 27 49 55 4
 * 5 3
 *
 * Sample Output 1
 * 13 4 49 38 27 49 55 65 97 76
 */
public class Main {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int T = Integer.parseInt(sc.nextLine().trim());
        for (int t = 0; t < T; t++) {
            String[] s = sc.nextLine().trim().split(" ");
            int[] arr = new int[s.length];//保存数组
            for (int i = 0; i < s.length; i++) {
                arr[i] = Integer.parseInt(s[i]);
            }
            String[] s1 = sc.nextLine().trim().split(" ");
            int path[] = new int[s1.length];//保存步数
            for (int i = 0; i < path.length; i++) {
                path[i] = Integer.parseInt(s1[i]);
            }
            shellOrder(arr, path);
            //打印
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i]+" ");
            }
            System.out.println("");
        }
        sc.close();


    }


    private static void shellOrder(int[] arr, int[] path) {
        for (int i = 0; i < path.length; i++) {
            orderByPath(arr, path[i]);
        }
    }

    /**
     * 根据步长进行排序
     *
     * @param array
     * @param h
     */
    private static void orderByPath(int[] array, int h) {
        for (int i = h; i < array.length; i++) {
            for (int k = i; k < array.length; k += h) {
                //判断是否需要重新排序,如果小于k-h处的值,需要重新排序
                if (array[k] < array[k - h]) {
                    int tempValue = array[k];
                    int j = k;
                    for (; j >= i && tempValue < array[j - h]; j -= h) {
                        array[j] = array[j - h];
                    }
                    array[j] = tempValue;
                }
            }
        }
    }
}

计数排序

Description
实现计数排序,通过多次遍历数组,统计比每一个元素小的其它元素个数,根据该统计量对数据进行排序。
Input
输入的每一行表示一个元素为正整数的数组,所有值用空格隔开,第一个值为数值长度,其余为数组元素值。
Output
输出的每一行为排序结果,用空格隔开,末尾不要空格。

分析:此题的重点是统计比每个元素小的其他元素的个数。

import java.util.Scanner;

public class Main {
    public static void bsort(int array[])
    {
        int counts[]=new int[array.length];
        int newarray[]=new int[array.length];
        for(int i=0;i<array.length-1;i++)
            for(int j=i+1;j<array.length;j++)
                if(array[i]>=array[j])
                    counts[i]++;//计算小于等于array[i]的个数 加不加等号不影响结果
                else
                    counts[j]++;//计算大于array[j]的个数
        
        for(int i=0;i<array.length;i++)
            newarray[counts[i]]=array[i];//根据位置存放元素
        for(int i=0;i<newarray.length;i++)//按照题意输出结果
            if(i!=newarray.length-1)
                System.out.print(newarray[i]+" ");
            else
                System.out.println(newarray[i]);


    }
    public static void main(String args[])
    {
        Scanner in=new Scanner(System.in);
        String arr[]=in.nextLine().split(" ");//按照题意输入,注意第一个是元素个数
        int array[]=new int[arr.length-1];//保存要排序的数据
        for(int i=1;i<arr.length;i++)
            array[i-1]=Integer.parseInt(arr[i]);//将数据转换
        bsort(array);


    }
}

非递归归并排序

public class Main {
    static Scanner scanner=new Scanner(System.in);
    public static  void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int N=sc.nextInt();
        int[] nums=new int[N];
        for(int j=0;j<N;j++){
            nums[j]=sc.nextInt();
        }
        mergeSort(nums);
        for(int j=0;j<N;j++){
            System.out.print(nums[j]+" ");
        }

    }

    /**
     * 非递归归并排序
     * @param nums
     */

    private static void mergeSort(int[] nums) {
        //建立步长path
        int path=1;
        int n=nums.length;
        while(path<=n){
            //确定排序边界
            for(int i=0;i<n-path;i=i+path+path){
                int mid=Math.min(i+path-1,n-1);
                int right=Math.min(i+path*2-1,n-1);
                merge(nums,i,mid,right);
            }
            path=path*2;
        }

    }

    /**
     * 将子数组left到mid 以及 子数组 mid+1 right 进行合并
     * @param nums
     * @param left
     * @param mid
     * @param right
     */
    static void merge(int nums[],int left,int mid,int right){
        //建立辅助数组
        int length=right-left+1;
        int[] auxiliaryArray=new int[length];
        int i=left;
        int j=mid+1;
        int index=0;
        while(i<=mid&&j<=right){
            if(nums[i]<=nums[j]){
                auxiliaryArray[index++]=nums[i++];
            }else{
                auxiliaryArray[index++]=nums[j++];
            }
        }

        while(i<=mid){
            auxiliaryArray[index++]=nums[i++];
            i++;
        }

        while (j<=right) {
            auxiliaryArray[index++] = nums[j++];
        }

        //将辅助数组的结果填到原数组中
        for(int t=0;t<auxiliaryArray.length;t++){
            nums[left+t]=auxiliaryArray[t];
        }


    }
}

合并数组——n路归并——借助优先队列


import java.util.Scanner;
import java.util.PriorityQueue;
import java.util.Comparator;

/**
 * 描述:给定k个已经排好序的数组。arr[k][k]
 * 合并k个数组,并排好序。
 * 输入 :第一行 T
 *       第二行 N 数组数量
 *       第三行 数组
 * 思路:使用堆。
 */

public class Main {


    public static void main(String[] args){

        Scanner sc=new Scanner(System.in);
        int T=sc.nextInt();
        for(int i=0;i<T;i++){
            int N=sc.nextInt();
            int [][]arr=new int[N][N];
            for(int j=0;j<N;j++) {
                for (int k = 0; k < N; k++){
                    arr[j][k] = sc.nextInt();
                }
            }
            int[] res = mergeKArrays(arr, N);
            //打印
            for(int j=0;j<res.length;j++){
                System.out.print(res[j]+" ");
            }
            System.out.println("");
        }
        sc.close();


    }

    static class Element{
        int row,col,val;
        public Element(int row, int col, int val) {
            this.row = row;
            this.col = col;
            this.val = val;
        }

    }
    public static int[] mergeKArrays(int[][] arr, int k){
        PriorityQueue<Element> queue=new PriorityQueue<>(k, new Comparator<Element>() {
            @Override
            public int compare(Element o1, Element o2) {
                return o1.val-o2.val;
            }
        });//默认小顶堆
        int[] res=new int[k*k];
        int index=0;
        //初始化
        for(int j=0;j<k;j++){
            queue.offer(new Element(j,0,arr[j][0]));
        }
        while(!queue.isEmpty()){
            //出队列
            Element e=queue.poll();
            res[index++]=e.val;
            if(e.col+1<k) queue.offer(new Element(e.row,e.col+1,arr[e.row][e.col+1]));
        }

        return res;

    }
}


倒置对的个数——归并排序应用

import java.util.Scanner;

/**
 * Description
 * 有一个由N个实数构成的数组,如果一对元素A[i]和A[j]是倒序的,即i<j但是A[i]>A[j]则称它们是一个倒置,
 * 设计一个计算该数组中所有倒置数量的算法。要求算法复杂度为O(nlogn)
 *
 * Input
 * 输入有多行,第一行整数T表示为测试用例个数,后面是T个测试用例,每一个用例包括两行,第一行的一个整数是元素个数,第二行为用空格隔开的数组值。
 *
 *
 * Output
 * 输出每一个用例的倒置个数,一行表示一个用例。
 *
 * Sample Input 1
 * 1
 * 8
 * 8 3 2 9 7 1 5 4
 *
 * Sample Output 1
 * 17
 * 思路:采用归并排序
 *
 */
public class Main {
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int T=sc.nextInt();
        for(int i=0;i<T;i++){
            int N=sc.nextInt();
            int a[]=new int[N];
            for(int j=0;j<N;j++) a[j]=sc.nextInt();
            System.out.println(mergeSort(a,0,a.length-1));
        }

    }

    public static int   mergeSort(int[] array,int start,int end){
        if(start>=end) return 0;
        int mid=(start+end)/2;
        return  mergeSort(array,start,mid)+mergeSort(array, mid+1, end)+merge(array,start,end,mid);
    }
    public static int  merge(int[] array,int left,int right,int mid){
        //合并
        int total=0;
        int i=left;//左
        int j=mid+1;//右侧
        int newArray[]=new int[right-left+1];
        int index=0;
        while(i<=mid&&j<=right){
            if(array[i]<=array[j]){
               newArray[index++]=array[i++];
            }else{
                newArray[index++]=array[j++];
                //则i比j要大,则i后面都比j大
                total+=mid-i+1;
            }
        }
        while(i<=mid){
            newArray[index++]=array[i++];
        }
        while (j<=right){
            newArray[index++]=array[j++];
        }
        //写回
        for(int k=0;k<right-left+1;k++){
            array[k+left]=newArray[k];
        }
        return  total;

    }

}

非递归快排

import java.util.Scanner;
import java.util.Stack;
/**
 * Input
 * 输入的每一行表示一个元素为正整数的数组,所有值用空格隔开,第一个值为数值长度,其余为数组元素值。
 * Output
 * 输出的每一行为排序结果,用空格隔开,末尾不要空格。
 *
 *
 * Sample Input 1
 * 13 24 3 56 34 3 78 12 29 49 84 51 9 100
 * Sample Output 1
 * 3 3 9 12 24 29 34 49 51 56 78 84 100
 */
public class Main {
    static Scanner scanner=new Scanner(System.in);
    public static  void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int N=sc.nextInt();
        int[] nums=new int[N];
        for(int j=0;j<N;j++){
            nums[j]=sc.nextInt();
        }
        quickSort(nums);
        for(int j=0;j<N;j++){
            System.out.print(nums[j]+" ");
        }

    }

    /**
     * 非递归快速排序
     * @param nums
     */
    private static void quickSort(int[] nums) {
        int low=0;
        int high=nums.length-1;
        int pivot;
        if (low >= high)
            return;
        Stack<Integer> stack = new Stack<Integer>();
        stack.push(low);
        stack.push(high);
        while (!stack.empty()) {
            // 先弹出high,再弹出low
            high = stack.pop();
            low = stack.pop();
            pivot = partion(nums, low, high);
            // 先压low,再压high
            if (low < pivot - 1) {
                stack.push(low);
                stack.push(pivot - 1);
            }
            if (pivot + 1 < high) {
                stack.push(pivot + 1);
                stack.push(high);
            }
        }

    }


    /**
     * 根据分界点移动元素,并返回新的分界点
     * @return
     */
    static int partion(int[] array,int low,int high){//合并排序部分
        int tmp = array[low];
        while(low<high){
            while(low < high && array[high] >= tmp){
                --high;
            }
            if(low >= high){
                break;
            }else{
                array[low]= array[high];//交换小值去前面
            }

            while(low < high && array[low] <= tmp){
                ++low;
            }
            if(low >= high){
                break;
            }else{
                array[high] = array[low];//交换大值去后面
            }
        }
        array[low] = tmp;//枢值归位
        return low;
    }

}

递归快排

  private static void quickSort(int[] nums) {
        int low=0;
        int high=nums.length-1;
        quick(nums,low,high);
    }
    private static void quick(int nums[],int low,int high){
        if(low>=high) return;
        int pivot=partion(nums,low,high);
        quick(nums,low,pivot-1);
        quick(nums,pivot+1,high);


    }

按照数值个数排序

按照数值个数排序
Description

对给定数组中的元素按照元素出现的次数排序,出现次数多的排在前面,如果出现次数相同,则按照数值大小排序。例如,给定数组为{2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12},则排序后结果为{3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5}。

Input

输入的第一行为用例个数;后面每一个用例使用两行表示,第一行为数组长度,第二行为数组内容,数组元素间使用空格隔开。

Output

每一个用例的排序结果在一行中输出,元素之间使用空格隔开。

Sample Input 1

1
4
2 3 2 5
Sample Output 1

2 2 3 5

public class Main {
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int T=sc.nextInt();
        for(int t=0;t<T;t++){
            int N=sc.nextInt();
            int arr[]=new int[N];
            for(int i=0;i<N;i++){
                arr[i]=sc.nextInt();
            }
            Map<Integer,Integer> map=sortByTime(arr,N);
            for(Map.Entry<Integer,Integer> entry:map.entrySet()){
                int mapKey = entry.getKey();
                int mapValue = entry.getValue();
                //打印
                for(int j=0;j<mapValue;j++){
                    System.out.print(mapKey+" ");
                }
            }
            System.out.println("");

        }
    }

    /**
     * 按照数字出现的次数进行排序
     * @param arr
     */
    private static Map<Integer,Integer> sortByTime(int[] arr,int n) {
       // Arrays.sort(arr);
        Map<Integer,Integer> map=new TreeMap<>();
        for(int i=0;i<n;i++){
            map.put(arr[i],map.getOrDefault(arr[i],0)+1);
        }
        Set<Integer> keySet=map.keySet();
        
        map.entrySet().stream().sorted(Map.Entry.comparingByValue());
        return map;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值