[leetcode 第 400 場周賽]題解

fishcanfly發表於2024-06-02

第一題:

class Solution {
  public int minimumChairs(String s) {
    int x = 0;
    int ans = 0;
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) == 'E') {
        x--;
        if (x<0) {
          ans++;
          x = 0;
        }
      }
      else {
        x++;
      }
    }
    return ans;
  }
}

第2題

import java.util.*;
class Solution {
  public static void main(String[] args) {
    Solution solution = new Solution();
    int ans = solution.countDays(10, new int[][]{
        {5,7},{1,3},{9,10}
    });
    System.out.println(ans);
  }
  public int countDays(int days, int[][] meetings) {
    TreeSet<List<Integer>> treeSet = new TreeSet<List<Integer>>(new Comparator<List<Integer>>() {
      @Override
      public int compare(List<Integer> a, List<Integer> b) {
        int x0 = a.get(0);
        int y0 = a.get(1);
        int x = b.get(0);
        int y = b.get(1);

        if (x0 != x) {
          return x0 - x;
        }
        return y0 - y;
      }
    });

    Arrays.sort(meetings, new Comparator<int[]>() {
      @Override
      public int compare(int[] a, int[] b) {
        return a[0] - b[0];
      }
    });

    for (int i = 0; i < meetings.length; i++) {
      if (treeSet.isEmpty()) {
        treeSet.add(new ArrayList<>(Arrays.asList(meetings[i][0], meetings[i][1])));
      }
      else {
        List<Integer> last = treeSet.last();
        // last
        int x0 = last.get(0);
        int y0 = last.get(1);

        int x = meetings[i][0];
        int y = meetings[i][1];

        if ( x <= y0) {
          // can merge;
          treeSet.remove(last);
          treeSet.add(new ArrayList<>(Arrays.asList(x0, Math.max(y0, y))));
        }
        else {
          treeSet.add(new ArrayList<>(Arrays.asList(x, y)));
        }
      }
    }
    int ans = days;
    for (List<Integer> list : treeSet) {
      ans -= (list.get(1) - list.get(0) + 1);
    }
    return ans;
  }
}

第三題

import java.util.*;
class Solution {
  public String clearStars(String s) {
    TreeSet<List<Integer>> set = new TreeSet<List<Integer>>(new Comparator<List<Integer>>() {
      @Override
      public int compare(List<Integer> a, List<Integer> b) {
        int ch1 = a.get(0);
        int index1 = a.get(1);
        int ch2 = b.get(0);
        int index2 = b.get(1);

        if (ch1 != ch2) {
          // 小的排在前面
          return ch1 - ch2;
        }
        // 序號打的排前面
        return (index2 - index1);
      }
    });

    int n = s.length();
    boolean[] marked = new boolean[n];

    char ch = s.charAt(0);
    if (ch != '*') {
      set.add(new ArrayList<>(Arrays.asList(ch - 'a', 0)));
    }

    for (int i = 1; i < n; i++) {
      ch = s.charAt(i);
      if (ch == '*') {
        marked[i] = true;
      }
      if (ch == '*' && !set.isEmpty()) {
        List<Integer> first = set.pollFirst();
        marked[first.get(1)] = true;
      } else {
        set.add(new ArrayList<>(Arrays.asList(ch - 'a', i)));
      }
    }
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < n; i++) {
      if (!marked[i]) {
        sb.append(s.charAt(i));
      }
    }
    return  sb.toString();
  }
}

第4題

  • 注意and會越來越小,所以考慮大於k和小於k的情況,然後再用雙指標實現
class Solution {
  public boolean hasMask(int num, int i) {
    return (num & (1 << i)) != 0;
  }

  public static void main(String[] args) {
    Solution solution = new Solution();
    int ans = solution.minimumDifference(new int[]{
        1, 10, 6
    }, 7);
    System.out.println(ans);
  }

  public int minimumDifference(int[] nums, int k) {
    // dp[i][b] 表示前i個數第b位為0個數
    int n = nums.length;
    int[][] dp = new int[n][32];
    for (int i = 0; i < n; i++) {
      for (int b = 31; b >= 0; b--) {
        if (i == 0) {
          dp[i][b] = hasMask(nums[i], b) ? 0 : 1;
          continue;
        }
        dp[i][b] = dp[i - 1][b] + (hasMask(nums[i], b) ? 0 : 1);
      }
    }

    //
    int j = -1;
    int ans = Integer.MAX_VALUE;
    int x = Integer.MAX_VALUE;
    while (j < n && x > k) {
      j++;
      if (j == n) {
        break;
      }
      x = x & nums[j];
      ans = Math.min(ans, Math.abs(x - k));
    }
    // [0..j] 其中a0...aj是小於等於k的。
    // [i..j]開始重新計算
    for (int i = 1; i < nums.length && j < n; i++) {
      if (j < i) {
        j = i;
        x = nums[i];
      } else {
        int last = nums[i - 1];
        // 考慮哪些為0的位,是否會改變,為1的位是沒有變化的
        // [i-1,j][b]有多少個0
        for (int b = 31; b >= 0; b--) {
          if (!hasMask(x, b) && !hasMask(last, b) && isGreater0(i, j, b, dp)) {
            // need change.
            x = x + (1 << b);
          }
        }
      }
      ans = Math.min(ans, Math.abs(x - k));
      while (j<n && x > k) {
        j++;
        if ( j == n) {
          break;
        }
        x = x & nums[j];
        ans = Math.min(ans, Math.abs(x - k));
      }
    }
    return ans;
  }

  public boolean isGreater0(int i, int j, int b, int[][] dp) {
    int x = dp[i - 1][b];
    int y = dp[j][b];
    int zero = y - x;
    int one = j - i + 1 - zero;
    return zero == 0 && one >=1;
  }
}

相關文章