前言

第一题:特殊数组的特征值

题解一:枚举

因为数组只有n个元素,因此可能的结果属于 [1,n] 。先对原数组排序,从n开始递减枚举,统计比x大的数的个数,直到找到符合答案。

  1. import java.util.Arrays;
  2. class Solution {
  3. public int specialArray(int[] nums) {
  4. final int n = nums.length;
  5. Arrays.sort(nums);
  6. int[] bigger = new int[n + 2];
  7. int index = n - 1;
  8. for (int i = n; i >= 0; --i) {
  9. bigger[i] = bigger[i + 1];
  10. while ((index >= 0) && (nums[index] >= i)) {
  11. ++bigger[i];
  12. --index;
  13. }
  14. if (i == bigger[i]) {
  15. return i;
  16. }
  17. }
  18. return -1;
  19. }
  20. public static void main(String[] args) {
  21. Solution s = new Solution();
  22. s.specialArray(new int[]{0, 0});
  23. }
  24. }

第二题:奇偶树

题解一:广度优先遍历

广度优先遍历,判断每层结点是否符合要求。

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. public boolean isEvenOddTree(TreeNode root) {
  18. Queue<TreeNode> queue = new LinkedList<>();
  19. if (root != null) {
  20. queue.offer(root);
  21. }
  22. int depth = -1;
  23. while (!queue.isEmpty()) {
  24. ++depth;
  25. int size = queue.size();
  26. int[] list = new int[size];
  27. int cur = -1;
  28. int last = -1;
  29. for (int i = 0; i < size; ++i) {
  30. TreeNode node = queue.poll();
  31. if (i > 0) {
  32. last = cur;
  33. cur = node.val;
  34. if (depth % 2 == 0) { // 偶数层
  35. if (cur % 2 == 0) {
  36. return false;
  37. }
  38. if (cur <= last) {
  39. return false;
  40. }
  41. } else { // 奇数层
  42. if (cur % 2 == 1) {
  43. return false;
  44. }
  45. if (cur >= last) {
  46. return false;
  47. }
  48. }
  49. } else {
  50. cur = node.val;
  51. if (depth % 2 == 0) { // 偶数层
  52. if (cur % 2 == 0) {
  53. return false;
  54. }
  55. } else { // 奇数层
  56. if (cur % 2 == 1) {
  57. return false;
  58. }
  59. }
  60. }
  61. if (node.left != null) {
  62. queue.offer(node.left);
  63. }
  64. if (node.right != null) {
  65. queue.offer(node.right);
  66. }
  67. }
  68. }
  69. return true;
  70. }
  71. }

第三题:可见点的最大数目

题解一:滑动窗口法

计算每个点相对于观察者的角度,如果与观察者位置相等则一定可见,不再纳入后续的统计范围。对角度数组进行排序,每个角度加上360度并加入角度数组(因为观察角度一定小于360度),形成环。然后维护一个滑动窗口,首部和尾部的差距不大于观察角度,找出包含点数最多的窗口。(注意判断 double 类型变量相等的问题)

  1. import java.util.ArrayList;
  2. import java.util.Comparator;
  3. import java.util.List;
  4. class Solution {
  5. public int visiblePoints(List<List<Integer>> points, int angle, List<Integer> location) {
  6. final int n = points.size();
  7. int base = 0;
  8. // 每个点相对于我的角度
  9. List<Double> angles = new ArrayList<>(n);
  10. for (List<Integer> p : points) {
  11. double tmp = getAngle(location, p);
  12. if (Double.isNaN(tmp)) {
  13. ++base;
  14. } else {
  15. angles.add(tmp);
  16. }
  17. }
  18. Comparator<Double> doubleComparator = new Comparator<Double>() {
  19. @Override
  20. public int compare(Double o1, Double o2) {
  21. return o1.compareTo(o2);
  22. }
  23. };
  24. angles.sort(doubleComparator);
  25. for (int i = 0, size = angles.size(); i < size; ++i) {
  26. angles.add(angles.get(i) + 360);
  27. }
  28. //System.out.println(angles);
  29. int begin = 0;
  30. double beginAngle = angles.get(begin);
  31. double endAngle = beginAngle + angle;
  32. int end = 0;
  33. while ((angles.get(end) < endAngle)||equal(angles.get(end), endAngle)) {
  34. ++end;
  35. }
  36. --end;
  37. int max = end - begin + 1;
  38. while (begin < angles.size() / 2) {
  39. while (equal(angles.get(begin + 1), angles.get(begin))) {
  40. ++begin;
  41. }
  42. ++begin;
  43. if ((begin >= angles.size() / 2)) {
  44. break;
  45. }
  46. beginAngle = angles.get(begin);
  47. endAngle = beginAngle + angle;
  48. // System.out.println(beginAngle + " " + endAngle);
  49. while ((angles.get(end) < endAngle)||equal(angles.get(end), endAngle)) {
  50. ++end;
  51. }
  52. --end;
  53. max = Math.max(end - begin + 1, max);
  54. }
  55. return max + base;
  56. }
  57. private boolean equal(double o1, double o2) {
  58. return Math.abs(o1 - o2) <= 1e-5;
  59. }
  60. private double getAngle(List<Integer> origin, List<Integer> p) {
  61. int deltaX = p.get(0) - origin.get(0);
  62. int deltaY = p.get(1) - origin.get(1);
  63. double r = Math.sqrt(Math.pow(deltaX, 2.0) + Math.pow(deltaY, 2.0));
  64. double angle = Math.acos(deltaX / r) / Math.PI * 180;
  65. if (deltaY < 0) {
  66. angle = 360 - angle;
  67. }
  68. return angle;
  69. }
  70. }

第四题:使整数变为 0 的最少操作次数

题解一:

思路。