hdu 1040 As Easy As A+B 各种排序

22 篇文章 0 订阅
21 篇文章 0 订阅

题意:给整数数组排序,且是升序。

1)简单排序

#include<iostream>
using namespace std;

void sort1(int *a,int n){
    for(int i=0;i<n-1;i++){
        for(int j=i+1;j<n;j++){
            if(a[i]>a[j]){
                a[i] = a[i] ^ a[j];
                a[j] = a[i] ^ a[j];
                a[i] = a[i] ^ a[j];
            }
        }
    }
}

int main(){
    int t,n;
    int mat[1000];// 最大只有1000个
    cin>>t;
    while(t--){
        // 1输入一行数据
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>mat[i];
        }
        // 2排序,要求升序
        sort1(mat,n);
        // 3输出结果
        for(int i=0;i<n;i++){
            if(i==0){
                cout<<mat[i];
            }else{
                cout<<' '<<mat[i];
            }
        }
        cout<<endl;
    }
    return 0;
}

2)冒泡排序

#include<iostream>
using namespace std;

void sort2(int *a,int n){
    /*
    冒泡排序
    */
    // 总共有n-1,[0,n-1)趟排序
    for(int i=0;i<n-1;i++){
        // 每一趟有n-i次比较
        for(int j=0;j<n-i-1;j++){
            // 每次两个相邻的数进行比较
            if(a[j]>a[j+1]){
                a[j] = a[j] ^ a[j+1];
                a[j+1] = a[j] ^ a[j+1];
                a[j] = a[j] ^ a[j+1];
            }
        }
    }
}

int main(){
    int t,n;
    int mat[1000];// 最大只有1000个
    cin>>t;
    while(t--){
        // 1输入一行数据
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>mat[i];
        }
        // 2排序,要求升序
        sort2(mat,n);
        // 3输出结果
        for(int i=0;i<n;i++){
            if(i==0){
                cout<<mat[i];
            }else{
                cout<<' '<<mat[i];
            }
        }
        cout<<endl;
    }
    return 0;
}

---1)java冒泡排序

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			//bubbleSort(mat, n);
			bubbleSort(mat, n);
			print(mat, n);
		}
	}
	
	// 冒泡排序升级版
	private static void bubbleSort(int[] mat, int n) {
		// 进行n-1次排序
		for (int i = 0; i < n - 1; i++) {
			// 两两比较,每一次都到mat.length-i-1的位置
			// 例如mat.length=10,那么j只遍历到8,9会越位
			for (int j = 0; j < n - i - 1; j++) {
				// 升序
				if (mat[j] > mat[j + 1]) {
					swap(mat, j, j + 1);
				}
			}
		}
	}

	private static void swap(int[] mat, int j, int i) {
		mat[i] = mat[i] ^ mat[j];
		mat[j] = mat[i] ^ mat[j];
		mat[i] = mat[i] ^ mat[j];
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}


---2)java升级版冒泡排序

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			//bubbleSort(mat, n);
			bubbleSort2(mat, n);
			print(mat, n);
		}
	}
	
	// 冒泡排序升级版
	private static void bubbleSort2(int[] mat, int n) {
		// 进行n-1次排序
		for (int i = 0; i < n - 1; i++) {
			boolean boo = true;
			// 两两比较,每一次都到mat.length-i-1的位置
			// 例如mat.length=10,那么j只遍历到8,9会越位
			for (int j = 0; j < n - i - 1; j++) {
				// 升序
				if (mat[j] > mat[j + 1]) {
					swap(mat, j, j + 1);
					boo = false;
				}
			}
			// 如果已是指定有序的数列,那么就不要在排序了
			if(boo){
				break;
			}
		}
	}

	private static void swap(int[] mat, int j, int i) {
		mat[i] = mat[i] ^ mat[j];
		mat[j] = mat[i] ^ mat[j];
		mat[i] = mat[i] ^ mat[j];
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}


3)选择排序

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			selectSort(mat, n);
			print(mat, n);
		}
	}

	// 选择排序
	public static void selectSort(int[] mat, int n) {
		for (int i = 0; i < n - 1; i++) {
			int k = i;
			for (int j = i + 1; j < n; j++) {
				// 升序
				if (mat[k] > mat[j]) {
					k = j;
				}
			}
			if (k != i) {
				swap(mat, i, k);
			}
		}
	}

	private static void swap(int[] mat, int j, int i) {
		mat[i] = mat[i] ^ mat[j];
		mat[j] = mat[i] ^ mat[j];
		mat[i] = mat[i] ^ mat[j];
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}



