面試題-算法篇

一、單鏈表倒序排列

public static void revse(Node node){
        //拿到頭結點
        Node head = node;
        //拿到當前循環的節點
        Node curNode = node.next;
        //頭結點的next置爲null
        head.next = null;
        //如果當前節點不爲空
        while(curNode != null){
            //取出當前節點的下一個節點,作爲下次循環遍歷用
            Node next = curNode.next;
            //將當前節點的下一個節點,指向前一個節點
            curNode.next = head;
            //前一個節點指向當前節點
            head = curNode;
            //把取出的下一個節點作爲當前節點,繼續循環
            curNode = next;
        }
    }

         算法不難,網上案例比較多,但是就是在寫的時候思路亂了,沒寫好,只把思路說出來了

二、兩個數組交叉打印,線程同時start,必須從1開始打印

//題目要求必須打出1,2,3,4,5,6,7,8,9,10
private static int[] arr1 = new int[]{1,3,5,7,9};
private static int[] arr2 = new int[]{2,4,6,8,10};
//線程間通信用volatile修飾的關鍵字
private static volatile boolean status = false;
    public static void main(String[] args) {
        //使用jdk提供的鎖
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        //開啓線程並在循環開始的時候加鎖
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i =0;i< arr2.length;i++){
                    lock.lock();
                    try {
                        //如果status!=true,那麼當前線程阻塞(await會釋放鎖)
                        if(status != true){
                            condition.await();
                        }
                        //打印數據
                        System.out.println(arr2[i]);
                        //喚醒其他線程
                        condition.signalAll();
                        try {
                        //阻塞當前線程
                            condition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } catch (Exception e) {
                        lock.unlock();
                    }
                }
            }
        });

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < arr1.length; i++) {
                    lock.lock();
                    try {
                        //當前線程拿到鎖之後打印出1
                        System.out.println(arr1[i]);
                        //status置爲true
                        if(status ==false) {
                            status = true;
                        }
                        //喚醒正在阻塞的線程
                        condition.signalAll();
                        try {
                            //當前線程阻塞
                            condition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } catch (Exception e) {
                        lock.unlock();
                    }
                }
            }
        });
        thread1.start();
        thread2.start();

    }

           這道題考察的是對線程的等待喚醒機制,及線程間通信的理解

三,發紅包算法,如何公平的將100元,分配給10個人(二倍均值法)

/**
     * 發紅包算法,入參人數和總金額,返回,人和金額的map
     * @param person
     * @param totalMoney
     * @return
     */
    public static Map<Integer,Double> sendRedPackage(Integer person,Double totalMoney){
        if(person<=0 || totalMoney<=0.0){
            return new HashMap<>();
        }
        Map<Integer,Double> result = new HashMap<>();
        for(int i = 0;i<person;i++){
            if(i == person -1){
                result.put(i,new BigDecimal(totalMoney+"").setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
                break;
            }

            double avgMoney = totalMoney / (person-i);
            double money = new Random().nextDouble() * avgMoney * 2;
            money = new BigDecimal(money+"").setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
            if(money<0.01){
                money = 0.01;
            }
            if(money>avgMoney){
                money =new BigDecimal(avgMoney+"").setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
            }
            result.put(i,money);
            totalMoney = totalMoney - money;
        }
        return result;
    }

 

四,一個不知道長度的鏈表,輸出鏈表中倒數第n個值

//實現思路,使用兩個指針,步長爲n,當第一個指針走到最後的時候,此時第二個指針的位置就是倒數第n個值
public static Node sout(Node node,int n){
        int i = 0;
        Node result =null;
        Node firstNode = node;
        Node secondNode = node;
        while (firstNode!=null){
            i++;
            if(i >= n){
                result = secondNode;
                secondNode = secondNode.next;
            }
            firstNode = firstNode.next;
            if(firstNode ==null){
                break;
            }
        }
        return result;
    }

 

五,快速排序算法及優化

     

    public static int[] arr = new int[]{4,2,3,7,6,5,0,9,1};
    public static void main(String[] args) {
        quickSort(arr,0,arr.length-1);
        System.out.println(arr);
    }
    public static void quickSort(int[] arr,int low ,int high){
        if(low > high){
            return;
        }
        int temp = arr[low];
        int i = low;
        int j = high;
        int t ;
        //將數組中按照基準值左右排開
        while(i<j){
            while(temp<=arr[j]&&i<j){
                j--;
            }
            while(temp>=arr[i]&&i<j){
                i++;
            }
            if(i<j){
                t = arr[i];
                arr[i]= arr[j];
                arr[j] = t;
            }
        }
        //交換基準值和第i或j的值
        arr[low] = arr[i];
        arr[i] = temp;
        //交換完成後,左右兩邊分別遞歸按照二分法思想做排序
        quickSort(arr,low,j-1);
        quickSort(arr,j+1,high);
    }

 

六,打印金額問題,給定的一個三位數,輸出對應的中文金額,如365,輸出爲叄佰陸拾伍元整,儘可能多的處理一些邊界值

         考察的是對事物思考的全面性,邊界值的處理

//僅支持三位整數,四位及以上或者小數不支持
public static void printToString(Integer money){
        String[] capital = { "零", "壹", "貳", "叄", "肆", "伍", "陸", "柒", "捌", "玖" };
        String[] integerUnit = { "", "拾", "佰", "仟", "萬" };

        int length = String.valueOf(money).length();
        for(int i = length;i>0;i--){
            int every = money / (int) (Math.pow(10, (i - 1)));
            money = money % (int) (Math.pow(10, (i - 1)));
            if(every==0 && money==0){
                break;
            }
            System.out.print(capital[every]);//輸出數字大寫
            if(every ==0){
                continue;
            }
            System.out.print(integerUnit[i - 1]);//輸出單位,
        }
        System.out.print("元整");
    }

 

      以上是關於美團和滴滴最近相關的算法面試題,有些當時只給出了思路,但是沒有寫出來,事後總結還是因爲當時思路並

      不是太明確,導致寫的時候思路不清晰只能給出大概的實現思路

      總結出來就是,看到算法題,第一步應該明確要考查的點,第二步就應該把整體的實現思路在腦子裏過一遍,分析完後在

      動筆去寫,算法題有很多,但是大多數的解決思路都差不太多,只要基礎夠好,臨場發揮問題不太大,就算是最後沒有實

       現,但是也要給出具體的實現思路

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章