LeetCode: 第 160 场周赛题解
5238. 找出给定方程的正整数解
题目
给出一个函数 f(x, y) 和一个目标结果 z,请你计算方程 f(x,y) == z 所有可能的正整数 数对 x 和 y。
给定函数是严格单调的,也就是说:
f(x, y) < f(x + 1, y)
f(x, y) < f(x, y + 1)
函数接口定义如下:
interface CustomFunction {
public:
// Returns positive integer f(x, y) for any given positive integer x and y.
int f(int x, int y);
};如果你想自定义测试,你可以输入整数 function_id 和一个目标结果 z 作为输入,其中 function_id 表示一个隐藏函数列表中的一个函数编号,题目只会告诉你列表中的 2 个函数。
你可以将满足条件的 结果数对 按任意顺序返回。
实例
示例 1:
输入:function_id = 1, z = 5
输出:[[1,4],[2,3],[3,2],[4,1]]
解释:function_id = 1 表示 f(x, y) = x + y
示例 2:
输入:function_id = 2, z = 5
输出:[[1,5],[5,1]]
解释:function_id = 2 表示 f(x, y) = x * y
题解
简单题:暴力求解,遍历所有情况即可
/*
* // This is the custom function interface.
* // You should not implement it, or speculate about its implementation
* class CustomFunction {
* // Returns f(x, y) for any given positive integers x and y.
* // Note that f(x, y) is increasing with respect to both x and y.
* // i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
* public int f(int x, int y);
* };
*/
class Solution {
public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
List<List<Integer>> res = new ArrayList<>();
for(int i = 1 ; i <= 1000 ; i ++){
for(int j = 1 ; j <= 1000; j++){
int d = customfunction.f(i,j);
if(d > z) break;
else if(d == z) {
List<Integer> l = new ArrayList<>();
l.add(i);
l.add(j);
res.add(l);
}
}
}
return res;
}
}
5239. 循环码排列
题目
给你两个整数 n 和 start。你的任务是返回任意 (0,1,2,…,2^n-1) 的排列 p,并且满足:
p[0] = start
p[i]
和p[i+1]
的二进制表示形式只有一位不同p[0]
和p[2^n -1]
的二进制表示形式也只有一位不同
提示:
1 <= n <= 16
0 <= start < 2^n
实例
示例 1:
输入:n = 2, start = 3
输出:[3,2,0,1]
解释:这个排列的二进制表示是 (11,10,00,01)
所有的相邻元素都有一位是不同的,另一个有效的排列是 [3,1,0,2]
示例 2:
输出:n = 3, start = 2
输出:[2,6,7,5,4,0,1,3]
解释:这个排列的二进制表示是 (010,110,111,101,100,000,001,011)
题解
中等难度题。
在比赛的时候用了搜索,超时了╮(╯▽╰)╭。
其实这是一道规律题,大家可以去搜一下格雷码生成规律(•‾̑⌣‾̑•)✧˖°,下面只讲一下我用到的规律:n 位的格雷码可以由n - 1位的格雷码生成
例如 :
2 位的格雷码:
00 01 11 10
3 位的格雷码:
000 001 011 010 110 111 101 100
有下面的规律:
3 位的格雷码前四个数就是 2位格雷码
后四个数110 111 101 100 就是 逆序的 2位格雷码(10 11 01 00) 前加1。
这就可以生成n位格雷码。
题目要求从start
作为第一个数,这很好办,因为格雷码是个环,遍历n位格雷码,找到start
,位置前移就可以了。
class Solution {
static boolean flag = false;
public List<Integer> circularPermutation(int n, int start) {
flag = false;
int m = 1 << n;
int i,j;
List<Integer> l = new ArrayList<>(m);
List<Integer> ans = new ArrayList<>(m);
ans.add(0);
ans.add(1);
for(i = 2 ; i <= n ; i ++){
int size = ans.size();
for(j = size - 1 ; j >= 0; j --)
ans.add(ans.get(j) + (1 << ( i - 1)));
}
for( i = 0 ; i < ans.size(); i ++)
if(ans.get(i) == start) break;
for(j = i ; j <ans.size(); j ++) l.add(ans.get(j));
for(j = 0 ; j < i; j ++) l.add(ans.get(j));
return l;
}
}
5240. 串联字符串的最大长度
题目
给定一个字符串数组 arr
,字符串 s
是将 arr
某一子序列字符串连接所得的字符串,如果 s
中的每一个字符都只出现过一次,那么它就是一个可行解。
请返回所有可行解s
中最长长度。
示例
示例 1:
输入:arr = [“un”,“iq”,“ue”]
输出:4
解释:所有可能的串联组合是 “”,“un”,“iq”,“ue”,“uniq” 和 “ique”,最大长度为 4。
示例 2:
输入:arr = [“cha”,“r”,“act”,“ers”]
输出:6
解释:可能的解答有 “chaers” 和 “acters”。
示例 3:
输入:arr = [“abcdefghijklmnopqrstuvwxyz”]
输出:26
提示:
1 <= arr.length <= 16
1 <= arr[i].length <= 26
arr[i]
中只含有小写英文字母
题解
中等题:DFS列出所有情况,找出符合要求的最大长度就可以。
应该还有更时间复杂度更低的算法。
class Solution {
public int maxLength(List<String> arr) {
List<String> ans = new ArrayList<>();
dfs(arr,0, arr.size(),"", ans);
Collections.sort(ans, (a,b) ->{
return - a.length()+b.length();
});
int d = 0 , i = 0 , len = 0;
for(String s: ans){
int []a = new int[30];
len = s.length();
for(i = 0 ; i < len ; i ++)
if(a[s.charAt(i) - 'a'] == 1) break;
else a[s.charAt(i) - 'a'] = 1;
if(i == len) {
d = len;
break;
}
}
return d;
}
public void dfs(List arr ,int i,int n , String s, List ans){
if(i == n){
ans.add(s);
return ;
}
dfs(arr,i + 1,n,s, ans);
dfs(arr,i + 1,n,s + arr.get(i) , ans);
}
}
5241. 铺瓷砖
题目
你是一位施工队的工长,根据设计师的要求准备为一套设计风格独特的房子进行室内装修。
房子的客厅大小为 n x m,为保持极简的风格,需要使用尽可能少的 正方形 瓷砖来铺盖地面。
假设正方形瓷砖的规格不限,边长都是整数。
请你帮设计师计算一下,最少需要用到多少块方形瓷砖?
实例
输入:n = 2, m = 3
输出:3
解释:3 块地砖就可以铺满卧室。
2 块 1x1 地砖
1 块 2x2 地砖
题解
高难度题,没做出来。
看了高手的答案,竟然是用打表,学到了 (…•˘_˘•…)。
还有用广搜的方法。
class Solution {
public int tilingRectangle(int n, int m) {
int[] a1 = {1};
int[] a2 = {2,1};
int[] a3 = {3,3,1};
int[] a4 = {4,2,4,1};
int[] a5 = {5,4,4,5,1};
int[] a6 = {6,3,2,3,5,1};
int[] a7 = {7,5,5,5,5,5,1};
int[] a8 = {8,4,5,2,5,4,7,1};
int[] a9 = {9,6,3,6,6,3,6,7,1};
int[] a10 = {10,5,6,4,2,4,6,5,6,1};
int[] a11 = {11,7,6,6,6,6,6,6,7,6,1};
int[] a12 = {12,6,4,3,6,2,6,3,4,5,7,1};
int[] a13 = {13,8,7,7,6,6,6,6,7,7,6,7,1};
int[][] a = {a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13};
int mx = Math.max(n, m) - 1;
int mi = Math.min(n, m) - 1;
return a[mx][mi];
}
}