4)插入排序

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			insertSort(mat, n);
			print(mat, n);
		}
	}

	// 插入排序
	private static void insertSort(int[] mat, int n) {
		// 最后一个数据是不用排的,因为插入排序的最后一个在
		// 插入倒数第二个时就会被排好
		for (int i = 0; i < n - 1; i++) {
			// 注意,所有数据原先是放在mat中的
			// 第一个数据是有序的,所以第一个插入的数据是第二个
			int temp = mat[i + 1];
			/*
			 * 用来移动的索引
			 * 插入排序是从第i个有序的序列,从后到前的遍历
			 */
			int j = i;
			while (mat[j] > temp) {
				// 从右往左移动
				mat[j + 1] = mat[j];
				j--;
				if (j < 0) {
					break;
				}
			}
			// 插入temp
			mat[j + 1] = temp;
		}
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}

----插入排序之二分查找

注意:二分查找一定是有序的数列才可以,否则后果自负,这个一定会遇到的,千万要注意。

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			binarySort(mat, n);
			print(mat, n);
		}
	}

	// 插入排序之二分查找
	private static void binarySort(int[] mat, int n) {
		// 最后一个数据是不用排的,因为插入排序的最后一个在
		// 插入倒数第二个时就会被排好
		for (int i = 0; i < n - 1; i++) {
			/*
			 * 只有一个数据是,这个数据就是有序的
			 * 那么第一个插入的数据是第二个
			 */
			int temp = mat[i + 1];
			int low = 0;
			int high = i;
			int mid = 0;
			// 确定temp需要插入的位置
			// 这个位置由mid确定
			while (low <= high) {
				mid = (low + high) / 2;
				// 落在了左半区
				if (temp < mat[mid]) {
					high = mid - 1;
				} else {
					low = mid + 1;
				}
			}
			// 无论是奇数还是偶数high+1的位置正好是插入位置
			// 把【high+1,i]的数据友右移
			for (int j = i; j > high; j--) {
				mat[j + 1] = mat[j];
			}
			// 放入temp
			mat[high + 1] = temp;
		}
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}



5)希尔排序

---1效率最低,比冒泡的时间还长:

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			shellSort(mat, n);
			print(mat, n);
		}
	}

	// 希尔排序
	private static void shellSort(int[] mat, int n) {
		/*
		 * 希尔排序思想:
		 * 缩小增量排序
		 * 所有距离为gap的倍数的元素放在同一组中
		 * 然后在各组中进行排序
		 */
		for (int gap = (n + 1) / 2; gap > 0; gap = (gap + 1) / 2) {
			/*
			 * 小组内排序---这里有gap个组,可以用冒泡排序,所有小组合起来,就是i++
			 * 每次分成gap个小组
			 * gap越小每一个小组的成员就越多
			 * --当gap=1时,那么就是对整个数组排序,
			 * ---这时,整个数组基本有序,那么排序过程就很简单了。
			 */
			for (int i = 0; i < n - gap; i++) {
				for (int j = i; j < n - gap; j += gap) {
					// 升序
					if (mat[j] > mat[j + gap]) {
						swap(mat, j, j + gap);
					}
				}
			}
			if (gap == 1) {
				break;
			}
		}
	}

	// 这个方法比较鸡助
	private static void swap(int[] mat, int i, int j) {
		mat[i] = mat[i] ^ mat[j];
		mat[j] = mat[i] ^ mat[j];
		mat[i] = mat[i] ^ mat[j];
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}


---2冒泡升级版

import java.util.Scanner;

public class p1040 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1000];
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			shellSort(mat, n);
			print(mat, n);
		}
	}

	// 希尔排序
	private static void shellSort(int[] mat, int n) {
		/*
		 * 希尔排序思想:
		 * 缩小增量排序
		 * 所有距离为gap的倍数的元素放在同一组中
		 * 然后在各组中进行排序
		 */
		for (int gap = (n + 1) / 2; gap > 0; gap = (gap + 1) / 2) {
			/*
			 * 小组内排序---这里有gap个组,可以用冒泡排序,所有小组合起来,就是i++
			 * 每次分成gap个小组
			 * gap越小每一个小组的成员就越多
			 * --当gap=1时,那么就是对整个数组排序,
			 * ---这时,整个数组基本有序,那么排序过程就很简单了。
			 */
			for (int i = 0; i < n - gap; i++) {
				boolean boo = true;
				for (int j = i; j < n - gap; j += gap) {
					// 升序
					if (mat[j] > mat[j + gap]) {
						swap(mat, j, j + gap);
						boo = false;
					}
				}
				if (gap == 1 && boo) {
					break;
				}
			}
			if (gap == 1) {
				break;
			}
		}
	}

	// 这个方法比较鸡助
	private static void swap(int[] mat, int i, int j) {
		mat[i] = mat[i] ^ mat[j];
		mat[j] = mat[i] ^ mat[j];
		mat[i] = mat[i] ^ mat[j];
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}


