1. 程式人生 > 實用技巧 >leetcode刷題總結851-900

leetcode刷題總結851-900

851. 喧鬧和富有

  描述:
    

  思路:深度優先(帶記憶)。 這個題有點秒。。

853. 車隊

  描述:

    

  思路:

    我們首先對這些車輛按照它們的起始位置降序排序,並且用 (target - position) / speed 計算出每輛車在不受其餘車的影響時,行駛到終點需要的時間。對於相鄰的兩輛車 S 和 F,F 的起始位置大於 S,如果 S 行駛到終點需要的時間小於等於 F,那麼 S 一定會在終點前追上 F 並形成車隊。這是因為在追上 F 之前,S 的行駛速度並不會減小,而 F 卻有可能因為追上前面的車輛而速度減小,因此 S 總能在終點前追上 F。

854. 相似度為 K 的字串

  描述:

    

  思路:

class Solution {
public:

    int res , n ;

    void dfs(int pos , int step , string& A , string &B) {
        if (step >= res)
            return ;
        if (pos == n) {
            res = min(res , step) ;
            return ;
        }
        if (A[pos] == B[pos]) {
            dfs(pos 
+ 1 , step , A , B) ; } else { for (int i = pos + 1 ; i < n ; ++i) { if (A[i] == B[pos] && A[i] != B[i]) { swap(A[i] , A[pos]) ; dfs(pos + 1 , step + 1 , A , B) ; swap(A[i] , A[pos]) ; } } } }
int kSimilarity(string A, string B) { n = A.length() ; res = n + 1 ; dfs(0 , 0 , A , B) ; return res ; } };
View Code

856. 括號的分數

  描述:

    

  思路:棧

861. 翻轉矩陣後的得分

  描述:

    

  思路:

    先橫豎變換保證第一列全部是1
    豎變換保證其他列1比0多

862. 和至少為 K 的最短子陣列  

  描述:

    

  思路:字首和。然後進行雙指標判斷。

863. 二叉樹中所有距離為 K 的結點

  描述:

    

  思路:對於tartget進行深度優先,。

866. 迴文素數

  描述:

    

  思路:

      

class Solution {
    public int primePalindrome(int N) {
        while (true) {
            if (N == reverse(N) && isPrime(N))
                return N;
            N++;
            if (10_000_000 < N && N < 100_000_000)
                N = 100_000_000;
        }
    }

    public boolean isPrime(int N) {
        if (N < 2) return false;
        int R = (int) Math.sqrt(N);
        for (int d = 2; d <= R; ++d)
            if (N % d == 0) return false;
        return true;
    }

    public int reverse(int N) {
        int ans = 0;
        while (N > 0) {
            ans = 10 * ans + (N % 10);
            N /= 10;
        }
        return ans;
    }
}
View Code

869. 重新排序得到 2 的冪

  描述:

    

  思路:排列組合問題。 。。。回溯演算法。

    

class Solution {
    public boolean reorderedPowerOf2(int N) {
        // Build eg. N = 128 -> A = [1, 2, 8]
        String S = Integer.toString(N);
        int[] A = new int[S.length()];
        for (int i = 0; i < S.length(); ++i)
            A[i] = S.charAt(i) - '0';
        return permutations(A, 0);
    }

    // Return true if A represents a valid power of 2
    public boolean isPowerOfTwo(int[] A) {
        if (A[0] == 0) return false;  // no leading zero

        // Build eg. A = [1, 2, 8] -> N = 128
        int N = 0;
        for (int x: A)
            N = 10 * N + x;

        // Remove the largest power of 2
        while (N > 0 && ((N & 1) == 0))
            N >>= 1;

        // Check that there are no other factors besides 2
        return N == 1;
    }

    /**
     * Returns true if some permutation of (A[start], A[start+1], ...)
     * can result in A representing a power of 2.
     */
    public boolean permutations(int[] A, int start) {
        if (start == A.length)
            return isPowerOfTwo(A);

        // Choose some index i from [start, A.length - 1]
        // to be placed into position A[start].
        for (int i = start; i < A.length; ++i) {
            // Place A[start] with value A[i].
            swap(A, start, i);

            // For each such placement of A[start], if a permutation
            // of (A[start+1], A[start+2], ...) can result in A
            // representing a power of 2, return true.
            if (permutations(A, start + 1))
                return true;

            // Restore the array to the state it was in before
            // A[start] was placed with value A[i].
            swap(A, start, i);
        }

        return false;
    }

    public void swap(int[] A, int i, int j) {
        int t = A[i];
        A[i] = A[j];
        A[j] = t;
    }
}
View Code

870. 優勢洗牌

  描述:

    

  思路:貪心。田忌賽馬

    

class Solution {
    public int[] advantageCount(int[] a, int[] b) {
        int n = b.length;
        Arrays.sort(a);
        int[][] pair = new int[n][2];
        for (int i = 0; i < n; i ++)
            pair[i] = new int[]{b[i], i};//把下標儲存下來
        Arrays.sort(pair, (x, y)->x[0] - y[0]);

        int[] res = new int[n];
        for (int i = 0, r = n - 1, l = 0; i < n; i ++)//r最大值,l標明最小值;
        {
            if (a[i] <= pair[l][0]) res[pair[r --][1]] = a[i];//要放到原陣列對應的位置上
            else res[pair[l ++][1]] = a[i];////要放到原陣列對應的位置上
        }
        return res;
    }
}
View Code

