【leetcode 399 周賽】【題解】

fishcanfly發表於2024-05-26
  • 第一題和第三題一樣。就是求約數

  • 第二題就是模擬

  • 第4題使用線段樹

  • 1,3題程式碼

  • 實際上發現沒有下面程式碼複雜,比如: a*b = n ,列舉a就好,a在[1, sqrt(n)內。

import java.util.*;

class Solution {

    public int numberOfPairs(int[] nums1, int[] nums2, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums2.length; i++) {
            map.put(nums2[i], map.getOrDefault(nums2[i], 0) + 1);
        }
        int ans = 0;
        for (int i = 0; i < nums1.length; i++) {
            if (nums1[i] % k == 0) {
                List<Integer> list = getfactor(nums1[i] / k);
                for (int num : list) {
                    ans += map.getOrDefault(num, 0);
                }
            }
        }
        return ans;
    }

    public List<int[]> getPrime(int n) {
        List<int[]> ans = new LinkedList<>();
        int p = 2;
        while (p * p <= n) {
            if (n % p == 0) {
                int cnt = 0;
                while (n % p == 0) {
                    n = n / p;
                    cnt++;
                }
                ans.add(new int[]{p, cnt});
            }
            p++;
        }
        if (n != 1) {
            ans.add(new int[]{n,1});
        }
        return ans;
    }

    public List<Integer> getfactor(int n) {
        List<int[]> ans = getPrime(n);
        List<Integer> res = new ArrayList<>();
        res.add(1);
        dfs(ans, res, 0, 1);
        return res;
    }

    public int pow(int base, int p) {
        if (p == 0) {
            return 1;
        }
        if (p == 1) {
            return base;
        }
        int ans = pow(base, p / 2);
        if (p % 2 == 0) {
            return ans * ans;
        }
        return ans * ans * base;
    }

    public void dfs(List<int[]> ans, List<Integer> res, int depth, int curr) {
        if (depth == ans.size()) {
            if (curr != 1) {
                res.add(curr);
            }
            return;
        }
        int[] tmp = ans.get(depth);
        int p = tmp[0];
        int cnt = tmp[1];
        for (int c = 0; c <= cnt; c++) {
            dfs(ans, res, depth + 1, curr * pow(p, c));
        }
    }
}
  • 第2題
class Solution {
    public String compressedString(String word) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < word.length(); ) {
            char c = word.charAt(i);
            int j =  i;
            int cnt = 0;
            while(j < word.length() && cnt < 9 && word.charAt(j) == c) {
                cnt++;
                j++;
            }
            sb.append(String.format("%d%c",cnt,c));
            i = j;
        }
        return sb.toString();
    }
}
  • 第4題 線段樹
class Solution {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int ans = solution.maximumSumSubsequence(new int[]{
                3,5,9
        }, new int[][]{
                {1, -2},
                {0, -3}
        });
        System.out.println(ans);
    }
    public int maximumSumSubsequence(int[] nums, int[][] queries) {
        int n = nums.length;
        Segment segment = new Segment(0, n - 1);
        for (int i = 0; i < nums.length; i++) {
            segment.update(i, nums[i]);
        }

        long ans = 0;
        for (int i = 0; i < queries.length; i++) {
            int pos = queries[i][0];
            int x = queries[i][1];
            nums[pos] = x;

            segment.update(pos, x);
            ans += segment.max();
            ans %= 1000_000_007;
        }
        return (int)ans;
    }

    class Segment {
        int l, r;
        Segment left, right;
        // f00, f01, f10, f11
        // f00 表示左端點一定不選,右端點也一定不選 最大值
        // f01 表示左端點一定不選,右端點可選可不選 最大值
        // f10 表示左端點可選可不選,右端點一定不選 最大值
        // f11 表示左端點可選可不選,右端點可選可不選 最大值
        int[] f = new int[4];

        public Segment(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int max() {
            return Math.max(Math.max(f[0], f[1]), Math.max(f[2], f[3]));
        }
        
        public void update(int L, int value) {
            if (l == L && L == r) {
                f[0] = 0;
                f[1] = 0;
                f[2] = 0;
                f[3] = Math.max(value, 0);
                return;
            }
            int mid = (l + r) / 2;
            if (this.left == null) {
                this.left = new Segment(l, mid);
            }
            if (this.right == null) {
                this.right = new Segment(mid + 1, r);
            }
            if (L <= mid) {
                this.left.update(L, value);
            } else {

                this.right.update(L, value);
            }

            pushup();
        }

        public void pushup() {
            int[] a = this.left.f;
            int[] b = this.right.f;

            f[0] = Math.max(a[0] + b[2], a[1] + b[0]);
            f[1] = Math.max(a[0] + b[3], a[1] + b[1]);
            f[2] = Math.max(a[2] + b[2], a[3] + b[0]);
            f[3] = Math.max(a[2] + b[3], a[3] + b[1]);
        }
    }
}

相關文章