筆試演算法題總結

小強Zzz發表於2022-04-11

HashMap

hashmap的原理這裡不再講述,不知道的小夥伴可以看這篇文章。Hash與HashMap
hashmap資料結構的引入能幫助我們將O(n)的時間複雜度降低為O(1)的時間複雜度,代價是使用了O(n)的空間複雜度。這麼一看好像功過參半。但是如果我們原來的時間複雜度是O(n^2),使用了hashmap後時間複雜度變為o(n),而只是空間複雜度變為O(n),那麼還是很划算的。
力扣第一題,兩數之和:
image.png
如果我們用單純的二維遍歷做的話

public int[] twoSum(int[] nums, int target) {
    int n = nums.length;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (nums[i] + nums[j] == target) {
                return new int[]{i, j};
            }
        }
    }
    return new int[0];
}

image.png
第一種方法時間高原因是,對於每一個第一層遍歷的i,我們都需要再次遍歷陣列找到target - i。
如果我們用hashmap將陣列元素值及對應下標存入hashmap裡,我們就可以直接獲得target - i對應下標值,而不需要第二次遍歷。

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
    for (int i = 0; i < nums.length; i++) {
        if (hashtable.containsKey(target - nums[i])) {
            return new int[]{hashtable.get(target - nums[i]), i};
        }
        hashtable.put(nums[i], i);
    }
    return new int[0];
}

image.png
image.png
遇到的實際題目是三數之和,給一個陣列和一個目標值,在這個陣列中找到三個數相加為目標值,如果找得到返回true,如果找不到返回false。三數之和就可以使用hashmap將三層迴圈降為兩層迴圈,其他跟兩數之和相似。

動態規劃

基本思想:將待求解的問題分解成若干個子問題,先求解子問題,然後從這些子問題的解得到原問題的解。
某音公司筆試題,力扣原題改編
image.png
思路是依次確定是否能到達第i個位置。到達第i個位置的要求是能到達第j個位置(i>j)並能從第j個位置直接跳躍至第i個位置。

public boolean canJump(int[] nums) {
    // 邊界判斷
    if (nums.length == 1) {
        return true;
    }
    boolean[] dp = new boolean[nums.length];
    int i;
    // 從第1個下標可以直接到達的地方標記為可到達。
    for (i = 0; i < nums[0] + 1 && i < nums.length; i++) {
        dp[i] = true;
    }

    // 其餘標記為不可達
    for (; i < nums.length; i++) {
        dp[i] = false;
    }

    // 對於每一個位置i,確定是否能能到達第j個位置(i>j)並能從第j個位置直接跳躍至第i個位置
    for (i = nums[0] + 1; i < nums.length; i++) {
        for (int j = 0; j < i; j++) {
            if (dp[j] && j + nums[j] >= i) {
                dp[i] = true;
                break;
            }
        }
    }

    return dp[nums.length -1];
}

image.png
image.png
當然這只是一種思路,這題還有更快更好的方法。
力扣139題:單詞拆分
image.png
遇上題相同思路,不過在判斷一個單詞是否在陣列中時使用hashmap判斷即可。
這題也可以使用字典樹來實現,有興趣的小夥伴可以搜尋什麼是字典樹。

貪心演算法

基本思想:貪心演算法並不從整體最優上加以考慮,它所做的選擇只是在某種意義上的區域性最優解。
某公司面試題,力扣原題改編:
image.png
看起來很簡單,但是思考起來沒想到最優解。因為買入的天數一定小於賣出的天數,那麼買入天數的價格一定是賣出天數到第一天裡所有價格的最小值。解題思想是依次假設第i天是賣出那天,找第i天的之前最小价格那天價格,維護最大利潤。

public int maxProfit(int[] prices) {
    if (prices.length <= 1)
        return 0;
    int min = prices[0], profit = 0;
    for (int i = 0; i < prices.length; i++) {
        min = Math.min(min, prices[i]);
        profit = Math.max(profit, prices[i] - min);
    }
    return profit;
}

其他

某音筆試有一道核心是判斷否是雙端佇列的問題,就是一個佇列只能從兩端進。一次放入n個數,給一個陣列判斷是否是雙端佇列。
6 3 1 2 4 5 7 8
筆試過程中想複雜了,後邊看到其實就是找到最小數,然後判斷最小數到頭尾是否是遞增序列。其實在學資料結構的時候做過類似的選擇題,但是不需要程式碼實現。對於平常的思想落實到程式碼實現很重要。

應試技巧

在網上看見說演算法題通過率*本題分數為最後得分。對於一些輸出True或False的題不會做可以直接輸出結果,或者輸出最小次數的題也可以直接輸出3或4或5。

相關文章