力扣刷题2-回溯、阶乘、区间调度、区间合并

55 阅读2分钟
1 回溯算法

伪代码

void backtrack(nums, i) {
  if (i == nums.len) {
    if (达到target) {
      res +=1
      return
    }
  }

  for op in {+1, -1} {
    选择 op* nums[i]
    // 穷举nums[i+1]
    backtrack(nums, i+1)
    撤销选择
  }
}
22 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

题解:回溯算法

private void backTrack(char[] cur, int pos, List<String> res) {
    if (pos >= cur.length) {
        if (isValidParenthesis(cur)) {
            res.add(String.valueOf(cur));
        }
        return;
    }
    cur[pos] = '(';
    backTrack(cur, pos+1, res);
    cur[pos] = ')';
    backTrack(cur, pos+1, res);
}

// 判断括号是否有序
private boolean isValidParenthesis(char[] cur) {
    int balance = 0;
    int n = cur.length;
    for (int i = 0; i < n; i++) {
        if (balance < 0) {
            return false;
        }
        if (cur[i] == '(') {
            balance++;
        } else {
            balance--;
        }
    }
    return (balance == 0);
}

注意字符数组char[] 转string:String.valueOf(cur)

93.复原IP地址

题目描述:有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。输入字符串s,输出所有可能有效IP地址。

题解:

// 
static constexpr int SEG_COUNT = 4;
vector<int> segments;
vector<string> ans;

// segId IP编号,取值[0,1,2,3],segStart  搜索开始索引
void dfs(string s, int segId, int segStart) {
  // 结束条件:IP段搜完
  if (segId == SEG_COUNT) {
    if (segStart == s.size()) {
      string ipAddr;
      for (int i = 0; i < SEG_COUNT; i++) {
        ipAddr += to_string(segments[i]);
        if (i != SEG_COUNT - 1) {
          ipAddr += ".";
        }
      }
      ans.push_back(ipAddr);
    }
    return;
  }
  // 结束条件:IP段未搜完,已遍历完s
  if (segStart == s.size()) {
    return;
  }
  // 特殊情况,不能含有前导0,遇到0元素,只能识别为0
  if (s[segStart] == '0') {
    segments[segId] = 0;
    dfs(s, segId + 1, segStart + 1);
    return;
  }
  // 一般情况
  int addr = 0;
  for (int i = segStart; i < s.size(); i++) {
    addr = 10 * addr + (s[i] - '0');
    if (addr > 0 && addr <= 0xFF) {
      segments[segId] = (addr);
      dfs(s, segId + 1, i+1);
    } else {
      break;
    }
  }
}
2 阶乘
172 阶乘后的零

思路:尾部零数量等于因子10的个数 -》因子5个数
25!因子5个数=25/5 + 25/25 = 6
125! 因子5个数=125/5 + 125/25 + 125/125 = 25 + 5+1 = 31

3 区间调度

最大不重叠区间子集

435 无重叠区间

思路:移除区间最小数 =》最多不相交区间数

452 用最少的箭头射爆气球

思路:等价于最多不相交区间数 注意点:边界重叠算 相交

Arrays.sort(points, (v1, v2) -> { // 大数比较,防止越界
    if (v1[1] < v2[1]) {
        return -1;
    } else if (v1[1] > v2[1]) {
        return 1;
    } else {
        return 0;
    }
});
4 区间合并

TODO

5 二叉树

完全二叉树定义:每层都是紧凑靠左 满二叉树:每层都是满的

完全二叉树节点个数

普通二叉树O(N)

int countNodes(Node root) {
  if (root == null) {
    return 0;
  }
  return 1 + countNodes(root.left) + countNodes(root.right);
}

满二叉树 O(logN)

int h = 0;
while(root != null) {
  root = root.left;
  h++;
}
return (Math.pow(2, h) -1);
6 高效寻找缺失、重复字符

解法1:hashmap 记录次数,空间 O(N)
解法2:dup、miss