5238. 找出给定方程的正整数解
这个题主要考阅读理解,除去阅读之外,很容易就可解决。有两种解法:
-
暴力
O(n^2)
public List<List<Integer>> findSolution(CustomFunction customfunction, int z) { List<List<Integer>> listListInt = new ArrayList<>(); for (int x = 1; x <= 1000; x ++) { for (int y = 1; y <= 1000; y ++) { if (z == customfunction.f(x,y)) { List<Integer> listInt = new ArrayList<>(); listInt.add(x); listInt.add(y); listListInt.add(listInt); } } } return listListInt; }
-
第二种方法,根据题目中说到的单调性,我们可以尝试构造出
O(n)
时间复杂度的解决方案这里参考了这位同学的解法
- 通时,LeetCode第74题也是这种解法或者用二分法
public List<List<Integer>> findSolution(CustomFunction customfunction, int z) { List<List<Integer>> listListInt = new ArrayList<>(); int x = 1, y = 1000; while (x <= 1000 && y >= 1) { if (z > customfunction.f(x,y)) x ++; else if (z < customfunction.f(x,y)) y --; else { List<Integer> listInt = new ArrayList<>(); listInt.add(x); listInt.add(y); listListInt.add(listInt); y --; // 此处换为x ++也可 } } return listListInt; }
5239. 循环码排列
这个题是格雷码的变种题,如果不了解格雷码,可以参考这个题:格雷码
格雷码构成一般方法(非公式):
// 法一:用参考题的方法也可解决,不过要修改add的位数
// 法二:异或:值相同为0,不同为1
public List<Integer> circularPermutation(int n, int start) {
List<Integer> grayCode = new ArrayList<>();
grayCode.add(start);
int offset = 0;
for (int i = 0; i < n; i ++) {
for (int j = grayCode.size() - 1; j >= 0; j --) {
grayCode.add(grayCode.get(j) ^ (1 << offset));
}
offset ++;
}
return grayCode;
}
5240. 串联字符串的最大长度
对于这个题来说,可以用DFS来解决。DFS即Depth first search
,深度优先遍历,这是在树中所必学的一个算法。
对于本题来说,我们也可以把这个List当做一个树,因为每一个元素都有两种遍历方式,即比较或者不比较,用题目中的例子来说:["cha", "r", "act", "ers"]
,它所派生出的二叉树如下:
按照上面的例子,一共有16中情况,DFS流程为:
- 从第一个字符串开始遍历
- 两种情况,第一种是加入第一个字符串
- 第二种是不要第一个字符串
- 遇到第二个字符串,比较第一个字符串和第二个字符串是否有相同的字符
- 如果相同,跳过第二个字符,如果不同,把第二个字符加入
- 如果字符串到达List的最后一个,结束。否则,跳转到第一步
int maxLen = 0;
public int maxLength(List<String> arr) {
dfs(arr, 0, 0, 0);
return maxLen;
}
private void dfs(List<String> arr, int index, int ck, int tempMax) {
if (index == arr.size()) {
maxLen = Math.max(maxLen, tempMax);
return;
}
String str = arr.get(index);
int tempCk = getCk(ck, str);
if (tempCk != -1) dfs(arr, index + 1, tempCk, tempMax + str.length());
dfs(arr, index + 1, ck, tempMax);
}
// 比较str和之前ck代表的字符串是否有相同字符,如果没有,则把str代表的ck加去,如果有,则返回-1
private int getCk(int ck, String str) {
char[] chars = str.toCharArray();
for(char c: chars) {
int tempInt = c - 'a';
if ((ck & (1 << tempInt)) != 0) {
return -1;
}
ck = ck | (1 << tempInt);
}
return ck;
}
说句题外话,查看两个字符串(只含有小写字符)是否有相同字符的方法:
-
使用一个一维数组,遍历两边字符串。空间复杂度O(1),时间复杂度O(n)
private boolean notEqual(String a, String b) { int[] charArray = new int[30]; for (int i = 0; i < a.length(); i ++) { charArray[a.charAt(i) - 'a'] = 1; } for (int i = 0; i < b.length(); i ++) { if (charArray[b.charAt(i) - 'a'] == 1) { return false; } } return true; }
-
使用位运算:``ck & (1 << i) == 0`
其中,ck是一个最少26byte的字符,从左至右,每一位分别代表a,b,x,y,x
i代表字符串中的字符
// 比较str和之前ck代表的字符串是否有相同字符,如果没有,则把str代表的ck加去,如果有,则返回-1 private int notEqual(int ck, String str)) { char[] chars = str.toCharArray(); for(char c: chars) { if (ck & 1 << (a - 'a')) != 0) { return -1; } ck = ck | 1 << (a - 'a'); } return ck; }
4.
这个题水平不够,,,没有题解。。。。