1. 程式人生 > >算法設計 第三次作業

算法設計 第三次作業

count param RR ima static 整數 for else if bubuko

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 結果

技術分享圖片

算法設計 第三次作業