第二章&第三章 查找和排序(下)

1、

描述

给定一个正整数数组,请求出自第一个元素开始到每个元素为终点的中位数。

输入

第一行:N(1<N<=1000),代表数组的长度
第二行:N个整数,作为数组的元素,空格分开

输出

N个整数,空格隔开;第一位是数组第一个元素,第二位是前两个元素的上中位数……

样例输入

5
4 6 9 4 5

样例输出

4 4 6 4 5
import java.util.Arrays;
import java.util.Scanner;

class Main{
    public static void main(String[] args) {
        int x;
        int mid = 0;

        Scanner sc = new Scanner(System.in);
        x = sc.nextInt();
        int arr[] = new int[x];
        for(int i=0;i<x;i++){
            arr[i] = sc.nextInt();
        }
        for(int i=0;i<x;i++){
            int [] copy = Arrays.copyOfRange(arr,0,i+1);
            Arrays.sort(copy);
            mid = copy[i/2];
            System.out.print(mid+" ");
        }
    }
}

2、

描述

数组小和的定义如下:

例如:数组s = [1, 3, 5, 2, 4, 6],在s[1]的左边小于或等于s[1]的数的和为1,在s[2]的左边小于或等于s[2]的数有1和3,求和为4,……,将所有位置的左边比它小或者等于的数的和相加起来就是真个数组的小和。

给定一个数组,输出数组的小和。

输入

第一行:N(1<N<=100000),代表数组的长度
第二行:N个整数(<=100),作为数组的元素,空格分开

输出

数组的小和

样例输入

5
58 74 14 39 15

样例输出

86

思路:

不要爆破 我们要转变思想把当前数前面比她小的和转变为当前数要被加几次(就是跟后面数做比较,后面数比当前数大,就要加一次),这个正符合归并排序,每次比较,我们需要改进的是在比较是若后面数比当前数大,sum就加当前数,只需加一句:smallSum += s[i] * (right - j+ 1);
 

public class test3 {

    public static void merSort(int[] arr,int left,int right){

        if(left<right){
            int mid = (left+right)/2;
            merSort(arr,left,mid);//左边归并排序,使得左子序列有序
            merSort(arr,mid+1,right);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right);//合并两个子序列
        }
    }
    static int smallsum =0;
    private static void merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right - left + 1];//ps:也可以从开始就申请一个与原数组大小相同的数组,因为重复new数组会频繁申请内存
        int i = left;
        int j = mid+1;
        int k = 0;
        while(i<=mid&&j<=right){
            if (arr[i] < arr[j]) {
                smallsum+= arr[i]*(right-j+1);

            } else {
                temp[k++] = arr[j++];

            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[k++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[k++] = arr[j++];
        }
        //将temp中的元素全部拷贝到原数组中
        for (int k2 = 0; k2 < temp.length; k2++) {
            arr[k2 + left] = temp[k2];
        }
    }
    public static void main(String args[]){
        int[] test = {9,2,6,3,5,7,10,11,12};
        merSort(test,0,test.length-1);
        for(int i=0; i<test.length;i++){
            System.out.print(test[i] + " ");
        }
        System.out.println(smallsum);
    }

}

这个是我的代码,,但是有问题,,输出不出来??

copy了别人的一份正确代码



public class test{

    public static int getSmallSum(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        return func(arr, 0, arr.length - 1);
    }

    public static int func(int[] s, int l, int r) {
        if (l == r) {
            return 0;
        }
        int mid = (l + r) / 2;
        return func(s, l, mid) + func(s, mid + 1, r) + merge(s, l, mid, r);
    }

    public static int merge(int[] s, int left, int mid, int right) {
        int[] h = new int[right - left + 1];
        int hi = 0;
        int i = left;
        int j = mid + 1;
        int smallSum = 0;
        while (i <= mid && j <= right) {
            if (s[i] <= s[j]) {
                smallSum += s[i] * (right - j + 1);
                h[hi++] = s[i++];
            } else {
                h[hi++] = s[j++];
            }
        }
        for (; (j < right + 1) || (i < mid + 1); j++, i++) {
            h[hi++] = i > mid ? s[j] : s[i];
        }
        for (int k = 0; k != h.length; k++) {
            s[left++] = h[k];
        }
        return smallSum;
    }

