算法设计 第三次作业

1 题目1 所有同学往右侧看到的同学之和

青海大学的体育课经常排在上午3、4节,一节课下来大家都筋疲力尽、饥肠辘辘。将近下课,体育老师一吹口哨大家立即集合,不过这次集合大家都站成了一排,然后老师说向右看齐,这时每个人只能看到右侧比自己矮的人头,如果突然出现一个高于或等于自己身高的同学,那么这名同学以及其右侧的同学将会被挡住。那么,问题来了,现给定所有同学的身高(假设体育课大家修炼了一种神秘技能,改变了自己的身高,(身高最大值为2*106),要求每个人能往右侧看到的人数之和(建议使用long long存储)。

输入

输入包括两行
第一行是人数N(2<=N <= 2*106)
第二行包括N个数字 表示N个同学的身高

输出

输出一个整数,表示所有同学往右侧看到的同学之和

1.1 思路

单调栈的思想运用,从左往右扫描

if 栈为空,或者栈顶元素大于当前元素  
    当前元素进栈。  
else if 当前元素大于栈顶元素,  
    n = 栈顶元素对应的同学能看到的同学数,就是当前同学的编号减去栈顶同学编号再减去1,  
    sum += n  (将这个值累加到sum)
    

在同学向右看的队列的最后一个同学后面再插入一个同学,假设此同学是所有同学中最高的。保证每个同学都能从栈里面出来。

1.2 java代码(在最大矩形面积的代码基础上改)

import java.util.Stack;
import java.math.BigInteger;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        float[] array = {1.54f, 1.32f, 1.87f, 1.54f, 1.32f, 
                1.76f, 1.32f, 1.62f, 1.94f, 1.89f, 
                1.36f, 1.35f, 1.87f, 1.57f, 1.12f, 
                1.87f, 1.32f, 1.82f, 1.74f, 1.80f, 
                1.39f, 1.29f, 1.45f, 1.82f, 1.29f, 9999f};
        // 9999f即为哨兵学生, 假设他的身高比所有人都高
        System.out.print("学生的身高:");
        for(float e: array) System.out.print(e + " ");

        BigInteger sum = sum_count(array);
        System.out.println("\n所有人右看齐人数之和:" + sum);
    }

    public static BigInteger sum_count(float[] array){
        BigInteger sum = new BigInteger("0");
        int len = array.length;
        Stack<Integer> s = new Stack<Integer>();

        for(int i=0; i<len; i++){
            if(!s.isEmpty() && array[i] < s.peek())   s.push(i);
            else {
                while(!s.isEmpty() && array[i] >= s.peek()){
                    int top = s.pop();
                    sum = sum.add(new BigInteger((i-top-1)+""));
                }
                s.push(i);
            }
        }
        return sum;
    }

}

1.3 结果

题目2 求任意给定数组的逆序对总数

数据量10^6 (利用归并排序的思想)

2.1 思路

  • 归并排序思想
  • 在归并排序中,归并操作时,在每次右半部的数小于左半部某个数i时,逆序对count进行累加一次,并将值返回

2.2 Java代码

public class Main {
    public static void main(String[] args) {
        int[] array= {2, 3, 32, 5, 83, 9, 23, 4, 53, 4, 3, 2, 1, 2, 4, 7, 86, 21};
        System.out.print("Array:");
        for(int e: array) System.out.print(e + " ");

        System.out.println("\nInversion counts:" + inversion_count(array));
        System.out.println("Sorted array:" + java.util.Arrays.toString(array));
    }

    public static int inversion_count(int [] array) {
        if(array.length<=0) return 0;
        return merge_sort(array,0,array.length-1);
    }

    public static int  merge_sort(int[] array,int lo,int hi){
        if(lo>=hi) return 0;
        int mid=(lo+hi) >> 1;
        int lnums=merge_sort(array,lo,mid);
        int rnums=merge_sort(array,mid+1,hi);
        return  lnums+rnums+merge(array,lo,mid,hi);
    }

    public static int merge(int[] array, int lo, int mid ,int hi){
       int[] temp = new int[hi-lo+1]; 
       int count = 0;
       int i = lo, j = mid+1, t = 0;

       while( i<=mid || j<=hi ){
           if( i>mid && j<=hi ){
               temp[t++] = array[j++]; continue;
           }else if(i<=mid && j>hi){
               temp[t++] = array[i++]; continue;
           }

           if(array[i] > array[j]){
               temp[t++] = array[j++];
               count += mid-i+1;
           }else {
               temp[t++] = array[i++];
           }
       }
       for(i=lo; i<=hi; i++)
           array[i] = temp[i-lo];
       return count;
    }

}

2.3 结果

猜你喜欢

转载自www.cnblogs.com/liyuquan/p/8904601.html