题目1
编写一个程序,找出第 n
个丑数。
丑数就是质因数只包含 2, 3, 5
的正整数。
示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
是前 10 个丑数。
说明:
1
是丑数。n
不超过1690。
思路及代码
任意一个丑数一定是另一个丑数乘以2或3或5得到的,我们可以使用一个数组将已经确认为丑数的数按照从小到大的顺序记录下来,每个丑数都是前面的丑数乘以2、3或5得来的。
class Solution {
public:
int nthUglyNumber(int n) {
if(n < 1){
return 0;
}
int num[n];
num[0] = 1;
int n2 = 0;
int n3 = 0;
int n5 = 0;
for(int i = 1; i<n;i++){
num[i] = min(min(num[n2]*2,num[n3]*3),num[n5]*5);
if(num[i] == num[n2]*2){
n2++;
}
if(num[i] == num[n3]*3){
n3++;
}
if(num[i] == num[n5]*5){
n5++;
}
}
return num[n - 1];
}
};
题目2
有 N
个网络节点,标记为 1
到 N
。
给定一个列表 times
,表示信号经过有向边的传递时间。 times[i] = (u, v, w)
,其中 u
是源节点,v
是目标节点, w
是一个信号从源节点传递到目标节点的时间。
现在,我们从某个节点 K
发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1
。
示例:
输入:times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2 输出:2
注意:
N
的范围在[1, 100]
之间。K
的范围在[1, N]
之间。times
的长度在[1, 6000]
之间。- 所有的边
times[i] = (u, v, w)
都有1 <= u, v <= N
且0 <= w <= 100
。
思路及代码
有图+要遍历+最短路,应该是第一时间想到迪杰斯特拉。附一篇算法介绍,当然这个地方还需要多加学习。
https://blog.csdn.net/qq_35644234/article/details/60870719
class Solution {
public:
static const int maxn = 105;
static const int emax = 6005;
static const int inf = 0x3f3f3f3f;
int dist[maxn], tot = 0;
int head[emax], Next[emax], ver[emax], edge[emax];
bool vis[maxn];
void add(int x, int y, int z)//邻接表
{
Next[++tot] = head[x], head[x] = tot;
ver[tot] = y, edge[tot] = z;
}
void dijkstar(int st)
{
dist[st] = 0;
priority_queue<pair<int, int>> q;
q.push(make_pair(-dist[st], st));
while (!q.empty())
{
int x = q.top().second;
q.pop();
if (vis[x])
continue;
vis[x] = 1;
for (int i = head[x]; i; i = Next[i])
{
int y = ver[i], z = edge[i];
if (dist[y] > dist[x] + z)
{
dist[y] = dist[x] + z;
q.push(make_pair(-dist[y], y));
}
}
}
}
public:
int networkDelayTime(vector<vector<int>> ×, int N, int K)
{
memset(vis, 0, sizeof(vis));
memset(dist, 0x3f, sizeof(dist));
for (int i = 0; i < times.size(); ++i)
add(times[i][0], times[i][1], times[i][2]);
dijkstar(K);
int ans = *max_element(dist + 1, dist + N + 1);
return ans == inf ? -1 : ans;
}
};
题目3
如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。
给你一个字符串 text
,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。
示例 1:
输入:text = "ababa" 输出:3
示例 2:
输入:text = "aaabaaa" 输出:6
示例 3:
输入:text = "aaabbaaa" 输出:4
示例 4:
输入:text = "aaaaa" 输出:5
示例 5:
输入:text = "abcdef" 输出:1
提示:
1 <= text.length <= 20000
text
仅由小写英文字母组成。
思路及代码
滑动窗口思想
维持一个‘窗口‘, 它拥有左右边界, 并且可以扩展
本题中, ‘窗口‘以某一位置为起点, 向右移动,
1)等于原位置字符的,则+1,
2)不等于的,则看右边还有没有可以交换的相等字符并有没有容错空间(原为1, 使用后为0)
- 注意:特殊情况
"aaba" 这种右边有交换字符, 但紧接着容错字符(不相等但可以容忍的), 会计算出超过字符频数的结果
class Solution {
public:
int maxRepOpt1(string text) {
if (text.size() <= 0)
return 0;
int len = text.size();
//cnt 字符串中所出现字符的频数
int cnt[30] = {0};
// type 字符串中字符种类
int type = 0;
for (char c : text) {
int ind=c-'a';
if (cnt[ind]==0) type++;
cnt[ind]++;
}
// 字符串中字符没有重复
if (type == len) return 1;
// 字符串中字符全部单字符重复
if (type == 1) return len;
// size 重复子串最大长度/滑动窗口最大长度
int size = 0;
for (int i = 0; i < len;) {
char begin = text[i];
// now 当前重复子串最大长度
// time 容错余裕 可以结合字符频数提前判断
// cnt[begin-'a']==1 --> time=0 没有可以交换字符 容错余裕为0
// next 下一个窗口开始位置(因为i++ 会导致有些计算冗余 可以直接从容错位置开始)
int now = 0, time = 1, next=i+1;
// 滑动窗口向右扩展
for (int j = i; j < len; j++) {
// 相等
if (text[j]==begin) now++;
// 不相等 但有容错和可交换字符
else if ((time-- > 0) && (cnt[begin-'a']-now >= 1)) {now++; next=j;}
else break;
}
// 特殊情况 计算长度必定不大于字符频数
now = now > cnt[begin-'a'] ? cnt[begin-'a'] : now;
// 比较原最大长度与当前长度
size = now > size ? now : size;
i = next;
}
return size;
}
};