LeetCode刷題總結-數組篇(番外)

本期講思維轉換類型問題,共7道題,三道簡單題,四道中等題。

此部分題目是作者認爲有價值去做的一些題,但是其考察的知識點不在前三篇總結系列裏面。

  • 例1解法:採用數組索引位置排序的思想。
  • 例2解法:考察了組合數學的組合公式應用。有點類似動態規劃的思想。
  • 例3解法:  考察靈活運用二進制和整除餘數的數學知識。
  • 例4解法:動態規劃思想的應用。
  • 例5解法:分類討論的數學思想。
  • 例6解法:考察靈活運用哈希字典。
  • 例7解法:考察閏年的數學判斷公式,計算周幾的細節處理能力。

例1 最大寬度坡

題號:962,難度:中等

題目描述:

解題思路:

採用索引排序的思路,使得從前往後遍歷時,A[i] < A[j]。然後不斷更新i的最小值,當前遍歷的索引即爲j。即可求取最終結果。

具體代碼:

class Solution {
    public int maxWidthRamp(int[] A) {
        int N = A.length;
        Integer[] B = new Integer[N];
        for (int i = 0; i < N; ++i)
            B[i] = i;

        Arrays.sort(B, (i, j) -> ((Integer) A[i]).compareTo(A[j]));

        int result = 0;
        int i = N;
        for (int j: B) {
            result = Math.max(result, j - i);
            i = Math.min(i, j);
        }

        return result;
    }
}

 

執行結果:

 

例2 總持續時間可被60整除的歌曲

題號:1010,難度:簡單

題目描述:

 

解題思路:

本題考察了組合數學公式的應用,以及數學知識的轉換和遷移應用。

具體代碼:

class Solution {
    public int numPairsDivisibleBy60(int[] time) {
        int[] temp = new int[60];
        int result = 0;
        for(Integer t: time) {
            if(t % 60 == 0)
                result += temp[0];
            else
                result += temp[60 - (t % 60)];
            temp[t % 60]++;
        }
        
        return result;
    }
}

 

執行結果:

 

例3 可被5整除的二進制前綴

題號:1018,難度:簡單

題目描述:

 

解題思路:

此題需要抓住整除的核心,即個位數是5的倍數時,即可整除5。我們只需要統計當前二進制數的個位數即可。

具體代碼:

class Solution {
    public List<Boolean> prefixesDivBy5(int[] A) {
        List<Boolean> ans = new ArrayList<>();
        
        int num = 0;
        for (int i = 0;i < A.length;i++) {
            num <<= 1;
            num += A[i];
            num %= 10;
            ans.add(num % 5 == 0);
        }
        
        return ans;
    }
}

執行結果:

 

例4 不相交的線

題號:1035,難度:中等

題目描述:

 

解題思路:

此題考察我們動態規劃思想的應用。動態遞推方程:可參考代碼。

具體代碼:

class Solution {
    public int maxUncrossedLines(int[] A, int[] B) {
        
        int[][] dp = new int[A.length + 1][B.length + 1];
        for (int i = 1; i < dp.length; i++) {
            for (int j = 1; j < dp[0].length; j++) {
                if (A[i - 1] == B[j - 1])
                    dp[i][j] = dp[i - 1][ j - 1] + 1;
                else
                    dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
            }
        }
        return dp[A.length][B.length];
    }
}

執行結果:

 

例5 遞減元素使數組呈鋸齒狀

題號:1144,難度:中等

題目描述:

 

解題思路:

分類討論。按照題目的意思,分奇數偶數討論求解最終的最小操作次數即可。

具體代碼:

