leetcode链接
你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。
你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。
这道题目只要是末尾的边界条件比较恶心一点
class Solution {
public:
bool isLongPressedName(string name, string typed)
{
int cur = 0;
if(name[0] != typed[0]) return false;
for(auto ch : name)
{
if(ch == typed[cur])
{
// 匹配成功
++cur;
}
else
{
// 匹配失败
// 可能上一个字符多键入了
auto prev_chr = typed[cur - 1];
while(cur < typed.size() && typed[cur] == prev_chr) cur++;
if(cur < typed.size() && typed[cur] == ch)
{
cur++;
}
else return false;
}
}
// 找找还有没有词
auto prev_chr = typed[cur - 1];
while(cur < typed.size() && typed[cur] == prev_chr) cur++;
if(cur < typed.size()) return false;
return true;
}
};
leetcode链接
给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。
k-diff 数对定义为一个整数对 (nums[i], nums[j]) ,并满足下述全部条件:
0 <= i, j < nums.length
i != j
|nums[i] - nums[j]| == k
注意,|val| 表示 val 的绝对值。
示例 1:
输入:nums = [3, 1, 4, 1, 5], k = 2
输出:2
解释:数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。
尽管数组中有两个 1 ,但我们只应返回不同的数对的数量。
示例 2:
输入:nums = [1, 2, 3, 4, 5], k = 1
输出:4
解释:数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5) 。
示例 3:
输入:nums = [1, 3, 1, 5, 4], k = 0
输出:1
解释:数组中只有一个 0-diff 数对,(1, 1)
第一版的思路就是直接查找, 但是k == 0单独讨论一下, 不然确实不好处理
class Solution {
public:
int getPrevDiffNum(vector<int>& num,int pos)
{
int res = pos - 1;
while(res >= 0 && num[res] == num[pos]) res--;
return res;
// -1
}
int getNextDiffNum(vector<int>& num,int pos)
{
int res = pos + 1;
while(res < num.size() && num[res] == num[pos]) res++;
return res;
}
int findPairs(vector<int>& nums, int k)
{
// 暴力算法
// 单独处理k == 0
sort(nums.begin(), nums.end());
if(k == 0)
{
int count = 0;
for(int i = 0;i < nums.size();i = getNextDiffNum(nums,i))
if(i + 1 < nums.size() && nums[i] == nums[i + 1]) count++;
return count;
}
int n = nums.size();
int count = 0;
for(int i = 0;i < n;i = getNextDiffNum(nums,i))
{
auto prev_diff_pos = i;
while(prev_diff_pos != -1)
{
if(nums[i] - nums[prev_diff_pos] >= k) break;
prev_diff_pos = getPrevDiffNum(nums, prev_diff_pos);
}
if(prev_diff_pos != -1 && nums[i] - nums[prev_diff_pos] == k)
{
count++;
}
}
return count;
}
};
我们在查找的时候可以使用二分进行速度的优化。确实快了一些
class Solution {
public:
int getPrevDiffNum(vector<int>& num,int pos)
{
int res = pos - 1;
while(res >= 0 && num[res] == num[pos]) res--;
return res;
// -1
}
int getNextDiffNum(vector<int>& num,int pos)
{
int res = pos + 1;
while(res < num.size() && num[res] == num[pos]) res++;
return res;
}
int findPairs(vector<int>& nums, int k)
{
// 暴力算法
// 单独处理k == 0
sort(nums.begin(), nums.end());
if(k == 0)
{
int count = 0;
for(int i = 0;i < nums.size();i = getNextDiffNum(nums,i))
if(i + 1 < nums.size() && nums[i] == nums[i + 1]) count++;
return count;
}
// 如果k != 0, 首先进行去重
// 通过二分查找进行优化之前的逻辑
int count = 0;
for(int i = getNextDiffNum(nums,0);i < nums.size();i = getNextDiffNum(nums,i))
{
int left = 0, right = i - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[i] - nums[mid] > k) left = mid + 1;
else right = mid;
}
if(nums[i] - nums[left] == k) count++;
}
return count;
}
};
leetcode
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
class Cmp
{
public:
// we must guarentee vector.size() == 2
bool operator()(const vector<int>& l,const vector<int>& r)
{
return l[0] < r[0];
}
};
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals)
{
vector<vector<int>> ret;
std::sort(intervals.begin(),intervals.end(),Cmp());
int prev_end = intervals[0][0];
int prev_begin = intervals[0][0];
intervals.push_back({INT32_MAX,INT32_MAX});
for(auto& area : intervals)
{
int begin = area[0], end = area[1];
if(prev_end < begin)
{
// 更新区间
ret.push_back({prev_begin,prev_end});
prev_begin = begin, prev_end = end;
}
else if(begin <= prev_end)
{
// 出现交叉
// 合并
prev_end = std::max(prev_end,end);
}
}
return ret;
}
};
leetcode
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库内置的 sort 函数的情况下解决这个问题。
示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
class Solution {
public:
// 通过快排
void sortColors(vector<int>& nums) {
int left = -1, right = nums.size();
int cur = 0;
while(cur < right)
{
if(nums[cur] == 0) std::swap(nums[cur++], nums[++left]);
else if(nums[cur] == 1) cur++;
else std::swap(nums[cur], nums[--right]);
}
}
};
leetcode
给定一个二进制数组 nums , 计算其中最大连续 1 的个数。
示例 1:
输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:
输入:nums = [1,0,1,1,0,1]
输出:2
提示:
1 <= nums.length <= 105
nums[i] 不是 0 就是 1.
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
// 很简单的双指针的算法
// count表示当前位置前面需要删除的个数
int symbol = INT32_MAX;
int symbol_count = 0;
int offset = 0;
for(int i = 0;i < nums.size();i++)
{
if(nums[i] == symbol)
{
symbol_count++;
if(symbol_count > 2)
offset++;
else
{
nums[i - offset] = nums[i];
}
}
else
{
symbol = nums[i];
symbol_count = 1;
nums[i - offset] = nums[i];
}
}
auto res = nums.size() - offset;
nums.resize(res);
return res;
}
};
leetcode
给定一个二进制数组 nums , 计算其中最大连续 1 的个数。
示例 1:
输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:
输入:nums = [1,0,1,1,0,1]
输出:2
class Solution {
public:
int findMaxConsecutiveOnes(vector<int>& nums)
{
int res = 0;
int count = 0;
for(auto i : nums)
{
if(i == 0)
{
count = 0;
}
else
{
count++;
res = std::max(res,count);
}
}
return res;
}
};
给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。
如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。
示例 1:
输入:s = “abpcplea”, dictionary = [“ale”,“apple”,“monkey”,“plea”]
输出:“apple”
示例 2:
输入:s = “abpcplea”, dictionary = [“a”,“b”,“c”]
输出:“a”
class Solution {
public:
Solution() : _hash(26)
{}
void initHashTable(const std::string& str)
{
for(int i = 0;i < str.size();i++)
_hash[str[i] - 'a'].push_back(i);
}
bool isFitChildString(const std::string& src)
{
int cur = -1;
for(auto ch : src)
{
// 判断ch是否在(cur, end]中存在, 若存在找到最近的一个
// 通过二分查找进行优化
auto& posSet = _hash[ch - 'a'];
if(posSet.empty()) return false;
else
{
int left = 0, right = posSet.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(posSet[mid] <= cur) left = mid + 1;
else right = mid;
}
if(posSet[left] <= cur) return false;
else cur = posSet[left];
}
}
return true;
}
// 这道题目的本质就是判断dictionary中是否存在s的子序列, 对于大量判断, 通过hash来解决
string findLongestWord(string s, vector<string>& dictionary)
{
initHashTable(s);
string res;
for(auto& dict : dictionary)
{
if(isFitChildString(dict))
{
if(dict.size() > res.size()) res = dict;
else if(dict.size() == res.size() && dict < res) res = dict;
}
}
return res;
}
// 通过hash + 二分进行优化
private:
vector<vector<int>> _hash;
};
leetcode
给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。
返回这 两个区间列表的交集 。
形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。
两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。
示例 1:
输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
示例 2:
输入:firstList = [[1,3],[5,9]], secondList = []
输出:[]
示例 3:
输入:firstList = [], secondList = [[4,8],[10,12]]
输出:[]
示例 4:
输入:firstList = [[1,7]], secondList = [[3,10]]
输出:[[3,7]]
class Solution {
public:
struct InterArea
{
InterArea(int left = -1,int right = -1) :
_left(left), _right(right)
{}
operator bool()
{
return _left != -1;
}
int _left;
int _right;
};
// 判断两个区间是否存在公共部分
InterArea isHasInterSection(vector<int>& l, vector<int>& r)
{
if(l[0] > r[1] || l[1] < r[0]) return {-1, -1 };
else return InterArea((int)std::max(l[0],r[0]), (int)std::min(l[1], r[1]));
}
vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList)
{
vector<vector<int>> res;
int start = 0;
for(auto& List : secondList)
{
while(start < firstList.size() && firstList[start][1] < List[0]) start++;
auto cur = start;
// 计算区间
while(cur < firstList.size() && firstList[cur][0] <= List[1])
{
auto inter = isHasInterSection(firstList[cur], List);
res.push_back({inter._left, inter._right});
cur++;
}
}
return res;
}
};