6)快速排序

import java.util.Scanner;

public class p1040 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        int[] mat = new int[1001];// 快排一定要多一点内存,
        while (t-- > 0) {
            int n = sc.nextInt();
            for (int i = 0; i < n; i++) {
                mat[i] = sc.nextInt();
            }
            quickSort(mat, 0, n - 1);
            print(mat, n);
        }
    }

    /*
     * 快速排序,这个要用递归,慢慢来,有的是时间
     * [begin,end]左包含,右包含,封闭区间
     */
    private static void quickSort(int[] mat, int begin, int end) {
        /*
         * 递归鸿沟
         * 数组指针相同,用异或运算时会出错的,如果不确定这句话那么你自己在用“数组”指针相同运算一次
         * --如果答案是没出错误,那么重复操作。。。
         * 这个地方我解决了
         */
        if (begin >= end) {
            return;
        }
        /*
         * 任取待排序记录序列中的某个记录(一般为第一个)作为中轴,
         * 按照该记录的关键字大小将该记录序列划分为左右两个子序列。
         * 这三个区间为[begin,mid-1],[mid],[mind+1,end];
         */
        int mid = partition(mat, begin, end);
        quickSort(mat, begin, mid - 1);
        quickSort(mat, mid + 1, end);
    }

    /*
     * partition-划分的意思
     */
    private static int partition(int[] mat, int begin, int end) {
        // 产生随机数,使得排序的时间更平均
        // int ran = (int) (Math.random() * (end - begin));
        // swap(mat, begin, begin + ran);
        /*
         * i指针的目的是找到一个比中轴大的数;
         * j指针的目的是找到一个比中轴小的数。
         * x中轴值
         */
        int i = begin;
        int j = end + 1;
        int x = mat[begin];
        while (true) {
            // i小于j就可以结束了
            while (mat[++i] < x && i < j)
                ;
            // mat[j]不可能大于x
            while (mat[--j] > x)
                ;
            if (i >= j) {
                break;
            }
            swap(mat, i, j);
        }
        // 把中轴放在中间的位置
        swap(mat, begin, j);
        return j;
    }

    private static void swap(int[] mat, int i, int j) {
        if (i == j) {
            return;
        }
        mat[i] = mat[i] ^ mat[j];
        mat[j] = mat[i] ^ mat[j];
        mat[i] = mat[i] ^ mat[j];
    }

    // 统一输出
    private static void print(int[] mat, int n) {
        for (int i = 0; i < n; i++) {
            if (i == 0) {
                System.out.print(mat[i]);
            } else {
                System.out.print(" " + mat[i]);
            }
        }
        System.out.println();
    }
}

---优化

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		int[] mat = new int[1001];// 快排一定要多一点内存,
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			quickSort(mat, 0, n - 1);
			print(mat, n);
		}
	}

	/*
	 * 快速排序,这个要用递归,慢慢来,有的是时间
	 * [begin,end]左包含,右包含,封闭区间
	 */
	private static void quickSort(int[] mat, int begin, int end) {
		/*
		 * 递归鸿沟
		 * 数组指针相同,用异或运算时会出错的,如果不确定这句话那么你自己在用“数组”指针相同运算一次
		 * --如果答案是没出错误,那么重复操作。。。
		 * 这个地方我解决了
		 */
		if (begin >= end) {
			return;
		}
		/*
		 * 任取待排序记录序列中的某个记录(一般为第一个)作为中轴,
		 * 按照该记录的关键字大小将该记录序列划分为左右两个子序列。
		 * 这三个区间为[begin,mid-1],[mid],[mind+1,end];
		 */
		int mid = partition(mat, begin, end);
		quickSort(mat, begin, mid - 1);
		quickSort(mat, mid + 1, end);
	}

	/*
	 * partition-划分的意思
	 */
	private static int partition(int[] mat, int begin, int end) {
		// 产生随机数,使得排序的时间更平均
		int ran = (int) (Math.random() * (end - begin));
		swap(mat, begin, begin + ran);
		/*
		 * i指针的目的是找到一个比中轴大的数;
		 * j指针的目的是找到一个比中轴小的数。
		 * x中轴值
		 */
		int i = begin;
		int j = end + 1;
		int x = mat[begin];
		while (true) {
			// i小于j就可以结束了
			while (mat[++i] < x && i < j)
				;
			// mat[j]不可能大于x
			while (mat[--j] > x)
				;
			if (i >= j) {
				break;
			}
			swap(mat, i, j);
		}
		// 把中轴放在中间的位置
		swap(mat, begin, j);
		return j;
	}

	private static void swap(int[] mat, int i, int j) {
		if (i == j) {
			return;
		}
		mat[i] = mat[i] ^ mat[j];
		mat[j] = mat[i] ^ mat[j];
		mat[i] = mat[i] ^ mat[j];
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}




