LC 406. 根据身高重建队列

  1. class Solution {
  2. int[][] people;
  3. boolean[] flag;
  4. List<int[]> path = new ArrayList();
  5. List<int[]> result;
  6. public int[][] reconstructQueue(int[][] people) {
  7. this.people = people;
  8. this.flag = new boolean[people.length];
  9. backtrack(0, 0);
  10. return result.toArray(new int[people.length][]);
  11. }
  12. // 当前是第 stage 阶段
  13. // 当前阶段的决策为让下标为 index 的人站到队列 stage 下标的位置
  14. public void backtrack(int stage, int index) {
  15. if (path.size() == people.length) {
  16. result = new ArrayList(path);
  17. return;
  18. }
  19. for (int i = 0; i < people.length && result == null; i++) {
  20. if (flag[i] == false && judge(i)) {
  21. int[] ints = {people[i][0], people[i][1]};
  22. path.add(ints);
  23. flag[i] = true;
  24. backtrack(stage + 1, i);
  25. flag[i] = false;
  26. path.remove(stage);
  27. }
  28. }
  29. }
  30. // 判断 下标为 index 的人 站在此时的队列后面是否满足要求
  31. public boolean judge(int i) {
  32. int size = 0;
  33. for (int j = 0; j < path.size(); j++) {
  34. int[] ints = path.get(j);
  35. if (ints[0] >= people[i][0]) {
  36. size++;
  37. }
  38. }
  39. if (size == people[i][1]) {
  40. return true;
  41. } else {
  42. return false;
  43. }
  44. }
  45. }

LC 435. 无重叠区间

  1. import java.util.Arrays;
  2. import java.util.Comparator;
  3. class Solution {
  4. int[][] intervals;
  5. int result = Integer.MAX_VALUE;
  6. // 备忘录
  7. int[][] memo;
  8. public int eraseOverlapIntervals(int[][] intervals) {
  9. Arrays.sort(intervals, new Comparator<int[]>() {
  10. @Override
  11. public int compare(int[] o1, int[] o2) {
  12. return Integer.compare(o1[0], o2[0]);
  13. }
  14. });
  15. this.intervals = intervals;
  16. memo = new int[intervals.length + 1][100000];
  17. for (int[] ints : memo) {
  18. Arrays.fill(ints, -1);
  19. }
  20. // maxValue 初始化赋为 -5 * 10000 的原因:start 的取值范围为 -5 * 104 <= start
  21. backtracking(0, 0, -5 * 10000);
  22. return result;
  23. }
  24. // index 为:当前阶段为决策下标为 index 的区间
  25. // num 为:截止到目前需要移除的区间数量
  26. // maxValue 为:最大右边界
  27. public void backtracking(int index, int num, int maxValue) {
  28. // 由于 maxValue 有可能为负数, 因此需要偏移
  29. if (memo[index][maxValue + 5 * 10000] != -1 && num >= memo[index][maxValue + 5 * 10000]) {
  30. return;
  31. }
  32. if (index >= intervals.length) {
  33. result = Math.min(result, num);
  34. return;
  35. }
  36. memo[index][maxValue + 5 * 10000] = num;
  37. // 决策一:移除下标为 index 的区间
  38. backtracking(index + 1, num + 1, maxValue);
  39. // 决策二:不移除(需要满足不重叠的条件)
  40. if (intervals[index][0] >= maxValue) {
  41. backtracking(index + 1, num, Math.max(maxValue, intervals[index][1]));
  42. }
  43. }
  44. }

LC 455. 分发饼干

  1. class Solution {
  2. public int findContentChildren(int[] g, int[] s) {
  3. // g 是孩子的胃口
  4. Arrays.sort(g);
  5. // s 是饼干的尺寸
  6. Arrays.sort(s);
  7. int result = 0;
  8. // index 是饼干数组的下标
  9. int index = s.length - 1;
  10. for (int i = g.length - 1; i >= 0; i--) {
  11. if (index >= 0 && s[index] >= g[i]) {
  12. result++;
  13. index--;
  14. }
  15. }
  16. return result;
  17. }
  18. }

LC 491. 递增子序列

本题求自增子序列,是不能对原数组进行排序的。所以不能使用之前的使用 used[] 去重逻辑

  1. class Solution {
  2. {
  3. /*
  4. 输入[1,1,1]
  5. 输出[[1,1],[1,1,1],[1,1],[1,1]]
  6. 预期结果[[1,1],[1,1,1]]
  7. */
  8. }
  9. List<List<Integer>> result = new ArrayList<>();
  10. List<Integer> path = new ArrayList<>();
  11. boolean[] used;
  12. int[] nums;
  13. public List<List<Integer>> findSubsequences(int[] nums) {
  14. this.nums = nums;
  15. this.used = new boolean[nums.length];
  16. backtracking(0, -1);
  17. return result;
  18. }
  19. // 集合的区间范围 [startIndex, nums.length - 1]
  20. public void backtracking(int startIndex, int frontFloorIndex) {
  21. if (startIndex > 0) {
  22. if (path.size() > 1) {
  23. result.add(new ArrayList<>(path));
  24. }
  25. }
  26. if (startIndex >= nums.length) {
  27. return;
  28. }
  29. for (int i = startIndex; i < nums.length; i++) {
  30. if (frontFloorIndex >= 0) {
  31. boolean judge = judge(frontFloorIndex, i - 1, nums[i]);
  32. if (judge) {
  33. continue;
  34. }
  35. }
  36. if (path.size() > 0 && nums[i] < path.get(path.size() - 1)) {
  37. continue;
  38. }
  39. used[i] = true;
  40. path.add(nums[i]);
  41. backtracking(i + 1, i);
  42. path.remove(path.size() - 1);
  43. used[i] = false;
  44. }
  45. }
  46. // 如果树层重复,返回 true; 否则返回 false
  47. public boolean judge(int l, int r, int value) {
  48. int index = judgeExist(l, r, value);
  49. if (index != -1) {
  50. return !used[index];
  51. }
  52. return false;
  53. }
  54. // 判断数组的 [l, r] 区间范围内, 是否有值为 value 的元素
  55. // 如果有, 返回元素的下标; 如果没有, 返回 - 1;
  56. public int judgeExist(int l, int r, int value) {
  57. for (int i = l; i <= r; i++) {
  58. if (value == nums[i]) {
  59. return i;
  60. }
  61. }
  62. return -1;
  63. }
  64. }