871. 最低加油次數

  描述:

    

    

  思路:

    

class Solution {
    public int minRefuelStops(int target, int startFuel, int[][] stations) {

        if(stations.length == 0)
            return startFuel>=target?0:-1;
        PriorityQueue<Integer>queue = new PriorityQueue<Integer>((o1,o2)->{
            return o2-o1;
        });
        int sum = startFuel;
        int ans = 0;
        for(int i = 0;i < stations.length;i++)
        {
            while(sum < stations[i][0])
            {
                Integer ii = queue.poll();
                if(ii == null)return -1;
                sum += ii;
                ans++;
            }
            queue.offer(stations[i][1]);
        }
        while(sum < target)
            {
                Integer ii = queue.poll();
                if(ii == null)return -1;
                sum += ii;
                ans++;
            }
        return ans;
        
        
    }
    
   
}

873. 最長的斐波那契子序列的長度

  描述;
    

  思路:dp[i][j]:表示以A[i],A[j]結尾的斐波那契數列的最大長度

       

    

for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int diff = A[j] - A[i];
            if (intMap.count(diff)) {
                int index = intMap[diff];
                if (index < i) {
                    dp[i][j] = max(dp[i][j], dp[index][i] + 1);
                }
            }
            MAX = max(MAX, dp[i][j]);
        }
    }
View Code

875. 愛吃香蕉的珂珂

  描述:

    

  思路:二分。

877. 石子游戲

  描述:
    

  思路:動態規劃。

880. 索引處的解碼字串

  描述:

    

  思路:棧。

881. 救生艇

  描述:

    

  思路:貪心。

    

class Solution {
    public int numRescueBoats(int[] people, int limit) {
        Arrays.sort(people);
        int i = 0, j = people.length - 1;
        int ans = 0;

        while (i <= j) {
            ans++;
            if (people[i] + people[j] <= limit)
                i++;
            j--;
        }

        return ans;
    }
}
View Code

886. 可能的二分法

  描述;

    

  思路:深度優先,標記顏色。。類似於二部圖的方法,。

887. 雞蛋掉落

  描述:

    

  思路:

def superEggDrop(K: int, N: int):

    memo = dict()
    def dp(K, N) -> int:
        # base case
        if K == 1: return N
        if N == 0: return 0
        # 避免重複計算
        if (K, N) in memo:
            return memo[(K, N)]

        res = float('INF')
        # 窮舉所有可能的選擇
        for i in range(1, N + 1):
            res = min(res, 
                      max(
                            dp(K, N - i), 
                            dp(K - 1, i - 1)
                         ) + 1
                  )
        # 記入備忘錄
        memo[(K, N)] = res
        return res

    return dp(K, N)
View Code

890. 查詢和替換模式

  描述:

    

  思路:

class Solution {
    public List<String> findAndReplacePattern(String[] words, String pattern) {
        List<String> ans = new ArrayList();
        for (String word: words)
            if (match(word, pattern))
                ans.add(word);
        return ans;
    }

    public boolean match(String word, String pattern) {
        Map<Character, Character> m1 = new HashMap();
        Map<Character, Character> m2 = new HashMap();

        for (int i = 0; i < word.length(); ++i) {
            char w = word.charAt(i);
            char p = pattern.charAt(i);
            if (!m1.containsKey(w)) m1.put(w, p);
            if (!m2.containsKey(p)) m2.put(p, w);
            if (m1.get(w) != p || m2.get(p) != w)
                return false;
        }

        return true;
    }
}
View Code

894. 所有可能的滿二叉樹

  描述:

   

  思路:

    Java 首先偶數是不能構成滿二叉樹的。 思路是把總node數分別左邊,根,右邊進行遞迴,如7個node可以分成1,1,5;3,1,5;5,1,1(左,根,右)。 5個node又可以分為1,1,3和3,1,1。 3個node又可以分為1,1,1。 1個node直接返回。

class Solution {
    private HashMap<Integer, List<TreeNode>> hm = null;
    public List<TreeNode> allPossibleFBT(int N) {
        List<TreeNode> rtn = new ArrayList<>();
        if(N % 2 == 0) return rtn;
        if(N == 1) {
            TreeNode root = new TreeNode(0);
            rtn.add(root);
            return rtn;
        }
        if(hm == null) hm = new HashMap<>();
        for(int i = 1; i < N; i += 2) {
            List<TreeNode> left = hm.getOrDefault(i, null);
            if(left == null) {
                left = allPossibleFBT(i);
                hm.put(i, left);
            }
            List<TreeNode> right = hm.getOrDefault(N - 1 - i, null);
            if(right == null) {
                right = allPossibleFBT(N - 1 - i);
                hm.put(N - 1 - i, right);
            }
            for(TreeNode l : left) {
                for(TreeNode r : right) {
                    TreeNode root = new TreeNode(0);
                    root.left = l;
                    root.right = r;
                    rtn.add(root);
                }
            }
        }
        return rtn;
    }
}
View Code