class Solution {
     public int movesToMakeZigzag(int[] nums) {
        int odd = 0;
        int eve = 0;
        //偶數最高
        for (int i = 0; i < nums.length; i+=2) {
            int temp = 0;
            if(i ==0){
               temp = nums [1];
            }else if (i==nums.length -1){
                temp= nums[nums.length -2];
            }else {
                temp = nums [i-1]>nums[i+1]?nums[i+1]:nums [i-1];
            }
            if(temp<=nums[i]){
                eve+=nums[i]-temp+1;
            }
        }

        //奇數最高
        for (int i = 1; i < nums.length; i+=2) {
            int temp = 0;
           if (i==nums.length -1){
                temp= nums[nums.length -2];
            }else {
                temp = nums [i-1]>nums[i+1]?nums[i+1]:nums [i-1];
            }
            if(temp<=nums[i]){
                odd+=nums[i]-temp+1;
            }
        }

        return eve>odd?odd:eve;
    }
}

執行結果:

 

例6 快照數組

題號:1146, 難度:中等

題目描述:

 

解題思路:

考察哈希字典的應用。

具體代碼:

import java.util.Map.Entry;
class SnapshotArray {
    int snap_id;
    ArrayList<TreeMap<Integer,Integer>> list = new ArrayList<TreeMap<Integer,Integer>>();
    public SnapshotArray(int length) {
        list.clear();
        for(int i = 0;i < length;i++) {
            list.add(new TreeMap<Integer,Integer>());
        }
    }    
    public void set(int index, int val) {
        TreeMap<Integer, Integer> pairMap = list.get(index);  
        Integer value = pairMap.getOrDefault(snap_id, val);
        pairMap.put(snap_id, val);
    }    
    public int snap() {   
        return snap_id++;
    }   
    public int get(int index, int snap_id) {
        Entry<Integer, Integer> entry = list.get(index).floorEntry(snap_id);
        return entry == null ? 0 : entry.getValue();
    }
}

/**
 * Your SnapshotArray object will be instantiated and called as such:
 * SnapshotArray obj = new SnapshotArray(length);
 * obj.set(index,val);
 * int param_2 = obj.snap();
 * int param_3 = obj.get(index,snap_id);
 */

 

執行結果:

 

例7 一週中的第幾天

題號:1185,難度:簡單

題目描述:

 

解題思路:

此題考察閏年的數學判定公式,以及對於月份的邊界處理,對於細節的處理考察比較多。也是一道鍛鍊我們代碼能力的經典算法題。(PS:不能調用庫函數)當然,此題還可以參考LeetCode的評論中,一個名爲蔡樂公式的解法,但是一般是記不住的。

具體代碼:

class Solution {
    public String dayOfTheWeek(int day, int month, int year) {
        int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        String[] result = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
        int init_y = 1999, init_m = 7, init_d = 18;
        int all_days = 0;
        if(year > init_y) {
            all_days += 13;
            for(int i = 7;i < 12;i++)
                all_days += months[i];
            for(int j = 2000;j < year;j++) {
                if((j % 4 == 0 && j % 100 != 0) || j % 400 == 0)
                    all_days += 366;
                else
                    all_days += 365;
            }
            for(int i = 0;i < month - 1;i++)
                all_days += months[i];
            all_days += day;
            if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
                if(month > 2)
                    all_days++;
            return result[all_days % 7];        
        } else if(year == init_y) {
            if(month > init_m) {
                all_days += 13;
                for(int i = 7;i < month - 1;i++)
                    all_days += months[i];
                all_days += day;
                return result[all_days % 7]; 
            } else if(month == init_m) {
                if(day >= init_d)
                    all_days += (day - init_d);
                int k = all_days % 7;
                if(day < init_d) {
                    all_days += (init_d - day);
                    k = (7 - all_days % 7) % 7;
                }
                return result[k];  
            }
        } else {
            all_days += 18;
            for(int i = 0;i < 6;i++)
                all_days += months[i];
            for(int j = 1998;j > year;j--) {
                if((j % 4 == 0 && j % 100 != 0) || j % 400 == 0)
                    all_days += 366;
                else
                    all_days += 365;
            }
            for(int i = month;i < 12;i++)
                all_days += months[i];
            all_days += months[month - 1] - day;
            if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
                if(month < 2)
                    all_days++;
            all_days = (7 - all_days % 7) % 7;
            return result[all_days]; 
        }
        return result[0];
    }
}

執行結果:

 

 

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