便利店搞促销,numExchange个空酒瓶可以兑换1瓶新酒,你买了numBottles瓶新酒,求你最多能喝多少酒?
输入:numBottles = 9,numExchange = 3
输出:9+3+1 = 13
解释:9瓶喝完可以兑换三瓶新酒,这三瓶喝完可以再兑换一瓶,因此为13瓶
输入:numBottles = 15,numExchange = 4
输出:15+3+1 = 19
解释:15瓶喝完可以兑换3瓶新酒,这3瓶喝完加上之前剩下的3个空瓶还可以再兑换一瓶,因此为19瓶
首先根据上述两个示例的解释你大致可以想到本题需要一个while循环解决问题,当然这无关紧要。结果集为numBottles+可以兑换的酒的数目。可以兑换的酒的数目也就是空瓶的计算,空瓶包含的是前面喝完的空瓶里面没兑换完的和再次兑换来的酒喝完剩下的空瓶之和,因此需要注意这两点即可
class Solution{
public int numWaterBottles(int numBottles,int numExchange) {
int res = numBottles;
int tmp = numBottles;
while ( tmp >= numExchange) {
tmp -= numExchange;
res++;
tmp++;
}
return res;
}
}
给定一棵树,连通的无环无向图。这棵树的编号从0 - (n-1)的n个节点组成,恰好有n-1条edges,树的根节点为节点0,树上的每一个节点都有一个标签,也就是字符串labels中的一个小写字符(编号为i的节点的标签就是labels[i])。
边数组由edges给出以edges[i] = [a,b]的形式给出,该格式表示节点a和b之间存在一条边。
返回一个大小为n的数组,其中ans[i] 表示第i个节点的子树中与节点i标签相同的节点数。
本题的思路其实是很明确的,首先题目给出了edges二维数组,也就是说你可以利用其构图存图,将此图存入map或者TreeSet中,然后就直接dfs即可完成对子树中相同标签节点数的求值,注意书写细节。此处在阅读大神的代码时找到一种更加先进的构图方法,或者说,用TreeSet构图更加的方便也更加容易理解。
class Solution {
public int[] countSubTrees(int n,int[][] edges,String labels) {
// 存图,此为list存图法,下列一种TreeSet存图法更加容易理解。
/*
*/
Map<Integer,List<Integer>> edgesMap = new HashMap<Integer,List<Integer>>();
for (int[] edge : edges) {
int node0 = edge[0],node1 = edge[1];
List<Integer> list0 = edgesMap.getOrDefault(node0,new ArrayList<Integer>());
List<Integer> list1 = edgesMap.getOrDefault(node1,new ArrayList<Integer>());
list0.add(node1);
list1.add(node0);
edgesMap.put(node0,list0);
edgesMap.put(node1,list1);
}
// dfs
int[] counts = new int[n];
boolean[] visited = new boolean[n];
dfs(0,counts,visited,edgesMap,labels);
return counts;
}
public int[] dfs(int node,int[] counts,boolean[] visited,Map<Integer,List<Integer>> edgesMap,String labels) {
visited[node] = true;
int[] curCounts = new int[26];
curCounts[labels.charAt(node) - 'a']++;
List<Integer> nodesList = edgesMap.get(node);
for (int nextNode:nodesList) {
if (!visited[nextNode]) {
int[] childCounts = dfs(nextNode,counts,visited,edgesMap,labels);
for (int i = 0; i < 26; i++) {
curCounts[i] += childCounts[i];
}
}
}
counts[node] = curCounts[labels.charAt(node) - 'a'];
return curCounts;
}
}
给定只包含小写字母的字符串s,你需要找到s中最多数目的非空子字符串:
返回字符串总长度最小的组合,可以按任意顺序返回。
输入:s = “adefaddaccc”
输出:[“e”,“f”,“ccc”]
输入:s = “abbaccd”
输出:[“d”,“bb”,“cc”]
对于本题而言,你大致可以想到需要一个贪心的解法,
思路为:
首先枚举所有满足第2个条件且有可能加入结果集的子串,最多26个,然后按照子串的长度暴力加贪心,选择不重叠的子串加入到结果集。
代码如下:
class Solution {
public List<String> maxNumOfSubstrings (String s) {
List<int[]> res = getCandidateIntervals(s);
// 重写sort函数,获取最终结果
Collections.sort(res,(o1,o2) -> (o1[1] - o1[0] - o2[1] + o2[0]));
for (int i = 0; i < res.size(); i++) {
for (int j = i - 1; j >= 0; j--) {
if (!(res.get(i)[0] > res.get(j)[1] || res.get(i)[1] < res.get(j)[0])) {
res.remove(i--);
break;
}
}
}
return res.stream().map(o -> (s.substring(o[0],o[1] + 1))).collect(Collectors.toList());
}
// 获取满足第二个条件的所有子字符串
private List<int[]> getCandidateIntervals (String s) {
char[] chs = s.toCharArray();
int[] end = new int[26];
for (int i = 0; i < s.length(); i++) {
end[chs[i] - 'a'] = i;
}
List<int[]> res = new ArrayList<>();
boolean[] vis = new boolean[26];
/*
输入:s = "adefaddaccc"
输出:["e","f","ccc"]
输入:s = "abbaccd"
输出:["d","bb","cc"]
*/
for (int i = 0; i < s.length(); i++) {
if (!vis[chs[i] - 'a']) {
int last = end[chs[i] - 'a'];
for (int j = i + 1; j <= last; j++) {
if (vis[chs[j] - 'a']) {
last = -1;
break;
}
last = Math.max(last,end[chs[j] - 'a']);
}
vis[chs[i] - 'a'] = true;
if (last != -1) {
res.add(new int[] {i,last});
}
}
}
return res;
}
}
Winston构造了一个如下所示的函数
func(arr,l,r) {
if (r < l) {
return -1000000000
}
ans = arr[l]
for (i = l + 1; i <= r; i++) {
ans = ans & arr[i]
}
return ans
}
他有一个整数数组arr和一个整数target,他想找到能够让 | func(arr,l,r) - target|最小的值。请你返回这个值。
输入:arr = [9,12,3,7,15] target = 5
输出 : 2
解释: Winston的func函数得到的所有可能的l和r的组合为
{
[0,0],[1,1],[2,2],[3,3],[4,4],
[0,1],[1,2],[2,3],[3,4],
[0,2],[1,3],
[2,4],[0,3],
[1,4],[0,4]
}
Winston的func结果为[9,12,3,7,15,8,0,3,7,0,0,3,0,0,0]
最接近5的为7和3,因此返回最小差值为2
不会做,纯照抄的zerotrac大佬的C++代码复制成了我的java代码
抄完理解完之后的马后炮解题思路如下:
题目意思都懂,但是就是菜,func给的意思是计算arr[l]到arr[r]的按位与之和。然后让你算出这些按位与之和里面和target最接近的那个数与target的差值的绝对值。
按位与的两个性质为:
由此思路就清楚了,
class Solution{
public int closestToTarget(int[] arr,int target) {
// 结果set
HashSet<Integer> set= new HashSet<>();
int min = Integer.MAX_VALUE;
// 遍历arr,
for (int i : arr) {
HashSet<Integer> cur2 = new HashSet<>();
set1.add(i);
min = Math.min(min,Math.abs(target - i));
for (int j : set) {
int val = j & i;
set1.add(val);
min = Math.min(min,Math.abs(target - val));
}
set= set1;
}
return min;
}
}