可能的二分法:DFS染色法
1604 · 两数最大和
给定一个由N个整数组成的数组A,返回两个数字的最大总和,规定这两个数的所有位加起来相等。 如果没有两个数字的各个位相加和相等,则该函数应返回-1。
- N的范围是
[1, 200000]
- A中的每一个参数的范围是
[1, 1000000000]
样例
示例1:
输入:
A = [51, 71, 17, 42]
输出: 93
解释:这里有两对各个位相加和相等的数:(51, 42) 和 (17,71),第一对的和是93
示例2:
输入:
A = [42, 33, 60]
输出: 102
解释:所有的数各个位相加的和都相等,选择42 + 60 = 102
示例3:
输入:
A = [51, 32, 43]
输出: -1
解释: 所有数的各个位相加和都不一样,因此返回-1
遍历,相同的个位数和放在一起。
public class Solution {
/**
* @param a: An Integer array
* @return: returns the maximum sum of two numbers
*/
public int maximumSum(int[] a) {
// write your code here
Map<Integer,List<Integer>> map = new HashMap<>();
for(int n:a) {
int bitSum = getBitSum(n);
if(!map.containsKey(bitSum)) {
map.put(bitSum,new ArrayList<>());
}
map.get(bitSum).add(n);
}
int result = -1;
for(int key:map.keySet()) {
List<Integer> list = map.get(key);
if(list.size()==1) continue;
Collections.sort(list,(x,y)->y-x);
result = Math.max(result,list.get(0)+list.get(1));
}
return result;
}
private int getBitSum(int num) {
int result = 0;
while(num!=0) {
result += num%10;
num/=10;
}
return result;
}
}
1704 · 二叉搜索树的范围和
给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和。
二叉搜索树保证具有唯一的值。
树中的结点数量最多为 10000 个。最终的答案保证小于 2^31。
样例 1:
输入:root = [10,5,15,3,7,null,18], L = 7, R = 15
输出:32
中序遍历
这个还是比较容易想到的。
/**
* Definition of TreeNode:
* public class TreeNode {
* public int val;
* public TreeNode left, right;
* public TreeNode(int val) {
* this.val = val;
* this.left = this.right = null;
* }
* }
*/
public class Solution {
/**
* @param root: the root node
* @param l: an integer
* @param r: an integer
* @return: the sum
*/
public int rangeSumBST(TreeNode root, int l, int r) {
// 10
// 5 15
// 3 7 null 18
// 中序遍历
if(root==null) return 0;
Deque<TreeNode> deque = new ArrayDeque<>();
List<Integer> list = new ArrayList<>();
deque.addLast(root);
TreeNode cur = root.left;
while(!deque.isEmpty()||cur!=null) {
if(cur!=null) {
deque.addLast(cur);
cur = cur.left;
} else {
cur = deque.pollLast();
list.add(cur.val);
cur = cur.right;
}
}
System.out.println(list);
int sum = 0;
boolean findL = false;
for(int i=0;i<list.size();i++) {
if(list.get(i)==l) {
findL = true;
}
if(findL) sum+=list.get(i);
if(list.get(i)==r) return sum;
}
return sum;
}
}
递归查找(不查多余的)
public class Solution {
/**
* @param root: the root node
* @param l: an integer
* @param r: an integer
* @return: the sum
*/
public int rangeSumBST(TreeNode root, int l, int r) {
if(root==null) return 0;
if(root.val<l) {
return rangeSumBST(root.right, l, r);
}
if(root.val>r) {
return rangeSumBST(root.left, l, r);
}
return root.val+rangeSumBST(root.left, l, r)+rangeSumBST(root.right, l, r);
}
}
1596 · 可能的二分法
DFS 染色法
给定一组 N 人(编号为 1, 2, ..., N), 我们想把每个人分进任意大小的两组。
每个人都可能不喜欢其他人,那么他们不应该属于同一组。
形式上,如果 dislikes[i] = [a, b],表示不允许将编号为 a 和 b 的人归入同一组。
当可以用这种方法将每个人分进两组时,返回 true;否则返回 false。
1 <= N <= 2000
0 <= dislikes.length <= 10000
1 <= dislikes[i][j] <= N
dislikes[i][0] < dislikes[i][1]
对于 dislikes[i] == dislikes[j] 不存在 i != j
样例
例 1:
输入:N = 4, dislikes = [[1,2],[1,3],[2,4]]
输出:true
解释:group1 [1,4], group2 [2,3]
例 2:
输入:N = 3, dislikes = [[1,2],[1,3],[2,3]]
输出:false
例 3:
输入:N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
输出:false
public class Solution {
/**
* @param n: sum of the set
* @param dislikes: dislikes peoples
* @return: if it is possible to split everyone into two groups in this way
*/
public boolean possibleBipartition(int n, int[][] dislikes) {
List<List<Integer>> edges = new ArrayList<>();
for(int i=0;i<=n;i++) {
edges.add(new ArrayList<>());
}
for(int i=0;i<dislikes.length;i++) {
edges.get(dislikes[i][0]).add(dislikes[i][1]);
edges.get(dislikes[i][1]).add(dislikes[i][0]);
}
int[] colors = new int[n+1];
for(int i=1;i<=n;i++) {
if(colors[i]==0) {
if(!paint(-1,edges,colors,i)) return false;
}
}
return true;
}
private boolean paint(int icolor,List<List<Integer>> edges,int[] colors,int i) {
if(colors[i]!=0) return colors[i]==icolor;
colors[i] = icolor;
for(int k=0;k<edges.get(i).size();k++) {
if(!paint(-icolor,edges,colors,edges.get(i).get(k))) return false;
}
return true;
}
}