    public static void swap(int[] arr, int index1, int index2) {
        int tmp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = tmp;
    }

    public static void main(String[] args) {
        int[] arr = { 58, 74, 14, 39, 15 };
        System.out.println(getSmallSum(arr));

    }

}

3、

描述

给定一个数组,求最小的K个数。由于数组规模很大,请精心设计算法。

输入

第一行:N(1<N<=100000),代表数组的长度
第二行:K(<=1000,<N),代表求从小到大的K个数
第三行:N个整数,作为数组的元素,空格分开

输出

从小到大输出K个数组中最小的数,空格隔开

思路:利用堆排序,特别适用于海量数据中寻找最大或者最小的k个数字。即构建一个大堆容器,初始化大小为k,变量初始数,如初始数组大小小于等于k直接返回,如果大于k,则选择数组的前k个元素,填充堆,然后调整为最大堆。调整完之后,继续从初始数组中拿出一个元素,如果该元素比大堆的堆顶小,则替换堆顶,继续调整为最大堆,如果大于等于堆顶则直接丢弃,不作调整。 
PS:大堆还是小堆的选择很重要,不是寻找最小的k个元素就要选择小堆,而且恰恰相反。寻找最小的k个数,其实就是寻找第k个大的元素,即寻找k个数中最大的,不断调整堆,堆得元素个数是k,堆顶是最大值,遍历完初始数组后,堆中存在的元素即使我们所要寻找的k个最小元素。
 

import java.util.Scanner;

class Main{

    static int[] heap;
    static int index = 0;
    static int k;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int count = sc.nextInt();
        k = sc.nextInt();
        heap = new int[k];
        int x=0;

        for(int i=0;i<count;i++){

            x = sc.nextInt();
            deal(x);
        }

        for(int i=k-1;i>=0;i--){
            System.out.print(heap[i]+" ");
        }
    }


    static void deal(int x){
        if(index<k){
            heap[index++] = x;
            if(index == k){
                makeMinHeap(heap);  //堆化
            }
        }else {
            if(heap[0]>x){  //如果找最小的数,就选大顶堆,,如果x>heap[0],x就把他挤掉并向下调整
                heap[0]  =x;
                MinHeapFixDown(heap,0,k);
            }
        }
    }
    static void makeMinHeap(int [] heap){
        int n = heap.length;
        for(int i=n/2-1;i>=0;i--){
            MinHeapFixDown(heap,i,n);
        }
    }

    static void MinHeapFixDown(int[] heap,int i,int n){
        int left  = 2*i+1;
        int right = 2*i+2;

        if( left>=n){
            return;
        }
        int max = left;
        if(right>=n){
            max = left;
        }else{
            if(heap[right]>heap[left]){
                max = right;
            }
        }

        if(heap[i]>heap[max]){
            return;
        }
        int temp = heap[i];
        heap[i] = heap[max];
        heap[max] = temp;

        MinHeapFixDown(heap,max,n);
    }
}

4、

给定一个字符串类型的数组strs,请找到一种拼接顺序,使得将所有的字符串拼接起来组成的大字符串是所有可能性中字典顺序最大的,并输出这个大字符串。

输入

第一行:N(1<N<=100),代表数组的长度
第二行:N个字符串,作为数组的元素,空格分开,字符串长度<=10

输出

字典序最大的大字符串

样例输入

5
a ac ab def d

样例输出

defdacaba

 



import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x= sc.nextInt();
        String a[] = new String[x];
        for (int i=0;i<x;i++){
            String st1 = sc.next();
            a[i]  = st1;
        }
        lowstring(a);
        System.out.println(res);

    }
    static String res = "";
    static String lowstring (String[] a){
        if(a==null || a.length==0) {
            return "";
        }
        Arrays.sort(a,new Mycomparator());

        for(int i=0;i<a.length;i++){
            res+= a[i];
        }
        return res;
    }

    static class Mycomparator implements Comparator<String>{
        @Override
        public int compare(String s, String t1) {
            return(t1+s).compareTo(s+t1);
        }
    }
}

