- 至少有K个重复字符的最长子串
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
首先用哈希表算出每个字符出现个数,出现个数少于K的则作为分治的分割点,然后分割后长度小于当前最大子串长的则不需要计算了,直接剔除
class Solution {
public:
int longestSubstring(string s, int k)
{
unordered_map<char, int> umap;
for (auto c : s) umap[c]++;
vector<int> split;
for (int i = 0; i < s.size(); i++)
{
if (umap[s[i]] < k) split.push_back(i);
}
if (split.size() == 0) return s.length();
int ans = 0, left= 0;
split.push_back(s.length());
for (int i = 0; i < split.size(); i++)
{
int len = split[i] - left;
if (len > ans) ans = max(ans, longestSubstring(s.substr(left, len), k));
left = split[i]+1;
}
return ans;
}
};
- 旋转函数
给定一个长度为 n 的整数数组 A 。假设 Bk 是数组 A 顺时针旋转 k 个位置后的数组,我们定义 A 的“旋转函数” F 为:
F(k) = 0 * Bk[0] + 1 * Bk[1] + … + (n-1) * Bk[n-1]。
计算F(0), F(1), …, F(n-1)中的最大值。
数学计算题,数列求规律即可
class Solution {
public:
int maxRotateFunction(vector<int>& A) {
long N = A.size();
long S = 0;
long t = 0;
for (int i = 0; i < N; ++i) {
S += A[i];
t += i * A[i];
}
long res = t;
for (int i = N - 1; i >= 0; --i) {
// F(k+1) = F(k) + S - n * Bk[n-1]
t += S - N * (long)A[i];
res = max(res, t);
}
return res;
}
};
- 整数替换
给定一个正整数 n,你可以做如下操作:1. 如果 n 是偶数,则用 n / 2替换 n。2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n。n 变为 1 所需的最小替换次数是多少?
本题的思路是采取位操作,然后针对奇数,希望尽可能多的一次性消除多位1,以此为判断依据来选择加1还是减1.注意3是特殊情况,需要排除
class Solution {
public:
int integerReplacement(int n) {
if (n == INT_MAX) // 处理溢出,也可以直接用long tmp = n;
return 32;
int count = 0;
while (n != 1)
{
if ((n & 1) == 0)
{ // 偶数直接右移
n >>= 1;
}
else
{
// 奇数 01减一, 11加1,特殊情况n = 3也是减1
n += ((n & 2) == 0 || n == 3)? -1:1;
}
count++;
}
return count;
}
};
- 随机数索引
给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。
蓄水池采样法
class Solution {
public:
vector<int>& nums;
Solution(vector<int>& nums): nums(nums) {
}
int pick(int target) {
int idx = -1, cnt = 0;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] == target && rand() % (++cnt) == 0)
idx = i;
}
return idx;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(nums);
* int param_1 = obj->pick(target);
*/
- 除法求值
给出方程式 A / B = k, 其中 A 和 B 均为用字符串表示的变量, k 是一个浮点型数字。根据已知方程式求解问题,并返回计算结果。如果结果不存在,则返回 -1.0。
输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。
把除法视为边,则该过程实际是一个邻接矩阵,如果存在边和边的逆,则返回,否则则为-1
class Solution {
public:
vector<vector<double>> g;
unordered_map<string, int> h;
int n = 0;
void floyd() {
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
// 只有当g[i][k], g[k][j]能走的时候才进行更新 g[i][j]
if(g[i][k] >= 0 && g[k][j] >= 0) g[i][j] = g[i][k] * g[k][j];
}
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
// 将字符串映射到数组下标
for(int i = 0; i < equations.size(); i++) {
string a = equations[i][0], b = equations[i][1];
if(!h.count(a)) h[a] = n++;
if(!h.count(b)) h[b] = n++;
}
// 初始化邻接矩阵
g = vector<vector<double>>(n ,vector<double>(n, -1)); // g[i][j] = -1 表示不能从 i 到 j
for(int i = 0; i < n; i++)
g[i][i] = 1; // 对角线初始化为 1 因为 a/a = 1
for(int i = 0; i < equations.size(); i++) {
// 添加边(双向)
string a = equations[i][0], b = equations[i][1];
g[h[a]][h[b]] = values[i];
g[h[b]][h[a]] = 1 / values[i];
}
vector<double> res;
floyd();
for(auto q : queries) {
string a = q[0], b = q[1];
// 如果节点不存在或者a、b不联通则输出 -1
if(!h.count(a) || !h.count(b) || g[h[a]][h[b]] == -1) res.push_back(-1.0);
else {
res.push_back(g[h[a]][h[b]]);
}
}
return res;
}
};
- 第N个数字
在无限的整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …中找到第 n 个数字。
理解了题意就很简单
class Solution {
public:
int findNthDigit(int n) {
// bit记录所在区间的位数,p记录所在区间的长度
long long bit = 1, p = 9;
while(n - bit * p > 0){
n -= p * bit;
bit++;
p *= 10;
}
// num是答案所在数字
int num = pow(10, bit - 1) + (n-1) / bit;
// pos是答案在num中的位数(从左向右数)
int pos = n % bit;
pos = pos == 0 ? bit : pos;
int t = pow(10, bit - pos);
return num / t % 10;
}
};
- 二进制手表
给定一个非负整数 n 代表当前 LED 亮着的数量,返回所有可能的时间。
简单回溯法
class Solution {
public:
vector<string>res;
unordered_map<int,int> hash={{0,1},{1,2},{2,4},{3,8},{4,1},{5,2},{6,4},{7,8},{8,16},{9,32}};
void backtrack(int num,int start,pair<int,int>& time)
{
if(num==0)
{
if(time.first>11||time.second>59)//判断合法性
return;
string temp_hour=to_string(time.first);
string temp_minute=to_string(time.second);
if(temp_minute.size()==1)//如果minute只有一位要补0
temp_minute.insert(0,"0");
res.push_back(temp_hour+":"+temp_minute);//构造格式
return;
}
for(int i=start;i<10;i++)
{
if(time.first>11||time.second>59)
continue;
pair<int,int>store=time;//保存状态
if(i<4)
time.first+=hash[i];
else
time.second+=hash[i];
backtrack(num-1,i+1,time);//进入下一层,注意下一层的start是i+1,即从当前灯的下一盏开始
time=store;//恢复状态
}
}
vector<string> readBinaryWatch(int num) {
pair<int,int>time(0,0);//初始化时间为0:00
backtrack(num,0,time);
return res;
}
};