7)归并排序

定义成静态的变量,减少内存。

import java.util.Scanner;

public class Main {
	static int[] mat = new int[1001];// 快排一定要多一点内存,
	static int[] arr = new int[1001];

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while (t-- > 0) {
			int n = sc.nextInt();
			for (int i = 0; i < n; i++) {
				mat[i] = sc.nextInt();
			}
			mergeSort(0, n - 1);
			print(mat, n);
		}
	}

	/*
	 * 1)将N个记录分解成n个记录,
	 * --这时原数组没有移动,而是利用递归。
	 * 2)两两合并,得到n/2个长度为2或1的有序序列
	 * --这时数组被分成最小状态
	 * 3)将数据合并到一个新的数组里,然后原位拷贝到原来的数组中
	 * 4)重复2步骤
	 * --递归回退
	 */
	private static void mergeSort(int start, int end) {
		// 鸿沟
		if (start >= end) {
			return;
		}
		/*
		 *  1拆开数组
		 *  最开始是1个,最终被分成n个
		 */
		int mid = (start + end) / 2;
		mergeSort(start, mid);
		mergeSort(mid + 1, end);
		/*
		 *  2两两合并
		 *  最开始是n个,最终被合成1个
		 */
		merger(start, mid, end);
		/*
		 * 3拷贝
		 */
		copyArray(start, end);
	}

	private static void copyArray(int start, int end) {
		for (int i = start; i <= end; i++) {
			mat[i] = arr[i];
		}
	}

	/*
	 *  把以mid分界的两个数组合并到另一个数组中
	 *  升序
	 */
	private static void merger(int start, int mid, int end) {
		int i = start;
		int j = mid + 1;
		int k = start;
		while (i <= mid && j <= end) {
			if (mat[i] < mat[j]) {
				arr[k++] = mat[i++];
			} else {
				arr[k++] = mat[j++];
			}
		}
		if (i > mid) {// 表明左半区已经已经没有数据了
			while (j <= end) {
				arr[k++] = mat[j++];
			}
		} else {
			while (i <= mid) {
				arr[k++] = mat[i++];
			}
		}
	}

	// 统一输出
	private static void print(int[] mat, int n) {
		for (int i = 0; i < n; i++) {
			if (i == 0) {
				System.out.print(mat[i]);
			} else {
				System.out.print(" " + mat[i]);
			}
		}
		System.out.println();
	}
}




As Easy As A+B

和A+B一样容易
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 46139    Accepted Submission(s): 19710


Problem Description
These days, I am thinking about a question, how can I get a problem as easy as A+B? 
这些天,我想起了一个问题,我怎样才能可以得到一个和A+B一样N的水题?
It is fairly difficulty to do such a thing. Of course, I got it after many waking nights.
这件事相当的难。当然,在经过多个日夜后,我突然想出来了。
Give you some integers, your task is to sort these number ascending (升序).
给你一些整数,你的任务是给这些数进行排序,且是升序。
You should know how easy the problem is now!
现在你因该知道这道题有多难了吧!
Good luck!
 祝你好运!

Input
Input contains multiple test cases. The first line of the input is a single integer T which is the number of test cases. 
输入将包含多组测试事件。输入的第一行是一个整数T,表示测试事件的个数。
T test cases follow. Each test case contains an integer N (1<=N<=1000 the number of integers to be sorted) and then N integers follow in the same line. 
然后又T行测试数据,每一行的第一个整数是n,表示接下来要输入n个整数;
It is guarantied that all integers are in the range of 32-int.
 保证所有整数都在32-int范围内。

Output
For each case, print the sorting result, and one line one case.
 对于每一个测试事件,在新的一行输出排序后的结果。

Sample Input
  
  
2 3 2 1 3 9 1 4 7 2 5 8 3 6 9
 

Sample Output
  
  
1 2 3 1 2 3 4 5 6 7 8 9
 

Author
lcy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值