You are given two positive integer arrays spells
and potions
, of length n
and m
respectively, where spells[i]
represents the strength of the ith
spell and potions[j]
represents the strength of the jth
potion.
You are also given an integer success
. A spell and potion pair is considered successful if the product of their strengths is at least success
.
Return an integer array pairs
of length n
where pairs[i]
is the number of potions that will form a successful pair with the ith
spell.
Input: spells = [5,1,3], potions = [1,2,3,4,5], success = 7
Output: [4,0,3]
Explanation:
- 0th spell: 5 * [1,2,3,4,5] = [5,10,15,20,25]. 4 pairs are successful.
- 1st spell: 1 * [1,2,3,4,5] = [1,2,3,4,5]. 0 pairs are successful.
- 2nd spell: 3 * [1,2,3,4,5] = [3,6,9,12,15]. 3 pairs are successful.
Thus, [4,0,3] is returned.
Input: spells = [3,1,2], potions = [8,5,8], success = 16
Output: [2,0,2]
Explanation:
- 0th spell: 3 * [8,5,8] = [24,15,24]. 2 pairs are successful.
- 1st spell: 1 * [8,5,8] = [8,5,8]. 0 pairs are successful.
- 2nd spell: 2 * [8,5,8] = [16,10,16]. 2 pairs are successful.
Thus, [2,0,2] is returned.
Constraints:
n == spells.length
m == potions.length
1 <= n, m <= 10^5
1 <= spells[i], potions[i] <= 10^5
1 <= success <= 10^10
class Solution {
public:
vector<int> successfulPairs(vector<int> &spells, vector<int> &potions, long long success) {
sort(potions.begin(), potions.end());
vector<int> result(spells.size());
for (int i = 0; i < spells.size(); ++i) {
int lo = min(100001ll, (success - 1) / spells[i] + 1);
result[i] = potions.end() - lower_bound(potions.begin(), potions.end(), lo);
}
return result;
}
};
You are given two strings s
and sub
. You are also given a 2D character array mappings
where mappings[i] = [oldi, newi]
indicates that you may replace any number of oldi
characters of sub
with newi
. Each character in sub
cannot be replaced more than once.
Return true
if it is possible to make sub
a substring of s
by replacing zero or more characters according to mappings
. Otherwise, return false
.
A substring is a contiguous non-empty sequence of characters within a string.
Input: s = "fool3e7bar", sub = "leet", mappings = [["e","3"],["t","7"],["t","8"]]
Output: true
Explanation: Replace the first 'e' in sub with '3' and 't' in sub with '7'.
Now sub = "l3e7" is a substring of s, so we return true.
Input: s = "fooleetbar", sub = "f00l", mappings = [["o","0"]]
Output: false
Explanation: The string "f00l" is not a substring of s and no replacements can be made.
Note that we cannot replace '0' with 'o'.
Constraints:
1 <= sub.length <= s.length <= 5000
0 <= mappings.length <= 1000
mappings[i].length == 2
oldi != newi
s
and sub
consist of uppercase and lowercase English letters and digits.oldi
and newi
are either uppercase or lowercase English letters or digits.class Solution:
def matchReplacement(self, s: str, sub: str, mappings: List[List[str]]) -> bool:
mp = set((x, y) for x, y in mappings)
for i in range(len(sub), len(s) + 1):
if all(x == y or (x, y) in mp for x, y in zip(sub, s[i - len(sub):i])):
return True
return False
The score of an array is defined as the product of its sum and its length.
[1, 2, 3, 4, 5]
is (1 + 2 + 3 + 4 + 5) * 5 = 75
.Given a positive integer array nums
and an integer k
, return the number of non-empty subarrays of nums
whose score is strictly less than k
.
A subarray is a contiguous sequence of elements within an array.
Input: nums = [2,1,4,3,5], k = 10
Output: 6
Explanation:
The 6 subarrays having scores less than 10 are:
- [2] with score 2 * 1 = 2.
- [1] with score 1 * 1 = 1.
- [4] with score 4 * 1 = 4.
- [3] with score 3 * 1 = 3.
- [5] with score 5 * 1 = 5.
- [2,1] with score (2 + 1) * 2 = 6.
Note that subarrays such as [1,4] and [4,3,5] are not considered because their scores are 10 and 36 respectively, while we need scores strictly less than 10.
Input: nums = [1,1,1], k = 5
Output: 5
Explanation:
Every subarray except [1,1,1] has a score less than 5.
[1,1,1] has a score (1 + 1 + 1) * 3 = 9, which is greater than 5.
Thus, there are 5 subarrays having scores less than 5.
Constraints:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
1 <= k <= 10^15
class Solution:
def countSubarrays(self, nums: List[int], k: int) -> int:
ans = s = lo = 0
for hi, num in enumerate(nums):
s += num
while s * (hi - lo + 1) >= k:
s -= nums[lo]
lo += 1
ans += hi - lo + 1
return ans
You are given an integer array nums
and an integer k
. You may partition nums
into one or more subsequences such that each element in nums
appears in exactly one of the subsequences.
Return the minimum number of subsequences needed such that the difference between the maximum and minimum values in each subsequence is at most k
.
A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
Input: nums = [3,6,1,2,5], k = 2
Output: 2
Explanation:
We can partition nums into the two subsequences [3,1,2] and [6,5].
The difference between the maximum and minimum value in the first subsequence is 3 - 1 = 2.
The difference between the maximum and minimum value in the second subsequence is 6 - 5 = 1.
Since two subsequences were created, we return 2. It can be shown that 2 is the minimum number of subsequences needed.
Input: nums = [1,2,3], k = 1
Output: 2
Explanation:
We can partition nums into the two subsequences [1,2] and [3].
The difference between the maximum and minimum value in the first subsequence is 2 - 1 = 1.
The difference between the maximum and minimum value in the second subsequence is 3 - 3 = 0.
Since two subsequences were created, we return 2. Note that another optimal solution is to partition nums into the two subsequences [1] and [2,3].
Constraints:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^5
0 <= k <= 10^5
class Solution {
public:
int partitionArray(vector<int> nums, int k) {
int result = 0;
sort(nums.begin(), nums.end());
for (int lo = 0, hi, up; lo < nums.size(); lo = hi) {
hi = nums.size(), up = nums[lo] + k, result++;
while (lo < hi) {
int mi = lo + ((hi - lo) >> 1);
nums[mi] <= up ? lo = mi + 1 : hi = mi;
}
}
return result;
}
};
给你一个下标从 0 开始的数组 nums
,它包含 n
个 互不相同 的正整数。请你对这个数组执行 m
个操作,在第 i
个操作中,你需要将数字 operations[i][0]
替换成 operations[i][1]
。
题目保证在第 i
个操作中:
operations[i][0]
在 nums
中存在。operations[i][1]
在 nums
中不存在。请你返回执行完所有操作后的数组。
输入:nums = [1,2,4,6], operations = [[1,3],[4,7],[6,1]]
输出:[3,2,7,1]
解释:我们对 nums 执行以下操作:
- 将数字 1 替换为 3 。nums 变为 [3,2,4,6] 。
- 将数字 4 替换为 7 。nums 变为 [3,2,7,6] 。
- 将数字 6 替换为 1 。nums 变为 [3,2,7,1] 。
返回最终数组 [3,2,7,1] 。
输入:nums = [1,2], operations = [[1,3],[2,1],[3,2]]
输出:[2,1]
解释:我们对 nums 执行以下操作:
- 将数字 1 替换为 3 。nums 变为 [3,2] 。
- 将数字 2 替换为 1 。nums 变为 [3,1] 。
- 将数字 3 替换为 2 。nums 变为 [2,1] 。
返回最终数组 [2,1] 。
Constraints:
n == nums.length
m == operations.length
1 <= n, m <= 10^5
nums
are distinct.operations[i].length == 2
1 <= nums[i], operations[i][0], operations[i][1] <= 10^6
operations[i][0]
will exist in nums
when applying the ith
operation.operations[i][1]
will not exist in nums
when applying the ith
operation.class Solution:
def arrayChange(self, nums: List[int], operations: List[List[int]]) -> List[int]:
idx = {num: i for i, num in enumerate(nums)}
for x, y in operations:
i = idx[x]
nums[i] = y
del idx[x]
idx[y] = i
return nums
Design a text editor with a cursor that can do the following:
When deleting text, only characters to the left of the cursor will be deleted. The cursor will also remain within the actual text and cannot be moved beyond it. More formally, we have that 0 <= cursor.position <= currentText.length
always holds.
Implement the TextEditor
class:
TextEditor()
Initializes the object with empty text.void addText(string text)
Appends text
to where the cursor is. The cursor ends to the right of text
.int deleteText(int k)
Deletes k
characters to the left of the cursor. Returns the number of characters actually deleted.string cursorLeft(int k)
Moves the cursor to the left k
times. Returns the last min(10, len)
characters to the left of the cursor, where len
is the number of characters to the left of the cursor.string cursorRight(int k)
Moves the cursor to the right k
times. Returns the last min(10, len)
characters to the left of the cursor, where len
is the number of characters to the left of the cursor.Input
["TextEditor", "addText", "deleteText", "addText", "cursorRight", "cursorLeft", "deleteText", "cursorLeft", "cursorRight"]
[[], ["leetcode"], [4], ["practice"], [3], [8], [10], [2], [6]]
Output
[null, null, 4, null, "etpractice", "leet", 4, "", "practi"]
Explanation
TextEditor textEditor = new TextEditor(); // The current text is "|". (The '|' character represents the cursor)
textEditor.addText("leetcode"); // The current text is "leetcode|".
textEditor.deleteText(4); // return 4
// The current text is "leet|".
// 4 characters were deleted.
textEditor.addText("practice"); // The current text is "leetpractice|".
textEditor.cursorRight(3); // return "etpractice"
// The current text is "leetpractice|".
// The cursor cannot be moved beyond the actual text and thus did not move.
// "etpractice" is the last 10 characters to the left of the cursor.
textEditor.cursorLeft(8); // return "leet"
// The current text is "leet|practice".
// "leet" is the last min(10, 4) = 4 characters to the left of the cursor.
textEditor.deleteText(10); // return 4
// The current text is "|practice".
// Only 4 characters were deleted.
textEditor.cursorLeft(2); // return ""
// The current text is "|practice".
// The cursor cannot be moved beyond the actual text and thus did not move.
// "" is the last min(10, 0) = 0 characters to the left of the cursor.
textEditor.cursorRight(6); // return "practi"
// The current text is "practi|ce".
// "practi" is the last min(10, 6) = 6 characters to the left of the cursor.
Constraints:
1 <= text.length, k <= 40
text
consists of lowercase English letters.2 * 10^4
calls in total will be made to addText
, deleteText
, cursorLeft
and cursorRight
.struct Node {
char val;
Node *prev, *next;
Node(char val = 0) : val(val), prev(nullptr), next(nullptr) {}
Node(char val, Node *prev, Node *next) : val(val), prev(prev), next(next) {}
};
class TextEditor {
private:
Node *dummyHead, *dummyTail, *curNode;
inline void insertBefore(char val) {
auto node = new Node(val, curNode->prev, curNode);
curNode->prev->next = node;
curNode->prev = node;
}
inline bool deleteBefore() {
if (curNode->prev == dummyHead) return false;
curNode->prev = curNode->prev->prev;
curNode->prev->next = curNode;
return true;
}
string readBefore(int n = 10) {
auto node = curNode;
while (n-- && node->prev != dummyHead)
node = node->prev;
string s;
while (node != curNode) {
s.push_back(node->val);
node = node->next;
}
return s;
}
public:
TextEditor() {
dummyHead = new Node();
dummyTail = new Node();
dummyHead->next = dummyTail;
dummyTail->prev = dummyHead;
curNode = dummyTail;
}
void addText(string text) { for (char ch:text) insertBefore(ch); }
int deleteText(int k) {
for (int i = 0; i < k; i++) { if (!deleteBefore()) return i; }
return k;
}
string cursorLeft(int k) {
while (k-- && curNode->prev != dummyHead) curNode = curNode->prev;
return move(readBefore());
}
string cursorRight(int k) {
while (k-- && curNode->next != nullptr) curNode = curNode->next;
return move(readBefore());
}
};
给你两个下标从 0 开始的字符串 s
和 target
。你可以从 s
取出一些字符并将其重排,得到若干新的字符串。
从 s
中取出字符并重新排列,返回可以形成 target
的 最大 副本数。
输入:s = "ilovecodingonleetcode", target = "code"
输出:2
解释:
对于 "code" 的第 1 个副本,选取下标为 4 、5 、6 和 7 的字符。
对于 "code" 的第 2 个副本,选取下标为 17 、18 、19 和 20 的字符。
形成的字符串分别是 "ecod" 和 "code" ,都可以重排为 "code" 。
可以形成最多 2 个 "code" 的副本,所以返回 2 。
提示:
1 <= s.length <= 100
1 <= target.length <= 10
s
和 target
由小写英文字母组成class Solution {
public:
int rearrangeCharacters(const string &s, const string &target) {
unordered_map<char, int> mpTarget; // 由于 s 和 target 由小写字母组成, 因此使用数组做哈希更合适一些
for (char ch:target) mpTarget[ch]++;
unordered_map<char, int> mpSource;
for (char ch:s) {
if (mpTarget.count(ch)) mpSource[ch]++;
}
int result = INT_MAX;
for (char ch:target) {
result = min(mpSource[ch] / mpTarget[ch], result);
}
return result;
}
};
A sentence is a string of single-space separated words where each word can contain digits, lowercase letters, and the dollar sign '$'
. A word represents a price if it is a sequence of digits preceded by a dollar sign.
"$100"
, "$23"
, and "$6"
represent prices while "100"
, "$"
, and "$1e5"
do not.You are given a string sentence
representing a sentence and an integer discount
. For each word representing a price, apply a discount of discount%
on the price and update the word in the sentence. All updated prices should be represented with exactly two decimal places.
Return a string representing the modified sentence.
Note that all prices will contain at most 10
digits.
Input: sentence = "there are $1 $2 and 5$ candies in the shop", discount = 50
Output: "there are $0.50 $1.00 and 5$ candies in the shop"
Explanation:
The words which represent prices are "$1" and "$2".
- A 50% discount on "$1" yields "$0.50", so "$1" is replaced by "$0.50".
- A 50% discount on "$2" yields "$1". Since we need to have exactly 2 decimal places after a price, we replace "$2" with "$1.00".
Constraints:
1 <= sentence.length <= 10^5
sentence
consists of lowercase English letters, digits, ' '
, and '$'
.sentence
does not have leading or trailing spaces.sentence
are separated by a single space.10
digits.0 <= discount <= 100
class Solution:
def discountPrices(self, sentence: str, discount: int) -> str:
words = sentence.split(' ')
for i, word in enumerate(words):
if word[0] == '$' and word[1:].isdigit():
ct = eval(word[1:]) * (100.0 - discount) / 100.0
words[i] = f'${ct:.2f}'
return ' '.join(words)
给你一个整数数组 nums
,按要求返回一个新数组 counts
。数组 counts
有该性质: counts[i]
的值是 nums[i]
右侧小于 nums[i]
的元素的数量。
输入:nums = [5,2,6,1]
输出:[2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
class Solution {
private:
vector<int> segTree;
void build(unsigned int n) {
segTree.assign(n << 2, 0);
}
void insert(int start, int end, int node, int val) {
segTree[node]++;
if (start == end) return;
int mid = start + ((end - start) >> 1);
int left_node = (node << 1) + 1, right_node = (node << 1) + 2;
val <= mid ? insert(start, mid, left_node, val) : insert(mid + 1, end, right_node, val);
}
int query(int start, int end, int L, int R, int node) {
if (start > R || end < L) return 0;
if (L <= start && end <= R) return segTree[node];
int mid = start + ((end - start) >> 1);
int left_node = (node << 1) + 1, right_node = (node << 1) + 2;
return query(start, mid, L, R, left_node) + query(mid + 1, end, L, R, right_node);
}
public:
vector<int> countSmaller(const vector<int> &nums) {
vector<int> tmp(nums.begin(), nums.end());
sort(tmp.begin(), tmp.end());
tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
build(tmp.size());
unordered_map<int, int> mp;
for (int i = 0; i < tmp.size(); ++i) mp[tmp[i]] = i;
vector<int> result(nums.size());
for (int i = nums.size() - 1; i >= 0; --i) {
int idx = mp[nums[i]];
result[i] = query(0, mp.size() - 1, 0, idx - 1, 0);
insert(0, mp.size() - 1, 0, idx);
}
return result;
}
};
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
输入: [7,5,6,4]
输出: 5
提示:
0 <= 数组长度 <= 50000
class Solution {
private:
vector<int> segTree;
void build(unsigned int n) {
segTree.assign(n << 2, 0);
}
void insert(int start, int end, int node, int val) {
segTree[node]++;
if (start == end) return;
int mid = start + ((end - start) >> 1);
int left_node = (node << 1) + 1, right_node = (node << 1) + 2;
val <= mid ? insert(start, mid, left_node, val) : insert(mid + 1, end, right_node, val);
}
int query(int start, int end, int L, int R, int node) {
if (start > R || end < L) return 0;
if (L <= start && end <= R) return segTree[node];
int mid = start + ((end - start) >> 1);
int left_node = (node << 1) + 1, right_node = (node << 1) + 2;
return query(start, mid, L, R, left_node) + query(mid + 1, end, L, R, right_node);
}
public:
int reversePairs(const vector<int> &nums) {
vector<int> tmp(nums.begin(), nums.end());
sort(tmp.begin(), tmp.end());
tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
build(tmp.size());
unordered_map<int, int> mp;
for (int i = 0; i < tmp.size(); ++i) mp[tmp[i]] = i;
int result = 0;
for (int i = nums.size() - 1; i >= 0; --i) {
int idx = mp[nums[i]];
result += query(0, mp.size() - 1, 0, idx - 1, 0);
insert(0, mp.size() - 1, 0, idx);
}
return result;
}
};
给你一个下标从 0 开始的整数数组 nums
。在一步操作中,移除所有满足 nums[i - 1] > nums[i]
的 nums[i]
,其中 0 < i < nums.length
。
重复执行步骤,直到 nums
变为 非递减 数组,返回所需执行的操作数。
输入:nums = [5,3,4,4,7,3,6,11,8,5,11]
输出:3
解释:执行下述几个步骤:
- 步骤 1 :[5,3,4,4,7,3,6,11,8,5,11] 变为 [5,4,4,7,6,11,11]
- 步骤 2 :[5,4,4,7,6,11,11] 变为 [5,4,7,11,11]
- 步骤 3 :[5,4,7,11,11] 变为 [5,7,11,11]
[5,7,11,11] 是一个非递减数组,因此,返回 3 。
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9
class Solution {
public:
int totalSteps(vector<int> &nums) {
int ans = 0;
stack<pair<int, int>> st;
for (int num : nums) {
int maxT = 0;
while (!st.empty() && st.top().first <= num) {
maxT = max(maxT, st.top().second);
st.pop();
}
maxT = st.empty() ? 0 : maxT + 1;
ans = max(ans, maxT);
st.emplace(num, maxT);
}
return ans;
}
};
class Solution {
public:
int totalSteps(vector<int> &nums) {
stack<int> st;
int res = 0, f[nums.size()];
for (int i = 0; i < nums.size(); ++i) {
int cur = 0;
while (!st.empty() && nums[st.top()] <= nums[i]) {
cur = max(cur, f[st.top()]);
st.pop();
}
if (!st.empty()) {
res = max(res, cur + 1);
f[i] = cur + 1;
}
st.push(i);
}
return res;
}
};
给你一个下标从 0 开始的二维整数数组 grid
,数组大小为 m x n
。每个单元格都是两个值之一:
0
表示一个 空 单元格,1
表示一个可以移除的 障碍物 。你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
现在你需要从左上角 (0, 0)
移动到右下角 (m - 1, n - 1)
,返回需要移除的障碍物的 最小 数目。
输入:grid = [[0,1,1],[1,1,0],[1,1,0]]
输出:2
解释:可以移除位于 (0, 1) 和 (0, 2) 的障碍物来创建从 (0, 0) 到 (2, 2) 的路径。
可以证明我们至少需要移除两个障碍物,所以返回 2 。
注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。
class Solution {
static constexpr int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public:
int minimumObstacles(vector<vector<int>> &grid) {
int m = grid.size(), n = grid[0].size();
int dis[m][n];
memset(dis, 0x3f, sizeof(dis));
dis[0][0] = 0;
deque<pair<int, int>> q;
q.emplace_front(0, 0);
while (!q.empty()) {
auto[x, y] = q.front();
q.pop_front();
for (auto &[dx, dy] : dirs) {
int nx = x + dx, ny = y + dy;
if (0 <= nx && nx < m && 0 <= ny && ny < n) {
int g = grid[nx][ny];
if (dis[x][y] + g < dis[nx][ny]) {
dis[nx][ny] = dis[x][y] + g;
g == 0 ? q.emplace_front(nx, ny) : q.emplace_back(nx, ny);
}
}
}
}
return dis[m - 1][n - 1];
}
};