1389. 按照既定顺序创建目标数组
给你两个整数数组 nums 和 index。你需要按照以下规则创建目标数组:
目标数组 target 最初为空。
按从左到右的顺序依次读取 nums[i] 和 index[i],在 target 数组中的下标 index[i] 处插入值 nums[i] 。
重复上一步,直到在 nums 和 index 中都没有要读取的元素。
请你返回目标数组。
题目保证数字插入位置总是存在。
示例 1:
输入:nums = [0,1,2,3,4], index = [0,1,2,2,1]
输出:[0,4,1,3,2]
解释:
nums index target
0 0 [0]
1 1 [0,1]
2 2 [0,1,2]
3 2 [0,1,3,2]
4 1 [0,4,1,3,2]
示例 2:
输入:nums = [1,2,3,4,0], index = [0,1,2,3,0]
输出:[0,1,2,3,4]
解释:
nums index target
1 0 [1]
2 1 [1,2]
3 2 [1,2,3]
4 3 [1,2,3,4]
0 0 [0,1,2,3,4]
示例 3:
输入:nums = [1], index = [0]
输出:[1]
提示:
1 <= nums.length, index.length <= 100
nums.length == index.length
0 <= nums[i] <= 100
0 <= index[i] <= i
第一题,送分题,如果想给自己增加难度的话,可以自己写一个数据结构实现。
class Solution {
public int[] createTargetArray(int[] nums, int[] index) {
ArrayList result = new ArrayList();
for(int i=0;i
1390. 四因数
给你一个整数数组 nums,请你返回该数组中恰有四个因数的这些整数的各因数之和。
如果数组中不存在满足题意的整数,则返回 0 。
示例:
输入:nums = [21,4,7]
输出:32
解释:
21 有 4 个因数:1, 3, 7, 21
4 有 3 个因数:1, 2, 4
7 有 2 个因数:1, 7
答案仅为 21 的所有因数的和。
提示:
1 <= nums.length <= 10^4
1 <= nums[i] <= 10^5
同样是送分题,就是注意一点,循环范围要取根号n,因为后面的部分就是重复计算了。如果不取,会超时。
class Solution {
public int sumFourDivisors(int[] nums) {
int res = 0;
for(int i=0;i tmp = judge(nums[i]);
if(tmp.get(0)==1)
{
for(int j=1;j res = new ArrayList();
if(num==1)
{
res.add(0);
return res;
}
for(int i=1;i<=Math.sqrt(num);i++)
{
if(num%i==0)
{
res.add(i);
if(i!=num/i)
res.add(num/i);
if(res.size()>4)
break;
}
}
if(res.size()==4)
{
res.add(0,1);
}
else
{
res.add(0,0);
}
return res;
}
}
1391. 检查网络中是否存在有效路径
给你一个 m x n 的网格 grid。网格里的每个单元都代表一条街道。grid[i][j] 的街道可以是:
1 表示连接左单元格和右单元格的街道。
2 表示连接上单元格和下单元格的街道。
3 表示连接左单元格和下单元格的街道。
4 表示连接右单元格和下单元格的街道。
5 表示连接左单元格和上单元格的街道。
6 表示连接右单元格和上单元格的街道。
你最开始从左上角的单元格 (0,0) 开始出发,网格中的「有效路径」是指从左上方的单元格 (0,0) 开始、一直到右下方的 (m-1,n-1) 结束的路径。该路径必须只沿着街道走。
注意:你 不能 变更街道。
如果网格中存在有效的路径,则返回 true,否则返回 false 。
示例 1:
输入:grid = [[2,4,3],[6,5,2]]
输出:true
解释:如图所示,你可以从 (0, 0) 开始,访问网格中的所有单元格并到达 (m - 1, n - 1) 。
示例 2:
输入:grid = [[1,2,1],[1,2,1]]
输出:false
解释:如图所示,单元格 (0, 0) 上的街道没有与任何其他单元格上的街道相连,你只会停在 (0, 0) 处。
示例 3:
输入:grid = [[1,1,2]]
输出:false
解释:你会停在 (0, 1),而且无法到达 (0, 2) 。
示例 4:
输入:grid = [[1,1,1,1,1,1,3]]
输出:true
示例 5:
输入:grid = [[2],[2],[2],[2],[2],[2],[6]]
输出:true
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
1 <= grid[i][j] <= 6
这个题证明我的编程水平是真的下降了,往常应该能马上想到并查集的,确实太典型了。现在我遇见这个题的第一反应是深度优先搜索,其实很容易看到,这个题目中,如果有路径,那么路径只此一条。因此从起点开始,只要有路,我们就走,能走到重点就是true,反之则是false。看上去蛮简单的,但是一个极大的问题就是,实在是太麻烦了!每种地图的对应编码写的我头疼,所以这个题还是最好用并查集,与前文思路不同的地方是,我们不需要分析地图点和点间是怎样联通的,只需要计算两个点间是不是联通的就可以了。
代码来自leetcode题解。
class Solution {
public:
static constexpr int MAX_N = 300 * 300 + 5;
int n = -1;
int m = -1;
vector> g;
struct DisjointSet {
int f[MAX_N];
DisjointSet() {
for (int i = 0; i < MAX_N; ++i) f[i] = i;
}
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
void merge(int x, int y) {
f[find(x)] = find(y);
}
} ds;
int getId (int x, int y)
{
return x * m + y;
}
void detectL(int x, int y)
{
if (y - 1 >= 0 && (g[x][y - 1] == 4 || g[x][y - 1] == 6 || g[x][y - 1] == 1))
{
ds.merge(getId(x, y), getId(x, y - 1));
}
}
void detectR(int x, int y)
{
if (y + 1 < m && (g[x][y + 1] == 3 || g[x][y + 1] == 5 || g[x][y + 1] == 1))
{
ds.merge(getId(x, y), getId(x, y + 1));
}
}
void detectU(int x, int y)
{
if (x - 1 >= 0 && (g[x - 1][y] == 3 || g[x - 1][y] == 4 || g[x - 1][y] == 2))
{
ds.merge(getId(x, y), getId(x - 1, y));
}
}
void detectD(int x, int y)
{
if (x + 1 < n && (g[x + 1][y] == 5 || g[x + 1][y] == 6 || g[x + 1][y] == 2))
{
ds.merge(getId(x, y), getId(x + 1, y));
}
}
void handle(int x, int y)
{
switch (g[x][y]) {
case 1: {
detectL(x, y); detectR(x, y);
} break;
case 2: {
detectU(x, y); detectD(x, y);
} break;
case 3: {
detectL(x, y); detectD(x, y);
} break;
case 4: {
detectR(x, y); detectD(x, y);
} break;
case 5: {
detectL(x, y); detectU(x, y);
} break;
case 6: {
detectR(x, y); detectU(x, y);
}
}
}
bool hasValidPath(vector>& grid) {
g = grid;
n = grid.size();
m = grid[0].size();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
handle(i, j);
}
}
return ds.find(getId(0, 0)) == ds.find(getId(n - 1, m - 1));
};
};
1392. 最长快乐前缀
「快乐前缀」是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。
给你一个字符串 s,请你返回它的 最长快乐前缀。
如果不存在满足题意的前缀,则返回一个空字符串。
示例 1:
输入:s = "level"
输出:"l"
解释:不包括 s 自己,一共有 4 个前缀("l", "le", "lev", "leve")和 4 个后缀("l", "el", "vel", "evel")。最长的既是前缀也是后缀的字符串是 "l" 。
示例 2:
输入:s = "ababab"
输出:"abab"
解释:"abab" 是最长的既是前缀也是后缀的字符串。题目允许前后缀在原字符串中重叠。
示例 3:
输入:s = "leetcodeleet"
输出:"leet"
示例 4:
输入:s = "a"
输出:""
提示:
1 <= s.length <= 10^5
s 只含有小写英文字母
KMP算法的应用,答案来自leetcode题解。
class Solution {
public String longestPrefix(String s) {
int[] next = getNext(s);
int n = next[s.length()];
return s.substring(0, n);
}
int[] getNext(String s) {
int[] next = new int[s.length() + 1];
int i = 0, j = -1;
next[0] = -1;
while (i < s.length()) {
if (j == -1 || s.charAt(j) == s.charAt(i))
// 已有 [0, ..., j - 1] 与 [i - j, ..., i - 1] 匹配, 同时 s[j] == s[i]
next[++i] = ++j;
// 匹配长度增加 1, 查看下一个匹配位置
else
j = next[j];
// 不匹配, 说明当前查看的前缀太长, 将 j 跳回到上一个可能的匹配位置
}
return next;
}
}
你可能感兴趣的:(数据结构与算法)