5、

一般我们在对字符串排序时,都会按照字典序排序。当字符串只包含小写字母时,相当于按字母表"abcdefghijklmnopqrstuvwxyz"的顺序排序。  

现在我们打乱字母表的顺序,得到一个26个字母的新顺序:bdceafghijklmnopqrstuvwxyz,代表'b'排在'd'前,'d'在'c'前,'c'在'e'前……  

给定N个字符串,请你按照新的字母顺序对它们排序。

输入

第一行包含一个整数N。(1 <= N <= 1000)

第二行包含26个字母,代表新的顺序。

以下N行每行一个字符串S。 (|S| <= 100)

输出

按新的顺序输出N个字符串,每个字符串一行。

样例输入

5
bdceafghijklmnopqrstuvwxyz
abcde
adc
cda
cad
ddc

样例输出

ddc
cda
cad
abcde
adc

额。。。。。这道题好想吐槽,java字符串修改要用char,字符串排序要用string,换来换去好麻烦

import java.util.Arrays;
import java.util.Scanner;
 
public class Main {
	static int n;
	static int[] ma=new int[26];
	static int[] jie=new int[26];
	static String a=new String();
	static char[][] b=new char[1005][105];
	static String[] ans=new String[1005];
	public static void main(String args[]) {
		Scanner in=new Scanner(System.in);
		n=in.nextInt();
		a=in.next();
		for(int i=0;i<a.length();i++) {
			ma[i]=a.charAt(i)-'a';
			jie[a.charAt(i)-'a']=i;
		}
		for(int i=0;i<n;i++) {
			a=in.next();
			b[i]=a.toCharArray();
			for(int j=0;j<b[i].length;j++) {
				b[i][j]=(char)(jie[b[i][j]-'a']+'a');
			}
			ans[i]=String.valueOf(b[i]);
		}
		Arrays.sort(ans,0,n);
		for(int i=0;i<n;i++) {
			b[i]=ans[i].toCharArray();
			for(int j=0;j<b[i].length;j++) {
				b[i][j]=(char)(ma[b[i][j]-'a']+'a');
			}
			System.out.println(b[i]);
		}
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构与算法是计算机科学的基础和核心领域之一,第ba章介绍了数据结构的相关内容。 本章主要包括以下几个方面的内容: 1. 线性结构:线性结构是指数据元素之间存在一对一的关系,包括线性表、栈和队列。线性表是最基本的数据结构之一,它分为顺序表和链表两种形式。顺序表使用数组实现,插入和删除操作相对低效。链表使用指针实现,插入和删除操作较为灵活。 2. 树结构:树结构是一种层次结构,由节点和边组成。常见的树结构有二叉树、二叉搜索树和平衡二叉树等。二叉树中每个节点最多有两个子节点,二叉搜索树中左子节点的值小于根节点,右子节点的值大于根节点,查找效率较高。平衡二叉树是一种保持左右子树高度差不大于1的二叉搜索树。 3. 图结构:图结构是由节点和边组成的非线性结构。图分为有向图和无向图。图的表示方法有邻接矩阵和邻接表两种。深度优先搜索和广度优先搜索是图的常用遍历方法,可用于寻找路径、连通分量等问题。 4. 排序算法:排序算法是对一组无序数据进行按照某个规则进行有序排列的算法。第ba章介绍了常见的排序算法,包括冒泡排序、插入排序、选择排序、归并排序、快速排序等。每种排序算法的时间复杂度和空间复杂度不同,选择合适的排序算法可以提高性能。 5. 查找算法:查找算法是在一组数据中搜索某个特定元素的算法。第ba章介绍了顺序查找、二分查找和哈希查找等常见的查找算法。二分查找是在有序数组中应用最广泛的查找算法,通过不断缩小查找范围来快速定位目标值。 通过学习这些内容,我们可以了解不同数据结构的特点和应用场景,以及常见的排序查找算法。掌握好这些知识,对于解决实际问题和提高程序效率都有很大帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值